您的位置:首页 > 编程语言 > C语言/C++

黑马程序员--IOS基础第十三天(C语言)

2015-07-15 10:59 477 查看


1.
结构体数组:

用来存放大量的结构体相同的结构体变量.结构数组的每一个元素都是具有相同结构类型的下标结构变量

结构体数组定义:

定义格式:

Struct 结构名{

成员表列

}数组名][数组长度];

结构体数组定义的第一种方式:

1)定义结构体的同时,定义数组

struct Student{

int age;

char *name;

int s_no;

float score;

}stu[5];

2)先定义结构体,后定义数组

struct Student boy[5];

#include
<stdio.h>

int main(int
argc, const
char * argv[]) {

struct Student{

int age;

char *name;

int s_no;

float score;

}stu[5];

struct Student boy[5];

return 0;

}

2.结构化数组的初始化和遍历

#include
<stdio.h>

void test1(){

//结构体数组的初始化方法

//1、定义结构体数组的时候,进行初始化

struct Student{

char name[20];

int age;

}boys[3]={{"sb",18},{"zbz",38},{"cgx",28}};

//2、定义的同时进行初始化

struct Student girls[2]={{"fengjie",18},{"cjk",28}};

//3、先定义后初始化,整体赋值

struct Student ds[2];

ds[0]=(struct Student){"xzmly",18};

ds[1]=(struct Student){"bdjy",18};

//4、先定义结构体数组,后初始化

struct Student stu[2];

//stu[0].name = "zhangsan";

//strcpy(stu[0].name,"zhangsan");

scanf("%s",stu[0].name);

stu[0].age = 19;

//
char ch[10];

// scanf("%s",ch);

//2、结构数组的遍历**********

for(int
i=0;i<3;i++){

printf("name:%s,age:%d\n",boys[i].name,boys[i].age);

}

}

int main(int
argc, const
char * argv[]) {

//结构体

struct stu{

int num;

char *name;

char sex;

float score;

};

//1、定义结构体数组

struct stu boy[5]={

{101,"Li
ping",'F',45},

{102,"Zhangping",'M',62.5},

{103,"He
fang",'F',92.5},

{104,"Chengling",'M',87},

{105,"Wangming",'M',58}};

//2、有一个循环

//

float sum = 0.0f;

int count=0;
//保存不及格的人数

for (int
i=0; i<5; i++) {

//
计算总成绩

sum+=boy[i].score;

//
判断成绩是否小于60
,如果小于了60 要让计算器+1

if(boy[i].score<60) {

count++;

}else
if(boy[i].score>=80 && boy[i].score<=100){

//
判断是否大于80小于100

//
如果在这个区间,应该输出姓名和成绩

printf("姓名:%s,成绩:%.2f\n",boy[i].name,boy[i].score);

}

}

printf("平均值:%.2f\n",sum/5);

printf("不及格人得个数:%d\n",count);

return 0;

}

3.结构指针定义和初始化

1、什么是结构体指针?

用来存放结构体变量地址的指针变量。结构指针变量中的值是所指向的结构体变量的首地址。

2、结构体指针定义

struct 结构体名 *指针变量名;

//定义一个结构体

struct Car{

int lunzi;

int speed;

}car1;

struct Car *p=NULL; //定义一个结构体指针变量

p = &car1;//正确的

p = &Car;//错误的

*/

#include
<stdio.h>

int main(int
argc, const
char * argv[]) {

//定义一个结构体

struct Car{

int lunzi;

int speed;

}car1;

//定义一个结构体指针

struct Car *p=NULL;
//定义一个结构体指针变量

p = &car1;//正确的

//p = &Car;//错误的

//结构体名:Car

//结构体变量名 car1

//结构体指针: p

return 0;

}

4.结构体指针间接访问成员值

1、结构体变量的成员值

struct Student{

int age;

char *name;

};

//定义一个结构体的变量

struct Student stu1={18,"张三丰"};

//结构体变量的成员值有2个

// stu1.age 值 18

// stu1.name 值 张三丰

2、用结构体指针间接的访问结构体变量的成员值

//

struct Student *p = &stu1;

//使用p 获取 18
张三丰

有两种方法:

1) (*p).age
访问年龄 (*p)--->stu1

(*p).name 访问姓名

2) p->age 访问的年龄

p->name 访问的是姓名

注意:p一定是一个结构体指针

stu1->name; //错误的

#include
<stdio.h>

int main(int
argc, const
char * argv[]) {

struct Student{

int age;

char *name;

};

//定义一个结构体的变量

struct Student stu1={18,"张三丰"};

//结构体变量的成员值有2个

// stu1.age
值18

// stu1.name
值 张三丰

// 2、用结构体指针间接的访问结构体变量的成员值

//

struct Student *p = &stu1;

printf("姓名:%s,年龄:%d\n",(*p).name,(*p).age);

printf("姓名:%s,年龄:%d\n",p->name,p->age);

return 0;

}

5.
结构体的嵌套:

结构体定义中,结构体的成员又是另外一个结构体变量

结构体的嵌套的注意事项:

1)结构体定义中可以嵌套其他结构体类型的变量

不可以嵌套自己这个类型的变量

struct Date{

int month;

int year;

int day;

};

struct Student {

char *name;

int age;

float score;

struct Student stu; //错误的

}

2)可以嵌套自己类型的指针

#include
<stdio.h>

//定义了一个时间的结构体

struct Time{

int hour;

int min;

int sec;

};

//定义一个Date的结构体

struct Date{

int year;

int month;

int day;

//嵌套Time的结构体

struct Time time;

};

//定义了一个学生的结构体

struct Student {

char *name;

int age;

float score;

struct Date birthday;

//struct Student stu; //错误的

//struct Student *stu; //正确的

};

int main(int
argc, const
char * argv[]) {

//1、嵌套的结构体如何进行初始化

struct Student stu1={"张三丰",28,59.99f,{1200,2,14,{12,12,12}}};
//定义了一个结构体变量

//2、嵌套的结构体如何进行访问

printf("姓名:%s,年龄:%d(生日:%d-%02d-%02d),成绩:%.2f\n",stu1.name,stu1.age,stu1.birthday.year,stu1.birthday.month,stu1.birthday.day,stu1.score);

//访问时间

printf("姓名:%s,年龄:%d(生日:%d-%02d-%02d
%02d:%02d:%02d),成绩:%.2f\n",stu1.name,stu1.age,stu1.birthday.year,stu1.birthday.month,stu1.birthday.day,stu1.birthday.time.hour,stu1.birthday.time.min,stu1.birthday.time.sec,stu1.score);

//3、结构体嵌套自身的指针

struct Person {

char *name;

int age;

//嵌套自己类型的指针

struct Person *child;

};

//结构体嵌套自身指针的,初始化

//定义kim

struct Person kim={"kim",8,NULL};

//struct Person *child = &kim;

struct Person p1={"林志颖",38,&kim};

//结构体嵌套自身指针的,访问

printf("%s
的儿子是:%s,儿子的年龄:%d\n",p1.name,p1.child->name,p1.child->age);

return 0;

}

6.结构体变量及成员作为函数参数

成员值做函数的参数:结构体成员属性作为函数的参数就是值传递(成员变量是数组除外)

结构体变量名作为函数的参数:

在ANSI C标准中允许用结构变量作函数参数进行整体传送。但是这种传送要将全部成员逐个传送,特别是成员为数组时将会使传送的时间和空间开销很大,严重降低了程序的效率。因此最好的办法就是使用指针,即用指针变量作函数参数进行传送。这是由实参传向形参的只是地址,从而减少了空间和时间的开销。

#include
<stdio.h>

struct Car{

int lunzi;

int speed;

};

void xiuche(int
n){

n = 2;

}

//用结构体变量作为函数的参数

void xiuche1(struct
Car c1){

c1.lunzi = 2;

}

int main(int
argc, const
char * argv[]) {

//定义一个结构体变量

struct Car car1={4,200};

//car1.lunzi
结构体变量成员值
4

//1、用结构体变量的成员值作为函数的参数,实质是值传递

xiuche(car1.lunzi);

//2、用结构体变量作为函数的参数

//实质上还是值传递

xiuche1(car1);

printf("%d\n",car1.lunzi);
//4

return 0;

}

7.结构指针作为函数的参数

#include
<stdio.h>

struct Car{

int lunzi;

int speed;

};

/**

*
结构体指针作为函数的参数

*

* @param c1
是一个结构体指针

*/

void xiuche2(struct
Car *c1){

c1->lunzi = 2;

}

int main(int
argc, const
char * argv[]) {

//定义一个结构体变量

struct Car car1={4,200};

//注意:用结构体变量的地址传递给函数

//
也可以理解为用结构体指针作为函数的参数

//
实质:是地址传递

xiuche2(&car1);

printf("%d\n",car1.lunzi);
//2

return 0;

}

8.学过的类型:基础数据类型、指针、空类型
void、构造类型(数组、结构体)、定义类型

9.枚举类型(是一种基本数据类型,而不是一种构造类型,因为它不能再分解为任何基本类型)

C语言提供了一个种类型,这种类型的变量的取值被限定在一定的范围之内了

枚举类型的定义:

enum 枚举类型名{ 枚举值1,枚举值2,.... };

举例:

定义一个变量,保存一周的第几天

enum weekday{zhouyi,zhouer,zhousan,zhousi,zhouwu ,zhouliu,zhouri };

定义iPhone手机的颜色

关于枚举类型元素的命名习惯

enumiColor{kIcolorWhite,kIcolorBlack,kIcolorTHJ};

定义人得性别

enum Sex{kSexMan,kSexWomen,kSexYao};

//weekday iColor Sex 这些都是枚举类型

*/

#include
<stdio.h>

//全局的枚举类型

enum Sex{kSexMan,kSexWomen,kSexYao};

int main(int
argc, const
char * argv[]) {

//定义局部的枚举类型

enum weekday{ zhouyi,zhouer,zhousan,zhousi,zhouwu,zhouliu,zhouri
};

enum iColor{kIcolorWhite,kIcolorBlack,kIcolorTHJ};

return 0;

}

10.枚举类型变量

枚举类型的变量

枚举类型的变量的定义

enumiColor{kIcolorWhite,kIcolorBlack,kIcolorTHJ};

1)先定义枚举类型,再定义枚举变量

enum 枚举类型名 枚举变量名列表;

enum iColor iPhoneColor; //iPhoneColor的取值是有要求的

//取值应为kIcolorWhite,kIcolorBlack,kIcolorTHJ中的其中一个

2)定义枚举类型的同时,定义变量

enum Sex{kSexMan,kSexWomen,kSexYao}isex;

*/

#include
<stdio.h>

//默认值
0 1 2

//手动赋值
5 6 7

enumiColor{kIcolorWhite=5,kIcolorBlack,kIcolorTHJ};

int main(int
argc, const
char * argv[]) {

//1、枚举类型变量的定义

enum iColor iPhoneColor;
//iPhoneColor的取值是有要求的

//取值应为kIcolorWhite,kIcolorBlack,kIcolorTHJ中的其中一个

enum Sex{kSexMan,kSexWomen,kSexYao} isex;

//2、枚举类型变量的初始化

//给枚举变量赋值

iPhoneColor = kIcolorTHJ;

isex = kSexYao;

//3、枚举变量如何使用

printf("%d\n",iPhoneColor);

//4、枚举变量的值

//枚举类型定义完成以后,系统会自动给枚举的每个元素都会赋值一个整形的初值

//
默认初值:从第一个元素开始值为0,以后个元素的值,是上一个元素的值+1,

//

//5、应用

struct Person{

char *name;

//char sex; //'z'

enum Sex isex;
//kSexMan,kSexWomen,kSexYao

};

//6、不按套路的出牌

iPhoneColor = 3.4; //尽量不要这么干

printf("%d\n",iPhoneColor);

return 0;

}

11.typedef关键字:

typedef就是给数据类型取“别名”

定义一般类型:

typedef
原类型名
新类型名;

其中原类型名中含有定义部分,新类型名一般用大写表示,以便于区别。

有时也可用宏定义来代替typedef的功能,但是宏定义是预处理完成的,而typedef则是在编译时完成的,后者更为灵活。

#include
<stdio.h>

int main(int
argc, const
char * argv[]) {

//typedef就给给别人起外号

int a = 10;

printf("%d\n",a+10);

//给int起个别名

typedef
int MALATANG;
//typedef语句要以分号结束

//用别名定义了一个新的变量 qiezi

MALATANG qiezi = 3;

MALATANG *p = &qiezi;

printf("%d\n",qiezi+100);

printf("%d\n",*p);

return 0;

}

12.typedef的使用方法:

#include
<stdio.h>

int sum(int
a,int b){

return a+b;

}

int jian(int
a,int b){

return a-b;

}

int main(int
argc, const
char * argv[]) {

//1、基本数据类型

typedef
int
MALATANG;

//2、用在数组,给数组起别名

typedef
int
ARRAY[5]; //int a[5];
数组长度为5

ARRAY a1={1,2,3,4,5},b1={5,4,3,2,1}; //int a1[5],b1[5];

for (int
i=0; i<5; i++) {

printf("%d\t",b1[i]);

}

//3、给结构体其别名

struct Person {

char *name;

int age;

};

printf("\n");

struct Person p1={"zbz",18};

//给 struct Person
起个别名 P

typedef
struct Person P;

//用别名定义新的变量

P p2 = {"xzmly",28};

printf("name:%s,age:%d\n",p2.name,p2.age);

//给结构体定义别名2

typedef
struct Car {

int lunzi;

int speed;

}MYCAR; //表示把结构体起个别名 MYCAR

MYCAR car1={1,200};

//给匿名的结构体起个别名

typedef
struct {

int screenSize;

int ram;

}IPHONE;

//用新类型定义结构体变量

IPHONE iphone7Plus={10,8};

//4、给枚举类型起别名

//

typedef
enum Sex{kSexMan,kSexWomen,kSexYao} ISEX;
//ISEX别名

//WEEKDAY也是别名

typedef
enum {zhouyi,zhouer,zhousan,zhousi} WEEKDAY;

//给枚举类型起个别名 S

typedef
enum Sex S;

S s1,s2;

s1 = kSexYao;

printf("%d\n",s1);

//5、给函数指针

//指向函数的指针

int (*p)(int,int);
//函数指针

//给函数中指针其别名

typedef
int (*FUN)(int,int);
//FUN是一个别名

FUN f1,f2; //f1和f2都是函数指针

f1 = jian;

printf("%d\n",f1(61,23));

return 0;

}

14.预处理指令:以#开头的都是预处理指令。在源程序中这些命令都放在函数之外,而且一般都放在源文件前面,它们称之为预处理指令。

预处理:在进行编译的第一遍扫描(词法扫描和语法分析)之前所作的工作。

15.c语言提供预处理功能,如宏定义、文件包含、条件编译等。

16.宏的概念及无参宏定义方法

宏:

C语言中我们自定义的特殊标示符,习惯大写

宏的定义:

#define 宏名 宏字符串(可以是常量、变量、表达式)

注意:预处理指令,经常写在函数之前

宏不是一个语句,是一个预处理指令,所以不需要加分号结束

3、宏替换

源程序在编译之前,由预处理程序对我们写的源代码进行处理:会把源代码中所有出现 宏名 的地方一律使用 宏的字符串 去替换

4、注意事项:

(1)习惯上红名用大写字母表示,以便于与变量区别,但也允许用小写字母

(2)宏定义是用宏名来表示一个字符串,在宏展开时又以该字符串取代宏名,这只是一种简单的代换,字符串中更可以含任何字符,可以是常量,也可以说表达式,预处理程序对它不做任何检查。如有错误,只能在编译已被展开后的源程序时发现

(3)宏定义不是说明或语句,在行末不必加分号,如加上分号则连分号一起置换

(4)宏定义必须写在函数之外,其作用域为宏定义命令祈祷源程序结束。如要终止其作用域可使用#undef命令。

*/

#include
<stdio.h>

#define M 10

#define M1 y*y+3*y

#define R 4

#define PI 3.14

#define AREA PI*R*R
//嵌套定义

#define INT1
int

#define P
struct Person

void test(){

printf("M = %d\n",M);

}

//#undefM
//此处的作用是,取消宏定义

void test1(){

printf("test1 =%d\n",M);

}

int main(int
argc, const
char * argv[]) {

int a[M+2];
//int a[12]

printf("%d\n",M);
//把M的值打印出来

int y = 3,result=0;

result = 3*M1+2*M1-50;

//错误的

// 3*(y*y+3*y)+2*(y*y+3*y)-50;

//
54 +36 -50;

//
40

//正确的

// 3*y*y+3*y+2*y*y+3*y-50;

//
27 +9 +18
+ 9 -50;

//
13

printf("result =%d\n",result);

//宏使用的注意事项

//1、宏是有作用域的
#undef 宏名 可以取消宏定义

test();

test1();

//2、在字符串中出现的宏名不会被替换

//3、宏可以嵌套定义

printf("%.2f\n",AREA);

//4、使用宏其别名

INT1 a1;

a1 = 10;

printf("a1 =%d\n",a1);

P{

int age;

};

P p1 = {23};

return 0;

}

17.
有参宏的定义和使用方法

宏的分类:

无参宏 #define M 10

有参宏 #define SUM(a) a+a

对带参数的宏,在调用中,不仅要宏展开,而且要用实参去代换形参。

SUM(3) //不仅要a+a替换,而且还要把 实参3代入到 字符串中

注意事项:

(1)宏的形参之间可以出现空格,但是宏名和形参之间不能出现空格

(2)在带参宏定义中,形式参数不分配内存单元,因此不必做类型定义,而宏调用中的实参有具体的值,要用他们去代换形参,因此必须做类型说明。这是与函数中的情况不同的。在函数中,形参和实参是两个不同的量,各有自己的作用域,调用时要把实参赋予形参,进行“值传递”。而在带参宏中,只是符号代换,不存在值传递的问题。

(3)在宏定义中的形参是标识符,而宏调用中的实参可以是表达式

(4)在宏定义中,字符串内的形参通常要用括号括起来以避免出错,

(5)可以用宏定义多个语句

*/

#include
<stdio.h>

#define SUM(a) a+a

#define M1(x
,y) (x)*(y)+(x)+(y)

#define M2(a) a+3*y

#define M3(m,n) m =a+2;n=a*2;

int main(int
argc, const
char * argv[]) {

int result = SUM(3);
//6

//有参宏使用

result = M1(4, 5); //29

int y = 2;

//有参宏使用

result = M2(3); //9

//有参宏的使用注意事项

//1、宏的形参之间可以出现空格,但是宏名和形参之间不能出现空格

int a = 3;

//2、有参宏宏的参数最好用括号括起来

result = M1(a+3, a-1);

//(x
,y) x*y+x+y

//
6*2 +6+2

// 20

//
a+3*a-1+a+3+a-1

//
a+9 -1+a+3+a-1

//
3+9-1+3+3+3-1

//
19

int i,j;

printf("%d\n",result);

printf("i=%d,j=%d\n",i,j);

//3、可以用宏来定义多个语句

M3(i, j);

printf("i=%d,j=%d\n",i,j);

return 0;

}

18.#define和typedef的区别:

宏定义只是简单的字符串代换,是在预处理完成的,而typedef是在编译时处理的,它不是简单的代换,而是对类型说明符重新命名,被命名的标识符具有类型定义说明的功能

19.为什么要使用条件编译:

(1)按不同的条件去编译不同的程序部分,因而产生不同的目标代码文件。有利于程序的移植和调试

(2)条件编译当然也可以用条件语句来实现。但是用条件语句将会对整个源程序进行编译,生成的目标代码程序很长,而采用条件编译,则根据条件只编译其中的程序段1或程序段2,生成的目标程序较短

条件编译:

发生在预处理阶段,在编译之前做的事情

核心:根据条件编译指定的代码

条件不同,编译的部分也不同,生成的目标文件(.o)大小也不一样

#if=#else条件编译指令:

第一种形式格式:

#if常量表达式

程序段1

#elif

代码段3

#else

程序段2

#endif

注意:忒傲剑编译后面的条件表达式中不能识别变量,它里面只能识别常量和宏定义

20.#ifdef条件编译指令

条件编译指令

1) #if #elif
#else #endif

2) #ifdef
用来判断某个宏是否定义

#ifdef
标识符

程序段1

#else

程序段2

#endif

3)#ifndef
条件编译指令 用来判断某个宏是不是没定义,如果没定义

格式:

#ifndef
标识符

程序段1

#else

程序段2

#endif

3

#include
<stdio.h>

#define DEBUG1 1

#define DEBUG2 0

int main(int
argc, const
char * argv[]) {

int a = 0;

//ifdef检测宏是否定义

#ifdef DEBUG1
//DEBUG
系统已经定义了这个宏了

a = 10;

#else

a = 10000;

#endif

//ifndef
检测宏是否定义
ifndef 如果没有定义

#ifndef DEBUG2

a = 100;

#else

a = -1;

#endif

printf("%d\n",a);

return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: