天天看點

ios學習之旅------玩轉結構體

1.全局變量和局部變量

局部變量:

    概念:定義函數内部變量

    定義格式:變量類型 變量名稱;

    作用域:從定義那一行開始到所在代碼塊結束

    生命周期:從代碼執行到定義的哪一行開始,到其所在的代碼的結束為止

    特點:相同的代碼塊中不可以有同名的變量

         不同的代碼塊中可以有同名的變量,内部的變量會覆寫外部定義的變量

全局變量:

    概念:定義在函數外部變量

    定義:變量類型 變量名稱 = 值;

    聲明:變量類型 變量名稱;

    特點:1、不可以重複定義,但可以重複聲明

         2、局部變量可以與全局變量同名,在局部變量的作用域範圍内,那麼局部變量會覆寫全局變量

         3、如果沒有定義僅有聲明,系統自動給它定義并将其初始化為0

    作用域:從定義的那一行開始,直到檔案結束

    生命周期:從程式啟動開始,直到程式退出才消亡

#include <stdio.h> 
 int num;//聲明
int main(int argc, const char * argv[]) {    
    printf("num = %d\n",num);    
    int num = 20;
    printf("num = %d\n",num);
    {
        num = 40;
        int num = 10;
        printf("num = %d\n",num);
        num = 30;
    }
    printf("num = %d\n",num);         
    return 0;
}
           

2.結構體

  構造類型:由已有的資料類型構成類型

  1、數組:多個同種類型的資料構成的那麼一種類型

     特點:隻能存放一種數類型

  2、結構體:從來存放表示某種特定含義的一組資料

           它是對資料封裝

           函數對功能封裝

     好處:提高代碼的可讀性

          提高資料易用性

          提高代碼可維護性

     定義結構體:

         1、定義結構類型

             struct 結構類型名稱{

             成員類型 成員名稱;

             ...

             };//必須加分号

         2、通過結構體類型定義結構變量

            struct 結構類型名稱 結構體變量名稱;

#include <stdio.h>
int main(int argc, const char * argv[]) {

    //    int scores[] = {59,60};    
    //     int  年齡  姓名 char *  性别 char  身高 double  體重 double        
    //    int age;
    //    char sex;
    //    double height;
    //    double weight;
    //    char *name;
    //
    //    int ages[50];
    //    char sex[50];
    //    ....
    //  定義一個人結構體類型
    struct Person{
        int age;
        char sex;
        double height;
        double weight;
        char *name;
    };    
    //  int num;
    //  int * pointer;
    //  定義結構體變量
    struct Person person;    
    //  通路結構體成員
    person.age = 10;    
    person.sex = 'M'; 
    person.weight = 20.2;    
    person.height = 1.2;    
    person.name = "小明";    
    printf("age = %d,sex = %c,weight = %.2lf,height = %.2lf,name = %s\n",person.age,person.sex,person.weight,person.height,person.name);
   
    return 0;
}
           
ios學習之旅------玩轉結構體

3.定義結構體的多種類型

#include <stdio.h>
/*
 第一種方式
  1、先定義結構體類型
  2、定義結構變量
 */
void test()
{
    
    struct Person{
        int age;
        double height;
    };
    
    struct Person p1;
}

/*
第二種方式
   定義結構體類型的同時定義結構變量
 */
void test1()
{
    struct Person{
        int age;
        double height;
    } p1,p2 = {20,1.75};
    
    p1 =(struct Person){10,1.2};
    
    printf("age = %d,height = %.2lf\n",p1.age,p1.height);
    
    printf("age = %d,height = %.2lf\n",p2.age,p2.height);
    //  結構體類型定義是不可以重名的
    //    struct Person{
    //        int age;
    //        double height;
    //    } p3,p4 = {20,1.75};
}
/*
第三種方式
   定義匿名的結構類型的同時定義結構體變量
 */
int main(int argc, const char * argv[]) { 
    struct{
        int age;
        char sex;
    } p1,p2 = {20,'M'};
    p1.age = 10;
    p1.sex = 'W';
    printf("age = %d,sex = %c\n",p1.age,p1.sex);
    p1 = p2;
    printf("age = %d,sex = %c\n",p1.age,p1.sex);
    //
    //    p1 = (struct) {10,'w'};
    //   1、不支援整體指派
    //   2、結構體類型不能重複使用
    struct{
        int age;
        char sex;
    } p3,p4 = {20,'M'};   
    return 0;
}
           

4.結構體作用域

   在函數内部,結構類型作用域就如同局部變量一樣

   在外邊定義的結構體類型像全局變量的作用域

   作用域:從定義的那一行開始直到檔案的結束

   注意點:結構類型不能聲明

   結構體類型的作用,除了不能聲明以外,其他與普通變量一樣

#include <stdio.h>
struct Person{
    int age;
    char sex;
};
int main(int argc, const char * argv[]) {  
    struct Person p2;    
    p2.sex = 's';
    p2.age = 10;    
    struct Person{
        int age;
    };  
    struct Person p = {10};
    printf("age = %d\n",p.age);  
    {
        struct Person p = {20};
        struct Monkey{
            char *name;
        };    
    }    
    return 0;
}
           
ios學習之旅------玩轉結構體

5.結構體數組

   結構體數組:數組元素為結構體數組

   定義結構體數組

   結構類型 數組名稱[元素個數];

   數組元素的類型 數組名稱[元素個數];

#include <stdio.h>
//一般情況下結構體類型都是定義在函數的外部
struct Dog{
    char *name;
    int age;
};
void test()
{
    //    int nums[] = {1,2,3,4};
    //    結構體如果沒有初始化,它裡面都是垃圾值
    //  第一種方式:向定義結構體數組然後初始化
    struct Dog dogs[5];
    dogs[0] = (struct Dog){"旺财",1};
    dogs[1].age = 1;
    dogs[1].name = "大黃";   
    //  周遊結構體數組    
    for(int i = 0;i < 5;i++)
    {
        printf("age = %d,name = %s\n",dogs[i].age,dogs[i].name);
    }
}
void test2()
{
    //  定義結構體數組的同時進行初始化
    //  如果沒有顯式初始化的結構體,那麼這個結構體中所有成員都會被初始化為0
    struct Dog dogs[10] = {{"旺财",1},{"大黃",2},{"來福",3},{"小黑",4},{"小白",5}};
    //  計算數組的元素個數
    int len = sizeof(dogs) / sizeof(struct Dog);    
    for(int i = 0;i < len ;i++)
    {
        printf("age = %d,name = %s\n",dogs[i].age,dogs[i].name);
    }
    
}
int main(int argc, const char * argv[]) {  
//    test();
    tset2();
    return 0;
}
           
ios學習之旅------玩轉結構體

6.結構體與指針

   結構體指針:指向結構體的指針

   指針所指向的資料類型 * 指針變量名稱;

   結構類型 * 指針變量名稱;

#include <stdio.h>
struct Student{
    char *name;//姓名
    int no;//學号
    double score;//成績
};
int main(int argc, const char * argv[]) {   
    struct Student stu = {"大木",60,59};    
//   定義結構體指針
    struct Student *sp1;
    sp1 = &stu;
//  定義的同時進行初始化
    struct Student *sp = &stu;
//  通過指針通路結構體的成員的第一種方式
    (*sp).score = 60;    
//  第二種方式(重點)
    sp->name = "小木";
    sp->no = 59;
    printf("name = %s,no = %d,score = %.2lf\n",stu.name,stu.no,stu.score);
      
    return 0;
}
           
ios學習之旅------玩轉結構體

7.結構體嵌套

       一個結構體内部可以有其他類型的結構體成員

 結構體嵌套的注意點:

   1、結構體不可以嵌套自己,不能有位元組這種類型的成員

   2、結構體可以嵌套自己類型的指針

#include <stdio.h>
//定義了一個日期的結構體
struct Time{
    int hour; // HH
    int minute;//mm
    int second;//ss
};
struct Date{
    int year;
    int month;
    int day;
    struct Time time;
};
struct Employee{    
    int no;
    char name[20];
//  入職日期
//    int year;
//    int month;
//    int day;
    struct Date inDate;
//  生日
//    int birthyear;
//    int birthmonth;
//    int birthday;
    struct Date birthday;
//  離職日期
//    int goyear;
//    int gomonth;
//    int goday;
    struct Date outDate;
};
void test()
{
    struct Employee emp = {1,"大幕",{2014,10,14,{12,12,12}},{1990,10,14},{2014,11,14}};
    
    printf("no = %d,name = %s,入職日期 = %d-%d-%d %d:%d:%d\n"
           ,emp.no,emp.name,emp.inDate.year,emp.inDate.month,emp.inDate.day,
           emp.inDate.time.hour,emp.inDate.time.minute,emp.inDate.time.second);
    }
struct Person{
    char *name;
//    struct Person son;
    struct Person *son;
};
/*
 1.某班有5個學生,三門課。分别編寫3個函數實作以下要求:
 (1) 求各門課的平均分;
 (2) 找出有兩門以上不及格的學生,并輸出其學号和不及格課程的成績;
 (3) 找出三門課平均成績在85-90分的學生,并輸出其學号和姓名
 */
int main(int argc, const char * argv[]) {   
    struct Person father = {"father"};   
    struct Person son = {"son"};    
    father.son = &son;    
    printf("son name = %s\n",father.son->name);

    return 0;
}
           

8.枚舉

  枚舉:一個一個列舉出來

  枚舉作用:消除魔法數字

  使用場景:當某個東西隻有那麼幾個取值時候就是用枚舉

  定義枚舉格式

     enum 枚舉類型的名稱{

     元素,//逗号

     ...

     };

   注意點:

   1、枚舉類型定義中,所有元素都是整形常量

   2、枚舉類型的本質就是整形

#include <stdio.h>
//定義性别枚舉類型
enum Sex{
     Man,
     Woman,
     Other
};

//int Man = 10;//枚舉定義之後,後面不可定義與成員相同變量
void test()
{
    //  在代碼中出現的這種表示特殊含義數字,我們魔法數字
    //    int sex = 0;  
    enum Sex sex;
    printf("%d\n",Man);
    int Man = 10;
    printf("%d\n",Man);  
    //    sex = 1;// 這裡不能把要給數字指派給一個枚舉類型的變量,這樣枚舉存在的意義就沒有了
    //    Man = 1;
    
}
// 可以指定枚舉中每一個元素值
enum Season{
   Spring = 2,
   Summer,
   Autumn,
   Winter,
   SOther = 9
};
void PrintSeason(enum Season season)
{
    switch (season) {
        case Spring: //Case後面的值務必與枚舉中成員一緻,不要出現魔法數字
            printf("春季\n");
            break;
        case Summer:
            printf("夏季\n");
            break;
        case Autumn:
            printf("秋季\n");
            break;
        case Winter:
            printf("冬季\n");
            break;
        case SOther:
            printf("不是地球上季節\n");
            break;
        default:            
            break;
    }
}
int main(int argc, const char * argv[]) {
    printf("%d,%d,%d\n",Man,Woman,Other);
    printf("%d,%d,%d,%d\n",Spring,Summer,Autumn,Winter);       
    enum Season season = Summer;    
    PrintSeason(season);
    
    return 0;
}
           
ios學習之旅------玩轉結構體

9. typedef:

    給已有資料類型起别名   

   基本資料類型

   int char float double

   結構體

   枚舉

   指針

      1、普通變量的指針

      2、結構體指針

      3、函數指針

   基本資料類型

  定義格式:typedef 已有資料類型 别名;

#include <stdio.h>
void testBaseType()
{   
    typedef int  Int;   
    Int num = 10;   
    typedef Int Integer;    
    Integer a = 20;    
    printf("%d\n",a);   
}
/*
    給結構體類型起别名 
 */
void testStruct()
{    
//  第一種方式:先定義結構體類型再給結構體類型起别名
    struct _Person{
        int age;
        char *name;
    };    
    typedef struct _Person Person;    
    Person p1 = {10,"小紅"};
    printf("age = %d,name = %s\n",p1.age,p1.name);   
// 第二種方式,定義結構體類型的同時給結構體類型起别名       
    typedef struct _Dog{
        int age;
        char *name;
    } Dog;    
    Dog dog = {1,"大黃"};    
//  第三種方式:定義匿名結構體類型的同時給結構體起一個别名   
    typedef struct{
        int age;
        char * name;
    } Cat;    
    Cat cat = {1,"tom"};   
}
//給枚舉起别名
void testEnum()
{
//  1、先定義枚舉類型然後給枚舉起别名   
    enum _Sex{
      Man,
      Woman,
      Other
    };   
    typedef enum _Sex Sex;    
    Sex sex = Man;
//  2、定義枚舉類型的同時給枚舉類型起一個别名   
   typedef enum _Season{
        Spring,
        Summer
    } Season;        
    Season season = Spring;    
//  3、定義匿名枚舉類型同時給枚舉起一個别名   
    typedef enum {
         Cong,
         Suan,
         Jiang
    } TiaoWei;    
    TiaoWei zuoLiao = Cong; 
}
//4、指針類型
//4.1 基本資料類型的指針
void testTypedefBasicPointer()
{
    typedef  int * IntPointerType;
    int a = 10;    
    IntPointerType p = &a;   
    *p = 20;   
    printf("%d\n",a);    
}
//4.2 給結構體類型的指針起别名
void testTypedefStructPointer()
{
    typedef struct {
        char *name;
        int age;
    } Person;    
    typedef Person * PersonPointerType;    
    Person p = {"張三",10};    
    PersonPointerType pp = &p;        
    typedef struct _Cat{
        char *name;
        int age;    
    } Cat, * CatPointerType;    
    Cat cat = {"小貓",1};    
    CatPointerType catPointer = &cat;    
    printf("name = %s,age = %d\n",catPointer->name,catPointer->age);    
}
//4.3 給枚舉類型的指針起别名
void testTypedefEnumPointer()
{
//  先定義枚舉類型
    enum _Sex{
         Man,
        Woman,
        Other
    };    
    typedef enum _Sex * SexPointer;   
    enum _Sex sex = Man;        
    SexPointer sexPointer = &sex;    
    *sexPointer = Woman;    
    printf("%d\n",sex);    
}
//4.4 給函數指針起别名
int sum(int num1,int num2){    
    return num1 + num2;
}
int minus(int num1,int num2){    
    return num1 + num2;
}
//給函數指針起别名
//typedef 指針所指向的函數的傳回值類型 (*函數指針類型别名)(所指向的函數的形參清單);
void testTypedefMethodPointer()
{   
//    int (*sumPointer)(int num1,int num2) = sum;
//    
//    int (*minusPointer)(int num1,int num2) = minus;   
    typedef  int (*MethodPointerType)(int num1,int num2);    
    MethodPointerType sumPointer = sum;    
    MethodPointerType minusPointer = minus;    
    int rs =  sumPointer(10,20);
    printf("rs = %d\n",rs);    
}
//了解
void testTypedefArrayPointer()
{
    char names[][10] = {"xtf","zbz","wf"};   
    char (*arrayPoiner)[10];   
    arrayPoiner = names;    
    typedef char (*ArrayPointerType)[10];    
    ArrayPointerType pointer = names;   
    printf("%s\n",pointer[0]);   
}
int main(int argc, const char * argv[]) {        
//
//    testBaseType();
//    testStruct();
    testTypedefBasicPointer();    
    testTypedefStructPointer();    
    testTypedefEnumPointer();    
    testTypedefMethodPointer();    
    testTypedefArrayPointer();
    return 0;
}
           
ios學習之旅------玩轉結構體

繼續閱讀