当前位置:网站首页>Fundamentals of C language 13: file input / output
Fundamentals of C language 13: file input / output
2022-06-21 14:35:00 【jllws1】
Tips1:
function :fopen()、getc()、putc()、exit()、fclose() fprintf()、fscanf()、fgets()、fputs() rewind()、fseek()、ftell()、fflush() fgetpos()、fsetpos()、feof()、ferror() ungetc()、setvbuf()、fread()、fwrite()
How to use C standard I/O A series of functions deal with file mode and binary mode 、 Text and binary formats 、 Buffered and unbuffered I/O
Use functions that can access files sequentially or randomly
Tips2:
File operations
Files are an integral part of today's computer system . Files are used to store programs 、 file 、 Count According to the 、 letter 、 form 、 graphics 、 Photo 、 Video and many other kinds of information . As a programmer , Must be able to write programs to create files and read and write data from files . This chapter will introduce relevant contents .
13.1 Communicate with files
Sometimes , The program needs to read information from the file or write information to the file . This form of interaction between program and file is file redirection ( The first 8 Chapter introduced ). This method is very simple , But there are certain limitations . for example , Suppose you want to write an interactive program , Ask the user for the title of the book and save the complete list of book titles in a file . If redirection is used , It should be similar to :
books > bklist
User input is redirected to bklist in . Doing so will not only write unqualified text into bklist, And users can't see what questions to answer . C Provides a more powerful method of file communication , You can open the file in the program , Then use special I/O Function to read or write information in a file . Before studying these methods , First briefly introduce the nature of the file .
13.1.1 What is the file
file (file) A named section of storage, usually on a disk or solid state drive . For us ,stdio.h Is the name of a file , This file contains some useful information . However , For the operating system , The file is more complex . for example , Large files are stored separately , Or include some additional data , It is convenient for the operating system to determine the type of files . However , These are all operations What the system cares about , Programmers are concerned about C How the program handles files ( Unless you're writing an operating system ).
C Think of a file as a series of consecutive bytes , Each byte can be read separately . This is related to UNIX Environment (C The birthplace of ) The file structure corresponds to . Because other environments may not be able to fully match this model ,C Two file modes are available : Text mode and binary mode .
explain : The previous data is single , A file can be thought of as a named collection of contiguous data , Each byte can be read
13.1.2 Text mode and binary mode
First , Distinguish Text content and binary content 、 Text file format and binary file format , And the text mode and binary mode of the file .
The contents of all files are in binary form (0 or 1) Store . however , If the file originally uses binary encoded characters ( for example , ASCII or Unicode) For text ( It's like C String that sample ), This file is a text file , It contains text . If the binary values in the file represent machine language code or numerical data ( Use the same internal representation , hypothesis , be used for long or double Type value ) Or picture or music coding , This file is a binary file , It contains binary content .
explain : Files are stored in binary form , Such as 0x2f47386a( In hexadecimal 32 digit ), If Text in characters , It's a text file . For example, characters are used to represent the 32 digit , lookup ASCII code ,‘2f’=‘\',’47‘=’G‘,’38‘=’8‘( character 8),’6a‘=’j‘. So the characters are expressed as ’\G8j'. The content is the same , It's just that the representation is different , Hexadecimal 2 Bit represents a character .
UNIX Process the contents of text files and binary files in the same file format . No wonder , Whereas C As development UNIX Created with the tools of ,C and UNIX Use... In text \n( Line break operator ) Means line break .UNIX There is a count of file sizes in the directory , The program can use this count to determine whether the end of the file is read . However , Other systems already have other ways to deal with files , Dedicated to saving text . in other words , Other systems already have one that is similar to UNIX Different models Handle text files in the format of . for example , Former OS X Macintosh For documents \r ( A carriage return ) Represents a new line . In the early MS-DOS For documents \r\n The combination represents a new line , With embedded Ctrl+Z The character indicates the end of the file , Even if the actual file uses the method of adding empty characters to make its total size 256 Multiple ( stay Windows in ,Notepad Still build MS-DOS Format text file , But the new editor may use classes UNIX The format is mostly ). Other systems may keep the length of each line in the text file the same , If necessary, , Fill each line with empty characters , Keep its length consistent . perhaps , The system may mark the length of each line at the beginning of each line .
In order to standardize the processing of text files ,C Provides two ways to access files : Binary mode and text mode . In binary mode , The program can access every byte of the file . In text mode , What the program sees is different from the actual content of the document . When the program reads a file in text mode , Map the end of the line or the end of the file represented by the local environment to C Pattern . for example ,C The program is in the old style Macintosh When reading a file in text mode , Put... In the file \r convert to \n; When writing to a file in text mode , hold \n convert to \r. perhaps ,C Text mode program in MS-DOS When the platform reads the file , hold \r\n convert to \n; When writing a file , hold \n convert to \r\n. Text mode programs written in other environments do the same thing .
explain : When reading and writing files in binary mode and text mode , The content is different . The representation of newline character is different in the two modes , But these are well-defined , The programmer can select the mode , Write the program and still press C Language style , Reading will automatically convert
In addition to reading and writing text files in text mode , You can also read and write text files in binary mode . If you read and write an old style MS-DOS text file , The program will see... In the file \r and \n character , No mapping ( chart 13.1 Demonstrates some text ). If you want to write old style Mac Format 、MS-DOS Format or UNIX/Linux Format file mode program , You should use binary mode , In this way, the program can determine the actual file content and perform the corresponding action .

although C Provides binary mode and text mode , However, the implementation of these two modes can be Same as . As mentioned earlier , because UNIX Use a file format , These two modes are for UNIX Realization It's exactly the same .Linux So it is with .
13.1.3 I/O The level of
In addition to selecting the mode of the file , Most of the time , You can also choose I/O Two levels of ( There are two levels of handling file access ). Bottom I/O(low-level I/O) Use the basics provided by the operating system I/O service . Standard advanced I/O(standard high-level I/O) Use C Library's standard package and stdio.h Header file definition . Because there is no guarantee that all operating systems will use the same underlying I/O Model ,C Standards only support standards I/O package . Some implementations provide the underlying Libraries , however C The standard establishes a portable I/O Model , We mainly discuss these I/O. // Only the standards are discussed I/O
13.1.4 Standard document
C The program will open automatically 3 File , They're called standard inputs (standard input)、 standard output (standard output) And standard error output (standard error output). By default , Standard input is the common input device of the system , It's usually a keyboard ; Standard output and standard error output are common output devices of the system , Usually display screen . Usually , Standard input provides input to the program , It is getchar() and scanf() Documents used . Programs usually output to standard output , It is putchar()、puts() and printf() Documents used . The first 8 The redirection mentioned in this chapter treats other files as standard input or standard output . Standard error output provides a logically different place to send error messages . for example , If you use redirection, send the output to a file instead of the screen , Then the content sent to the standard error output will still be sent to the screen On . That's fine , Because if you send an error message to a file , You can only open the file to see .
13.2 standard I/O
And bottom I/O comparison , standard I/O In addition to being portable, the package has two benefits . First of all , standard I/O There are many specialized functions that simplify dealing with different I/O The problem of . for example ,printf() Put different forms The data of the terminal is converted into a string output corresponding to the terminal . second , Input and output are buffered . in other words , Transfer one large piece of information at a time instead of one byte of information ( Usually at least 512 byte ). for example , When the program reads a file , A piece of data is copied to the buffer ( A piece of intermediary storage area ). This buffer greatly increases the data transmission rate . The program can check the bytes in the buffer . Buffering is processed in the background , So people have the illusion of character by character access ( If you use the bottom layer I/O, Do most of the work by yourself ). Program listing 13.1 Demonstrates how to use standards I/O Read the number of characters in the file and statistics file . We will discuss program listings in the following sections 13.1 Some of the features in . The program uses command line arguments , If you are Windows user , After compilation, you must run the program in a command prompt window ; If you are Macintosh user , The easiest way is to use Terminal Compile and run the program in command line form . perhaps , As the first 11 Chapter , If in IDE Run the program in , have access to Xcode Of Product The menu provides command line parameters . Or you can use puts() and fgets() Function to replace the command line arguments to get the file name
Program listing 13.1 count.c Program
/* count.c -- Use standards I/O */
#include <stdio.h>
#include <stdlib.h> // Provide exit() The prototype of the
int main(int argc, char *argv [])
{
int ch; // When reading a file , Where each character is stored
FILE *fp; // “ The file pointer ”
unsigned long count = 0;
if (argc != 2)
{
printf("Usage: %s filename\n", argv[0]);
exit(EXIT_FAILURE);
}
if ((fp = fopen(argv[1], "r")) == NULL)
{
printf("Can't open %s\n", argv[1]);
exit(EXIT_FAILURE);
}
while ((ch = getc(fp)) != EOF)
{
putc(ch, stdout); // And putchar(ch); identical
count++;
}
fclose(fp);
printf("File %s has %lu characters\n", argv[1], count);
return 0;
}The program output is as follows ( There is a discrepancy with the book )
Usage: H:\C_Project\Test\Project1\Debug\Project1.exe filename
13.2.1 Check the command line parameters
First , Program listing 13.1 Program check in argc Value , See if there are command line parameters . without , The program will print a message and exit the program . character string argv[0] Is the name of the program call . Use... Explicitly argv[0] Not the program name , The description of the error message automatically changes with the executable name . This feature is like UNIX It is also convenient in an environment that allows a single file to have multiple filenames . however , Some operating systems may not recognize argv[0], So this usage is not completely portable .
exit() Function closes all open files and ends the program .exit() Parameters of are passed to some operating systems , Include UNIX、Linux、Windows and MS-DOS, For other programs to use . The usual practice is : Normal end of program delivery 0, An abnormally terminated program passes a non-zero value . Different The exit value of can be used to distinguish the different causes of program failure , This is also UNIX and DOS Programming is usually practice . however , Not all operating systems can recognize return values in the same range . therefore , C The standard specifies a minimum limit . In especial , Standard requirements 0 Or macro EXIT_SUCCESS Used to indicate that the program ended successfully , macro EXIT_FAILURE Used to indicate that the end program failed . These macros and exit() The prototypes are all located in stdlib.h Header file .
according to ANSI C The provisions of the , In the initial call main() Use in return With the call exit() The effect is the same . therefore , stay main(), The following statement :
return 0;
The same function as the following statement :
exit(0);
But be careful , We're talking about “ The initial call ”. If main() In a recursive program in ,exit() It will still terminate the program , however return Will only give control to the upper level of recursion , until The first level . then return End procedure .return and exit() Another difference is , Even in other functions ( except main() outside ) call exit() It can also end the whole process .
explain : A comparison of two sentences :
exit() Function to end the program directly ;
return 0 End the current call function ; If in main() Use in return 0; Indicates the end of the program
13.2.2 fopen() function
Continue parsing the program manifest 13.1, The program uses fopen() Function to open a file . This function is declared in stdio.h in . It's the first 1 The first parameter is the name of the file to be opened , More specifically, a string address containing the file name . The first 2 A parameter is a string , Specify the mode of the file to be opened . surface 13.1 Lists C Some patterns provided by the library .

explain :r: read-only ; w: Write or create new after emptying ; a: Add write or new... At the end of the file ;
r+: to update w+: Same as w; a+: Same as a // The difference between write mode and update mode is not obvious
Back plus b: Open in binary mode ;
Back plus x( limit w Use ):1. Open failed if the file already exists , Protect existing files from being emptied ;
2. For documents w+x When writing in the form of , Prevent other programs from accessing this file .
WX The benefits of mode writing : One is to protect existing files from being overwritten ; Second, access to other files is prohibited during writing .
image UNIX and Linux Such a system with only one file type , belt b Patterns of letters and without b The pattern of letters is the same
new C11 New with x The writing pattern of letters , It has more features than the previous write mode sex . First of all , If you open an existing file in a traditional write mode ,fopen() Will send this file The length of is truncated to 0, In this way, the contents of the file are lost . But use a belt x The writing pattern of letters , Even if fopen() operation failed , The contents of the original file will not be deleted . second , If circumstances permit , x The exclusive nature of mode prevents other programs or threads from accessing the file being opened .
Warning
If you use either "w" Pattern ( No x Letter ) Open an existing file , The contents of the file will be deleted , So that the program can start operating in a blank file . However , If tape is used x Any pattern of letters , Will not be able to open an existing file .
After the program successfully opens the file ,fopen() Will return the file pointer (file pointer), other I/O The function can use this pointer to specify the file . The file pointer ( In this case fp) The type of is pointing to FILE The pointer to ,FILE Is a definition in stdio.h Derived types in . The file pointer fp It doesn't point to the actual file , It points to a data object that contains file information , It contains the operation file of I/O The buffer information used by the function . because In the standard library I/O Functions use buffers , So they don't just have to know where the buffer is , Also know the extent to which the buffer is filled and which text to operate on Pieces of . standard I/O Based on this information, the function decides to fill or empty the buffer again if necessary .fp The data object pointed to contains this information ( The data object is a C structure , In the fourth 14 The chapter introduces ).
explain :fopen() Functions don't just mean opening a file , You can also create new files , And adding data at the end of the original file
13.2.3 getc() and putc() function
getc() and putc() Function and getchar() and putchar() Function similar to . The difference is , To tell getc() and putc() Which file does the function use . The following sentence means “ Get a character from standard input ”:
ch = getchar(); // amount to ch=getc(stdin);
However , The following sentence means “ from fp Get a character from the specified file ”:
ch = getc(fp); //getc() Function file format
A similar , The following sentence means “ Alphabet character ch Put in FILE The pointer fpout In the specified file ”:
putc(ch, fpout); //putc() Function file format
stay putc() Function's argument list , The first 1 The parameter to be written is a character , The first 2 The parameters are The file pointer .
Program listing 13.1 hold stdout As putc() Of the 2 Parameters .stdout As compared with standard output Associated file pointer , It's defined in stdio.h in , therefore putc(ch, stdout) And putchar(ch) It's the same thing . actually ,putchar() Generally through the function putc() To define . A similar ,getchar() also By using standard input getc() To define .
The definition code is as follows :
char getchar(void)
{
char ch;
ch=getc(stdin);
return ch;
}Why this example does not putchar() And want to use putc()? One reason is to introduce putc() Letter Count ; The second reason is , hold stdout Replace with other parameters , It's easy to rewrite this program into a file output .
13.2.4 End of file
A program that reads data from a file stops when it reads to the end of the file . How to tell the program that it has read the end of the file ? If getc() When the function reads a character, it is found to be the end of the file , It will return a special value EOF. therefore C The program will only find the end of the file when it reads beyond the end of the file ( Some other languages use a special function to test the end of the file before reading ,C Different language ). To avoid reading empty files , The entry condition loop should be used ( No do while loop ) File input . Whereas getc() ( And others C Input function ) The design of the , The program should try to read... Before entering the loop body . As shown in the following design :
// design paradigm #1
int ch; // use int Type of variable storage EOF
FILE * fp;
fp = fopen("wacky.txt", "r");
ch = getc(fp); // Get the initial input
while (ch != EOF)
{
putchar(ch); // Process input
ch = getc(fp); // Get the next input
}The above code can be simplified to :
// design paradigm #2
int ch;
FILE * fp;
fp = fopen("wacky.txt", "r");
while (( ch = getc(fp)) != EOF)
{
putchar(ch); // Process input
}
because ch = getc(fp) yes while Part of the test conditions , So the program reads the file before entering the loop body .
// Or you can simplify it a little bit :FILE * fp= fopen("wacky.txt", "r");
Other input functions will also use this processing scheme , They are An error signal will also be returned when reading to the end of the file (EOF or NULL The pointer ).
explain : Generation at the end of the file , When standard input , With the keyboard “Ctrl+z”, There is a null pointer or... At the end of other files EOF, These are artificially defined . Judgment at the end of the file : When the read character is EOF or NULL The pointer
13.2.5 fclose() function
fclose(fp) Function off fp Specified file , Refresh the buffer if necessary . For more formal procedures , You should check whether the file was successfully closed . If it's closed successfully ,fclose() The function returns 0, otherwise return EOF:
if (fclose(fp) != 0)
printf("Error in closing file %s\n", argv[1]);
If the disk is full 、 The mobile hard disk is removed or appears I/O error , Will cause a call to fclose() Function failed .
explain : The two red statements can be placed at the end of the file as standard statements .
13.2.6 Pointer to standard file
stdio.h Header file handle 3 A file pointer and 3 Associated with a standard file ,C The program will automatically open this 3 A standard file . As shown in the table 13.2 Shown :

These file pointers point to FILE The pointer to , So they can be used as a standard I/O The parameters of the function , Such as fclose(fp) Medium fp. Next , We use a program example to create a new file , And write content .
explain : When reading characters through the keyboard, it is equivalent to calling a function ch = getchar(); Which is the same thing as ch=getc(stdin); Also when using the display to output characters , amount to putchar(); That is to say putc(ch,stdout);----- When the implementation is defined ‘ch’ When
13.3 A simple file compression program
The following program example copies the selected data in one file to another file . This procedure Two files are opened at the same time , With "r" Mode opens a , With "w" Mode opens another . This procedure ( Program listing 13.2) To keep every 3 The... Of characters 1 Compress the number of characters 1 The contents of a file . Last , Store the compressed text in the 2 File . The first 2 The name of the first file is 1 Individual article Piece name plus .red suffix ( Here red representative reduced). Use command line arguments , Open multiple at the same time File , And adding a suffix to the original file name , Are very useful skills . This compression square The formula is finite , But it also has its uses ( It is easy to change the program to standard I/O Instead of the command line arguments, provide the file name ).
Program listing 13.2 reducto.c Program
// reducto.c – Compress the file into the original 1/3!
#include <stdio.h>
#include <stdlib.h> // Provide exit() The prototype of the
#include <string.h> // Provide strcpy()、strcat() The prototype of the
#define LEN 40
int main(int argc, char *argv [])
{
FILE *in, *out; // Declare two points to FILE The pointer to
int ch;
char name[LEN]; // Save output file name
int count = 0;
// Check the command line parameters
if (argc < 2)
{
fprintf(stderr, "Usage: %s filename\n", argv[0]);
exit(EXIT_FAILURE);
}
// Set input
if ((in = fopen(argv[1], "r")) == NULL)
{
fprintf(stderr, "I couldn't open the file \"%s\"\n",argv[1]);
exit(EXIT_FAILURE);
}
// Set output
strncpy(name, argv[1], LEN - 5); // Copy the file name
name[LEN - 5] = '\0';
strcat(name, ".red"); // Add... After the file name .red
if ((out = fopen(name, "w")) == NULL)
{ // Open the file in write mode
fprintf(stderr, "Can't create output file.\n");
exit(3);
}
// Copy the data
while ((ch = getc(in)) != EOF)
if (count++ % 3 == 0)
putc(ch, out);// Print 3 The... Of characters 1 Characters
// Finishing work
if (fclose(in) != 0 || fclose(out) != 0)
fprintf(stderr, "Error in closing files\n");
return 0;
}The program example demonstrates several programming techniques . Let's take a closer look at .
fprintf() and printf() similar , however fprintf() Of the 1 A parameter must be a file pointer . Used in program stderr The pointer sends the error message to the standard error ,C Standards usually do this .
//fprintf() Format of function :fprintf(stderr, "I couldn't open the file \"%s\"\n",argv[1]); Print content to the file pointed to by the file pointer , What's ahead stdout and stderr, It means to print to the screen
To construct a new output file name , The program uses strncpy() Put the name eddy Copy to array name in . Parameters LEN-5 by .red Space is reserved for suffixes and empty characters at the end . If argv[2] String ratio LEN-5 Long , You can't copy empty characters . When this happens , The program will add null characters . call strncpy() after ,name No 1 An empty character is calling strcat() Function time , By .red Of . Cover , Generated eddy.red. The program also checks whether the file named eddy.red The file of . This step is quite important in some environments , Because like strange.c.red Such a file name may be invalid . for example , In traditional DOS Environment , You cannot add a suffix after a suffix (MSDOS The method used is to use .red Replace existing suffix , therefore strange.c Will become strange.red. for example , It can be used strchr() Function positioning ( If any ), Then just copy the part in front of the point ).
//strncpy Limit on the number of copied strings : When the array length is zero LEN when , most LEN-1, Leave a blank character , Here we need to give .red Make room for , So the maximum number of copies is LEN-1-4=LEN-5 Characters . Then use this number as the index to give the null character
The program opens two files at the same time , So we want to state two FIFL The pointer . Be careful , Programs open and close each file separately . The number of files opened at the same time is limited , This limitation depends on the system and implementation , The scope is generally 10~20. The same file pointer can handle different file , Provided that these files do not need to be opened at the same time .
13.4 file I/O:fprintf()、fscanf()、fgets() and fputs()
Described in the previous chapter I/O Functions are similar to files I/O function . The main difference between them is , file I/O Function to use FILE Pointer specifies the file to be processed . And getc()、putc() similar , These functions require that you point to FILE The pointer to ( Such as ,stdout) Specify a file , Or use fopen() The return value of .
13.4.1 fprintf() and fscanf() function
file I/O function fprintf() and fscanf() The function works the same way as printf() and scanf() similar , The difference is that the former needs to use the second 1 A parameter specifies the file to be processed . We used it before fprintf(). Program listing 13.3 Demonstrates these two files I/O Functions and rewind() Function usage .
Program listing 13.3 addaword.c Program
/* addaword.c -- Use fprintf()、fscanf() and rewind() */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 41
int main(void)
{
FILE *fp;
char words[MAX];
if ((fp = fopen("wordy", "a+")) == NULL)
{
fprintf(stdout, "Can't open \"wordy\" file.\n");
exit(EXIT_FAILURE);
}
puts("Enter words to add to the file; press the #");
puts("key at the beginning of a line to terminate.");
while ((fscanf(stdin, "%40s", words) == 1) && (words[0] != '#'))
fprintf(fp, "%s\n", words);
puts("File contents:");
rewind(fp); /* Go back to the beginning of the file */
while (fscanf(fp, "%s", words) == 1)
puts(words);
puts("Done!");
if (fclose(fp) != 0)
fprintf(stderr, "Error closing file\n");
return 0;
}The program can add words to the file . Use "a+" Pattern , The program can read and write files . First use of the program , It will create wordy file , In order to put words in it . Then use the program , Can be in wordy Add the word after the file . although "a+" Mode only allows content to be added at the end of the file , But the whole file can be read in this mode .rewind() Function returns the program to the beginning of the file , convenient while Cycle through the contents of the entire file . Be careful ,rewind() Accept one File pointers as arguments .
As you can see ,fprintf() and fscanf() Working mode and printf() and scanf() similar . however , And putc() The difference is ,fprintf() and fscanf() All functions FILE Pointer as second 1 Parameters , Not the last parameter .
explain : Files have binary mode and text mode , All are ASCII Code form , therefore fprintf() and fscanf() Only strings are processed
13.4.2 fgets() and fputs() function
The first 11 The chapter introduced fgets() function . It's the first 1 Parameters and gets() The function is the same , It is also the address of the storage input location (char * type ); The first 2 The first parameter is an integer , Indicates the size of the string to be input [1]; The last parameter is the file pointer , Specify the file to be read . The following is an example of calling this function :
fgets(buf, STLEN, fp); here ,buf yes char The name of the type array ,STLEN It's the size of the string ,fp It's pointing FILE The pointer to . //fgets() Format of function
fgets() The function reads the input until the 1 After a line break , Or read to the end of the file , Or read STLEN-1 Characters ( On the surface of the above fgets() For example ). then ,fgets() Add an empty character at the end to make it a string . The size of a string is its number of characters plus a null character . If fgets() A whole line has been read before the upper character limit is read , It puts a newline character that represents the end of a line Put in front of empty characters .fgets() Function encountered EOF Will return NULL value , This mechanism can be used to check whether the end of the file is reached ; If you don't meet EOF The address passed to it is returned before .
//fgets() The return value of the function is the string it receives , stay s_gets() Function , Defined char *ret_val Receive its return value
explain :fgets() Function has an iterative version s_gets(), Enter a string from the screen , Just call it directly . Here we mainly look at reading from a file rather than inputting from the screen , Of course s_gets() The function can be modified to meet the requirements .
How to sort out fgets() function : It only specifies that a null character is added to the character after the specified length ,s_gets() The function handles the newline before the end , And exceed LEN after , Absorb extra characters .
fputs() The function takes two arguments : The first 1 One is the address of the string ; The first 2 One is a file pointer . This function writes the string found by the incoming address to the specified file . and puts() Functions are different , fputs() When printing a string, a newline character is not added at the end of it . The following is an example of calling this function :
fputs(buf, fp); //fputs(buf,stdout); Equivalent to no newline puts()
here ,buf It's the address of the string ,fp Used to specify the target file .
because fgets() Line breaks are preserved ,fputs() No more line breaks will be added , They cooperate very well . As the first 11 List of procedures in chapter 11.8 Shown , Even if the input line ratio STLEN Long , These two functions still work well .
Summary :getc() and putc() function : Handle character input and output , Pointer after ;fprintf() and fscanf() function : Format input and output , The pointer is in front of ;fgets() and fputs() function , Handle string input and output , Pointer after .
13.5 Random access :fseek() and ftell()
With fseek() function , You can think of the file as an array , stay fopen() Move the open file directly to any byte . We create a program ( Program listing 13.4) demonstration fseek() and ftell() Usage of . Be careful ,fseek() Yes 3 Parameters , return int Type value ;ftell() The function returns a individual long Type value , Represents the current location in the file .
explain :fopen() The file pointer obtained by the function is at the beginning of the file by default , If it is ‘a’ Pattern at the beginning ('a+','ab' etc. ) The default is at the end of the file , With fseek() function , You can move the pointer to any address in the file , The concept is very important . There's a front. rewind() Function can also be used fseek() Function substitution .
Program listing 13.4 reverse.c Program
/* reverse.c -- Display the contents of the file in reverse order */
#include <stdio.h>
#include <stdlib.h>
#define CNTL_Z '\032' /* DOS End of file mark in text file */
#define SLEN 81
int main(void)
{
char file[SLEN];
char ch;
FILE *fp;
long count, last;
puts("Enter the name of the file to be processed:");
scanf("%80s", file);
if ((fp = fopen(file, "rb")) == NULL)
{ /* read only mode */
printf("reverse can't open %s\n", file);
exit(EXIT_FAILURE);
}
fseek(fp, 0L, SEEK_END); /* Go to the end of the file */
last = ftell(fp);
for (count = 1L; count <= last; count++)
{
fseek(fp, -count, SEEK_END); /* Back off */
ch = getc(fp);
if (ch != CNTL_Z && ch != '\r') /* MS-DOS file */
putchar(ch);
}
putchar('\n');
fclose(fp);
return 0;
}// explain : Need to create a file , Replace with file name ‘if ((fp = fopen(file, "rb")) == NULL)’ Medium file, stay vs2019 The following is not yet perfect .
The program uses binary mode , To deal with MS-DOS The text and UNIX file . however , It may not work in environments that use text files in other formats .
Be careful If you run the program through the command line environment , The files to be processed should be in the same directory as the executable files ( Or folder ) in . If in IDE Run the program in , The specific search scheme sequence depends on the implementation different . for example , By default ,Microsoft Visual Studio 2012 Find... In the directory where the source code is located , and Xcode 4.6 Then look in the directory where the executable file is located .
Next , We need to discuss 3 A question :fseek() and ftell() How functions work 、 How to use binary streams 、 How to make the program portable .
13.5.1 fseek() and ftell() How it works
fseek() Of the 1 The parameters are FILE The pointer , Point to the file to be found ,fopen() Should have been hit Open the file .
fseek() Of the 2 One parameter is the offset (offset). This parameter represents the distance to be moved from the starting point ( See table 13.3 Starting point modes listed ). The parameter must be a long Type value , Can be positive ( Move forward )、 negative ( Move backward ) or 0( Keep still ).
fseek() Of the 3 The first parameter is the mode , This parameter determines the starting point . according to ANSI standard , stay stdio.h The header file specifies several explicit constants that represent patterns (manifest constant), As shown in the table 13.3 Shown .

Old implementations may lack these definitions , You can use numerical values 0L、1L、2L It means that 3 Kind of Pattern .L The suffix indicates that its value is long type . perhaps , Implementations may define these explicit constants in In other header files . If not sure , Please refer to the user manual or online help of the implementation .
Here is the call fseek() Some examples of functions ,fp Is a file pointer :
fseek(fp, 0L, SEEK_SET); // Navigate to the beginning of the file
fseek(fp, 10L, SEEK_SET); // Navigate to... In the file 10 Bytes
fseek(fp, 2L, SEEK_CUR); // Move forward from the current location of the file 2 Bytes
fseek(fp, 0L, SEEK_END); // Navigate to the end of the file
fseek(fp, -10L, SEEK_END); // Fallback from the end of the file 10 Bytes
There are some limitations to these calls , We'll discuss later .
If everything goes well ,fseek() The return value of is 0; If something goes wrong ( Such as the distance you try to move Beyond the scope of the file ), Its return value is -1. // Be careful fseek() The return value of the function
ftell() The return type of the function is long, It returns the current location .ANSI C Fix it The meaning lies in stdio.h in . In the initial implementation UNIX in ,ftell() Returns bytes from the beginning of the file Count to determine the location of the file . File first 1 The distance from the beginning of the file is 0, In this way PUSH .ANSI C Regulations , This definition applies to files opened in binary mode , Opening a file in file mode is different . This is also the program list 13.4 The reason for opening the file in binary mode .
below , Let's analyze the program list 13.4 The basic elements of .
First , The following statement : fseek(fp, 0L, SEEK_END);
Set the current location to the end of the file 0 Byte offset . in other words , This statement sets the current location at the end of the file . Next sentence :
last = ftell(fp);
Assign the number of bytes from the beginning of the file to the end of the file to last.
And then a for loop :
for (count = 1L; count <= last; count++)
{
fseek(fp, -count, SEEK_END); /* go backward */
ch = getc(fp);
}
The first 1 iteration , Locate the program at the end of the file 1 Characters ( namely , The last one in the file character ). then , The program prints this character . The next iteration locates the program to the previous character , And print the character . Repeat this process until you reach the... Of the file 1 Characters , And print .
13.5.2 Binary mode and text mode
The program list we designed 13.4 stay UNIX and MS-DOS Can be run in the environment .UNIX There is only one file format , So no special conversion is required . However MS-DOS Pay special attention to It means . many MS-DOS Editors use Ctrl+Z Mark the end of the text file . When opening such a file in text mode ,C Can recognize this character as the end mark of the file . however , In binary mode When you open the same file ,Ctrl+Z A character is treated as a character in a file , The actual end of the file is after this character . The end of the file may follow Ctrl+Z After the character , Or Wen Pieces may be filled with empty characters , Make the file size 256 Multiple . stay DOS No blank characters will be printed in the environment , Program listing 13.4 To prevent printing Ctrl+Z Character code .
Another difference between binary mode and text mode is :MS-DOS use \r\n The combination represents the line break of the text file . When opening the same file in text mode ,C The program put \r\n“ as ”\n. however , When you open the file in binary mode , The program can see these two characters . therefore , Program listing 13.4 Does not print... Is also included in \r Code for . Usually ,UNIX The text file has neither Ctrl+Z, either \r, So this part of the code will not affect most UNIX text file .
explain : The representation of the end of the file and the newline character is different between binary mode and text mode , yes , we have C Able to identify , Some cannot be identified , So there are some differences when writing code . In the program list 13.4 All of them reflect .
ftell() Functions work differently in text mode and binary mode . Many systematic documents The format of this document is the same as UNIX The models are very different , The number of bytes counted from the beginning of the file is For a meaningless value .ANSI C Regulations , For text mode ,ftell() The returned value can be by fseek() Of the 2 Parameters . about MS-DOS,ftell() Return value \r\n Count as a byte .
13.5.3 Portability
Theoretically ,fseek() and ftell() It should conform to UNIX Model . however , There are differences between different systems , Sometimes you really can't do it with UNIX The models are the same . therefore ,ANSI Reduced requirements for these functions . Here are some limitations .
In binary mode , The implementation does not have to support SEEK_END Pattern . Therefore, there is no guarantee that the program list 13.4 Portability of . A more portable method is to read the entire file byte by byte until the end of the file .C Preprocessor conditional compilation instructions ( The first 16 Chapter introduction ) A systematic method is provided to deal with this situation .
In text mode , Only the following calls guarantee their corresponding behavior .

however , Many common environments support more behaviors .
13.5.4 fgetpos() and fsetpos() function
fseek() and ftell() The potential problem is , They all limit the file size to long Within the range that the type can represent . Maybe 20 Gigabytes look quite large , But with the rapid growth of storage capacity , Files are getting bigger and bigger . In view of this ,ANSI C Added two new location functions to handle larger files :fgetpos() and fsetpos(). These two functions are not used long The value of type indicates the location , They use a new type :fpos_t( representative file position type, File location type ). fpos_t Types are not basic types , It is defined according to other types .fpos_t A variable or data object of type can specify a location in the file , It cannot be an array type , besides , There are no other restrictions . An implementation can provide a type that meets the requirements of a particular platform , for example ,fpos_t Can be implemented as a structure .
//fpos_t The type can be through typedef To define , such as long long unsigned int; Be similar to size_t You can find the definition, if any, in the header file , If not, you can define it yourself
ANSI C Defines how to use fpos_t type .
fgetpos() The prototype of the function is as follows :
int fgetpos(FILE * restrict stream, fpos_t * restrict pos);
When the function is called , It is the fpos_t The value of type is placed in pos Where it points to , This value describes A location in the file . If it works ,fgetpos() The function returns 0; If you fail , Return non 0.
fsetpos() The prototype of the function is as follows :
int fsetpos(FILE *stream, const fpos_t *pos);
When the function is called , Use pos Point to... In position fpos_t Type value to set the file pointer to the location specified by the value . If it works ,fsetpos() The function returns 0; If you fail , Then return to non 0. fpos_t The value of the type should be passed before calling. fgetpos() get .
// How to use :
FILE*fp = fopen(file, "rb") // Open a file
typedef long long unsigned int fpos_t;
fpos_t My_pos=0x23243dda0212da28; // Location in file
fgetpos(fp, &My_pos);
fsetpos(fp, &My_pos); // After execution fp Point to 0x23243dda0212da28 This position
explain : The above code is not verified
13.6 standard I/O Mechanism of
We learned the standard before I/O Package features , This section studies a typical conceptual model , Analytical criteria I/O How it works . Usually , Use standards I/O Of the 1 The next step is to call fopen() Open file ( As mentioned earlier ,C The program will open automatically 3 A standard document ).fopen() Function not only opens a file , It also creates a buffer ( In read-write mode, two buffers are created ) And a structure that contains file and buffer data . in addition ,fopen() Returns a pointer to the structure , So that other functions know how to find the structure . Suppose you assign this pointer to a pointer variable fp, We said fopen() function “ Open a stream ”. If you open the file in text mode , You get a text stream ; If you open the file in binary mode , You get a binary stream .
This structure usually contains a file location indicator that specifies the current position in the stream . In addition to this Outside , It also contains indicators of errors and the end of the file 、 A pointer to the beginning of the buffer 、 One File identifiers and a count ( Count the actual number of bytes copied into the buffer ).
We mainly consider file input . Usually , Use standards I/O Of the 2 The next step is to call a definition in stdio.h The input function in the , Such as fscanf()、getc() or fgets(). As soon as you call these functions , The data blocks in the file are copied to the buffer . The size of the buffer varies from implementation to implementation , It's usually 512 Byte or multiple of it , Such as 4096 or 16384( With the increasing capacity of computer hard disk , The size of the buffer is also getting larger and larger ). Initially call the function , In addition to filling the buffer , Also set fp The value in the structure pointed to . In particular, set the current position in the stream and the number of bytes copied into the buffer . Usually , The current position is from byte 0 Start .
After initializing structures and buffers , The input function reads data from the buffer as required . When it reads data , The file position indicator is set to point to the next character of the character just read . because stdio.h All input functions of the series use the same buffer , So calling any function will start from where the last function stopped .
When the input function finds that all characters in the buffer have been read , The next buffer size block is requested to be copied from the file to the buffer . In this way , The input function can read everything in the file , Until the end of the document . Function after reading the last character in the buffer , Set the end indicator to true . therefore , The next input function called will return EOF.
The output function writes data to the buffer in a similar way . When the buffer is full , The data will be copied to the file .
13.7 Other standards I/O function
ANSI Standards of the standard library I/O Series has dozens of functions . Although it is impossible to enumerate them here , But we will briefly introduce some , Let readers have a general understanding of them . Here are the letters The prototype of number , Indicates the parameter and return type of the function . The functions we're going to talk about , except setvbuf(), Other functions can be found in ANSI Used in previous implementations . Reference material V Of “ newly added C99 and C11 Standards for ANSI C library ” All are listed in ANSI C standard I/O package .
13.7.1 int ungetc(int c, FILE *fp)
function int ungetc() Function c Put the specified character back into the input stream . If you put a character back into the input flow , This character will be read the next time the standard input function is called ( See the picture 13.2). for example , Suppose you want to read Remove all characters before a colon , But not the colon itself , have access to getchar() or getc() The function reads characters to colons , And then use ungetc() Function returns the colon to the input stream . ANSI C The standard guarantees that only one character will be put back at a time . If the implementation allows multiple words in a line Character back into the input stream , Then the next time the input function reads the characters, the order is opposite to that when it is put back .

explain : Review how input queues come from , The initial input is placed in the buffer , When pressed enter Key to flush the buffer into the input sequence , then getchar() Take a character from the input sequence and give it to the variable ‘ch’. The input sequence shown in the figure above is from w Start , The second line uses the statement ch=getchar(); Now ch=‘w’, Input sequence comes ‘h’; The third line ungetc(ch,stdin); take w Put back the input sequence , At this time, the input sequence starts from w Start , If you execute the statement again ch=getchar(); here ‘ch’ It's equal to ‘w’.
extend : From this, I can think of whether I can use ungetc() Function to modify, for example, the content before a character in a string , Later I thought about it because I was not sure if I could , But with a pointer, you can .
13.7.2 int fflush() function
fflush() The prototype of the function is as follows :
int fflush(FILE *fp);
call fflush() Function causes all unwritten data in the output buffer to be sent to fp Specified output file . This process is called Refresh buffer . If fp Is a null pointer , All output buffers are flushed . Use... In the input stream fflush() The effect of the function is undefined . As long as the last operation is not an input operation , You can use this function to update the stream ( Any read-write mode ).
explain : Can only be used in an output stream , If the previous operation was fputs(),putc() etc. , Write file pointer *FILE Specified file
13.7.3 int setvbuf() function
setvbuf() The prototype of the function is :
int setvbuf(FILE * restrict fp, char * restrict buf, int mode, size_t size);
setvbuf() The function creates a standard I/O The buffer used by function replacement . After you open the file and before you do anything else with the stream , Call this function . The pointer fp Identify the stream to be processed ,buf Point to the storage area to be used . If buf The value is not NULL, You must create a buffer . for example , Declare a statement that contains 1024 Character array , And pass the address of the array . However , If you put NULL As buf Value , This function allocates a buffer for itself . Variable size tell setvbuf() Size of array (size_t Is a derived integer type , The first 5 Chapter introduced ).mode The choices are as follows :_IOFBF Indicates full buffering ( Flush when buffer is full );_IOLBF Indicates line buffer ( stay When the buffer is full or a newline character is written );_IONBF No buffer . If the operation is successful , The function returns 0, Otherwise, a non-zero value is returned .
Suppose a program wants to store a data object , The size of each data object is 3000 byte . have access to setvbuf() Function to create a buffer , Its size is a multiple of the size of the data object .
explain :setvbuf() The function creates a buffer of its own , To replace the fopen() The one that was built .
13.7.4 Binary system I/O:fread() and fwrite()
Introduce fread() and fwrite() Function before , First, you need to know some background knowledge . The standards used before I/O Functions are all text oriented , Used to process characters and strings . How to save numerical data in a file ? use fprintf() Functions and %f Conversion instructions just save values as strings . for example , The following code :
double num = 1./3.;
fprintf(fp,"%f", num);
hold num Stored as 8 Characters :0.333333. Use %.2f The conversion instructions save it as 4 Characters :0.33, use %.12f Conversion instructions are saved as 14 Characters :0.333333333333. Changing the conversion description will change the amount of space required to store the value , It also causes different values to be stored . hold num Stored as 0.33 after , When reading a file, it cannot be restored to higher accuracy . General and said , fprintf() Convert numeric values to character data , This conversion may change the value .
explain : Same as before ,fprintf() Function even if %f,%d And so on , It is also converted into characters
To ensure that the values are consistent before and after storage , The most accurate way is to use the same bit combination as the computer to store . therefore ,double The value of type should be stored in a double The size of the unit . If the data is stored in a file in the representation used by the program , It is called storing data in binary form According to the . There is no conversion from numeric form to string . For standards I/O,fread() and fwrite The function is used to process data in binary form ( See the picture 13.3).
actually , All data is stored in binary form , Even hyphens are stored in binary representations of character codes . If all the data in the file is interpreted as character code , The file contains text data . If some or all of the data is interpreted as numerical data in binary form , The file contains binary data ( in addition , The files that represent machine language instructions with data are binary files ).// The following figures show the difference between binary storage data and string storage data

Data stored in binary form ( Upper figure )
With fprintf() Function to write data to a file , Although it is %d The format of , Still store as a string ( Upper figure )

With fwrite() Function to write data to a file ( Upper figure )
The use of binary and text is easily confused .ANSI C And many operating systems recognize two file formats : Binary and text . Can store or read information in the form of binary data or text data . You can open files in text format in binary mode , You can store text in a binary file . You can call getc() Copy files containing binary data . However , generally speaking , Use binary mode to store binary data in binary format file . Similarly , The most common is to open the text data in the text file in text format ( Usually, the files generated by the word processor are binary files , Because these files contain a lot of non text information , Such as font and format ).
explain :fread() and fwrite() The appearance of the function makes Files can accurately store data other than character data , Note that it should be opened in binary mode during storage .
13.7.5 size_t fwrite() function
fwrite() The prototype of the function is as follows :
size_t fwrite(const void * restrict ptr, size_t size, size_t nmemb,FILE * restrict fp);
fwrite() Function to write binary data to a file .size_t According to the standard C Type of type definition , It is sizeof The type returned by the operator , Usually unsigned int, But implementations can choose to use other types . The pointer ptr Is the address of the data block to be written .size Indicates the size of the data block to be written ( In bytes ),nmemb Indicates the number of data blocks to be written . Like any other function , fp Specify the file to be written . for example , To save a file of size 256 Byte data object ( All in all Group ), You can do this :
char buffer[256];
fwrite(buffer, 256, 1, fp);
The above call puts a piece 256 Bytes of data from buffer write file . // The format of the calling function
Take another example , To save a Contents 10 individual double An array of type values , You can do this :
double earnings[10];
fwrite(earnings, sizeof(double), 10, fp);
The above call will earnings The data in the array is written to the file , The data is divided into 10 block , Every piece is double Size .
Be careful fwrite() In the prototype const void * restrict ptr Statement .fwrite() One of the problems is , It's the first 1 Arguments are not of fixed type . for example , The first 1 In the first two examples buffer, Its type is pointing to char The pointer to ; And the first 2 In the first two examples earnings, Its type is pointing to double The pointer to . stay ANSI C In the function prototype , These actual parameters are converted to point to void Pointer type of , This pointer can be used as a general type pointer ( stay ANSI C Before , These parameters use char * type , You need to cast the arguments to char * type ).
fwrite() The function returns the number of items successfully written . Under normal circumstances , The return value is nmemb, But if there is a write error , The return value will be greater than nmemb Small .
13.7.6 size_t fread() function
size_t fread() The prototype of the function is as follows :
size_t fread(void * restrict ptr, size_t size, size_t nmemb,FILE * restrict fp);
fread() Function accepts arguments and fwrite() The same function . stay fread() Function ,ptr Is to be read Get the address of file data in memory ,fp Specify the file to be read . This function is used to read the fwrite() Data written to a file . for example , To restore the contents saved in the above example 10 individual double An array of type values , You can do this :
double earnings[10];
fread(earnings, sizeof (double), 10, fp);
This call puts 10 individual double The value of size is copied into earnings Array .
fread() Function returns the number of items successfully read . Under normal circumstances , The return value is nmemb, But if there is a read error or the end of the file is read , The return value will be greater than nmemb Small .
explain :fread() and fwrite() Functions can be understood as being in pairs
13.7.7 int feof(FILE *fp) and int ferror(FILE *fp) function
If the standard input function returns EOF, It usually indicates that the function has reached the end of the file . However , When a read error occurs , The function also returns EOF.feof() and ferror() The function is used to distinguish between these two cases . When the last input call detected the end of the file ,feof() The function returns a non-zero value , Otherwise return to 0. When there is an error in reading or writing ,ferror() The function returns a non-zero value , Otherwise, they will return return 0.
explain :feof() Function to determine the end of a file , When writing data, you can use .ferror() Function post judgment .
if(feof(fp))
{
fgets(str,LEN,fp)
}; // Put all the contents of the file into str[] In the array
if(ferror(fp))
printf("error!\n") // After reading and writing errors , Print error message
13.7.8 A program example
Next , We use a program example to illustrate the usage of these functions . The program appends the contents of a series of files to the end of another file . There is a problem with this program : How to send a file Deliver information . This can be done interactively or using command-line arguments , Let's start with an interactive approach . The design scheme of the program is listed below .
Summary : Operations on files , There are open or new files , Or add several patterns at the end .
After getting the file pointer , Can read and write characters , character string . If you want to read and write data in other formats , It needs to be opened in binary mode . All operations begin with a file pointer , The file pointer does not move itself , Need to call fseek() function . The file operation can be seen as the movement of the file pointer and the file read / write function . That's why , The processing of files is better in the form of characters
Binary mode and text mode , Some documents (dos,Unix) stay C There are some differences in language , The newline character is different from the end of the file , Different treatment is required ,C Language default processing text mode .
I feel that the operation of file pointer is a little clumsy , Only through for Cycle plus fseek() function , You also need to know the number in advance ftell() Function . There's nothing like p++ That kind of pointer form .
边栏推荐
- Qmetaobject:: connectslotsbyname: no matching signal for problem solving
- Qt-4-common classes and components
- Make word2vec for Bert model
- Chapter 3 - data link layer
- Viewing tcp/ip network communication from the sending of an email
- C2 hiding of traffic encryption
- Imitation B station web, app, background
- Subshell
- Chapter 5 - application layer
- Timing method of MATLAB program running
猜你喜欢
![Cool background shadow effect [second with layered feeling] [picture hover style]](/img/ca/d68f2cf9f9af7b9346032b2a6e120b.jpg)
Cool background shadow effect [second with layered feeling] [picture hover style]

Mr. Ali taught you how to use JMeter for pressure test (detailed drawing)

HSV color model and color component range in opencv

Why is epoll efficient?

kernel GDB

Chapter 2 - physical layer (I)

LINQ extension methods - any() vs. where() vs. exists() - LINQ extension methods - any() vs. where() vs. exists()

Compile time annotation automatically generates dataholder

Getting started with qt-1-ui

Numpy: basic package for high performance scientific computing & data analysis
随机推荐
Pyqt environment in pycharm
Design and implementation of object system in redis
Promotion guide for large enterprises: material preparation, PPT writing and on-site defense
Calculate subtotal of advertising business
Qt-5-multi window programming
Win10 install tensorflow
Numpy: basic package for high performance scientific computing & data analysis
[googolu] takeout rebate system - business domain name of KFC configuration applet
Vscade, open a folder or workspace... (file - > open folder) solution
JS hand tear pen test questions ~ not sorted out
Record the processing process of slow response of primary system
Clickhouse cluster installation has too many dry goods
. bash_ profile
Reasonably set the number of threads 【 rpm 】
Timing method of MATLAB program running
Color segmentation based on RGB difference method
How can an e-commerce system automatically cancel an order when it times out?
How is the network connected
Two of my essays
Teach you how to design interface automation test cases: extract interface information and analyze it