0
点赞
收藏
分享

微信扫一扫

C语言---文件操作

云上笔记 2022-04-26 阅读 63
c语言

宏替换

带参宏

预处理条件

#ifdef宏名

#ifndef宏名

#if表达式

#pragma once

文件操作

单个字符读写

字符串读写

格式化读写

二进制形式读写

指定位置读写

补充


预处理

代码执行之前的事情,命令以#开头

头文件

define是C语言的宏定义,本质是替换,会在预处理阶段对程序中所有出现的"宏名"的地方进行替换

宏替换

#define 宏名 内容 
#define PI 3.14159 
#define LAND 0

带参宏

定义

// #define 宏名(形参列表) 内容 
#define ADD(a,b) a+b 

例子

#include <stdio.h> 
// #define 宏名(形参列表) 内容 
#define ADD(a,b) a+b 
#define ADD1(a,b) (a+b) 
// 注意:没有参数类型 没有返回值 本质:替换 
​
int main() 
{ 
    int n = ADD(1,2); 
    printf("n = %d\n", n); 
    n = ADD(1, ADD(5, 6))*ADD(3, 4); 
    // 1+5+6*3+4 // 应该直接替换 
    // 1+11*3+4 // 不要这样做 
    printf("n = %d\n", n); 
    n = ADD1(1, ADD1(5, 6))*ADD1(3, 4); 
    printf("n = %d\n", n); 
    double d = ADD(1.223, 2.456); 
    printf("d = %lf\n", d); 
    return 0; 
}

预处理条件

#ifdef宏名

定义:

#ifdef 宏名 

代码块;

#endif

规则:

根据宏名是否定义,如果定义了,就会执行代码块直到endif,否则不执行代码块

例子

#include <stdio.h> 
#define AAA 1 
int main() 
{
    #ifdef AAA 
    printf("666666\n"); 
    #endif
    return 0; 
}
​
#include <stdio.h> 
#define AAA 1 
​
int main() 
{
    #ifdef AAA 
    printf("666666\n"); 
    #else
    printf("88888888\n"); 
    #endif
    /* 
    #ifdef 宏名 
    代码块; 
    #else
    代码块; 
    #endif
    */
    return 0; 
}

#ifndef宏名

语法:

#ifndef 宏名 

代码块;

#else

代码块;

#endif

规则:

根据宏名是否定义,如果没有定义,就会执行相应代码块直到endif,否则不执行代码块

例子

#include <stdio.h> 
// #define AAA 1
int main() 
{
    #ifndef AAA 
    printf("666666\n"); 
    #else
    printf("88888888\n"); 
    #endif
    /* 
    #ifndef 宏名 
    代码块; 
    #else
    代码块; 
    #endif
    */
    return 0; 
}
​
//有些代码只能执行一次,那么久可以使用这一套预处理来实现
#ifndef AAA 
#define AAA 
#endif 

#if表达式

语法:

#if(表达式)

代码块1;

#else

代码块2;

#endif

规则

如果表达式为真,就会执行代码块1,否则执行代码块2

#else和代码块2 可以没有

例子

#include <stdio.h> 
​
int main() 
{
    #if(1)
    printf("666666\n"); 
    #else
    printf("88888888\n"); 
    #endif
    return 0; 
}

#pragma once

#pragma once是编译器相关的,有的编译器支持,有的编译器不支持,具体情况请查看编译器API文档,不过大部分编译器都有这个预处理指令了

#pragma once是一个比较常用的C/C++预处理指令,只要在头文件的最开始加入这条预处理指令,就能够保证头文件只被编译一次

文件操作

文件的后缀名: .docx .txt .c .cpp .exe .bat .csv .....

名字.后缀

文件路径

  1. 相对路径: 从当前项目开始到目标文件

  2. 绝对路径: 从根目录开始到目标文件

路径+名字.后缀

单个字符读写

在main.c同一个文件夹下 创建test1.txt

// 单个字符读写 
void function1() 
{ 
    // 1 定义变量:文件 
    FILE* pfile = NULL; 
    char ch = 0; 
    
    // 2 打开文件 fopen参数: 文件路径,打开方式 
    pfile = fopen("test1.txt", "r"); 
    
    // 3 读取(文件==>程序) 
    // 获取一个字符 fgetc参数: 文件 
    ch = fgetc(pfile); 
    
    // 4 在控制台输出读取的字符 
    putchar(ch); 
    printf("\nch = %c\n", ch); 
    
    // 5 继续向后读取 
    putchar(fgetc(pfile)); 
    printf("\n%c\n", fgetc(pfile)); 
    // ==> 只需要调用方法 会自动向后读取 
    
    // 6 关闭文件
    fclose(pfile); 
    pfile = NULL; 
    
    // 7 重新打开文件 
    pfile = fopen("test1.txt", "w"); 
    
    // 8 将单个字符写入到文件(程序==>文件) 
    fputc('X', pfile); 
    // ==> 会清除原来的数据 重新写入 
    fputc('Y', pfile); 
    // ==> 第一次写入到关闭之前 会自动依次写入 
    
    // 9 关闭文件 
    fclose(pfile); 
    pfile = NULL; 
}

字符串读写

// 字符串读写 
void function2() 
{ 
    FILE* pfile = NULL; 
    char str[20] = {}; 
    pfile = fopen("test2.txt","r"); 
    // 字符串读取函数(文件==>程序) 
    // 参数: 存储目标,长度,资源文件 
    fgets(str, 5, pfile); 
    puts(str); 
    printf("%s\n", str); 
    // ==> 虽然是说5个 实际上'\0'会占据一个位置 
    fclose(pfile); 
    pfile = NULL; 
    pfile = fopen("test2.txt", "a"); // a:追加 
    char str1[10] = "hello"; 
    // 字符串输出函数(程序==>文件) 
    // 参数:资源,文件 
    fputs(str1, pfile) ; 
    fclose(pfile); 
    pfile = NULL; 
}

格式化读写

// 格式化读写 
void function3() 
{ 
    FILE* pfile; 
    int num0 = 100, num1 = 0; 
    float f0 = 1.2f, f1 = 0.0f; 
    char str0[10] = "123abc#", str1[10] = {}; 
    pfile = fopen("test3.txt", "w"); 
    // 程序==>文件 
    // 参数: 文件,格式,obj 
    fprintf(pfile, "%d,%f,%s", num0, f0, str0); 
    fclose(pfile); 
    pfile = NULL; 
    pfile = fopen("test3.txt", "r"); 
    // 文件==>程序 
    fscanf(pfile, "%d,%f,%s", &num1, &f1, &str1); 
    printf("%d , %f , %s\n", num1, f1, str1); 
    fclose(pfile); 
    pfile = NULL; 
}

二进制形式读写

// 二进制形式读写 
void function4() 
{ 
    FILE* pfile = NULL; 
    int arr0[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; 
    int arr1[10] = {}; 
    pfile = fopen("test4.txt", "wb"); 
    fwrite(arr0, sizeof(int), 10, pfile); 
    fclose(pfile); 
    pfile = NULL; 
    pfile = fopen("test4.txt", "rb"); 
    fread(arr1, sizeof(int), 10, pfile); 
    for (size_t i = 0; i < 10; i++) 
    { 
        printf("%d ", arr1[i]); 
    }
    fclose(pfile); 
    pfile = NULL; 
}

指定位置读写

// 指定位置读写 
void function5() 
{ 
    FILE* pfile = NULL; 
    char str[100] = {}; 
    //if (pfile = fopen("test5.txt","r")) 
    if ((pfile = fopen("test5.txt", "r")) != NULL) 
    { 
        printf("文件打开成功! \n"); 
    }
    else 
    { 
        printf("文件打开失败! \n"); 
    }
    // 正常读取: 
    putchar(fgetc(pfile)); 
    printf("\n"); 
    /*
    int fseek(FILE * _File,long _Offset,int _Origin); 
    #define SEEK_CUR 1 当前位置 
    #define SEEK_END 2 文件末尾 
    #define SEEK_SET 0 文件开头 
    */
    // fseek(pfile, 2, SEEK_SET); 
    fseek(pfile, -7, SEEK_END); 
    fgets(str, 5, pfile); 
    puts(str); 
    fclose(pfile); 
    pfile = NULL; 
}

补充

// 指定位置读写 
void function5() 
{ 
    FILE* pfile; 
    char str[100] = {}; 
    if ((pfile = fopen("test5.txt", "r")) != NULL) 
    { 
        printf("文件打开成功!\n"); 
    }
    else 
    { 
        printf("文件打开失败!\n"); 
    }
    // 正常读取 
    putchar(fgetc(pfile)); 
    putchar('\n'); 
    /*
    C 库函数 int fseek(FILE *stream, long int offset, int whence) 
    设置流 stream 的文件位置为给定的偏移 offset, 
    参数 offset 意味着从给定的 whence 位置查找的字节数。 
    参数: 
    stream -- 这是指向 FILE 对象的指针,该 FILE 对象标识了流。 
    offset -- 这是相对 whence 的偏移量,以字节为单位。 
    whence -- 这是表示开始添加偏移 offset 的位置。它一般指定为下列常量之一: 
    SEEK_SET 文件的开头 
    SEEK_CUR 文件指针的当前位置 
    SEEK_END 文件的末尾 
    #define SEEK_CUR 1 
    #define SEEK_END 2 
    #define SEEK_SET 0 
    返回值: 
    如果成功,则该函数返回零,否则返回非零值。 
    */
    fseek(pfile, 2, SEEK_END); //使文件指针指向指定位置 
    fgets(str, 6, pfile); 
    /*
    C 库函数 int ferror(FILE *stream) 测试给定流 stream 的错误标识符。 
    参数: 
    stream -- 这是指向 FILE 对象的指针,该 FILE 对象标识了流。 
    返回值: 
    如果设置了与流关联的错误标识符,该函数返回一个非零值,否则返回一个零值。 
    */
    if (ferror(pfile)) 
    { 
        printf("文件读取失败!\n"); 
    }
    else 
    { 
        printf("文件读取成功!\n"); 
    }
    // 打印读取的内容 
    puts(str); 
    /*
    描述
    C 库函数 void clearerr(FILE *stream) 清除给定流 stream 的文件结束和错误标识符。 
    参数
    stream -- 这是指向 FILE 对象的指针,该 FILE 对象标识了流。 
    返回值 
    这不会失败,且不会设置外部变量 errno, 
    但是如果它检测到它的参数不是一个有效的流,则返回 -1,并设置 errno 为 EBADF。 
    */
    clearerr(pfile); //清除读取/写入/ferror函数报错后出现错误的错误标志
    /*
    描述
    C 库函数 void rewind(FILE *stream) 设置文件位置为给定流 stream 的文件的开头。 
    参数
    stream -- 这是指向 FILE 对象的指针,该 FILE 对象标识了流。 
    返回值 
    该函数不返回任何值。 
    */
    rewind(pfile);//强制使文件指针指向文件开头 
    /*
    描述
    C 库函数 int feof(FILE *stream) 测试给定流 stream 的文件结束标识符。 
    参数
    stream -- 这是指向 FILE 对象的指针,该 FILE 对象标识了流。 
    返回值 
    当设置了与流关联的文件结束标识符时,该函数返回一个非零值,否则返回零。 
    */
    while (!feof(pfile)) //feof函数判断是否读到文件末尾 
    { 
        putchar(fgetc(pfile)); 
    }
    putchar('\n'); 
    if (fclose(pfile) == EOF) 
    { 
        printf("文件关闭失败!\n"); 
    }
    else 
    { 
        printf("文件关闭成功!\n"); 
    } 
} 
  1. 定义文件指针 FILE*file;

  2. open(“路径”,“打开方式”)打开文件

    • 文件的打开方式

    • “r”(只读) 为了输入数据,打开一个已存在的文本文件 出错

    • “w”(只写) 为了输出数据,打开一个文本文件 新建文件

    • “a”(追加) 向文本文件尾部添加数据 出错

    • “rb”(只读) 为了输入数据,打开一个已存在的二进制文件 出错

    • “wb”(只写) 为了输出数据,打开一个二进制文件 新建文件

    • “ab”(追加) 向二进制文件尾部添加数据 出错

    • “r+”(读写) 为了读和写,打开一个文本文件 出错

    • “w+”(读写) 为了读和写,打开一个文本文件 新建文件

    • “a+”(读写) 为了读和写,打开一个文本文件 出错

    • “rb+”(读写) 为了读和写,打开一个二进制文件 出错

    • “wb+”(读写) 为了读和写,打开一个二进制文件 新建文件

    • “ab+”(读写) 为了读和写,打开一个二进制文件 出错

  3. fclose()关闭文件

  4. fgetc(文件指针) 读取一个字符

  5. fputc(字符,文件指针) 写入一个字符

  6. fgets(字符指针,大小,文件指针) 读取一行字符,读n个

  7. fpust(字符串,文件指针) 写入一串字符

  8. fprintf(文件指针,"格式占位符...",变量...); 格式化写入文件

  9. fscanf(文件指针,“格式占位符...",变量...); 格式化读取以二进制方式读写数据,注意一定要加&

  10. fread(用来保存的字符数组,数据类型的大小,数据的个数,文件指针);从文件中获取格式化的数据

  11. fwrite(需要写进去字符数组, 数据类型的大小,数据的个数, 文件指针);向文件中写入数据

    • fseek(文件指针,偏移量,起始点); 移动文件指针偏移量为正数往后移动,负数往前移动起始点用0、1、2代替

    • 0(SEEK_SET)代表文件开始位置

    • 1(SEEK_CUR)代表当前位置

    • 2(SEEK_END )代表文件末尾位置

  12. ftell(文件指针) 获取文件指针的偏移量

  13. feof(文件指针) 判断文件指针是否读到末尾,读到了末尾返回真,反之假

备注:进行文件操作的时候,记得文件怎么写入的就怎么读出来,读写最好不要同时进行,注意你的操作和打开方式

举报

相关推荐

0 条评论