IOS学习第14天
fputs与fgets函数
- fputs
1.fputs()函数
作用:将数据输出到 指定的流中
流: 标准输出流->控制台.
文件流 --> 磁盘上的文件.
使用格式:
char * name = "abcdef";
fputs(要输出的字符串,指定的流);
1. 将字符串数据输出到标准输出流.
fputs(要输出的字符串,stdout);
2. 将字符串存储到文件中.
fputs(要输出的字符串,文件流);
把大象装进冰箱的步骤:
1>打开冰箱
2>放进去
3>关闭冰箱
"写一个字符串到文件
File* fp = fopen("文件的路径",打开文件的模式);
//相当于 定义了一个文件指针,这个文件指针指向了 一个文件
char * name = "我爱好者能够过";
fputs(name,fp);//就是name存储的字符串 写到 fp指向文件里了
fclose(fp);
4
注意:打开文件的模式,"w","r","a" append,表示追加
当操作文件模式 是"w"的时候,如果文件不存在,那么 创建一个
如果文件存在,那么 覆盖原来内容,全部清空原来的内容
当操作文件模式 是"a"的时候,如果文件不存在,那么 创建一个
如果存存在,那么往后写
```
* gets函数
使用fgets函数从标准输入流中读取字符串
1.fgets()函数:接受字符串
使用语法:
fgets(要将字符串存储在哪一个数组中,最多接收多少长度的字符串n,指定的流)
第2个参数: 我们写1个n ,那么函数最多接收 n-1 个长度字节的字符串
这个参数一般情况下和第1个参数数组的长度一致.
2.特点:安全
如何实现安全性?
a.输入字符串的长度 > = n 只会接收 n-1个字符,还有一个末尾字符 自动加上’\0’
b.输入的字符串的长度 == n-1 ,非常完美
c.输入字符串的长度 < n-1 不仅会把你输入的字符串放进去,还会把'\n'一并接收
如果出现第c种情况,解决方案
找到’\n’的位置 把’\n’换成’\0’即可
只要计算字符串的长度就可以找到’\n’,
int len = strlen(字符数组名);
‘\n’所在的位置 就是 len-1下标
代码如下:
char input[5];
printf("请输入:\n");
fgets(input, 5, stdin);
size_t len = strlen(input);
if(input[len - 1] == '\n')
{
input[len-1] = '\0';
}
printf("你输入的是:%s\n",input);
```
使用fgets函数从文件流中读取数据
1.使用fgets函数从文件流中读取数据的步骤?
把刚刚装进冰箱的大象拿出来
1>开门
2>拿出来
3>关门
//1. 创建1个读取文件的文件流.
FILE* fp = fopen("/Users/Itcast/Desktop/abc.txt", "r");
//2.准备1个字符数组.准备存储读取到的字符串数据.
char content[50];
//3.使用fgets函数从指定的文件流中读取.
fgets(content, 50, fp);
//4. 读取成功.
printf("读取的内容是: %s\n",content);]
//5. 关闭文件流.
fclose(fp);
const修饰指针
const 常量
* 指针
1). const int* p1 = #//常量指针
//指向常量的指针
无法通过p1指针去修改指针指向的变量的值. 但是可以改变指针变量的值.
2). int const * p1 = #
等同于上面
3). int * const p1 = #//指针常量
p1的值不能修改,但是可以通过p1去修改p1指向的变量的值.
4). int const * const p1 = #
既不能修改p1的值,也不能通过p1去修改p1指向的变量的值
#pragma mark - 0_13 [了解]const关键字的使用场景
1,const的特点:
被const修饰的变量.是只读变量,只能取值.而不能改值.
2,使用场景:
1> 当某些数据是固定的,在整个程序运行期间都不会发生变化. 并且你也不允许别人去修改.
那么这个时候,我们就可以使用const修饰.
2> 当函数的参数是1个指针的时候,为了防止函数的内部修改实参变量的值.
那么这个时候,我们就可以使用const修饰
```
malloc() calloc()和realloc()函数
- malloc函数
1.堆中申请的字节空间的特点?
如果空间申请完后 不释放,会一直才程序中,知道程序结束
//如果不释放,内存泄漏
2.所以在堆中申请字节空间的步骤.
申请–>使用–>释放
3.如何在堆区申请指定字节数的字节空间呢?
#include <stdlib.h>
malloc(),calloc(),realloc();
```
4.malloc函数的使用
作用:向堆空间申请 指定字节数的空间
格式:malloc(字节数)
// 我要申请 4个int变量 所占的空间
//返回值 是一个 void* 通用指针
int * p = malloc(4 * sizeof(int));
注意的问题:
1>在堆区申请的字节空间是从低地址 到 高地址 连续的空间
2>在堆区申请的字节,里面是有值的.值是垃圾值.不会自动清零.
3>在向堆区申请字节空间的时候,有可能会申请失败.
如果申请失败 则返回NULL
所以 最好进行判断
//if(指针 != NULL){
// //进行操作
//}
4>申请的空间使用完毕之后,一定要记得释放.
free(申请空间的第一个字节的地址);
5.例题:
//定义一个用户指定长度的数组,让用户输入每一个学生的成绩保存在数组中.输入完毕后打印所有成绩
int num = 0;
printf("请输入学生的人数:\n");
scanf("%d",&num);
//int scores[num];这句话 在xcode中没问题,但是C语言标准是不允许的
//所以说 需要我们自己手动申请空间
float * p = malloc(num * sizeof(float));
//输入p[0] p[1] *p *(p+1)
for (int i = 0; i < num; i++) {
printf("请输入第%d个学生的成绩:\n",i+1);
scanf("%f",p+i);
// scanf("%f",&p[i]);//p[i] === > *(p+1)
}
for (int i = 0; i < num; i++) {
// printf("%d\n",p[i]);
printf("%f\n",*(p+i));
}
free(p);
```
* calloc与realloc
1.calloc函数的使用
作用:向堆空间申请 指定字节数的空间
格式:calloc(块数,每一个块字节数);
int *p_num = calloc(10,sizeof(int));
优点:申请的字节空间数据会全部清零
2.realloc
作用:如果已经的空间不够用,可以进行扩容
格式:realloc(原来字节空间的指针,扩容后的容量)
注意:
1>如果原来的空间 后面还有剩余的空间 并且足够扩容,那么直接扩容在尾部
2>如果原来的空间 后面还要剩余空间但是不够扩容,会重写找一个足够的空间,会把原来的空间中的数据全部移过去,而且原来的空间会自动释放
```
指针与函数
1.指针作为函数的参数.
优点:
1>在函数内部想改变 变量的值 ,同时也改变主函数中的实参:地址传递
2>当一个函数需要返回多个值
2.指针作为函数的返回值
1>函数可以返回局部变量,但是不能返回局部变量的地址
int num = returnInt();
2>如果我非要返回一个变量的地址,只能想办法 把这个变量 申请在堆区
```
* 指向函数的指针
1.如何声明一个指向函数的指针
返回值类型 (*指针名)([参数列表]);
2.指向函数的指针的初始化
因为函数名就是这个函数的地址
所以直接将符合条件的函数的名称赋值给这个指针.
3.有了函数的指针之后,如何使用这个函数的指针
void (*pFunc)() = test;//pFunc这个函数的指针 指向了test这个函数
pFunc(); (*pFunc)();
4.定义一个指针,指向一个函数的小技巧
直接拷贝函数的头部,去掉函数名
变为一个小括号,在小括号里写上一个* 然后跟上指针名字
“================================”
上面的内容都不是重点,比较重要的 “三个申请内存空间的函数
“指针与函数的关系:可以作为返回值,可以作为参数
“================================”
###结构体
* 初始化
初始化的语法:
结构体变量名称.成员变量名 = 数据;
struct Car bmw_520;
bmw_520.logo = “宝马”;
bmw_520.xinghao = “520”;
bmw_520.price = 50.6;
bmw_520.seatCount = 6;
bmw_520.color = “白色”;printf(“我有一辆%s车,他的型号是%s,价值%.2lf万\n”,bmw_520.logo,bmw_520.xinghao,bmw_520.price);
1.另外一种比较常用的初始化方式
struct Car
{
char * logo;
char * xinghao;
double price;
int seatCount;
char * color;
};struct Car bmw1 = {“宝马”,”520”,20.8,6,”白色”};
2.给结构体变量赋值的时候,
如果不给赋值,那么结构体变量中的每一个成员都是垃圾值
如果你通过 “点” 这种语法给结构体变量中的某几个成员赋值
那么没有赋值的 默认值是 “零”
注意:
赋值的时候大括号中的数据的顺序,类型,个数 要和 类型定义的时候 完全一致
“练习
定义1个变量,来保存1人的信息.并且初始化
struct Person
{
int age;
float weight;
float height;
double money;
};
struct Person zhangsan = {18,100.0f,180.5f,50000.0};
//Person.age
```
- 注意点
1.要先定义结构体类型 才可以根据这个类型声明变量
2.结构体变量也是1个变量,所以也可以批量声明
struct Car car1,car2;
3.定义结构体名称的命名规范,要求首字母大写
4.在声明结构体类型的同时,可以定义结构体变量
struct Car{
char * logo;
char * xinghao;
double price;
int seatCount;
char * color;
} bmw1,bmw2;
struct Car bmw3,bmw4;
5.匿名结构体:没有名字的结构体类型
struct
{
char * logo;
char * xinghao;
double price;
int seatCount;
char * color;
}bmw5,bmw6;
//strcut bmw7;
注意:匿名结构体类型 只能在定义类型的同时 定义结构体变量
```
* 作用域
全局结构体:定义在所有函数之外结构体类型
局部结构体:定义在函数内部的结构体
一般情况下,我们的结构体类型都是定义在函数的外面,文件的最上面,以便让所有的函数都可以使用
* 结构体变量之间的相互赋值
1.相同结构体类型的变量之间绝对是可以相互赋值的
因为他们的类型相同
2.结构体变量之间的赋值原理
将源结构体变量中的每一个成员的值 拷贝一份
赋值给 目标结构体变量中对应的成员
3) 结构体变量之间赋值 是值传递.
那么假设有一个函数,这个函数的参数是一个结构体,在函数内部,修改结构体变量中某一个成员的值,是不会影响主调函数中的实参
“`