[C language inspector training camp 22nd day] C language operation file

foreword

In fact, the title of this blog should be the twenty-third day, because the inspector camp is about twenty-three days. The 12-day notes are all about the real problems of computer composition principles related to compilation. Due to the long time of studying the computer group, all the knowledge related to the computer group has been forgotten. The idea (difficult!!!) So I decided to skip the twenty-second day or come back to summarize the content of the twenty-second day after learning the relevant parts of the meter group.


The content introduced today is about the knowledge of computer operating systems.
insert image description here

1. Analysis of file operation principle

程序执行时就称为进程,进程运行过程中的数据均在内存中. When you need to store the calculated data, you need to use a file. In this way, after the program is started next time, the data can be read directly from the file. (Unlike our previous program, which required manual data entry for each run). 文件是指存储在外部介质(如磁盘、磁带)上的数据集合. Operating systems (Windows, Linux, Mac, etc.) manage data in units of files, as shown in the figure below.
insert image description here
The language handles the file as follows.

  • 缓冲文件系统: The system automatically creates a buffer for each file in use in the memory area. I/O with a buffered file system is called Advanced Disk I/O.
  • 非缓冲文件系统: The system does not automatically create a buffer of a certain size, but the program sets a buffer for each file. I/O with an unbuffered file system is called low-level I/O.

The buffer principle is introduced below.
The buffer is actually a section of memory space, which is divided into read buffer and write buffer. The three characteristics of the C language buffer are as follows.

  • (1) Full buffering: In this case, the actual I/O operation is performed after the standard V/O buffer is filled. A typical example of full buffering is reading and writing operations on disk files.
  • (2) Line buffering: In this case, when a newline character is encountered in input and output, a real V/O operation will be performed. At this time, the characters we input are stored in the buffer first, and the actual VO operation is performed when the Enter key is pressed to change the line. Typical representatives are standard input buffer (stdin) and standard output buffer (stdout).
  • (3) Without buffering: that is, without buffering, the standard error situation (stderr) is a typical representative, which allows the error message to be displayed directly as soon as possible ( 无需掌握,考研不考).

After opening a file, we will get a file pointer fp of type FILE*, and then operate on the file through the file pointer. FILE is a structure type, and its specific content is as follows:

struct _iobuf i
	char *_ptr;l/下一个要被读取的字符地址
	int_ont;//剩余的字符,若是输入缓冲区,则表示缓冲区中还有多少个字符未被读取
	char *_base;//缓冲区基地址
	int_flag; //读写状态标志位
	int _file;l/文件描述符int_charbuf;
	int_bufsiz;//缓冲区大小
	char *_tmpfname;
};
typedef struct _iobuf FILE;

FILE*fp;//在main.c 写了FILE*fo;然后ctrl+左键就可以跳转到上面的结构体类型定义位置

fp is a pointer variable pointing to a FILE type structure. You can make fp point to the structure variable of a certain file, so as to access the file through the file information in the structure variable.
The member variable names in the FILE structure under the Windows operating system are inconsistent with those in the FILE structure under the Linux operating system and Mac operating system, but the principles can be referred to each other.

2. File opening and closing actual combat

The fopen function is used to open the file specified by fname (file name) and returns a stream associated with the file. If an error occurs, fopen returns NULL. mode (mode) is used to determine the purpose of the file (such as input, output, etc.), the specific form is as follows:

FILE*fopen(const char *fname, const char *mode);
insert image description here

The fclose function is used to close the given file stream and free any buffers associated with the stream. When fclose executes successfully, it returns 0, otherwise it returns EOF. The specific form is as follows:

int fclose(FILE *stream);

The fputc function is used to output the value of the character ch to the file pointed to by fp. If the output is successful, it returns the output character; if the output fails, it returns EOF. The specific form is as follows:

int fputc(int ch, FILE*stream);

The fgetc function is used to read a character from the specified file, which must be opened for reading or reading and writing. If a character is successfully read, it is assigned to ch. If an end-of-file character is encountered, the end-of-file flag EOF is returned. The specific form is as follows:

int fgetc(FILE*stream);

Next, combine an example to see how to open and close a file.

#include <stdio.h>

//练习文件打开
int main() {
    
    
    FILE *fp;//定义一个FILE类型的指针变量
    fp=fopen("file.txt","r+");//打开文件
    if(NULL==fp)//判断文件是否打开失败了
    {
    
    
        perror("fopen");//perror帮忙定位失败原因
        return -1;
    }
    char c;
//    c=fgetc(fp);
//    printf("%c\n",c);
//    c=fgetc(fp);
//    printf("%c\n",c);
    while((c=fgetc(fp))!=EOF)//读取文件内的所有内容
    {
    
    
        printf("%c",c);
    }
    printf("\n");
    c=fputc('H',fp);
    if(-1==c)
    {
    
    
        perror("fputc");
        return -1;
    }
    fclose(fp);//关闭文件
    return 0;
}

insert image description here

The content before the colon is the string we write into the perror function, and the content after the colon is the reason for the failure of the function prompted by perror, 注意perror函数必须紧跟失败的函数,如果中间执行了printf这样的打印函数,那么perror 函数将提示Success,也就是没有错误,原因是每个库函数执行时都会修改错误码,一旦函数执行成功,错误码就会被改为零,而 perror函数是读取错误码来分析失败原因的. (Perror does not take the postgraduate entrance examination, it is to help you locate the reason for the failure of the file operation)
After the file is opened successfully, use the fgetc function to read each character of the file, and then print the entire file in a loop, 读到文件结尾时返回EOFso it can be determined by judging whether the return value is equal to EOF Determines whether end-of-file was read. Note that you need to fill in some content in the newly created file.txt file (in the same directory as the exe, pay attention to watch the video operation).

3. File read and write combat

3.1 fread&fwrite

The specific forms of the fread function and the fwrite function are as follows:

int fread(void *buffer, size_t size, size_t num, FILE *stream);
int fwrite(const void buffer, size_t size, size_t count,FILEstream);

Among them, buffer is a pointer. For fread, it is the storage address of the read data. For fwrite, it is the address of the output data (both refer to the starting address); size is the number of bytes to be read and written; count is the number of bytes to be read and written. How many size bytes of data items to read and write; fp is a file pointer; the return value of the fread function is the amount of content read, and the return value after fwrite is successfully written is the number of written objects.

#include <stdio.h>
#include <string.h>

int main() {
    
    
    char buf[20]="hello\nworld";
    FILE *fp;
    int ret;//存储函数的返回值
    //r+代表以文本方式打开文件
    fp=fopen("file.txt","rb+");
    if(NULL==fp)
    {
    
    
        perror("fopen");
        return -1;
    }
//    ret=fwrite(buf,sizeof(char),strlen(buf),fp);//把buf中的字符串写入文件
    char buf1[20]={
    
    0};
    ret=fread(buf1,sizeof(char),sizeof(buf1),fp);
    printf("%s\n",buf1);
    fclose(fp);
    return 0;
}

The fread and fwrite functions can both read and write files in text mode and read and write files in binary mode . When opening a file with "r+" (text mode) for reading and writing, the character string is written into the file. After writing, right-click the file and select properties (as shown in the figure below), and you will find that the size is 12 bytes.
insert image description here

This is because in the text mode, 向文本文件中写入"\n"时实际存入磁盘的是"\r\n"all interface calls are Windows system calls, which is determined by the underlying implementation of Windows (Mac and Linux will not). Of course, if you write in text, you must read it in text. When encountering "\r\n", the underlying interface will automatically convert to "\n", so when you use the fread function to read data again, you will still get "hello\nworld", a total of 11 bytes.
If the "r+" in the fopen function is changed to "rb+", that is, to the binary mode, then when we write 11 bytes to the disk, the disk actually stores 11 bytes. If you double-click to open the file at this time , then you will find that there is no line break, that is, helloworld is connected together, and there is no line break in the middle. The reason is that the txt text editor must encounter "\r\n" before performing line break operations.
insert image description here

I believe readers have understood the difference between text mode and binary mode at this time (there is no such problem under Mac and Linux operating systems). After writing "\n" in text mode, the disk will store "\r\n", and of course "\r\n" will be read in the form of "\n" when reading. After writing "\n" in binary mode, the disk stores "\n". There is no difference between the two in other respects. So how to avoid mistakes? If the content is written in text, it must be read in text; if it is written in binary, it must be read in binary and cannot be mixed! (Everyone mainly Just understand the difference between text files and binary files).

#include <stdio.h>

int main() {
    
    
    FILE* fp;
    int i=123456;
    int ret;
    fp=fopen("file.txt","rb+");//以rb+模式打开文件
    if(NULL==fp)
    {
    
    
        perror("fopen");
        return -1;
    }
    //向文件中写入整型数,如果我们双击打开文件会发现乱码,因为打开文件都是以字符格式去解析的
//    ret=fwrite(&i,sizeof(int),1,fp);
    i=0;
    fread(&i,sizeof(int),1,fp);
    printf("i=%d",i);
    fclose(fp);
    return 0;
}

In the above example, when writing integers and floating-point numbers, you must use binary mode, and you need to open the file in "rb+" mode. What is stored in the memory in binary mode is what is written into the file, which is consistent. For example, if the integer variable i is written, its value is 123456, and the memory is stored as 4 bytes, that is, Ox0001E240, then 4 bytes are written into the memory. At this time, double-click to open the file and see garbled characters, so an integer variable is also used to store it when reading.

3.2 fgets&fputs

The function fgets reads [num-1] characters from the given file stream and dumps them into str(string). fgets stops when it reaches the end of the line, and fgets returns str (string) on ​​success, NULL on failure, and NULL on end-of-file. Its specific form is as follows:

char *fgets(char str, int num, FILEstream);

The fputs function writes the character pointed to by str(string) to the given output stream. Returns a non-negative value on success and EOF on failure. Its specific form is as follows:

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

#include <stdio.h>

int main()
{
    
    
    char buf[20]={
    
    0};//用于存储读取数据
    FILE* fp;
    fp=fopen("file.txt","r+");//可读可写打开文件
    if(NULL==fp)
    {
    
    
        perror("fopen");
        return -1;
    }
    //一次读一行,读空文件
    while(fgets(buf,sizeof(buf),fp)!=NULL)//fgets读取到文件结束时返回NULL
    {
    
    
        printf("%s",buf);
    }
    return 0;
}

Using the fgets function, we can read one line of the file at a time, so that we can easily count the number of lines in the file. Note that when doing some computer-based test questions (the computer-based test uses fgets to read the standard input, because the gets part of the school computer test is not available. use), the buf used for the fgets
function cannot be too small (buf is greater than the length of the longest line), otherwise it may not be able to read "'\n", resulting in an error in line number statistics. The fputs function writes a string to the file, not An additional "\n" will be written, you don't need fputs, just master fwrite.

4. File position pointer offset actual combat

insert image description here
insert image description here
insert image description here

#include <stdio.h>
#include <string.h>
int main()
{
    
    
    FILE *fp;
    char str[20]="hello\nworld";
    int len=0;//用于保存字符串长度
    long pos;
    int ret;//接函数返回值
    fp =fopen("file.txt","r+");//打开文件
    if(NULL==fp)
    {
    
    
        perror("fopen");
        return -1;
    }
    len=strlen(str);
    fwrite(str,sizeof(char),len,fp);
    ret=fseek(fp,-5,SEEK_CUR);
    if(ret!=0)
    {
    
    
        perror("fseek");
        fclose(fp);
        return -1;
    }
    pos= ftell(fp);
    printf("now pos=%ld\n",pos);
    memset(str,0,sizeof(str));//清空str
    fread(str,sizeof(char),sizeof(str),fp);//读取
    printf("str=%s\n",str);
    return 0;
}

The final running effect is shown in Figure 1.
We wrote "hello \nworld" into the file, because it is in text mode, so the total is 12 bytes. After offsetting forward by 5 bytes through the fseek function, the position pointer obtained by the ftell function is from the beginning of the file. It is 7, then use the fread function to read the contents of the file, and the result is "world".
insert image description here


insert image description here

Guess you like

Origin blog.csdn.net/apple_51931783/article/details/129327415