黑马程序员——ios基础---C语言:结构体、条件编译、文件操作

来源:互联网 发布:dota2数据分析师招聘 编辑:程序博客网 时间:2024/06/05 22:43

一、结构体:

1、安全的字符串读取和输出的函数 

读入字符串的方法: 

1) scanf 缺点:不能接收空格 

2) gets 优点:可以接受含有空格的字符串 

3) fgets(); 优点:可以帮我们根据数组的长度自动截取适当的长度保存 

使用格式:fgets(ch,sizeof(ch),stdin); 

 

输出字符串的方法: 

1) printf() %s 缺点:不能自动换行 

2) puts() 优点:可以自动换行 

3) fputs(); 不可以的自动换行 

使用格式:fputs(ch,stdout); 

stdout表示输出 

 

 

2const修饰符 

作用:const作用可以把变量变成只读的(常量) 

1)修饰变量 

const int a=23; 

a = 20; (错误的) 

2)修饰指针 

const int *p; //指向可变 ,值不能变 

int const *p; //同上 

int * const p; //指向不可变,值可变 

const intconst p;// 指向和值都不能变 

3)注意记下来:

const  * 的左侧  指向可变,值不能变 

const  * 的右侧 指向不可变 值可变 

const  * 的两侧 指向和值都不可以变 

 

3C语言中的内存管理 

栈区 -- 存放局部变量,临时变量 

堆区 -- 程序运行过程中,动态分配的内存 

BSS -- 未初始化的全局变量和静态变量 

数据段 -- 已经初始化的全局变量和静态变量 

代码段 -- 程序编译产生的二进制的数据 

 

4、动态内存管理 

1) malloc 

(void *)malloc(n)

动态的向内存申请连续的n个字节 返回的是新申请的内存空间的首地址 

int *p = (int *)malloc(100);

p是在栈区 malloc(100) 在堆区 

malloc不会把新申请的空间初始化 

memset(p,0,100);

全部初始化为0 

 

2)calloc 

int *p = (int *)calloc(5,4);

申请5个长度为4的空间 

calloc可以把新申请的空间初始化0 


注意:判断一个空间是否申请成功 

if(p!=NULL){ //只有申请成功了,才能操作 

 

3) realloc 

重新改变一块内存空间的大小 p= (int *)realloc(p,size); 

 

4) free 

释放我们指定的内存空间 

free(p);

注意:p是我们新申请的内存单元 free,p是一个野指针 如果不释放,造成内存的泄露 。 

 

5、指针和函数之间的关系 

1)返回值是指针的函数 指针函数 

char * getday(){ 

    return "星期一"; 

2)函数指针 

指向函数的指针 

格式:返回值 (*指针变量名)(函数的参数); 

int sum(int a,int b){ 

    return a+b; 

格式一:int (*p1)(int a,int b); // 函数指针p1 只能指向返回值是int类型,并且有两个int 类型参数的函数。 

格式二:int (*p2)(int,int); 

 

技巧: 

声明的格式:int sum(int a,int b); 

int (*p3)(int a,int b) = sum; 

p3 =sum; 

 

6、结构体若干个相同或者不同类型的数据组成的新的类型 

 

struct 结构体名{ 

    成员列表; 格式: 类型 变量名; 

}; 

  

7、什么是结构体变量 

结构体变量特点: 

一个复合类型,具备结构体的特性 

struct stu{ 

    int age; 

}stu1,stu2; 

 

8、匿名结构体 

struct{ 

    int model; 

}s1; 

 

先定义结构体,后定义变量 

struct stu stu3; 

 

 

9、如何初始化结构体变量 

初始化的时候,注意成员的顺序 

1) 

struct stu{ 

    int age; 

    char name[20]; 

}stu1={23,"sss"}; 

2) 

struct stu stu3={18,"sb"}; 

3) 

struct stu stu4; 

strcpy(stu4.name,"xxxx");//stu4.name="xxx"; 

访问姓名  stu4.name  // 结构体变量.成员名 

访问age   stu4.age 

 

10 结构体存储空间 

结构体在内存中占用的存储空间是 所有元素占用空间之和(考虑对齐) 

1.逐个元素对齐(下个元素与上个元素对齐) 

2.整体对齐(最后的和能单独整除所有元素)


理解指针

什么什么指针就是为了方便的访问里面的内容:例如结构体指针就是为了访问其中的东西。

指针什么什么就是为了方便的存储数据的地址:例如指针数组就是存储指针(地址)的东西。

11、结构体的数组 :由相同类型的结构体变量组成的有序的集合。 

定义格式: 

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

struct Car{ 

    int lunzi; 

    int speed; 

}cars[5]; 

 

2) 使用匿名结构体定义数组 

struct { 

    int lunzi; 

    int speed; 

}cars[5]; 

 

3)先定义结构体,再定义结构体数组 

struct Car cars[5]; 

 

初始化: 

1) 定义结构体数组的同时进行初始化 

struct Car{ 

    int lunzi; 

    int speed; 

    char name[20]; 

}cars[2]={{2,50},{80,300}}; 

 

2) 匿名 

struct { 

    int lunzi; 

    int speed; 

    int speed; 

}cars[2]={{2,50},{80,300}}; 

3) 

struct Car cars[2]={{2,50},{80,300}}; 

 

4)先定义数组,后初始化 

cars[0].lunzi= 4; 

cars[0].speed= 200; 

//cars[0].name="xxxx"; 错误的 

strcpy(cars[0].name,"xxxx"); const char a; 

 

通过数组角标整体去初始化 cars[1]=(struct Car){6,100}; 

 

 

12、结构体指针 

定义:指向结构体的指针 

格式:结构体类型 * 结构体指针变量名; 

struct Student stu1; 

struct Studetn *pstu; 

pstu =&stu1; 

 

作用:可以间接访问结构体变量中保存的成员变量值 

(*pstu).name 

(*pstu).sno 新的访问方法 

pstu->name  // 只有结构体指针变量才可以 

等价于 (*pstu).name 


13、结构体与函数之间的关系 

1)结构体变量作为函数的参数 (值传递) 

2)结构体指针作为函数的参数 (地址传递) 

 二、条件编译

1、枚举类型 :在开发中,如果一个变量只有有限的几个取值,可以使用枚举 

1)枚举类型 

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

2)枚举类型的变量 

enum SEX{man,women,yao}isex; 

enum {man,women,yao}s1; 

enum SEX s2; 

3)枚举类型变量的使用 

  枚举元素的值 

系统默认给枚举变量第一元素赋值为0,后面的元素依次是上一个元素+1 

 

  给枚举类型变量赋值 

isex =man; 

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

 

2、typedef定义给已经存在的数据类型取一个别名 

格式:typedef 原类型 新类型名; //新类型名尽量要大写 

 

3、预处理指令的概念 

定义:以“#” 开头的一些特殊的指令  

作用: 在编译之前做些处理(宏展开,条件编译,文件包含) 

常见的预处理指令: 宏  

宏:特殊的标示符 

宏替换 :在编译之前,在源文件中,所有出现宏名的地方 都用宏代表的字符串 去替换 

注意:宏不是语句,不需要分号结束 

 

1)无参宏 

#define 宏名 宏代表的字符串 

#define M 10 

#define AREA 3.14*M*M 

#define PI 3.14 

 

2)有参宏 

#define Mi(y) y*y+3*y   // y 是形参,不分配空间,不需要写类型 

#define MAX(a,b) a>b?a:b 

#define SUM(a,b) a+b 

 

4、条件编译 

当条件满足的时候去编译一段代码 

好处:可移植、生成更小的目标文件 

格式: 

#if 

 

#elif 

 

#else 

 

#endif

可以节省内存空间

三、文件操作

1static  extern使用 

1)修饰局部变量 

static修饰局部变量特点:延长局部变量的生命周期 

extern不能修饰局部变量 

 

2)修饰全局变量 

static修饰全局变量: 是一个内部变量,只能在本文件使用。 

extern修饰全局变量:是一个外部变量,可以在本文件和其他文件使用(有包含关系) 

 

3)修饰函数 

static修饰函数:是一个外部函数,只能在本文件中访问 

extern修饰函数:是一个内部函数,可以在本文件和其他文件访问(有包含关系) 

 

注意:默认情况下在.h文件中声明的变量和函数都是extern类型。 

 

2、文件的基本概念 

文件:存储外部介质上的数据集,数据集有一个名称就是文件名 

文件的分类: 

1)用户角度:普通文件和设备文件 

2)存储的内容: 

ascii文件(文本文件): 

 

存储的流程:根据文本找到其对应的ascii码值---->转为二进制--> 写到文件中 

 

读取流程二进制-->10进制-->找对应的字符-->显示出来 

 

二进制文件: 

二进制数据的存取 

文件的操作流程: 

1)导入头文件 stdio.h 

2定义文件指针 

3)打开文件 

4)操作文件 

5)关闭文件 

 

3、文件指针 

格式:FILE *fp; 结构体指针 

作用:存储一个文件的首地址,指向一个文件 

 

4、文件的打开和关闭 

打开 fopen(文件名,操作方式); 

fopen("a.txt","r"); 

//a.txt默认的去products目录去 

//文件的操作方式 

关闭文件: 

fclose(文件指针); 

 

5、文件操作的函数 

1字符读取和写入 

写入格式: fputc('字符',文件指针); 

char c='A'; 

fputc(c,fp); 

读取格式: char ch = fgetc(fp); 

 

2)字符串读取和写入 

写入格式: fputs(数组名/指针名,fp);  //fputs(数组名,stdout) 输出; 

Char str[] = "abcd"; 

Fputs(str,fp); 

读取格式: fgets(数组名/指针名,长度,fp); 

读取的个数 = 长度 - 1;遇到\n,EOF自动结束。 

 

3)数据块的读取和写入 

写入格式: fwrite(变量地址,数据块的大小,块数,fp); 

读取格式: fread(变量的地址,数据块的大小,块数,fp) 

 

4)格式化的读取和写入 

写入数据和读取数据按照一定的格式进行 

写入格式: fprintf(文件指针,"格式化的字符串",变量列表); 

fprintf(fp,"%d,%c,%d#",10,'a',20); 

读取格式: fscanf(fp,"%d,%c,%d#",&a,&ch,&b); 

 

6、文件的随机读取 

1)rewind(fp); //fp指向首地址 

2)fseek(fp,偏移的距离,起始点); 

fseek(fp,32L,SEEK_SET); //从文件头部开始,偏移32个字节 

 

7、文件的检测函数 

调用格式: feof(文件指针);  

功能:判断文件是否处于文件结束位置,如文件结束,则返回值为1,否则为0。 

缺点:会多执行一次



0 0