2

I'm having some trouble getting text into a char array. It worked fine when I set a static size for the array like

char speech[15000];

but that was inefficient so I tried using calloc instead. That made it stop working. The array exists at the right size, but nothing gets written in. Here's the relevant code. What am I doing wrong?

int main() {

FILE* inFile;
int i;
int count = 0;

printf("\nOpening file April_30_1789.txt\n");

inFile = fopen("./speeches/April_30_1789.txt", "r");

if(inFile == NULL) {
    printf("Could not find April_30_1789.txt\n");
    return -1;
}

char ch;

while((ch = fgetc(inFile) != EOF)) count++;

rewind(inFile);

int size = count;

printf("Size of the array is %d\n", size);

char *speech = (char *)malloc(size*sizeof(char) + 1*sizeof(char));

fscanf(inFile, "%s", speech);

printf("Closing the file.\n");
fclose(inFile);

printf("%s", speech);

printf("\n\nDone\n");

return 0;

}

Currently, this gives me

Opening file April_30_1789.txt
Size of the array is 8617
Closing the file.
Fellow-Citizens

Done
7
  • The internal file pointer is still pointing to the end of file. Commented Mar 27, 2014 at 19:33
  • using fseek move the file pointer to the 0th offset and initialize the count to 0 in the begining Commented Mar 27, 2014 at 19:36
  • Why do you think static allocation is inefficient when compared to dynamic allocation? Have you performed any tests to prove that? Or are you afraid of wasting memory when you have less than 15000 bytes to read? This question is weird because static allocation incurs less overhead than dynamic allocation. If anything, you'd want dynamic allocation to let your buffer grow as needed. Commented Mar 27, 2014 at 19:38
  • change &speech to speech. Commented Mar 27, 2014 at 19:39
  • @FilipeGonçalves Well, I have to use this program with text files of varying lengths, so I figured malloc/calloc would be better than a set number. Commented Mar 27, 2014 at 19:45

3 Answers 3

10

Possible duplicate of Reading the whole text file into a char array in C.


Your problem : fscanf with the "%s" format will read up to the first whitespace encountered.

Possible solution (error-checking is omitted for conciseness) :

#include <stdio.h>  /* printf */
#include <stdlib.h> /* fopen, fseek, ... */

char *buffer = NULL;
size_t size = 0;

/* Open your_file in read-only mode */
FILE *fp = fopen("your_file_name", "r");

/* Get the buffer size */
fseek(fp, 0, SEEK_END); /* Go to end of file */
size = ftell(fp); /* How many bytes did we pass ? */

/* Set position of stream to the beginning */
rewind(fp);

/* Allocate the buffer (no need to initialize it with calloc) */
buffer = malloc((size + 1) * sizeof(*buffer)); /* size + 1 byte for the \0 */

/* Read the file into the buffer */
fread(buffer, size, 1, fp); /* Read 1 chunk of size bytes from fp into buffer */

/* NULL-terminate the buffer */
buffer[size] = '\0';

/* Print it ! */
printf("%s\n", buffer);
Sign up to request clarification or add additional context in comments.

4 Comments

Well, this worked out really well. It looks cleaner than what I had before (never used fseek/fread before) and I may just stick with this. For future reference though, what was my original code doing wrong?
fscanf with the "%s" format will read up to the first whitespace encountered. For instance if I use your code to print my main.c file, only #include is actually printed.
Ah, that explains it. So if I had wanted to use my original code, I would just have to have it keep reading till EOF then, right?
You could use a loop, but since whitespaces are discarded, you would end up loosing your document's formatting. Using fread will keep the formatting. Oh and by the way, this line while((ch = fgetc(inFile) != EOF)) count++; should be rewritten as while((ch = fgetc(inFile)) != EOF) count++;.
1

Your file pointer inFile is pointing to end

I'd do something like following :

long lSize;

fseek( inFile , 0L , SEEK_END); //use the function instead
lSize = ftell( inFile );       // to know the file size
rewind( inFile );             // Now point to beginning 

char* speech = calloc( 1, lSize+1 );
if( speech )
{
    if( fread( speech , lSize, 1 , inFile) != 1)
    {
      fclose(inFile) ;
      free(speech); 
      exit(1);
    }
}

// Process the speech Here


fclose(inFile); 
free(speech); // Don't forget to free the allocated memory !

Comments

1

as pmg said while((ch = fgetc(inFile) != EOF)) count++; makes your file pointer point at the end, use rewind(FILE* fileptr); to return to beginning of file.

6 Comments

This seems to work, but it only worked for the first word of the text, which was "Fellow-Citizens". Would that be a problem in reading the text into the array or is it an error with printing the array?
@user2797058 Change fscanf(inFile, "%s", &speech); to fscanf(inFile, "%s", speech);
@FilipeGonçalves Whoops, forgot to mention that I already did. I'll update the OP. It still only prints out Fellow-Citizens
@nikolaMM94 It seems like the array is the correct size. Microsoft Word gave about the same number of characters that the variable count is reporting. If I did malloc right, it should be the right size
@nikolaMM94 Would this work? char speech = (char *)malloc(sizesizeof(char) + 1*sizeof(char)); This is what I have right now and it still gives only Fellow-Citizens
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.