01C语言基础(二)
阅读原文时间:2023年07月09日阅读:1

Day07

指针和函数:

    栈 帧:
        当函数调用时,系统会在 stack 空间上申请一块内存区域,用来供函数调用,主要存放 形参 和 局部变量(定义在函数内部)。

        当函数调用结束,这块内存区域自动被释放(消失)。

    传值和传址:

        传值:函数调用期间,实参将自己的值,拷贝一份给形参。 

        传址:函数调用期间,实参将地址值,拷贝一份给形参。 【重点】

            (地址值 --》 在swap函数栈帧内部,修改了main函数栈帧内部的局部变量值)

    指针做函数参数:

        int swap2(int *a, int *b);

        int swap2(char *a, char *b);

        调用时,传有效的地址值。

    数组做函数参数:

        void BubbleSort(int arr[10]) == void BubbleSort(int arr[])  == void BubbleSort(int *arr) 

        传递不再是整个数组,而是数组的首地址(一个指针)。

        所以,当整型数组做函数参数时,我们通常在函数定义中,封装2个参数。一个表数组首地址,一个表元素个数。

    指针做函数返回值:

        int *test_func(int a, int b);

        指针做函数返回值,不能返回【局部变量的地址值】。

    数组做函数返回值:

        C语言,不允许!!!!  只能写成指针形式。

指针和字符串:

    1)
        char str1[] = {'h', 'i', '\0'};         变量,可读可写

        char str2[] = "hi";             变量,可读可写

        char *str3 = "hi";              常量,只读

            str3变量中,存储的是字符串常量“hi”中首个字符‘h’的地址值。

            str3[1] = 'H';  // 错误!!

        char *str4 = {'h', 'i', '\0'};  // 错误!!!

    2)
        当字符串(字符数组), 做函数参数时, 不需要提供2个参数。 因为每个字符串都有 '\0'。

    练习:比较两个字符串: strcmp();实现

        比较 str1 和 str2, 如果相同返回0, 不同则依次比较ASCII码,str1 > str2 返回1,否则返回-1

数组方式:

int mystrcmp(char *str1, char *str2)
{
    int i = 0;

    while (str1[i] == str2[i])   // *(str1+i) == *(str2+i)
    {
        if (str1[i] == '\0')
        {
            return 0;           // 2字符串一样。
        }
        i++;
    }
    return str1[i] > str2[i] ? 1 : -1;
}

指针方式:

int mystrcmp2(char *str1, char *str2)
{
    while (*str1 == *str2)   // *(str1+i) == *(str2+i)
    {
        if (*str1 == '\0')
        {
            return 0;           // 2字符串一样。
        }
        str1++;
        str2++;
    }
    return *str1 > *str2 ? 1 : -1;
}

    练习:字符串拷贝:

//数组版本
void mystrcpy(char *src, char *dst)
{
    int i = 0;
    while (src[i] != 0)  // src[i] == *(src+i)
    {
        dst[i] = src[i];
        i++;
    }
    dst[i] = '\0';
}

//指针版
void mystrcpy2(char *src, char *dst)
{
    while (*src != '\0')  // src[i] == *(src+i)
    {
        *dst = *src;
        src++;
        dst++;
    }
    *dst = '\0';
}

    练习:在字符串中查找字符出现的位置:

char *myStrch(char *str, char ch)
{
    while (*str)
    {
        if (*str == ch)
        {
            return str;
        }
        str++;
    }
    return NULL;
}
// hellowrld --- 'o'
char *myStrch2(char *str, char ch)
{
    int i = 0;
    while (str[i])
    {
        if (str[i] == ch)
        {
            return &str[i];
        }
        i++;
    }
    return NULL;
}

    练 习:字符串去空格。

void str_no_space(char *src, char *dst)
{
    int i = 0;   // 遍历字符串src
    int j = 0;   // 记录dst存储位置
    while (src[i] != 0)
    {
        if (src[i] != ' ')
        {
            dst[j] = src[i];
            j++;
        }
        i++;
    }
    dst[j] = '\0';
}
// 指针版
void str_no_space2(char *src, char *dst)
{
    while (*src != 0)
    {
        if (*src != ' ')
        {
            *dst = *src;
            dst++;
        }
        src++;
    }
    *dst = '\0';
}

带参数的main函数:

    无参main函数:   int main(void) == int main()

    带参数的main函数: int main(int argc, char *argv[]) == int main(int argc, char **argv)

        参1:表示给main函数传递的参数的总个数。

        参2:是一个数组!数组的每一个元素都是字符串 char * 

    测试1:
        命令行中的中,使用gcc编译生成 可执行文件,如: test.exe

        test.exe abc xyz zhangsan nichousha 

        -->

        argc --- 5
        test.exe -- argv[0]
        abc -- argv[1]
        xyz -- argv[2]
        zhangsan -- argv[3]
        nichousha -- argv[4]

    测试2:

        在VS中。项目名称上 --》右键--》属性--》调试--》命令行参数 --》将 test.exe abc xyz zhangsan nichousha 写入。

        -->

        argc --- 5
        test.exe -- argv[0]
        abc -- argv[1]
        xyz -- argv[2]
        zhangsan -- argv[3]
        nichousha -- argv[4]

str 中 substr 出现次数:

    strstr函数: 在 str中,找substr出现的位置。

    char *strstr(char *str, char *substr)   -- #include <string.h>

        参1: 原串

        参2: 子串

        返回值: 子串在原串中的位置。(地址值);

             如果没有: NULL

实 现:
int str_times(char *str, char *substr)
{
    int count = 0;
    char *p = strstr(str, substr);  // "llollollo"

    while (p != NULL)
    {
        count++;
        p += strlen(substr);    // p = p+strlen(substr) --> "llollo"
        p = strstr(p, substr);  // 返回: "llo"
    }
    return count;
}

求非空字符串元素个数:

字符串逆置: str_inverse

判断字符串是回文:

字符串处理函数:

    字符串拷贝:

    字符串拼接:

    字符串比较:

    字符串格式化输入、输出:

        sprintf():

        sscanf():   

    字符串查找字符、子串:

        strchr()

        strrchr()

        strstr()

    字符串分割:

        strtok()

    atoi/atof/atol:
  • 01-传值和传址.c

    int swap(int, int); // 函数声明
    int swap2(int *, int *);

    int main0101(void)
    {
    int m = 23;
    int n = 57;

    printf("--before-- m = %d, n = %d\n", m, n);
    // 函数调用
    //swap(m, n);  // m/n 实参
    
    swap2(&m, &n);
    
    printf("--after-- m = %d, n = %d\n", m, n);
    
    system("pause");
    return EXIT_SUCCESS;

    }

    int swap2(int *a, int *b) // 形参a、b, 需传地址值
    {
    int tmp = 0;
    tmp = *a;
    *a = *b;
    *b = tmp;
    return 0;
    }

    // 函数定义
    int swap(int a, int b) // a/b 形参
    {
    int tmp = 0;

    tmp = a;
    a = b;
    b = tmp;
    
    return 0;

    }

  • 02-数组做函数参数.c

    //void BubbleSort(int arr[]) // void BubbleSort(int *arr)

    void BubbleSort(int *arr, int n)
    {
    for (int i = 0; i < n - 1; i++) { for (int j = 0; j < n - 1 - i; j++) { if (arr[j] > arr[j + 1])
    {
    int temp = arr[j];
    arr[j] = arr[j + 1];
    arr[j + 1] = temp;
    }
    }
    }
    }

    int main0202(void)
    {
    int arr[] = {5, 89, 3, 22, 40, 31, 9, 22, 67, 28, 45, 78};

    printf("main: sizeof(arr) = %d\n", sizeof(arr));
    
    int n = sizeof(arr) / sizeof(arr[0]);
    
    BubbleSort(arr, n);
    
    for (size_t i = 0; i < n; i++)
    {
        printf("%d ", arr[i]);
    }
    printf("\n");
    
    system("pause");
    return EXIT_SUCCESS;

    }

  • 03-数组做函数参数测试.c

    void test_func(int arr[])
    {
    printf("size 2 = %u\n", sizeof(arr)); // 整个数组大小

    printf("%d\n", arr[0]);

    }

    int main0301(void)
    {
    int arr[] = { 4, 5, 5, 6, 7 };

    printf("size 1 = %u\n", sizeof(arr));  // 整个数组大小
    
    test_func(arr);
    
    system("pause");
    return EXIT_SUCCESS;

    }

  • 04-指针做函数返回值.c

    int m = 100; // 全局变量 对应空间消失 ==> 程序结束。

    int *test_func2(int a, int b)
    {
    int p = 1234; // 局部变量
    //return &m;

    return &p;

    }

    int main0401(void)
    {
    int *ret = NULL; // NULL == 0

    ret = test_func2(10, 20);
    
    printf("ret = %d\n", *ret);
    
    system("pause");
    return EXIT_SUCCESS;

    }

  • 05-指针和字符串.c

    int main(void)
    {
    char str1[] = "hello"; // {'h',, 'e', 'l', 'l', 'o', '\0'}
    char m[] = "hello";

    char *str2 = "hello";       // "hello" 是一个字符串常量, 不能修改。
    char *n = "hello";
    
    str1[0] = 'R';
    str2[0] = 'R';
    
    printf("str1 = %p\n", str1);
    printf("m = %p\n", m);
    
    printf("str2 = %p\n", str2);
    printf("n = %p\n", n);
    
    system("pause");
    return EXIT_SUCCESS;

    }

  • 06-字符串比较.c

    // str1 和 str2 == -->0 str1 > str2 --> 1, str1 -1
    int mystrcmp(char *str1, char *str2)
    {
    int i = 0;

    while (str1[i] == str2[i])   // *(str1+i) == *(str2+i)
    {
        if (str1[i] == '\0')
        {
            return 0;           // 2字符串一样。
        }
        i++;
    }
    return str1[i] > str2[i] ? 1 : -1;

    }

    int mystrcmp2(char *str1, char *str2)
    {
    while (*str1 == *str2) // *(str1+i) == *(str2+i)
    {
    if (*str1 == '\0')
    {
    return 0; // 2字符串一样。
    }
    str1++;
    str2++;
    }
    return *str1 > *str2 ? 1 : -1;
    }

    int main0601(void)
    {
    char *str1 = "helloz";
    char *str2 = "helloz";

    //int ret = mystrcmp(str1, str2);
    int ret = mystrcmp2(str1, str2);
    
    if (ret == 0)
        printf("相同\n");
    else if (ret == 1)
        printf("str1 > str2\n");
    else if (ret == -1)
        printf("str1 < str2\n");
    else
        printf("异常\n");
    
    system("pause");
    return EXIT_SUCCESS;

    }

  • 07-字符串拷贝.c

    // src: 源 dst: 目标
    //数组版本
    void mystrcpy(char *src, char *dst)
    {
    int i = 0;
    while (src[i] != 0) // src[i] == *(src+i)
    {
    dst[i] = src[i];
    i++;
    }
    dst[i] = '\0';
    }
    //指针版
    void mystrcpy2(char *src, char dst) { while (src != '\0') // src[i] == *(src+i)
    {
    *dst = *src;
    src++;
    dst++;
    }
    *dst = '\0';
    }

    int main0701(void)
    {
    char *src = "helloworldfuoie11ll";

    char dst[100];
    
    mystrcpy2(src, dst);
    
    printf("dst = %s\n", dst);
    
    system("pause");
    return EXIT_SUCCESS;

    }

  • 08-在字符串中找字符.c

    // hellowrld --- 'm'
    char *myStrch(char *str, char ch)
    {
    while (str) { if (str == ch)
    {
    return str;
    }
    str++;
    }
    return NULL;
    }

    // hellowrld --- 'o'
    char *myStrch2(char *str, char ch)
    {
    int i = 0;
    while (str[i])
    {
    if (str[i] == ch)
    {
    return &str[i];
    }
    i++;
    }
    return NULL;
    }

    int main0801(void)
    {
    char str[] = "hello world";
    char ch = ' ';

    char *ret = NULL; 
    
    ret = myStrch2(str, ch);
    
    printf("ret = %s\n", ret);
    
    system("pause");
    return EXIT_SUCCESS;

    }

  • 09-字符串去空格.c

    // src : 有空格字符串, dst:没有空格的字符串
    void str_no_space(char *src, char *dst)
    {
    int i = 0; // 遍历字符串src
    int j = 0; // 记录dst存储位置
    while (src[i] != 0)
    {
    if (src[i] != ' ')
    {
    dst[j] = src[i];
    j++;
    }
    i++;
    }
    dst[j] = '\0';
    }
    // 指针版
    void str_no_space2(char *src, char *dst)
    {
    while (src != 0) { if (src != ' ')
    {
    *dst = *src;
    dst++;
    }
    src++;
    }
    *dst = '\0';
    }

    int main0901(void)
    {
    char str[] = "ni chou sha chou ni za di";
    char dst[100] = {0};

    str_no_space2(str, dst);
    
    printf("dst = %s\n", dst);
    
    system("pause");
    return EXIT_SUCCESS;

    }

  • 10-带参数的main.c

    int main1001(int argc, char *argv[])
    {
    int i;

    for (i = 0; i < argc; i++)
    {
        printf("argv[%d] = %s\n", i, argv[i]);
    }
    
    system("pause");
    return EXIT_SUCCESS;

    }

  • 11-字符串中找子串.c

    //strstr函数测试
    int main1101(void)
    {
    char *ret = strstr("hellollollo", "llo");

    printf("ret = %s\n", ret);
    
    system("pause");
    return EXIT_SUCCESS;

    }

    int str_times(char *str, char *substr)
    {
    int count = 0;
    char *p = strstr(str, substr); // "llollollo"

    while (p != NULL)
    {
        count++;
        p += strlen(substr);    // p = p+strlen(substr) --> "llollo"
        p = strstr(p, substr);  // 返回: "llo"
    }
    return count;

    }
    // 统计字符串中,子串出现的次数。
    int main1102(void)
    {
    char str[] = "helloabclloxyzllo";
    char substr[] = "llo";

    int ret = str_times(str, substr);
    
    printf("出现%d次\n", ret);
    
    system("pause");
    return EXIT_SUCCESS;

    }

Day08

求非空字符串元素个数:

    “ni chou sha chou ni za di”  

字符串逆置: str_inverse

    hello -- olleh 

void str_inserse(char *str)
{
    char *start = str;          // 记录首元素地址
    char *end = str + strlen(str) - 1;  // 记录最后一个元素地址。

    while (start < end)         // 首元素地址是否 < 最后一个元素地址
    {
        char tmp = *start;      // 三杯水 char 元素交换
        *start = *end;
        *end = tmp;
        start++;            // 首元素对应指针后移
        end--;              // 尾元素对应指针前移
    }
}

判断字符串是回文:

int str_abcbb(char *str)
{
    char *start = str;          // 记录首元素地址
    char *end = str + strlen(str) - 1;  // 记录最后一个元素地址。

    while (start < end)         // 首元素地址是否 < 最后一个元素地址
    {
        if (*start != *end)     // 判断字符是否一致。
        {
            return 0;       // 0 表示非 回文
        }
        start++;
        end--;
    }
    return 1;               // 1 表示 回文
}

字符串处理函数:   #include <string.h>

    字符串拷贝: 

        strcpy: 

            将 src 的内容,拷贝给 dest。 返回 dest。 保证dest空间足够大。【不安全】

            char *strcpy(char *dest, const char *src);

            函数调用结束 返回值和 dest参数结果一致。

        strncpy:

            将 src 的内容,拷贝给 dest。只拷贝 n 个字节。 通常 n 与dest对应的空间一致。 

            默认 不添加 ‘\0’

            char *strncpy(char *dest, const char *src, size_t n);   

            特性: n > src: 只拷贝 src 的大小

                   n < src: 只拷贝 n 字节大小。 不添加 ‘\0’

    字符串拼接:

        strcat:

            将 src 的内容,拼接到 dest 后。 返回拼接后的字符串。    保证 dest 空间足够大。

            char *strcat(char *dest, const char *src);

        strncat:

            将 src 的前 n 个字符,拼接到 dest 后。 形成一个新的字符串。保证 dest 空间足够大。

            char *strncat(char *dest, const char *src, size_t n);

            函数调用结束 返回值和 dest 参数结果一致。

    字符串比较:  不能使用 > < >= <= == != 

        strcmp:

            比较s1和s2两个字符串,如果相等 返回0.如果不相等,进一步表 s1 和 s2 对应位 ASCII码值。

            s1 > s2 返回1

            s1 < s2 返回-1

            int strcmp(const char *s1, const char *s2);

        strncmp:

            int strncmp(const char *s1, const char *s2, size_t n);

            比较s1和s2两个字符串的前n个字符,

            如果相等 返回0。如果不相等,进一步表 s1 和 s2 对应位 ASCII码值。(不比字符串ASCII码的和)

            s1 > s2 返回1

            s1 < s2 返回-1

    字符串格式化输入、输出:

        sprintf():  s -- string

            int sprintf(char *str, const char *format, ...);

            对应printf,将原来写到屏幕的“格式化字符串”,写到 参数1 str中。

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

            ---》
            char str[100];

            sprintf(str, "%d+%d=%d\n", 10, 24, 10+24);  格式串写入str数组中。

        sscanf():

            int sscanf(const char *str, const char *format, ...);

            对应scanf, 将原来从屏幕获取的“格式化字符串”, 从 参数1 str中 获取。

            scanf("%d+%d=%d", &a, &b, &c);

            ---》

            char str[]= "10+24=45";

            sscanf(str, "%d+%d=%d", &a, &b, &c);  a --> 10, b --> 24, c --> 45

    字符串查找字符、子串:

        strchr():

            在字符串str中 找一个字符出现的位置。 返回字符在字符串中的地址。

            char *strchr(const char *s, int c);

            printf("%s\n" strchr("hehehahahoho", 'a'));  --> "ahahoho"

        strrchr():

            自右向左,在字符串str中 找一个字符出现的位置。 返回字符在字符串中的地址。

            char *strrchr(const char *s, int c);

            printf("%s\n" strrchr("hehehahahoho", 'a'));  --> "ahoho"

        strstr():

            在字符串str中,找子串substr第一次出现的位置。返回地址。

            char *strstr(const char *str, const char *substr);

            在字符串中找子串的位置。 

            printf("%s\n" strrchr("hehehahahoho", "ho"));  --> "hoho"

            printf("%s\n" strrchr("hehehahahoho", "xixi"));  --> NULL

scanf("%s", str);

scanf("%[^\n]", str);

    字符串分割:

        strtok(): 按照既定的分割符,来拆分字符串。“www.baidu.com”  --> "www\0baidu.com"

        char *strtok(char *str, const char *delim);

            参1: 待拆分字符串

            参2: 分割符组成的“分割串”

        返回:字符串拆分后的首地址。 “拆分”:将分割字符用 '\0'替换。

    特性:
        1)strtok拆分字符串是直接在 原串 上操作,所以要求参1必须,可读可写(char *str = "www.baidu.com" 不行!!!)

        2)第一次拆分,参1 传待拆分的原串。 第1+ 次拆分时,参1传 NULL.

    练习: 拆分 ".itcast.cn$This is a strtok$test"

        char str[] = "www.itcast.cn$This is a strtok$test";

        char *p = strtok(str, "$ .");

        while (p != NULL)
        {
            p = strtok(NULL, " .$");
            printf("p = %s\n", p);
        }

    atoi/atof/atol:

        使用这类函数进行转换,要求,原串必须是可转换的字符串。

        错误使用:"abc123" --> 0;    "12abc345" ---> 12;  "123xyz" -->123

        atoi:字符串 转 整数。

        int atoi(const char *nptr);

        atof:字符串 转 浮点数

        atol:字符串 转 长整数

----------------------------------------------------------------------------------------------

局部变量:

    概念:定义在函数 内 部的变量。

    作用域:从定义位置开始,到包裹该变量的第一个右大括号结束。

全局变量:

    概念:定义在函数 外 部的变量。

    作用域:从定义位置开始,默认到本文件内部。 其他文件如果想使用,可以通过声明方式将作用域导出。

static全局变量:

    定义语法: 在全局变量定义之前添加 static 关键字。       static int a = 10;

    作用域:被限制在本文件内部,不允许通过声明导出到其他文件。

static局部变量:

    定义语法: 在局部变量定义之前添加 static 关键字。

    特性: 静态局部变量只定义一次。在全局位置。 通常用来做计数器。

    作用域:从定义位置开始,到包裹该变量的第一个右大括号结束。

全局函数:  函数

    定义语法: 函数原型 + 函数体

static函数:

    定义语法:static + 函数原型 + 函数体

    static 函数 只能在 本文件内部使用。 其他文件即使声明也无效。

生命周期:

    局部变量:从变量定义开始,函数调用完成。 --- 函数内部。

    全局变量:程序启动开始,程序终止结束。  --- 程序执行期间。

    static局部变量:程序启动开始,程序终止结束。  --- 程序执行期间。

    static全局变量:程序启动开始,程序终止结束。  --- 程序执行期间。

    全局函数:程序启动开始,程序终止结束。  --- 程序执行期间。

    static函数:程序启动开始,程序终止结束。  --- 程序执行期间。

内存4区模型:

    代码段:.text段。 程序源代码(二进制形式)。

    数据段:只读数据段 .rodata段。初始化数据段 .data段。 未初始化数据段 .bss 段。

    stack:栈。 在其之上开辟 栈帧。 windows 1M --- 10M  Linux: 8M --- 16M

    heap:堆。 给用户自定义数据提供空间。 约 1.3G+

开辟释放 heap 空间:

    void *malloc(size_t size);  申请 size 大小的空间

        返回实际申请到的内存空间首地址。 【我们通常拿来当数组用】

    void free(void *ptr);   释放申请的空间

        参数: malloc返回的地址值。

使用 heap 空间:

    空间时连续。 当成数组使用。

    free后的空间,不会立即失效。 通常将free后的 地址置为NULL。

    free 地址必须 是 malloc申请地址。否则出错。

    如果malloc之后的地址一定会变化,那么使用临时变量tmp 保存。

二级指针对应的 heap空间:

    申请外层指针: char **p = (char **)malloc(sizeof(char *) * 5);

    申请内层指针: for(i = 0; i < 5; i++)
            {
                p[i] = (char *)malloc(sizeof(char) *10);
            }

    使用: 不能修改 p 的值。

         for(i = 0; i < 5; i++)
        {
            strcpy(p[i], "helloheap");
        }

    释放内层:

         for(i = 0; i < 5; i++)
        {
            free(p[i]);
        }

    释放外层:

        free(p);

栈的存储特性:

    局部变量:

    形参: 

内存操作函数:

    memset:

    memmove:

    memcmp:

内存常见问题:

    1) 申请 0 字节空间

    2)free空指针

    3)越界访问

    4)free ++后的地址

    5)子函数malloc空间,main中用
  • 01-非空字符串元素个数.c

    int no_space_str(char *str)
    {
    int count = 0;

    char *p = str;
    
    while (*p)
    {
        if (*p != ' ')
        {
            count++;
        }
        p++;
    }
    return count;

    }

    int main0101(void)
    {
    char str[] = "ni chou sha";

    int ret = no_space_str(str);
    
    printf("%d\n", ret);
    
    system("pause");
    return EXIT_SUCCESS;

    }

  • 02-字符串逆序.c

    // o e l l h

    // 字符串逆序
    void str_inserse(char *str)
    {
    //int i, j; // str[i] *(str+i)
    char *start = str; // 记录首元素地址
    char *end = str + strlen(str) - 1; // 记录最后一个元素地址。

    while (start < end)         // 首元素地址是否 < 最后一个元素地址
    {
        char tmp = *start;      // 三杯水 char 元素交换
        *start = *end;
        *end = tmp;
        start++;            // 首元素对应指针后移
        end--;              // 尾元素对应指针前移
    }

    }
    // 判断回文字符串 abcddpba
    int str_abcbb(char *str)
    {
    char *start = str; // 记录首元素地址
    char *end = str + strlen(str) - 1;// 记录最后一个元素地址。

    while (start < end)     // 首元素地址是否 < 最后一个元素地址
    {
        if (*start != *end) // 判断字符是否一致。
        {
            return 0; // 0 表示非 回文
        }
        start++;
        end--;
    }
    return 1;       // 1 表示 回文

    }

    int main0201(void)
    {
    char str[] = "this is a test";

    str_inserse(str);
    
    printf("str=%s\n ---------------------\n", str);
    
    char s2[] = "abcmncba";
    
    int ret = str_abcbb(s2);
    
    if (ret == 0)
        printf("不是回文\n");
    else if (ret == 1)
        printf("是回文\n");
    
    system("pause");
    return EXIT_SUCCESS;

    }

  • 03-字符串拷贝strcpy和strncpy.c

    // strcpy
    int main0301(void)
    {
    char src[] = "abc efg zhansan wangwu ";
    char dest[10] = {0};

    char *p = strcpy(dest, src); ;// 字符串src 拷贝给dest
    
    printf("p= %s\n", p);
    printf("dest = %s\n", dest);
    
    system("pause");
    return EXIT_SUCCESS;

    }
    // strncpy
    int main0302(void)
    {
    char src[] = "hello world";
    char dest[100] = { 0 };

    char *p = strncpy(dest, src, 100); ;// 字符串src 拷贝给dest
    for (size_t i = 0; i < 10; i++)
    {
        printf("%c\n", p[i]);
    }
    
    printf("p= %s\n", p);
    printf("dest = %s\n", dest);
    
    system("pause");
    return EXIT_SUCCESS;

    }

  • 04-字符串拼接 strcat和strncat.c

    int main0401(void)
    {
    char src[] = "world";
    char dest[] = "hello";

    char *p = strcat(dest, src);
    
    printf("p = %s\n", p);
    printf("dest = %s\n", dest);
    
    system("pause");
    return EXIT_SUCCESS;

    }

    int main0402(void)
    {
    char src[] = "world";
    char dest[6] = "hello";

    char *p = strncat(dest, src, 3);
    
    printf("p = %s\n", p);
    printf("dest = %s\n", dest);
    
    printf("%d\n", strlen(dest));
    
    system("pause");
    return EXIT_SUCCESS;

    }

  • 05-strcmp和strncmp字符串比较.c

    int main0501(void)
    {
    char *str1 = "helloworld";
    char *str2 = "helloz";

    printf("ret = %d\n", strcmp(str1, str2));
    
    system("pause");
    return EXIT_SUCCESS;

    }

    int main0502(void)
    {
    char *str1 = "helloworld";
    char *str2 = "helloz";

    printf("ret = %d\n", strncmp(str1, str2, 8));
    
    system("pause");
    return EXIT_SUCCESS;

    }

  • 06-格式化读入和写出 sprintf、sscanf.c

    // sprintf
    int main0601(void)
    {
    char buf[100] = {0}; //buffer string str source src

    sprintf(buf, "%d%c%d=%d\n", 10, '+', 34, 10+34);
    
    puts(buf);
    
    system("pause");
    return EXIT_SUCCESS;

    }

    // sscanf
    int main0602(void)
    {
    char buf[100] = { 0 }; //buffer string str source src

    int a, b, c;
    
    char str[] = "13+56=89";
    
    sscanf(str, "%d+%d=%d", &a, &b, &c);
    
    printf("a = %d\n", a);
    printf("b = %d\n", b);
    printf("c = %d\n", c);
    
    system("pause");
    return EXIT_SUCCESS;

    }

  • 07-字符串分割strtok.c

    int main0701(void)
    {
    char str[] = "www.itcast.cn.com.net"; // www itcast cn

    char *p = strtok(str, ".");  // 第一次拆分,参1 传 待拆分的原串。
    
    while (p != NULL)
    {
        p = strtok(NULL, ".");  // 第1+ 次拆分是,参1传 NULL.
    printf("%s\n", p);
    } system("pause"); return EXIT_SUCCESS;

    }

    int main0702(void)
    {
    char str[] = "www.itcast.cn$This is a strtok$test";

    char *p = strtok(str, "$ .");
    
    while (p != NULL)
    {
        p = strtok(NULL, ". $");
        printf("p = %s\n", p);
    }
    
    system("pause");
    return EXIT_SUCCESS;

    }

  • 08-atoi_atof_atol.c

    static int a = 1034673;

    void test1(void)
    {
    static int b = 0;

    printf("b = %d\n", b++);

    }

    int main0801(void)
    {
    char str[] = "abc345";
    int num = atoi(str);
    printf("num = %d\n", num);

    char str1[] = "     -10";
    int num1 = atoi(str1);
    printf("num1 = %d\n", num1);
    
    char str2[] = "0.123f";
    double num2 = atof(str2);
    printf("num2 = %.2lf\n", num2);
    
    char str3[] = "123L";
    long num3 = atol(str3);
    printf("num3 = %ld\n", num3);
    
    system("pause");
    return EXIT_SUCCESS;

    }

  • 09-局部变量.c

    void test1(void); // 全局函数声明

    int m = 4456;

    int main0901(void)
    {
    int i = 10903;

    for (size_t j = 0; j < 10; j++)
    {
        printf("j = %d\n", j);
        //test1();
    }
    printf("i 2 = %d\n", i);
    
    system("pause");
    return EXIT_SUCCESS;

    }

  • 10-申请堆空间.c

    int main1001(void)
    {
    //int arr[1000000] = {10, 20, 40};
    int *p = (int *)malloc(sizeof(int) * 10);
    //char *str = (char *)malloc(sizeof(char)*10);
    if (p == NULL)
    {
    printf("malloc error\n");
    return -1;
    }
    char *tmp = p; // 记录malloc返回的地址值。用于free

    // 写数据到 malloc 空间。
    for (size_t i = 0; i < 10; i++)
    {
        p[i] = i + 10;
    }
    // 读出malloc空间中的数据
    //for (size_t i = 0; i < 10; i++)
    //{
    //  printf("%d ", *(p+i));
    //}
    for (size_t i = 0; i < 10; i++)
    {
        printf("%d ", *p);
        p++;
    }
    
    // 释放申请的内存。
    free(tmp);
    p = NULL;
    
    system("pause");
    return EXIT_SUCCESS;

    }

  • 11-二级指针malloc空间.c

    int main(void)
    {
    int **p = malloc(sizeof(int *) * 3); // int **p ==> int *p[10]; ==> [ int *, int *, int * ]

    for (size_t i = 0; i < 3; i++)
    {
        p[i] = malloc(sizeof(int) * 5);
    }
    
    // 使用空间 -- 写
    for (size_t i = 0; i < 3; i++)
    {
        for (size_t j = 0; j < 5; j++)
        {
            p[i][j] = i + j;
        }
    }
    
    // 使用空间 -- 读
    for (size_t i = 0; i < 3; i++)
    {
        for (size_t j = 0; j < 5; j++)
        {
            printf("%d ", *(*(p+i)+j));  // p[i][j] == *(p+i)[j] == *(*(p+i)+j)
        }
        printf("\n");
    }
    
    // 释放空间时,应先释放内层空间。
    for (size_t i = 0; i < 3; i++)
    {
        free(p[i]); //*(p+i)
        p[i] = NULL;
    }
    // 释放外层空间
    free(p);
    p = NULL;
    
    system("pause");
    return EXIT_SUCCESS;

    }

Day09

  • 01-结构体定义及初始化.c

    #define _CRT_SECURE_NO_WARNINGS
    #include
    #include
    #include
    #include
    #include

    struct student {
    int age;
    char name[10];
    int num;
    }obj1, obj2;

    struct {
    int age;
    char name[10];
    int num;
    }obj, *obj4, obj5 = { 100, "abc", 666 };

    int main0102(void)
    {
    obj4 = &obj5;
    printf("%x\n", obj5.name[0]);

    (*obj4).age = 200;//obj4->age = 200;
    strcpy((*obj4).name,"200");
    (*obj4).num = 200;
    
    printf("age=%d, name=%s, num=%d\n", obj4->age, obj4->name, obj4->num);
    
    printf("age=%d, |%s|, num=%d\n", (&obj5)->age, (&obj5)->name, (&obj5)->num);
    
    system("pause");
    return EXIT_SUCCESS;

    }

    int main0101(void)
    {
    struct student stu = { 18, "afei", 97 };
    struct student stu2;

    stu2.age = 17;
    strcpy(stu2.name, "andy");//stu2.name = "andy";
    stu2.num = 99;
    
    printf("age = %d, name=%s, num= %d\n", stu2.age, stu2.name, stu2.num);
    printf("age = %d, name=%s, num= %d\n", stu.age, stu.name, stu.num);
    
    system("pause");
    return EXIT_SUCCESS;

    }

  • 02-结构体数组.c

    #define _CRT_SECURE_NO_WARNINGS
    #include
    #include
    #include
    #include
    #include

    struct student {
    int age;
    char name[10];
    int num;
    };

    int main02(void)
    {
    struct student arr[5] = { 10, "andy", 10 ,11, "lucy", 11 ,12, "lily", 12 ,13, "mike", 13 ,14, "marry", 14 };

    int n = sizeof(arr) / sizeof(arr[0]);
    int sum = 0;
    
    for (size_t i = 0; i < n; i++)
    {
        sum += arr[i].age;
    }
    printf("avg age = %d\n", sum / n);
    
    system("pause");
    return EXIT_SUCCESS;

    }

    int main0201(void)
    {
    struct student arr[5] = {
    { 10, "andy", 10 },
    { 11, "lucy", 11 },
    { 12, "lily", 12 },
    { 13, "mike", 13 },
    { 14, "marry", 14 }
    };

    int n = sizeof(arr) / sizeof(arr[0]);
    for (size_t i = 0; i < n; i++)
    {
        printf("age=%d, name=%s, num=%d\n", arr[i].age, arr[i].name, arr[i].num);
    }
    printf("\n");
    
    system("pause");
    return EXIT_SUCCESS;

    }

    int main0203(void)
    {
    struct student arr2[5] = {
    10, "andy", 10 ,
    11, "lucy", 11 ,
    12, "lily", 12 ,
    13, "mike", 13 ,
    14, "marry", 14
    };

    struct student arr[5] = {10, "andy", 10 ,11, "lucy", 11 ,12, "lily", 12 ,13, "mike", 13 ,14, "marry", 14};
    
    int n = sizeof(arr) / sizeof(arr[0]);
    
    for (size_t i = 0; i < n; i++)
    {
        printf("age=%d, name=%s, num=%d\n", arr[i].age, arr[i].name, arr[i].num);
    }
    printf("\n");
    
    system("pause");
    return EXIT_SUCCESS;

    }

    int main0202(void)
    {
    struct student arr[5];

    arr[0].age = 19;
    strcpy(arr[0].name, "1111");
    arr[0].num = 19;
    
    (*(arr+1)).age = 191;
    strcpy((*(arr + 1)).name, "2222");
    (*(arr + 1)).num = 192;
    
    (arr + 2)->age = 193;
    strcpy((arr + 2)->name, "333");
    (arr + 2)->num = 192;
    
    struct student *p = arr;
    
    (*(p + 3)).age = 194;
    strcpy((*(p + 3)).name, "444");
    (*(p + 3)).num = 192;
    
    (p + 4)->age = 196;
    strcpy((p + 4)->name, "444");
    (p + 4)->num = 192;
    
    int n = sizeof(arr) / sizeof(arr[0]);
    
    for (size_t i = 0; i < n; i++)
    {
        printf("age=%d, name=%s, num=%d\n", arr[i].age, arr[i].name, arr[i].num);
    }
    printf("\n");
    
    system("pause");
    return EXIT_SUCCESS;

    }

  • 03-结构体嵌套.c

    #define _CRT_SECURE_NO_WARNINGS
    #include
    #include
    #include
    #include
    #include

    struct person {
    int age;
    char name[10];
    };

    struct student {
    struct person man;
    int score;
    };

    int main0302(void)
    {
    struct student stu = { 18, 21, "BBB" };

    printf("age = %d\n", (&stu)->man.age);
    printf("name = %s\n", (&stu)->man.name);
    printf("score = %d\n", (&stu)->score);
    
    system("pause");
    return EXIT_SUCCESS;

    }

    int main0301(void)
    {
    struct student stu;

    stu.man.age = 16;
    strcpy(stu.man.name, "zhangsan");
    stu.score = 61;
    
    printf("age = %d\n", (&stu)->man.age);
    printf("name = %s\n", (&stu)->man.name);
    printf("score = %d\n", (&stu)->score);
    
    struct student *p = &stu;
    
    p->man.age = 18;
    
    strcpy(p->man.name, "AAA");
    p->score = 100;
    
    printf("age = %d\n", (*p).man.age);
    printf("name = %s\n", (&(p->man))->name);
    printf("score = %d\n", p->score);
    
    system("pause");
    return EXIT_SUCCESS;

    }

  • 04-结构体做函数参数.c

    #define _CRT_SECURE_NO_WARNINGS
    #include
    #include
    #include
    #include
    #include

    struct student
    {
    int age;
    char name[10];
    int score;
    short num;
    };

    void func(struct student stu)
    {
    printf("func stu: age = %d, name= %s\n", stu.age, stu.name);
    printf("func stu: score = %d, num= %d\n", stu.score, stu.num);

    stu.age = 100;
    strcpy(stu.name, "super man");
    stu.num = 666;
    stu.score = 101;
    
    printf("2 func stu: age = %d, name= %s\n", stu.age, stu.name);
    printf("2 func stu: score = %d, num= %d\n", stu.score, stu.num);

    }

    void func2(struct student *stu)
    {
    printf("func stu: age = %d, name= %s\n", stu->age, stu->name);
    printf("func stu: score = %d, num= %d\n", stu->score, stu->num);

    stu->age = 100;
    strcpy(stu->name, "super man");
    stu->num = 666;
    stu->score = 101;
    
    printf("2 func stu: age = %d, name= %s\n", stu->age, stu->name);
    printf("2 func stu: score = %d, num= %d\n", stu->score, stu->num);

    }

    struct student func3(struct student stu)
    {
    printf("func stu: age = %d, name= %s\n", stu.age, stu.name);
    printf("func stu: score = %d, num= %d\n", stu.score, stu.num);

    stu.age = 100;
    strcpy(stu.name, "super man");
    stu.num = 666;
    stu.score = 101;
    
    printf("2 func stu: age = %d, name= %s\n", stu.age, stu.name);
    printf("2 func stu: score = %d, num= %d\n", stu.score, stu.num);
    
    return stu;

    }

    int main0401(void)
    {
    struct student stu1 = {15, "ABC", 67, 99};
    struct student stu2 = stu1;

    //func(stu2);       // 实参 给 形参 赋值
    //func2(&stu2);
    
    stu2 = func3(stu2);
    
    printf("stu2: age = %d, name= %s\n", stu2.age, stu2.name);
    printf("stu2: score = %d, num= %d\n", stu2.score, stu2.num);
    
    system("pause");
    return EXIT_SUCCESS;

    }

  • 05-含有指针成员的结构体.c

    #define _CRT_SECURE_NO_WARNINGS
    #include
    #include
    #include
    #include
    #include

    struct student {
    int age;
    char *name; // char name[10]; // 栈
    int num;
    };

    void init_struct(struct student **p)
    {
    *p = malloc(sizeof(struct student)); // 先申请外层
    if (p == NULL) { printf("malloc error"); return ; } (p)->age = 10;
    (p)->name = malloc(sizeof(char)10); // 再申请内层
    strcpy((p)->name, "hello"); (p)->num = 100;
    }

    int main0503(void)
    {
    struct student *p = NULL;
    p = malloc(sizeof(struct student)); // 先申请外层空间

    p->age = 100;
    p->name = malloc(sizeof(char)*10);      // 再申请内层空间
    strcpy(p->name, "world");
    p->num = 20;
    
    printf("age = %d, name=%s, num = %d\n", p->age, p->name, p->num);
    
    free(p->name);  // 先释放内层
    free(p);        // 再释放外层
    
    system("pause");
    return EXIT_SUCCESS;

    }

    int main0502(void)
    {
    struct student *p = NULL;

    init_struct(&p);
    printf("age = %d, name=%s, num = %d\n", p->age, p->name, p->num);
    
    free(p->name);  // 先释放内层
    free(p);        // 再释放外层
    
    system("pause");
    return EXIT_SUCCESS;

    }

    int main0501(void)
    {
    struct student stu;
    stu.age = 19;

    stu.name = malloc(sizeof(char) * 10);  // 堆
    
    strcpy(stu.name, "andy");  // stu.name  是 野指针。
    
    stu.num = 10;
    
    printf("age = %d, name= %s, num= %d\n", stu.age, stu.name, stu.num);
    
    free(stu.name);
    stu.name = NULL;
    
    system("pause");
    return EXIT_SUCCESS;

    }

  • 06-结构体数组作为函数参数.c

    #define _CRT_SECURE_NO_WARNINGS
    #include
    #include
    #include
    #include
    #include

    struct student {
    int age;
    char *name; // char name[10]; // ջ
    int num;
    };

    //void init_arr(struct student stu[5])
    //void init_arr(struct student stu[])
    void init_arr(struct student *stu, int n)
    {
    for (size_t i = 0; i < n; i++)
    {
    stu[i].age = i + 10;
    stu[i].name = malloc(10);
    strcpy(stu[i].name, "ABC");
    stu[i].num = i * 10;
    }
    }

    void print_arr(struct student *stu, int n)
    {
    for (size_t i = 0; i < n; i++)
    {
    printf("age = %d\n", stu[i].age);
    printf("name = %s\n", stu[i].name);
    printf("num = %d\n", stu[i].num);
    }
    }

    int main0601(void)
    {
    struct student stu[5];

    int n = sizeof(stu) / sizeof(stu[0]);
    
    init_arr(stu, n);
    print_arr(stu, n);
    
    for (size_t i = 0; i < n; i++)
    {
        free(stu[i].name);
    }
    
    system("pause");
    return EXIT_SUCCESS;

    }

  • 07-联合体.c

    #define _CRT_SECURE_NO_WARNINGS
    #include
    #include
    #include
    #include
    #include

    union test {
    char a;
    short b;
    int c;
    char str[13];
    };

    int main0701(void)
    {
    union test t1;

    t1.c = 0x87654321;
    
    printf("&t1 = %p\n", &t1);
    printf("&t1.a = %p\n", &(t1.a));
    printf("&t1.b = %p\n", &(t1.b));
    printf("&t1.c = %p\n", &(t1.c));
    
    printf("a = %x\n", t1.a);
    printf("b = %x\n", t1.b);
    printf("c = %x\n", t1.c);
    
    t1.b = 0x3A;
    
    printf("----------------\na = %x\n", t1.a);
    printf("b = %x\n", t1.b);
    printf("c = %x\n", t1.c);
    
    printf("sizeof(t1) = %u\n", sizeof(t1));
    
    system("pause");
    return EXIT_SUCCESS;

    }

  • 08-枚举.c

    #define _CRT_SECURE_NO_WARNINGS
    #include
    #include
    #include
    #include
    #include

    enum color { red, black, blue = 10, yellow, pink, green };

    int main08(void)
    {
    int flg = yellow;

    if (flg == 3)
        printf("flg = yellow\n");
    
    system("pause");
    return EXIT_SUCCESS;

    }

  • 09-typedef.c

    typedef long long int32;

    typedef struct student {
    int32 a;
    int32 b;
    int32 c;
    int32 d;
    int32 e;
    int32 f;
    }stu_t; // 给 struct student 类型起了一个别名: stu_t;

    int main09(void)
    {
    struct student stu;
    stu_t s1;

    s1.a = 10;
    s1.b = 20;
    
    system("pause");
    return EXIT_SUCCESS;

    }

Day10

共用体和联合体:

    union test {

        char ch;

        short sh;

        int var;
    };

    联合体,内部所有成员变量地址一致。等同于整个联合体的地址。

        联合体的大小,是内部成员变量中,最大的那个成员变量的大小。(对齐)

        修改其中任意一个成员变量的值,其他成员变量会随之修改。

枚  举:

    enum  color { 枚举常量 };

    enum  color { red, green, blue, black, pink, yellow };

         枚举常量: 是整型常量。不能是浮点数。可以是负值。 默认初值从 0 开始,后续常量较前一个常量 +1.

               可以给任意一个常量赋任意初值。后续常量较前一个常量 +1

-----------------------

读写文件与printf、scanf关联

    printf -- 屏幕 -- 标准输出

    scanf -- 键盘 -- 标准输入

    perror -- 屏幕 -- 标准错误

系统文件:

    标准输入 -- stdin -- 0

    标准输出 -- stdout -- 1

    标准错误 -- stderr -- 2

    应用程序启动时,自动被打开,程序执行结束时,自动被关闭。 ---- 隐式回收。

    1s = 1000ms 

    1ms = 1000us

    1us == 1000ns

文件指针和普通指针区别:

    FILE *fp = NULL;

    借助文件操作函数来改变 fp 为空、野指针的状况。   fopen();  --> 相当于 fp = malloc();

    操作文件, 使用文件读写函数来完成。 fputc、fgetc、fputs、fgets、fread、fwrite

文件分类:

    设备文件:

        屏幕、键盘、磁盘、网卡、声卡、显卡、扬声器...

    磁盘文件:

        文本文件:   ASCII

        二进制文件:  0101 二进制编码

文件操作一般步骤:

    1. 打开文件 fopen()  --》 FILE *fp;

    2. 读写文件 fputc、fgetc、fputs、fgets、fread、fwrite

    3. 关闭文件 fclose()  

打开、关闭文件函数:

    FILE * fopen(const char * filename, const char * mode);

        参1:待打开文件的文件名(访问路径)

        参2:文件打开权限:

            "r": 只读方式打开文件, 文件不存在,报错。存在,以只读方式打开。

            "w": 只写方式打开文件, 文件不存在,创建一个空文件。文件如果存在,清空并打开。

            "w+":读、写方式打开文件,文件不存在,创建一个空文件。文件如果存在,清空并打开。

            "r+":读、写方式打开文件, 文件不存在,报错。存在,以读写方式打开。

            "a": 以追加的方式打开文件。

            "b": 操作的文件是一个二进制文件(Windows)

        返回值:成功:返回打开文件的文件指针

            失败:NULL

    int fclose(FILE * stream);

        参1:打开文件的fp(fopen的返回值)

        返回值:成功 :0, 失败: -1;

文件访问路径:

    绝对路径:

        从系统磁盘的 根盘符开始,找到待访问的文件路径

        Windows书写方法:

            1)C:\\Users\\afei\\Desktop\\06-文件分类.avi

            2)C:/Users/afei/Desktop/06-文件分类.avi  --- 也使用于Linux。

    相对路径:

        1)如果在VS环境下,编译执行(Ctrl+F5),文件相对路径是指相对于 day10.vcxproj 所在目录位置。

        2)如果是双击 xxx.exe 文件执行,文件的相对路径是相对于 xxx.exe 所在目录位置。 

按字符写文件 fputc:

    int fputc(int ch, FILE * stream);

        参1:待写入的 字符

        参2:打开文件的fp(fopen的返回值)

        返回值: 成功: 写入文件中的字符对应的ASCII码

             失败: -1

    练习:写26个英文字符到文件中。

按字符读文件 fgetc

    int fgetc(FILE * stream);

        参1:待读取的文件fp(fopen的返回值)

        返回值: 成功:读到的字符对应的ASCII码

             失败: -1

    文本文件的结束标记: EOF ---》 -1 

feof()函数:

    int feof(FILE * stream);

        参1: fopen的返回值

        返回值: 到达文件结尾--》非0【真】

             没到达文件结尾--》0【假】

    作用:
        用来判断到达文件结尾。 既可以判断文本文件。也可以判断 二进制文件。

    特性:

        要想使用feof()检测文件结束标记,必须在该函数调用之前,使用读文件函数。

        feof()调用之前,必须有读文件函数调用。

fgets()函数:

    获取一个字符串, 以\n作为结束标记。自动添加 \0. 空间足够大 读\n, 空间不足舍弃\n, 必须有\0。

    char * fgets(char * str, int size, FILE * stream);

        char buf[10];   hello --> hello\n\0

        返回值: 成功: 读到的字符串

             失败: NULL

fputs()函数:

    写出一个字符串,如果字符串中没有\n, 不会写\n。

    int fputs(const char * str, FILE * stream);

        返回值: 成功: 0

             失败: -1

练习: 获取用户键盘输入,写入文件。

    假定:用户写入“:wq”终止接收用户输入,将之前的数据保存成一个文件。

    FILE *fp = fopen("test07.txt", "w");
    if (fp == NULL)
    {
        perror("fopen error");
        return -1;
    }
    char buf[4096] = {0};

    while (1)
    {
        fgets(buf, 4096, stdin);
        if (strcmp(buf, ":wq\n") == 0)   // 实际 fgets 读到的是“:wq\n”
        {
            break;
        }
        fputs(buf, fp);
    }

    fclose(fp);

练习: 文件版四则运算:

    1. 封装 write_file 函数,将4则运算表达式写入。

        FILE * fp = fopen("w");

        fputs("10/4=\n", fp);

        fputs("10+4=\n", fp);
        ....

        fputs("10*4=\n", fp);

    2. 封装 read_file 函数, 将4则运算表达式读出,拆分,运算,写回。

        1) 读出:

            FILE * fp = fopen("r");

            while (1) {

                fgets(buf, sizeof(buf), fp);    // buf中存储的 4则运算表达式
            }

        2) 拆分:

            sscanf(buf, "%d%c%c=\n", &a, &ch, &b);  // 得到运算数, 运算符

        3) 根据运算符,得到运算结果

            switch(ch) {

                case '+':
                    a+b;
            }

        4) 拼接 结果到  运算式 上

            char result[1024];

            sprintf(reuslt, "%d%c%d=%d\n", a, ch, b, a+b);      // reuslt 中包含带有结果的 运算式。

        5)将 多个带有结果的运算 拼接成一个字符串。

            char sum_ses[4096]; // 存总的字符串  -- "10/2=5\n10*3=30\n4+3=7\n8-6=2\n"

            strcat(sum_ses,reuslt);  // 在while中循环拼接

        6) 重新打开文件, 清空原有 4则运算表达式

            fclose(fp);

            fp = fopen("w");

        7) 将 拼接成一个字符串。写入到空的文件中

            fputs(sum_res);

10/2=    fgets(buf, 4096, 文件fp) --->"10/2=\n" --> 10   /   2   sscanf(buf, "%d%c%d=\n", &a, &c, &b);  -> a=10, b=2, c='/'
10*3=
4+3=
8-6=
        switch (c) {

            case '/':

                a / b;
                break;

            case '+':
                a + b;

                break;

            ....
        }

        fopen("", "w");

        char result[];   sprintf()/strcat()  --> "10/2=5\n10*3=30\n4+3=7\n8-6=2\n"  --> fputs(result, fp)
=====>

10/2=5
10*3=30
4+3=7
8-6=2
  • 01-联合体和枚举.c

    typedef union test {
    char ch;
    short sh;
    int a;
    }test_t;

    int main0101(void)
    {
    test_t obj;

    obj.a = 0x87654321;
    
    printf("&obj    = %p\n", &obj);
    printf("&obj.ch = %p\n", &obj.ch);
    printf("&obj.sh = %p\n", &obj.sh);
    printf("&obj.a  = %p\n", &obj.a);
    
    printf("sizeof(test_t) = %u\n", sizeof(test_t));
    
    printf("a  = 0x%x\n", obj.a);
    printf("sh = 0x%x\n", obj.sh);
    printf("ch = 0x%x\n", obj.ch);
    
    obj.ch = 0xFF;
    
    printf("a  = 0x%x\n", obj.a);
    printf("sh = 0x%x\n", obj.sh);
    printf("ch = 0x%x\n", obj.ch);
    
    system("pause");
    return EXIT_SUCCESS;

    }

    enum color { red, green = -5, blue, black, pink = 18, yellow };

    int main0102(void)
    {
    int flg = 2;

    // ......
    
    if (flg == blue)
    {
        printf("blue is 2\n");
    }
    else
    {
        printf("blue is not 2, blue = %d\n", blue);
    }
    printf("yellow = %d\n", yellow);
    
    system("pause");
    return EXIT_SUCCESS;

    }

  • 02-系统文件.c

    int main0201(void)
    {
    //fclose(stdout);

    printf("hello file\n");
    
    system("pause");
    return EXIT_SUCCESS;

    }

  • 03-文件的打开和关闭.c

    int main0301(void)
    {
    FILE *fp = NULL;

    fp = fopen("test2.txt", "w");
    if (fp == NULL)
    {
        perror("fopen error");  //printf("fopen error\n");  :xxxxxxx
        getchar();
        return -1;
    }
    
    fclose(fp);
    printf("------------finish\n");
    
    system("pause");
    return EXIT_SUCCESS;

    }

  • 04-fputc.c

    int main0401(void)
    {
    char *filename = "test04.txt";

    FILE *fp = fopen(filename, "w");
    if (fp == NULL)
    {
        perror("fopen error");
        return -1;
    }
    
    int ret = fputc('A', fp);
    
    printf("ret = %d\n", ret);
    
    fclose(fp);
    printf("---------------finish\n");
    
    system("pause");
    return EXIT_SUCCESS;

    }

    int main0402(void)
    {
    char *filename = "test04.txt";
    int ret = 0;

    FILE *fp = fopen(filename, "w");
    if (fp == NULL)
    {
        perror("fopen error");
        return -1;
    }
    char ch = 'a';
    
    while (ch <= 'z')
    {
        ret = fputc(ch, fp);
        if (ret == -1)
        {
            perror("fputc eror");
            return -1;
        }
        ch++;
    }
    
    system("pause");
    return EXIT_SUCCESS;

    }

    int main0403(void)
    {
    char *buf = "abcdefghijklmnopqrstuvwxyz";

    char *filename = "test04.txt";
    int ret = 0;
    
    FILE *fp = fopen(filename, "w");
    if (fp == NULL)
    {
        perror("fopen error");
        return -1;
    }
    int n = strlen(buf);
    for (size_t i = 0; i < n; i++)
    {
        ret = fputc(buf[i], fp);
        if (ret == -1)
        {
            perror("fputc eror");
            return -1;
        }
    }
    fclose(fp);
    
    system("pause");
    return EXIT_SUCCESS;

    }

  • 05-fgetc.c

    void write_file()
    {
    FILE *fp = fopen("05test.txt", "w");
    if (fp == NULL)
    {
    perror("fopen error");
    return ;
    }

    fputc('a', fp);
    fputc('b', fp);
    fputc('c', fp);
    fputc('d', fp);
    
    fclose(fp);

    }

    void read_file()
    {
    char ch = 0;

    FILE *fp = fopen("05test.txt", "r");
    if (fp == NULL)
    {
        perror("fopen error");
        return;
    }
    
    while (1)
    {
        ch = fgetc(fp);
        if (ch == EOF)
        {
            break;
        }
        printf("%d\n", ch);
    }
    
    fclose(fp);

    }

    int main0501(void)
    {
    //write_file();
    read_file();

    system("pause");
    return EXIT_SUCCESS;

    }

  • 06-feof函数.c

    void read_file06()
    {
    char ch = 0;

    FILE *fp = fopen("06test.txt", "r");
    if (fp == NULL)
    {
        perror("fopen error");
        return;
    }
    
    while (1)
    {
        ch = fgetc(fp);
    if (feof(fp))
    {
        break;
    }
    printf("%d\n", ch);
    } fclose(fp);

    }

    void test_feof()
    {
    FILE *fp = fopen("06test.txt", "r");
    if (fp == NULL)
    {
    perror("fopen error");
    return ;
    }
    while (1)
    {
    printf("没有到达文件结尾\n");
    fgetc(fp); // 一次读一个字符,读到字符直接丢弃。
    if (feof(fp))
    {
    break;
    }
    }
    fclose(fp);
    }
    void write_file06()
    {
    FILE *fp = fopen("06test.txt", "w");
    if (fp == NULL)
    {
    perror("fopen error");
    return;
    }
    fputc('a', fp);
    fputc('b', fp);
    fputc(-1, fp);
    fputc('c', fp);
    fputc('d', fp);
    fputc('\n', fp);

    fclose(fp);

    }

    int main0601(void)
    {
    //write_file06();
    //read_file06();
    test_feof();

    system("pause");
    return EXIT_SUCCESS;

    }

  • 07-fgets和fputs.c

    int main0701(void)
    {
    FILE *fp = fopen("test07.txt", "w");
    if (fp == NULL)
    {
    perror("fopen error");
    return -1;
    }
    char buf[4096] = {0};

    while (1)
    {
        fgets(buf, 4096, stdin);
        if (strcmp(buf, ":wq\n") == 0)
        {
            break;
        }
        fputs(buf, fp);
    }
    
    fclose(fp);
    
    system("pause");
    return EXIT_SUCCESS;

    }

  • 08-文件版4则运算.c

    void write_file08()
    {
    FILE *fp = fopen("test08.txt", "w");
    if (fp == NULL)
    {
    perror("fopen error");
    return;
    }

    fputs("10/2=\n", fp);
    fputs("10*3=\n", fp);
    fputs("4-2=\n", fp);
    fputs("10+2=\n", fp);
    
    fclose(fp);

    }

    int calc(char ch, int a, int b)
    {
    switch (ch)
    {
    case '/':
    return a / b;

    case '+':
        return a + b;
    
    case '-':
        return a - b;
    
    case '*':
        return a *b;
    default:
        break;
    }

    }

    void read_file08()
    {
    char buf[4096] = {0};
    char result[4096] = {0};

    char sum_res[4096] = {0};
    
    int a, b, ret;
    char ch;
    
    FILE *fp = fopen("test08.txt", "r");
    if (fp == NULL)
    {
        perror("fopen error");
        return;
    }
    
    while (1)
    {
        fgets(buf, 4096, fp);  //buf = "10/2=\n\0";
        if (feof(fp))
        {
            break;
        }
        sscanf(buf, "%d%c%d=\n", &a, &ch, &b);  // a:10, ch:'/' b: 2
    sprintf(result, "%d%c%d=%d\n", a, ch, b, calc(ch, a, b));  // 10 / 2 = 5;
    
    strcat(sum_res, result);
    } fclose(fp); // 将 只有表达式没有结果的文件关闭。 fp = fopen("test08.txt", "w"); // 清空 只有表达式没有结果的文件 if (fp == NULL) { perror("fopen error"); return; } fputs(sum_res, fp); // 将 既有表达式又有结果的字符串写到文件中。 fclose(fp);

    }

    int main(void)
    {
    write_file08();
    getchar();
    read_file08();

    system("pause");
    return EXIT_SUCCESS;

    }

Day11

printf --- sprintf --- fprintf: 

    变参函数:参数形参中 有“...”, 最后一个固参通常是格式描述串(包含格式匹配符), 函数的参数个数、类型、顺序由这个固参决定。

    printf("hello");

    printf("%s", "hello");

    printf("ret = %d+%d\n", 10, 5);

    printf("%d = %d%c%d\n", 10+5, 10, '+', 5);          --> 屏幕

    char buf[1024];   //缓冲区  

    sprintf(buf, "%d = %d%c%d\n", 10+5, 10, '+', 5);        --> buf 中

    FILE * fp = fopen();

    fprintf(fp, "%d = %d%c%d\n", 10+5, 10, '+', 5);         --> fp 对应的文件中

scanf --- sscanf --- fscanf

    scanf("%d", &m);        键盘 --> m

    char str[] = "98";

    sscanf(str, "%d", &m);      str --> m

    FILE * fp = fopen("r");

    fscanf(fp, "%d", &m);       fp指向的文件中 --> m

fprintf()函数:   ---> 将数据按指定的格式写进文件中

    写

    int fprintf(FILE * stream, const char * format, ...);

fscanf()函数:--->  从文件中读取指定格式的数据到内存中

    读

    int fscanf(FILE * stream, const char * format, ...);

        成功:正确匹配的个数。

        失败: -1

    1) 边界溢出。 存储读取的数据空间。在使用之前清空。

    2)fscanf函数,每次在调用时都会判断下一次调用是否匹配参数2, 如果不匹配提前结束读文件。(feof(fp) 为真)。

练习:文件版排序

    生成随机数,写入文件。将文件内乱序随机数读出,排好序再写回文件。

fgetc --- fputc

fgets --- fputs

fprintf -- fscanf        默认处理文本文件。

fwrite()函数:            既可处理以文本文件。也处理二进制文件。

    写出数据到文件中。

    stu_t stu[4] = { ...... };

    size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);

        参1:待写出的数据的地址

        参2:待写出数据的大小

        参3:写出的个数                -- 参2 x 参3 = 写出数据的总大小。

        参4:文件

        返回值: 成功:永远是 参3 的值。 --- 通常将参2 传 1. 将参3传实际写出字节数。

             失败:0 

fread()函数:

    从文件fp中读出数据。

    size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);

        参1:读取到的数据存储的位置

        参2:一次读取的字节数

        参3:读取的次数                -- 参2 x 参3 = 读出数据的总大小

        参4:文件

        返回值: 成功:参数3.    --- 通常将参2 传 1. 将参3传欲读出的字节数。             

             0:读失败 -- 到达文件结尾 -- feof(fp)为真。 

练习:大文件拷贝

    已知一个任意类型的文件,对该文件复制,产生一个相同的新文件。

    1. 打开两个文件, 一个“r”, 另一“w”

    2. 从r中 fread , fwrite到 w 文件中。

    3. 判断到达文件结尾 终止。  

    4. 关闭。

    注意: 在windows下,打开二进制文件(mp3、mp4、avi、jpg...)时需要使用“b”。如:“rb”、“wb”

随机位置 读:

    文件读写指针。在一个文件内只有一个。

    fseek():

        int fseek(FILE *stream, long offset, int whence);

            参1:文件

            参2:偏移量(矢量: + 向后, - 向前)

            参3: SEEK_SET:文件开头位置

                SEEK_CUR:当前位置

                SEEK_END:文件结尾位置

        返回值: 成功:0, 失败: -1

    ftell():

        获取文件读写指针位置。

        long ftell(FILE *stream);

        返回:从文件当前读写位置到起始位置的偏移量。

        借助 ftell(fp) + fseek(fp, 0, SEEK_END); 来获取文件大小。

    rewind():

        回卷文件读写指针。 将读写指针移动到起始位置。

        void rewind(FILE *stream);

Linux和windows文件区别:

    1)对于二进制文件操作, Windows 使用“b”, Linux下二进制和文本没区别。

    2)windows下,回车 \r, 换行 \n。 \r\n  , Linux下 回车换行\n

    3) 对文件指针,先写后读。windows和Linux效果一致。

               先读后写。Linux无需修改。windows下需要在写操作之前添加 fseek(fp, 0, SEEK_CUR); 来获取文件读写指针,使之生效。

获取文件状态:

    打开文件,对于系统而言,系统资源消耗较大。

    int stat(const char *path, struct stat *buf);

        参1: 访问文件的路径

        参2: 文件属性结构体

        返回值: 成功: 0, 失败: -1;

删除、重命名文件:

    int remove(const char *pathname); 删除文件。

    int rename(const char *oldpath, const char *newpath);  重名文件

缓冲区刷新:

    标准输出-- stdout -- 标准输出缓冲区。   写给屏幕的数据,都是先存缓冲区中,由缓冲区一次性刷新到物理设备(屏幕)

    标准输入 -- stdin -- 标准输入缓冲区。   从键盘读取的数据,直接读到 缓冲区中, 由缓冲区给程序提供数据。

    预读入、缓输出。

    行缓冲:printf(); 遇到\n就会将缓冲区中的数据刷新到物理设备上。

    全缓冲:文件。 缓冲区存满, 数据刷新到物理设备上。

    无缓冲:perror。 缓冲区中只要有数据,就立即刷新到物理设备。

    文件关闭时, 缓冲区会被自动刷新。  隐式回收:关闭文件、刷新缓冲区、释放malloc

    手动刷新缓冲区: 实时刷新。

        int fflush(FILE *stream);

            成功:0

            失败:-1
  • 01-sprintf 和 sscanf.c

    void write_file()
    {
    FILE *fp = fopen("abc.c", "w");
    if (!fp) // fp == NULL
    {
    perror("fopen error");
    return -1;
    }

    fprintf(fp, "%d\n", 10);
    fprintf(fp, "%d\n", 8);
    fprintf(fp, "%d\n", 6);
    
    fclose(fp);

    }

    void read_file()
    {
    int a;

    FILE *fp = fopen("abc.c", "r");
    if (!fp)  // fp == NULL
    {
        perror("fopen error");
        return -1;
    }
    
    fscanf(fp, "%d\n", &a);
    printf("%d\n" , a);
    
    fscanf(fp, "%d\n", &a);
    printf("%d\n", a);
    
    fscanf(fp, "%d\n", &a);
    printf("%d\n", a);
    
    a = 0;
    fscanf(fp, "%d\n", &a);
    printf("%d\n", a);
    
    fclose(fp);

    }

    // fscanf 循环读文件
    void read_file2()
    {
    int a;

    FILE *fp = fopen("abc.c", "r");
    if (!fp)  // fp == NULL
    {
        perror("fopen error");
        return -1;
    }
    while (1)
    {
        fscanf(fp, "%d\n", &a);  // 读
        printf("%d\n", a);
        if (feof(fp))       // 真-- 文件结尾
            break;
    }
    
    fclose(fp);

    }

    // fgets 循环读文件
    void read_file3()
    {
    char buf[1024];
    FILE *fp = fopen("abc.c", "r");
    if (!fp) // fp == NULL
    {
    perror("fopen error");
    return -1;
    }
    while (1)
    {
    memset(buf , 0, 1024);
    fgets(buf, 1024, fp);// 读 \n
    if (feof(fp)) // 真-- 文件结尾
    break;
    printf("%d\n", buf[0]);
    }

    fclose(fp);

    }

    int main0101(void)
    {
    //write_file();
    read_file3();

    system("pause");
    return EXIT_SUCCESS;

    }

    int main(void)
    {
    FILE *fp = fopen("test0101.txt", "r");
    if (!fp) // fp == NULL
    {
    perror("fopen error");
    return -1;
    }

    int a;
    char ch;
    char str[10];
    
    int ret = fscanf(fp, "%d %c %s", &a, &ch, str);
    printf("ret = %d\n", ret);
    
    fclose(fp);
    
    system("pause");
    return EXIT_SUCCESS;

    }

  • 02-文件版排序.c

    #include
    #include
    #include

    void write_rand()
    {
    FILE *fp = fopen("test02.txt", "w");
    if (!fp) // fp == NULL
    {
    perror("fopen error");
    return -1;
    }

    srand(time(NULL)); // 随机数种子
    
    for (size_t i = 0; i < 10; i++)
    {
        fprintf(fp, "%d\n", rand() % 100);  // 将生成的随机数写入文件
    }
    
    fclose(fp);

    }

    void BubbleSort(int * src, int len)
    {
    for (int i = 0; i < len - 1; i++) { for (int j = 0; j < len - 1 - i; j++) { if (src[j] > src[j + 1])
    {
    int temp = src[j];
    src[j] = src[j + 1];
    src[j + 1] = temp;
    }
    }
    }
    }

    void read_rand02()
    {
    int arr[10], i = 0;

    FILE *fp = fopen("test02.txt", "r");
    if (!fp)  // fp == NULL
    {
        perror("fopen error");
        return -1;
    }
    
    while (1)
    {
        fscanf(fp, "%d\n", &arr[i]);// 从文件中读取一个随机数,存入数组arr
        i++;
        if (feof(fp))               // 先存储,后判断,防止最后一个元素丢失
            break;
    }
    BubbleSort(arr, sizeof(arr)/sizeof(arr[0]));  // 对读取到的乱序数组排序
    
    fclose(fp);                         // 关闭文件
    fp = fopen("test02.txt", "w");      // 重新w方式打开文件, 清空原未排序文件。
    if (!fp)  // fp == NULL
    {
        perror("fopen error");
        return -1;
    }
    for (size_t i = 0; i < 10; i++)
        fprintf(fp, "%d\n", arr[i]);    // 写排好序的数组到文件
    
    fclose(fp);

    }

    int main0201(void)
    {
    write_rand();

    getchar();
    
    read_rand02();
    
    system("pause");
    return EXIT_SUCCESS;

    }

  • 03-fwrite 和 fread.c

    typedef struct student {
    int age;
    char name[10];
    int num;
    } stu_t;

    void write_struct()
    {
    stu_t stu[4] = {
    18, "afei", 10,
    20, "andy", 20,
    30, "lily", 30,
    16, "james", 40
    };

    FILE *fp = fopen("test03.txt", "w");
    if (!fp)
    {
        perror("fopen error");
        return -1;
    }
    
    int ret = fwrite(&stu[0], 1, sizeof(stu_t) * 4, fp);
    if (ret == 0)
    {
        perror("fwrite error");
        return -1;
    }
    
    printf("ret = %d\n", ret);
    
    fclose(fp);

    }

    // 一次读一个元素。
    void read_struct()
    {
    FILE *fp = fopen("test03.txt", "r");
    if (!fp)
    {
    perror("fopen error");
    return -1;
    }
    stu_t s1;

    int ret = fread(&s1, 1, sizeof(stu_t), fp);
    printf("ret = %d\n", ret);
    
    printf("age = %d, name=%s, num = %d\n", s1.age, s1.name, s1.num);
    
    fclose(fp);

    }

    // 读所有元素
    void read_struct2()
    {
    FILE *fp = fopen("test03.txt", "r");
    if (!fp)
    {
    perror("fopen error");
    return -1;
    }
    stu_t s1[10]; // stu_t *s1 = malloc(sizeof(stu_t) * 1024);
    int i = 0;
    while (1)
    {
    int ret = fread(&s1[i], 1, sizeof(stu_t), fp);
    //if (ret == 0) // 替代feof()函数来判断读到文件结尾。
    if (feof(fp))
    {
    break;
    }
    i++;
    printf("age = %d, name=%s, num = %d\n", s1[i].age, s1[i].name, s1[i].num);
    }
    fclose(fp);
    }

    int main0301(void)
    {
    //write_struct();
    read_struct2();

    system("pause");
    return EXIT_SUCCESS;

    }

  • 04-大文件拷贝.c

    void myfile_cp()
    {
    FILE *rfp = fopen("C:\itcast\08-fread函数.avi", "rb");
    FILE *wfp = fopen("C:\itcast\mycopy.avi", "wb");

    char buf[4096] = {0};  // 缓冲区。
    
    int ret = 0;
    
    while (1)
    {
        memset(buf, 0, sizeof(buf));
        ret = fread(buf, 1, sizeof(buf), rfp);
        if (ret == 0)
        {
            break;
        }
        printf("ret = %d\n", ret);
        fwrite(buf, 1, ret, wfp);
    }
    
    fclose(wfp);
    fclose(rfp);

    }

    int main0401(void)
    {
    myfile_cp();

    printf("---------------------finish\n");
    
    system("pause");
    return EXIT_SUCCESS;

    }

  • 05-随机读文件.c

    typedef struct student {
    int age;
    char name[10];
    int num;
    } stu_t;

    int main0501(void)
    {
    stu_t stu[4] = {
    18, "afei", 10,
    20, "andy", 20,
    30, "lily", 30,
    16, "james", 40
    };
    stu_t s1;

    FILE *fp = fopen("test05.txt", "wb+");
    if (!fp)  // fp == NULL
    {
        perror("fopen error");
        return -1;
    }
    int ret = fwrite(&stu[0], 1, sizeof(stu), fp);  // 以二进制形式写入,
    printf("ret = %d\n", ret);
    
    fseek(fp, sizeof(stu_t)*2, SEEK_SET);       // 从文件起始位置,向后偏移一个stu结构体
    
    ret = fread(&s1, 1, sizeof(s1), fp);
    printf("ret = %d\n", ret);
    
    printf("1 age= %d, name=%s, num=%d\n", s1.age, s1.name, s1.num);
    
    int len = ftell(fp); // 获取文件当前读写指针位置,到文件起始位置的偏移量。
    
    printf("len = %d\n", len);
    
    rewind(fp); // 将文件读写指针回卷到起始。
    
    ret = fread(&s1, 1, sizeof(s1), fp);
    
    printf("2 age= %d, name=%s, num=%d\n", s1.age, s1.name, s1.num);
    
    // 获取文件大小。
    fseek(fp, 0, SEEK_END); // 将文件读写指针放到文件结尾。
    len = ftell(fp);
    printf("文件大小为:%d\n", len);
    
    fclose(fp);
    
    system("pause");
    return EXIT_SUCCESS;

    }

    int main0502(void)
    {
    FILE *fp = fopen("test0501.txt", "w+"); // "r+"

    int ret = fputs("11111", fp);
    printf("ret 1 = %d\n", ret);        // 0 表示成功。
    
    ret = fputs("22222", fp);
    printf("ret 2 = %d\n", ret);
    
    ret = fputs("33333", fp);
    printf("ret 3 = %d\n", ret);
    
    char buf[1024] = { 0 };
    
    //fseek(fp, 5 * 2, SEEK_SET);  // 改变读写指针位置。
    rewind(fp); // 起始位置。
    char *ptr = fgets(buf, 1024, fp);
    if (ptr == NULL)
        printf("ptr == NULL \n");
    
    printf("fgets ptr = %s\n", ptr);
    printf("buf = %s\n", buf);
    
    fclose(fp);
    system("pause");
    return EXIT_SUCCESS;

    }

    #include
    #include
    #include

    int main0503(int argc, char *argv[])
    {
    FILE *fp = fopen("test1.txt", "r+");

    char buf[6] = { 0 };
    char *ptr = fgets(buf, 6, fp);
    
    printf("buf=%s, ptr=%s\n", ptr, buf);
    
    fseek(fp, 0, SEEK_CUR);
    int ret = fputs("AAAAA", fp);
    printf("ret = %d\n", ret);
    
    fclose(fp);
    
    system("pause");
    return 0;

    }

  • 06-获取文件属性-大小.c

    #define _CRT_SECURE_NO_WARNINGS
    #include
    #include
    #include
    #include
    #include

    #include
    #include

    /*
    FILE *fp = fopen("test05.txt", "r");

    fseek(fp, 0, SEEK_END);

    int len = ftell(fp);

    printf("文件大小:%d\n", len);

    fclose(fp);
    */

    int main0602(void)
    {
    struct stat buf;

    int ret = stat("test05.txt", &buf);  // 传出参数:在函数调用结束时,充当函数返回值。
    
    printf("文件大小:%d\n", buf.st_size); // 不打开文件,获取文件大小。
    
    system("pause");
    return EXIT_SUCCESS;

    }

  • 07-刷新缓冲区.c

    int main0701(void)
    {
    FILE *fp = fopen("test07.txt", "w+");
    if (!fp)
    {
    perror("fopen error");
    return -1;
    }
    char m = 0;

    while (1)
    {
        scanf("%c", &m);
        if (m == ':')
        {
            break;
        }
        fputc(m, fp);
        fflush(fp);  // 手动刷新文件缓冲到物理磁盘。
    }
    // 当文件关闭时,会自动刷新缓冲区。
    fclose(fp);
    
    system("pause");
    return EXIT_SUCCESS;

    }

Day12 -- 贪吃蛇游戏

  • 源文件 -- main.c

    #define _CRT_SECURE_NO_WARNINGS

    #include "snake.h" // 引入自定义头文件

    int main(void)
    {
    // 去除光标。
    CONSOLE_CURSOR_INFO cci;
    cci.dwSize = sizeof(cci);
    cci.bVisible = FALSE; // TRUE :
    SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cci);

    srand(time(NULL));  // 播种随机数种子。
    
    initSnake();    // 初始化蛇
    initFood();     // 初始化食物
    
    initWall();     // 画墙
    initUI();       // 画蛇和食物
    
    playGame();     // 启动游戏
    
    showScore();    // 打印分数
    
    system("pause");
    return EXIT_SUCCESS;

    }

    void showScore(void)
    {
    // 将光标默认位置移动至 不干扰游戏的任意位置。
    COORD coord;

    coord.X = 0;
    coord.Y = HIGH + 2;
    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
    
    printf("Game Over!!!\n");
    printf("成绩为:%d\n\n\n", score);

    }

    void initWall(void)
    {
    for (size_t i = 0; i <= HIGH; i++) // 多行
    {
    for (size_t j = 0; j <= WIDE; j++) // 一行中的多列
    {
    if (j == WIDE)
    {
    printf("|");
    }
    else if (i == HIGH)
    {
    printf("_");
    }
    else
    {
    printf(" ");
    }
    }
    printf("\n");
    }
    }

    void playGame(void)
    {
    char key = 'd';

    // 判断蛇撞墙
    while (snake.body[0].X >= 0 && snake.body[0].X < WIDE
        && snake.body[0].Y >= 0 && snake.body[0].Y < HIGH)
    {
        // 更新蛇
        initUI();
    // 接收用户按键输入  asdw
    if (_kbhit()) {             // 为真时,说明用户按下按键。
        key = _getch();
    }
    switch (key)
    {
    case 'w': kx = 0; ky = -1; break;
    case 's': kx = 0; ky = +1; break;
    case 'd': kx = +1; ky = 0; break;
    case 'a': kx = -1; ky = 0; break;
    default:
        break;
    }
    
    // 蛇头撞身体: 蛇头 == 任意一节身体
    for (size_t i = 1; i &lt; snake.size; i++)
    {
        if (snake.body[0].X == snake.body[i].X
            &amp;&amp; snake.body[0].Y == snake.body[i].Y)
        {
            return;     // 游戏结束。
        }
    }
    
    // 蛇头撞食物
    if (snake.body[0].X == food.X &amp;&amp; snake.body[0].Y == food.Y)
    {
        initFood();     // 食物消失
        snake.size++;   // 身体增长
        score += 10;    // 加分
    
        sleepSecond -= 100; // 加速
    }
    
    // 存储蛇尾坐标
    lastX = snake.body[snake.size - 1].X;
    lastY = snake.body[snake.size - 1].Y;
    
    // 蛇移动,前一节身体给后一节身体赋值。
    for (size_t i = snake.size - 1; i &gt; 0; i--)
    {
        snake.body[i].X = snake.body[i - 1].X;
        snake.body[i].Y = snake.body[i - 1].Y;
    }
    snake.body[0].X += kx;      // 蛇头坐标根据用户按键,修改。
    snake.body[0].Y += ky;
    
    Sleep(sleepSecond);
    // 清屏
    //system("cls");
    } return;

    }

    // 定义初始化蛇函数
    void initSnake(void)
    {
    snake.size = 2;

    snake.body[0].X = WIDE / 2;     //蛇头初始化
    snake.body[0].Y = HIGH / 2;
    
    snake.body[1].X = WIDE / 2 - 1; // 蛇一节身体初始化
    snake.body[1].Y = HIGH / 2;
    
    return;

    }

    // 初始化界面控件
    void initUI(void)
    {
    COORD coord = {0}; // 光标移动的位置。

    // 画蛇
    for (size_t i = 0; i < snake.size; i++)
    {
        coord.X = snake.body[i].X;
        coord.Y = snake.body[i].Y;
        SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
    if (i == 0)
        putchar('@');
    else
        putchar('*');
    } // 去除蛇尾 coord.X = lastX; coord.Y = lastY; SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord); putchar(' '); // 画食物 coord.X = food.X; coord.Y = food.Y; SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord); putchar('#');

    }

    // 食物的初始化函数
    void initFood(void)
    {
    food.X = rand() % WIDE; // 0-59
    food.Y = rand() % HIGH; // 0-59
    return;
    }

  • 头文件 -- snake.h

    #ifndef SNAKE_H
    #define SNAKE_H

    #include
    #include
    #include
    #include
    #include
    #include
    #include

    #define WIDE 60 // 宽度
    #define HIGH 20 // 高度

    // 一个身体的对象
    struct BODY {
    int X;
    int Y;
    };

    // 定义蛇对象
    struct SNAKE {
    struct BODY body[WIDE*HIGH];
    int size;
    }snake; // 一个蛇对象

                // 定义食物对象

    struct FOOD {
    int X;
    int Y;
    }food1; // 一个食物对象

    int score = 0; // 分数

    int kx = 0; // 用户按下 asdw 任意一个按键所得到的 坐标值。
    int ky = 0;

    int lastX = 0; // 蛇尾的坐标。
    int lastY = 0;

    int sleepSecond = 400;

    // 声明函数
    void initSnake(void);
    void initFood(void);
    void initUI(void);
    void playGame(void);
    void initWall(void);
    void showScore(void);

    #endif

Day13

vim 3 种工作模式:

    命令模式:

        使用所有输入都被vim当成命令看。

        i、a、o、s -- I、A、O、S

    文本模式(编辑模式):

        在该模式下编辑代码。

    末行模式:

        “:” 切换为末行模式。 

        w:保存。 q:退出。