zoukankan      html  css  js  c++  java
  • 《Linux C一站式学习》第七章 结构体


    1. 复合类型与结构体
    在编程语言中,最基本的、不可再分的数据类型称为基本类型(Primitive Type),例如整型、浮点型;根据语法规则由基本类型组合而成的类型称为复合类型(Compound Type),例如字符串是由很多字符组成的。
    struct complex_struct {
         double x, y;
    };
    struct complex_struct {
         double x, y;
    } z1, z2;
    struct complex_struct z3, z4;
    struct complext_struct z = { 3.0, 4.0 }
    Initializer中的数据依次赋给结构体的各成员。如果Initializer中的数据比结构体的成员多,编译器会报错,但如果只是末尾多个逗号则不算错。如果Initializer中的数据比结构体的成员少,未指定的成员将用0来初始化,就像未初始化的全局变量一样。
    这样是错误的:
    struct complex_struct z1;
    z1 = { 3.0, 4.0 };
    Designated Initializer是C99引入的新特性,用于初始化稀疏(Sparse)结构体和稀疏数组很方便。有些时候结构体或数组中只有某一个或某几个成员需要初始化,其它成员都用0初始化即可,用Designated Initializer语法可以针对每个成员做初始化(Memberwise Initialization),很方便。
    struct complex_struct z1 = { .y = 4.0 };
    结构体类型用在表达式中有很多限制,不像基本类型那么自由,比如+ - * /等算术运算符和&& || !等逻辑运算符都不能作用于结构体类型,if语句、while语句中的控制表达式的值也不能是结构体类型。
    结构体变量之间使用赋值运算符是允许的:z1 = z2;

    注:结构体作为变量声明、参数、返回值都要加上struct关键字。


    2. 数据抽象
    1、在本节的基础上实现一个打印复数的函数,打印的格式是x+yi,如果实部或虚部为0则省略,例如:1.0、-2.0i、-1.0+2.0i、1.0-2.0i。最后编写一个main函数测试本节的所有代码。想一想这个打印函数应该属于上图中的哪一层?
    答:
    void print_complex(struct complext_struct z)
    {
         if (z.x == 0 && z.y == 0) {
              printf("0");
         } else if (z.x == 0 && z.y != 0) {
              printf("%.1f i", z.y);
         } else if (z.x != 0 && z.y == 0) {
              printf("%.1f", z.x);
         } else {
              printf("%.1f + %.1f i", z.x, z.y);
         }
    }
    2、实现一个用分子分母的格式来表示有理数的结构体rational以及相关的函数,rational结构体之间可以做加减乘除运算,运算的结果仍然是rational。注意要约分为最简分数,例如1/8和-1/8相减的打印结果应该是1/4而不是2/8,可以利用第 3 节 “递归”练习题中的Euclid算法来约分。
    答:
    #include <stdio.h>
    #include "gcd.c"
    struct rational
    {
         int x;
         int y;
    };     //分号不能忘!
    struct rational add(struct rational a, struct rational b)
    {
         struct rational c;
         c.x = a.x + b.x;
         c.y = a.y + b.y;
         return simply(c);
    }
    // 变量和函数不能重名 int gcd会出错
    struct rational simply(struct rational a)
    {
         int gcdnum;

    if (abs(a.x) > abs(a.y)) {
    gcdnum = gcd(abs(a.x), abs(a.y));
    } else {
    gcdnum = gcd(abs(a.y), abs(a.x));
    }
    a.x = a.x / gcdnum;
    a.y = a.y / gcdnum;
    return a;

    }
    void print(struct rational a)
    {
         printf("%d/%d \n", a.x, a.y);
    }
    int main(void)
    {
         struct rational a = { -1, 8 };
         struct rational b = { -1, 8 };
         struct rational c = add(a, b);
         print(c);
         return 0;
    }
    3. 数据类型标志
    enum coordinate_type { RECTANGULAR, POLAR };
    struct complex_struct {
         enum coordinate_type t;
         double a, b;
    };
    枚举类型的成员是常量,它们的值由编译器自动分配,例如定义了上面的枚举类型之后,RECTANGULAR就表示常量0,POLAR表示常量1。如果不希望从0开始分配,可以这样定义:
    enum coordinate_type { RECTANGULAR = 1, POLAR };
    枚举常量也是一种整型,其值在编译时确定,因此也可以出现在常量表达式中,可以用于初始化全局变量或者作为case分支的判断条件。
    虽然结构体的成员名和变量名不在同一命名空间中,但枚举的成员名却和变量名在同一命名空间中,所以会出现命名冲突。例如这样是不合法的:
    int main(void)
    {
         enum coordinate_type { RECTANGULAR = 1, POLAR };
         int RECTANGULAR;
    }
    习题
    2. 编译运行下面这段程序:
    #include <stdio.h>

    enum coordinate_type { RECTANGULAR = 1, POLAR };

    int main(void)
    {
         int RECTANGULAR;
         printf("%d %d\n", RECTANGULAR, POLAR);
         return 0;
    }

    结果是什么?并解释一下为什么是这样的结果。
    答:3719156 2。main函数中的局部变量作用域覆盖了外部的枚举。
    4. 嵌套结构体
    struct segment {
         struct complex_struct start;
         struct complex_struct end;
    };
    Initializer也可以嵌套,因此嵌套结构体可以嵌套地初始化:
    struct segment s = { { 1.0, 2.0 }, { 4.0, 6.0 } };
    访问嵌套结构体的成员要用到多个.运算符,例如:
    s.start.t = RECTANGULAR;
    s.start.a = 1.0;

     

  • 相关阅读:
    ACM学习历程——POJ3321 Apple Tree(搜索,线段树)
    ACM学习历程——NOJ1113 Game I(贪心 || 线段树)
    ACM学习历程——HDU5202 Rikka with string(dfs,回文字符串)
    ACM学习历程——hihoCoder挑战赛10A 01串(策略)
    ACM学习历程——POJ3468 A Simple Problem with Integers(线段树)
    ACM学习历程——POJ1260 Pearls(动态规划)
    java入门了解09
    java入门了解08
    java入门了解之快捷键
    java入门了解07
  • 原文地址:https://www.cnblogs.com/xiaomaohai/p/6157914.html
Copyright © 2011-2022 走看看