标签:
------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
一个int类型的变量能保存一个人的年龄,如果想保存整个班的年龄呢?
数组,从字面上看,就是一组数据的意思,没错,数组就是用来存储一组数据的
元素类型数组名[元素个数];
1 int ages[3]; //int 是数组的类型 ages是数组名 3 是数组元素的个数
1)初始化方式
1 int a[3] = {10, 9, 6}; //数组一般的初始化方式 2 3 int a[3] = {10,9}; // 没有赋值的数组元素默认为0 4 5 int a[] = {11, 7, 6}; // 数组初始化的时候可以省略 元素个数 6 7 int a[4] = {[1]=11,[0] = 7}; // 利用索引给数组初始化也是可以的
2)初始化注意点
1 /* 这种写法是错误的 2 int ages[5]; 3 ages = {10, 11, 12, 14}; //一般在定义数组的同时进行初始化 4 */ 5 6 //下面这种写法也是错误的 7 int ages[count] = {10, 11, 12}; 8 //如果想再定义数组的同事进行初始化,数组元素个数必须是常量,或者不写 9 10 //这种方式是正确的 11 int count = 5; 12 int ages[count]; 13 ages[0] = 10; 14 ages[1] = 11; 15 ages[2] = 18;
1) 数组元素和数组作为函数参数实例
1 void change(int array[])// 数组作为函数参数,可以省略元素个数 2 { 3 //printf("array==%p\n", array); 4 5 array[0] = 100; 6 } 7 8 void change2(int n) 9 { 10 n = 100; 11 } 12 13 int main() 14 { 15 int ages[6] = {10, 11, 10, 11, 10, 11}; 16 17 //printf("ages==%p\n", ages); 输出结果为100 18 // 数组作为函数参数,传递是整个数组的地址,修改函数形参数组元素的值,会影响到外面的实参数组 19 20 change(ages); 21 22 //change2(ages[0]); 数组元素作为参数 23 24 printf("%d\n", ages[0]); //输出结果为 10 25 return 0; 26 }
2) 数组作为参数所占用内存空间(sizeof)与数组元素的遍历
1 int maxOfArray(int array[], int length) 2 { 3 // 数组当做函数参数传递时,会当做指针变量来使用,指针变量在64bit编译器环境下,占据8个字节 4 5 //int size = sizeof(array); 6 //printf("array=%d\n", size); 输出结果为 8 7 8 9 // 1.定义一个变量存储最大值(默认就是首元素) 10 int max = array[0]; 11 12 // 2.遍历所有元素,找出最大值 13 for (int i = 1; i<length; i++) 14 { 15 // 如果当前元素大于max,就用当前元素覆盖max 16 if (array[i] > max) 17 { 18 max = array[i]; 19 } 20 } 21 22 return max; 23 } 24 25 int main() 26 { 27 int ages[] = {11, 90, 67, 150, 78, 60, 70, 89, 100}; 28 29 //int size = sizeof(ages); 30 31 //printf("ages=%d\n", size); 32 int max = maxOfArray(ages, sizeof(ages)/sizeof(int)); 33 34 printf("%d\n", max); // 结果为 150 35 return 0; 36 }
1 //字符串一般以\0结尾 下面 都是字符串 2 char name[8] = "it"; //"it" 其实由‘i‘,‘t‘,‘\0‘组成 3 char name2[8] = {‘i‘, ‘t‘, ‘\0‘}; 4 char name3[8] = {‘i‘, ‘t‘, 0}; 5 char name4[8] = {‘i‘, ‘t‘}; 6 7 // 下面这个不算是一个字符串(只能说是一个字符数组) 8 char name5[] = {‘i‘, ‘t‘};
1 /* 2 \0的作用 3 1.字符串结束的标记 4 2.printf("%s", name2); 5 会从name2这个地址开始输出字符,直到遇到\0为止 6 */ 7 8 int main() 9 { 10 char name[] = "itc\0ast"; 11 12 char name2[] = {‘o‘, ‘k‘}; 13 14 // printf("%s\n", name); 输出结果是it 15 16 //printf("%s\n", name2); 输出的结果是 okitc 17 18 printf("%s\n", &name2[1]); //输出结果是 ktic 19 20 return 0; 21 }
strlen函数:计算字符串长度
1 int main() 2 { 3 //int size = strlen("哈haha"); 4 5 //printf("%d\n", size); 输出结果为7 6 /* 7 char name[] = "itcast"; 8 char name2[] = {‘0‘, ‘\0‘, ‘6‘}; 9 10 int size = strlen(name2); 11 12 printf("%d\n", size); 输出结果为 7 13 */ 14 15 char name[] = "itcast"; 16 17 //printf("%s\n", name); 输出结果是itcast 18 19 printf("%c\n", name[3]); // 输出结果为字符 a 20 21 22 return 0; 23 }
指针是C语言中非常重要的数据类型,如果你说C语言中除了指针,其他你都学得很好,那你干脆说没学过C语言。
类名标识符 *指针变量名;
int *p;// 定义了一个指针变量p
1 //简单取值 2 3 int a = 10; 4 5 int *p; 6 7 p = &a; 8 9 printf(“%d”, *p); 10 11 // 简单改值 12 13 *p = 9;
int a = 10; //定义变量a int *p = &a; //定义指针变量p的同时把 a地址复制给 p
1 int main() 2 { 3 4 int a = 90; 5 6 change(&a); 7 8 printf("a=%d\n", a); //输出结果为 10 9 10 return 0; 11 } 12 13 void change(int *n) 14 { 15 *n = 10; 16 }
1 int main() 2 { 3 /* 不建议的写法, int *p只能指向int类型的数据 4 int *p; 5 double d = 10.0; 6 p = &d;*/ 7 8 /* 指针变量只能存储地址 9 int *p; 10 p = 200; 11 */ 12 13 /* 指针变量未经过初始化,不要拿来间接访问其他存储空间 14 int *p; 15 printf("%d\n", *p); 16 */ 17 18 int a = 10; 19 /* 20 int a; 21 a = 10; 22 */ 23 24 /* 25 int *p; 26 p = &a; 27 */ 28 // 定义变量时的*仅仅是一个象征,没有其他特殊含义 29 int *p = &a; 30 31 // 不正确的写法 32 // *p = &a; 33 p = &a; 34 35 // 这个时候的*的作用:访问指向变量p指向的存储空间 36 *p = 20; 37 38 return 0; 39 }
指针变量所占用的存储空间
1 void test() 2 { 3 char c; // 1 4 int a; // 4 5 long b; // 8 6 7 char *cp; 8 int *ap; 9 long *bp; 10 11 printf("cp=%zd, ap=%zd, bp=%zd\n", 12 sizeof(cp), // cp输出结果为8 13 sizeof(ap), //ap 输出结果为8 14 sizeof(bp)); // bp输出结果为 8 15 //任何指针都占用8个字节的存储空间 16 }
为何指针变量要分类型
1 int main() 2 { 3 int a = 10 ; 4 char b = ‘A‘; 5 int * p ; 6 p = &b ; 7 printf("%d",*p); //输出的结果为 2625并不是 65,指针类型的作用是从指定的地址取一定字节的数据 ,*p 取的是 4个字节,取一个字节结果就为65 8 return 0 ; 9 }
1 int ages[5] = {10, 9, 8, 67, 56}; 2 3 int *p; 4 // 指针变量p指向了数组的首元素 5 p = &ages[0]; 6 // 数组名就是数组的地址,也是数组首元素的地址 7 //p = ages; 8 9 /* 10 p ---> &ages[0] 11 p + 1 ---> &ages[1] 12 p + 2 ---> &ages[2] 13 p + i ---> &ages[i] 14 */ 15 16 //printf("%d\n", *(p+2)); //指针可以通过以下这两种方式访问数组元素 17 18 printf("%d\n", p[2]); //输出的结果为 8
1 void change(int array[]); 2 3 int main() 4 { 5 // 20个字节 6 int ages[5] = {10, 11, 19, 78, 67}; 7 8 change(ages); 9 10 return 0; 11 } 12 13 // 利用一个指针来接收一个数组,指针变量array指向了数组的首元素 14 void change(int *array) 15 { 16 printf("%d\n", array[2]); // 输出结果为 19 17 //printf("%d\n", *(array+2)); 18 } 19 20 21 /* 以数组作为参数,其实就是一指针方式传递参数 22 void change(int array[]) 23 { 24 int s = sizeof(array); 25 26 printf("%d\n", s); //占8个字节 27 }*/
1 int ages[5] = {10, 9, 8, 67, 56}; 2 3 int *p; 4 // 指针变量p指向了数组的首元素 5 p = &ages[0]; 6 // 数组名就是数组的地址,也是数组首元素的地址 7 //p = ages; 8 /* 9 for (int i = 0; i<5; i++) { 10 printf("ages[%d] = %d\n", i, *(p+i)); 11 // printf("ages[%d] = %d\n", i, p+i); 12 }*/ 13
1 // 字符串变量 字符可以修改 2 char name[] = "it"; 3 name[0] = ‘T‘; 4 //printf("%s\n", name); 输出结果为 Tt 5 6 // 字符串常量 变量不可以修改 7 char *name2 = "it"; 8 // 指针变量name2指向了字符串的首字符 9 10 11
1 // 定义字符串数组 2 void test2() 3 { 4 char *name = "jack"; 5 6 7 // 指针数组(字符串数组) 8 char *names[5] = {"jack", "rose", "jake"}; 9 10 // 二维字符数组(字符串数组) 11 char names2[2][10] = {"jack", "rose"}; 12 }
1 char *test(); 2 3 int main() 4 { 5 char *name = test(); //定义一个指针来接受函数的返回值 6 7 printf("name=%s\n", name); //输出结果为 rose 8 9 return 0; 10 } 11 12 char *test() //函数的返回类型是指针 13 { 14 return "rose"; 15 }
1) 定义
返回值类型 (*指针变量)(参数1,参数2 .......);
1 double (*p)(double, char *, int); 2 //定义一个指向函数的指针 3 p = haha; 4 // 把 haha函数地址赋值给 指针p,函数名就是函数的地址
2) 利用指针间接调用函数
void test() { printf("调用了test函数\n"); } int main() { // (*p)是固定写法,代表指针变量p将来肯定是指向函数 // 左边的void:指针变量p指向的函数没有返回值 // 右边的():指针变量p指向的函数没有形参 void (*p)(); // 指针变量p指向了test函数 p = test; p(); //(*p)(); // 利用指针变量间接调用函数 //test(); // 直接调用函数 }
当一个整体由多个数据构成时,我们可以用数组来表示这个整体,但是数组有个特点:内部的每一个元素都必须是相同类型的数据。
* 在实际应用中,我们通常需要由不同类型的数据来构成一个整体,比如学生这个整体可以由姓名、年龄、身高等数据构成,这些数据都具有不同的类型,姓名可以是字符串类型,年龄可以是整型,身高可以是浮点型。
* 为此,C语言专门提供了一种构造类型来解决上述问题,这就是结构体,它允许内部的元素是不同类型的。
1) 定义结构体的类型
struct 结构体名{
类型名1 成员名1;
类型名2 成员名2;
........
类型名n 成员名n
};
1 struct Person //定义结构体类型 2 { 3 // 里面的3个变量,可以称为是结构体的成员或者属性 4 int age; // 年龄 5 double height; // 身高 6 char *name; // 姓名 7 };
1 /*定义结构体变量的3种方式 */ 2 1> 先定义类型,再定义变量(分开定义) 3 struct Student 4 { 5 int age; 6 }; 7 struct Student stu; 8 9 2> 定义类型的同时定义变量 10 struct Student 11 { 12 int age; 13 } stu; 14 struct Student stu2; 15 16 3> 定义类型的同时定义变量(省略了类型名称) 17 struct 18 { 19 int age; 20 } stu; 21 */ 22 23 /*结构体类型不能重复定义 24 struct Student 25 { 26 int age; 27 }; 28 29 struct Student 30 { 31 double height; 32 }; 33 34 struct Student stu; */ 35
1 //第一种初始化方式 2 struct Person p = {20, 1.55, "jack"}; 3 p.age = 30; //可以通过这种方式来修改成员的值 4 p.name = "rose"; 5 // 第二种出事化方式 6 struct Person p2 = {.height = 1.78, .name="jim", .age=30};
结构体所占用的存储空间 必须是 最大成员字节数的倍数
void test() { // 1.定义结构体类型(并不会分配存储空间) struct Student { int age;// 4个字节 char a; //char *name; // 8个字节 }; // 2.定义结构体变量(真正分配存储空间) struct Student stu; //stu.age = 20; //stu.name = "jack"; // 补齐算法(对齐算法) // 结构体所占用的存储空间 必须是 最大成员字节数的倍数 int s = sizeof(stu); printf("%d\n", s); //输出的结果为8 }
1)结构数组的定义及初始化
//定义结构体类型 struct RankRecord { int no; // 序号 4 int score; // 积分 4 char *name; // 名称 8 }; //定义结构体数组 struct RankRecord records[3] = { {1, "jack", 5000}, {2, "jim", 500}, {3, "jake",300} }; // 下面这种初始化方式是错误的 //records[0] = {4, "rose", 9000};
2) 遍历结构体数组
1 for (int i = 0; i<3; i++) 2 { 3 printf("%d\t%s\t%d\n", records[i].no, records[i].name,records[i].score); 4 }
每个结构体变量都有自己的存储空间和地址,因此指针也可以指向结构体变量
* 结构体指针变量的定义形式:struct 结构体名称 *指针变量名
* 有了指向结构体的指针,那么就有3种访问结构体成员的方式
1 int main() 2 { 3 struct Student 4 { 5 int no; 6 int age; 7 }; 8 // 结构体变量 9 struct Student stu = {1, 20}; 10 11 // 指针变量p将来指向struct Student类型的数据 12 struct Student *p; 13 14 // 指针变量p指向了stu变量 15 p = &stu; 16 17 p->age = 30; 18 19 // 第一种方式 20 printf("age=%d, no=%d\n", stu.age, stu.no); 21 22 // 第二种方式 23 printf("age=%d, no=%d\n", (*p).age, (*p).no); 24 25 // 第三种方式 26 printf("age=%d, no=%d\n", p->age, p->no); 27 28 29 return 0; 30 }
如果结构体作为函数参数,只是将实参结构体所有成员的值对应地赋值给了形参结构体的所有成员
修改函数内部结构体的成员不会影响外面的实参结构体
1 void test(struct Student s) 2 { 3 s.age = 30; 4 s.no = 2; 5 } 6 7 // 会影响外面的实参结构体 8 void test2(struct Student *p) 9 { 10 p->age = 15; 11 p->no = 2; 12 13 } 14 15 int main() 16 { 17 struct Student stu = {28, 1}; 18 19 //test(stu); // 成员值不变age =28,no=1 20 test2(&stu); //成员值改变age=15, no=2 21 22 23 printf("age=%d, no=%d\n", stu.age, stu.no); 24 25 return 0; 26 }
1)定义
struct 结构体名1{
类型名1 成员名1;
类型名2 成员名2;
........
类型名n 成员名n
};
struct 结构体名2{
类型名1 成员名1;
struct 结构体名1 成员名2;
........
类型名n 成员名n
};
2)简单使用
1 int main() 2 { 3 struct Date //先定义一个Date 结构体类型 4 { 5 int year; 6 int month; 7 int day; 8 }; 9 10 11 // 类型 12 struct Student 13 { 14 int no; // 学号 15 16 struct Date birthday; // 生日 17 18 struct Date ruxueDate; // 入学日期 19 20 // 这种写法是错误的,不能自己调用自己 21 //struct Student stu; 22 }; 23 24 25 struct Student stu = {1, {2000, 9, 10}, {2012, 9, 10}}; 26 27 printf("year=%d,month=%d,day=%d\n", stu.birthday.year, stu.birthday.month, stu.birthday.day); 28 29 30 31 32 33 return 0; 34 }
枚举是C语言中的一种基本数据类型,并不是构造类型,它可以用于声明一组常数。当一个变量有几个固定的可能取值时,可以将这个变量定义为枚举类型。比如,你可以用一个枚举类型的变量来表示季节,因为季节只有4种可能的取值:春天、夏天、秋天、冬天。
一般格式为:
enum 枚举名 {
枚举元素1,
枚举元素2,
……
};
enum Sex { Man, Woman, Unkown};
enum Sex s = Unkown;
C语言编译器会将枚举元素(Man、Woman等)作为整型常量处理,称为枚举常量。
enum Sex { Man, Woman, Unkown};
也就是说Man的值为0,Woman的值为1,Unkown的值为2
enum Sex { Man, Woman=2, Unkown};
没有指定值的枚举元素,其值为前一元素加1。也就说Man的值为0,Woman的值为2,Unkown的值为3
enum Sex { Man, Woman, Unkown}; enum Sex s = Unkown; //等价于s=2 enum Sex s = 0; //等价于s=Man
enum Sex { Man, Woman, Unkown} s; // 遍历枚举元素 for (s = spring; s <= Unkown; s++) { printf("枚举元素:%d \n", s); }
黑马程序员————C语言基本语法(数组、字符串、指针、其他数据类型)
标签:
原文地址:http://www.cnblogs.com/zhaoyutang/p/4510931.html