字符串相关的函数 const关键字 堆空间 结构体

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 = &num;//常量指针
//指向常量的指针
无法通过p1指针去修改指针指向的变量的值. 但是可以改变指针变量的值.

2). int const * p1 = &num;
等同于上面

3).  int  * const p1 = &num;//指针常量
p1的值不能修改,但是可以通过p1去修改p1指向的变量的值.

4).  int const  * const p1 = &num;
既不能修改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) 结构体变量之间赋值 是值传递.
那么假设有一个函数,这个函数的参数是一个结构体,在函数内部,修改结构体变量中某一个成员的值,是不会影响主调函数中的实参
“`

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值