character by character reading from a file in C
How to read text from a file into a dynamic array of characters? I found a way to count the number of characters in a file and create a dynamic array, but I can’t figure out how to assign characters to the elements of the array?
FILE *text; char* Str; int count = 0; char c; text = fopen("text.txt", "r"); while(c = (fgetc(text))!= EOF) { count ++; } Str = (char*)malloc(count * sizeof(char)); fclose(text);
Answer
To just do what you asked for, you would have to read the whole file again:
... // go back to the beginning fseek(text, 0L, SEEK_SET); // read ssize_t readsize = fread(Str, sizeof(char), count, text); if(readsize != count) { printf("woops - something bad happenedn"); } // do stuff with it // ... fclose(text);
But your string is not null terminated this way. That will get you in some trouble if you try to use some common string functions like strlen
.
To properly null terminate your string you would have to allocate space for one additional character and set that last one to ”:
... // allocate count + 1 (for the null terminator) Str = (char*)malloc((count + 1) * sizeof(char)); // go back to the beginning fseek(text, 0L, SEEK_SET); // read ssize_t readsize = fread(Str, sizeof(char), count, text); if(readsize != count) { printf("woops - something bad happenedn"); } // add null terminator Str[count] = ''; // do stuff with it // ... fclose(text);
Now if you want know the number of characters in the file without counting them one by one, you could get that number in a more efficient way:
... text = fopen("text.txt", "r"); // seek to the end of the file fseek(text, 0L, SEEK_END); // get your current position in that file count = ftell(text) // allocate count + 1 (for the null terminator) Str = (char*)malloc((count + 1) * sizeof(char)); ...
Now bring this in a more structured form:
// open file FILE *text = fopen("text.txt", "r"); // seek to the end of the file fseek(text, 0L, SEEK_END); // get your current position in that file ssize_t count = ftell(text) // allocate count + 1 (for the null terminator) char* Str = (char*)malloc((count + 1) * sizeof(char)); // go back to the beginning fseek(text, 0L, SEEK_SET); // read ssize_t readsize = fread(Str, sizeof(char), count, text); if(readsize != count) { printf("woops - something bad happenedn"); } fclose(text); // add null terminator Str[count] = ''; // do stuff with it // ...
Edit:
As Andrew Henle pointed out not every FILE
stream is seekable and you can’t even rely on being able to read the file again (or that the file has the same length/content when reading it again). Even though this is the accepted answer, if you don’t know in advance what kind of file stream you’re dealing with, his solution is definitely the way to go.