简体   繁体   中英

How do I read a text file and store its content into another string? C

I would like to copy the contents of "file.txt" into a string "buf". When I run the program, it seems to only print out the words "I love cake".

The contents of file.txt is below this line

Hi there how are you

do you like cake

I love cake

//Variable Declarations
char buf[256] = "";
char dest[256] = "";


//Check if the file exists
FILE* fp;
fopen_s(&fp ,"file.txt", "r");
if (fp != NULL) {
    printf("File has been opened\n");
}
else
{
    printf("File did not open\n");
}

while (!feof(fp)) 
{
    fgets(buf, 256, fp);
}


printf("%s\n", buf);

Read while (!feof(fp)) is always wrong .

Since you want to read the whole file at once, it is best to use fread , opening the file in read mode (non-binary):

FILE *fp = . . .;

fseek(fp, 0, SEEK_END);
long n = ftell(fp);
rewind(fp);

char *buf = malloc(n+1);
fread(fp, buf, 1, n);
buf[n] = 0;

fclose(fp);

Error handling omitted.

fgets stops after reading a newline or EOF. So you're writing into the same buffer all over again.

When you want to read and append lines into a fixed buffer, you need to keep track of the position in the buffer to append new characters and then the number of characters available after each addition. When you are reading lines from an input stream, you do NOT condition your read loop on while (!feof (file)) . (see: Why is while (?feof (file) ) always wrong? )

Instead, you either condition your read loop based on the return of the input function being used, or you loop continually, checking the return of the input function at the beginning of the loop and you break the loop when your input function returns EOF (or a read error you are not otherwise handling occurs) Both methods are essentially equivalent.

For your case of a 256 character buffer, you can simply declare the 256 character array for storage and then declare a pointer to the beginning of the array you will use to write new characters within the buffer advancing the pointer to the end of those written to prepare for the next read. When reading characters to add, you can only read up to the number of available characters that remain unused in your buffer. It doesn't matter whether you are using strcpy/strcat or simply reading characters into your buffer at the pointer location -- tracking the available characters that remain is the same.

The only caveat in computing the number of available characters that remain is you must reserve storage for the nul-terminating character. You only need one for the string your are building within your buffer, so it is added with the first string you add to your buffer.

When joining strings, you also need to consider how you will handle blank (empty) lines in your input file. Since they do not add to the strings you are joining, you can simply skip to the next line - unless you want to preserve them in the buffer.

When using a line-oriented read function like fgets() or POSIX getline() , you must also handle the '\n' read and included on each read. The simple way to handle the included '\n' when joining strings is to overwrite it with a ' ' (space) character to provide a space between adjacent strings in your buffer.

The last thing to consider is removing the final ' ' (space) from the end of your buffer when you exit your read loop. (the one that results from overwriting the '\n' with a ' ' ). Simply decrement the pointer you are using and overwrite the final ' ' with a nul-terminating character.

Putting it altogether, you could do something similar to:

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

#define MAXC 256    /* if you need a constant, #define one (or more) */

int main (void) {

    char buf[MAXC], *p = buf;   /* buffer and pointer to buffer  */
    size_t avail = MAXC;        /* character avaialble in buffer */

    while (fgets (p, avail, stdin)) {   /* read up to avail characters */
        size_t len = strlen(p);         /* get length read */
        if (*p == '\n')                 /* ignore blank lines in input */
            continue;
        if (len && p[len-1] == '\n')    /* overwrite \n with space */
            p[len-1] = ' ';
        p += len;                       /* advance len chars in buf */
        /* subtract len chars from avail (len + 1 chars 1st iteration) */
        avail -= (avail == MAXC) ? len + 1 : len;
    }
    if (*--p == ' ')    /* backup over space at end and nul-terminate */
        *p = 0;

    puts (buf);     /* output combined string */
}

( note: handling leading spaces, multiple intervening spaces, or trailing spaces is left to you)

Example Input Files

$ cat dat/cake.txt
Hi there how are you
do you like cake
I love cake

or a file with blank lines:

$ cat dat/cakedbl.txt
Hi there how are you

do you like cake

I love cake

Example Use/Output

Append all lines in file separated by a space up to MAXC - 1 characters (leaving room for the nul-termianting character).

$ ./bin/appendstr < dat/cake.txt
Hi there how are you do you like cake I love cake

The double-spaced file.

$ ./bin/appendstr < dat/cakedbl.txt
Hi there how are you do you like cake I love cake

Look things over and let me know if you have further questions. Rewrite the program using strcpy and strcat to join the strings. (you will find out it is basically a wash when using a single buffer). You can use separate buffers for reading and appending using the strcpy/strcat approach to simplify things, but the calculating of the available characters that remain will essentially be the same.

fgets will replace your old buffer with the new one, you have to put the next buffer in the next offset of your buffer pointer.

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

int main()
{
    //Variable Declarations
    char buf[256] = "";
    char dest[256] = "";
    char *ptr = buf;


    //Check if the file exists
    FILE* fp;
    fp = fopen("file.txt", "r");
    if (fp != NULL) {
        printf("File has been opened\n");
    }
    else
    {
        printf("File did not open\n");
    }

    while (!feof(fp)) 
    {
        fgets(ptr, 256, fp);
        ptr += strlen(ptr);
    }


    printf("%s\n", buf);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM