Why is my simple C program displaying garbage to stdout?

后端 未结 5 1501
你的背包
你的背包 2020-12-06 11:38

Consider the following simple C program that read a file into a buffer and displays that buffer to the console:

#include

main()
{
  FILE *fil         


        
相关标签:
5条回答
  • 2020-12-06 12:17

    You can use calloc instead of malloc to allocate memory that is already initialised. calloc takes on extra argument. It's useful for allocating arrays; the first parameter of calloc indicates the number of elements in the array that you would like to allocate memory for, and the second argument is the size of each element. Since the size of a char is always 1, we can just pass 1 as the second argument:

     buffer = calloc (fileLen + 1, 1);
    

    In C, there is no need to cast the return value of malloc or calloc. The above will ensure that the string will be null terminated even if the reading of file ended prematurely for whatever reason. calloc does take longer than malloc because it has to zero out all the memory you asked for before giving it to you.

    0 讨论(0)
  • 2020-12-06 12:28

    JesperE is correct regarding the nul-termination issue in your example, I'll just add that if you are processing text files it would be better to use fgets() or something similar as this will properly handle newline sequences across different platforms and will always nul-terminate the string for you. If you are really working with binary data then you don't want to use printf() to output the data as the printf functions expect strings and a nul byte in the data will cause truncation of the output.

    0 讨论(0)
  • 2020-12-06 12:30

    JesperE's approach will work, but you may be interested to know that there's an alternate way of handling this.

    You can always print a string of known length, even when there's no NUL-terminator, by providing the length to printf as the precision for the string field:

    printf("%.*s\n", fileLen, buffer);
    

    This allows you print the string without modifying the buffer.

    0 讨论(0)
  • 2020-12-06 12:31

    You need to NUL-terminate your string. Add

    buffer[fileLen] = 0;
    

    before printing it.

    0 讨论(0)
  • 2020-12-06 12:35

    Your approach to determine file size by seeking to the end of the file and then using ftell() is wrong:

    • If it is a text file, opened without "b" in the second parameter to the fopen() call, then ftell() may not tell you the number of characters that you can read from the file. For example, windows uses two bytes for end of line, but when read, it is one char. In fact, the return value of ftell() for streams opened in text mode is useful only in calls to fseek(), and not to determine file size.
    • If it is a binary file, opened with "b" in the second parameter to fopen(), then the C standard has this to say:

      Setting the file position indicator to end-of-file, as with fseek(file, 0, SEEK_END), has undefined behavior for a binary stream (because of possible trailing null characters) or for any stream with state-dependent encoding that does not assuredly end in the initial shift state.

    So, what you are doing isn't necessarily going to work in standard C. Your best bet is to use fread() to read, and if you happen to need more memory, use realloc(). Your system may provide mmap(), or may make guarantees about setting the file position indicator to end-of-file for binary streams—but relying on those is not portable.

    See also this C-FAQ: What's the difference between text and binary I/O?.

    0 讨论(0)
提交回复
热议问题