Reputation: 13
I tried to get the file's content and put it into a string. When I run my program and I print the string I get the file's content with some weird characters afterward.
My code:
int size = 0;
char ch = 0;
char* content = 0;
FILE* fs = fopen(file, "r");
//getting file's content and put it into a string
while (ch != EOF)
{
ch = (char)fgetc(fs);
size++;
content = myRealloc(content, size);
content[size - 1] = ch;
}
printf("%s", content);
myRealloc:
char* myRealloc(char* array, int size)
{
char* temp = 0;
temp = realloc(array, size * sizeof(char));
return temp;
}
The file's content:
1,2,3,4
5,6,7,8
a,b,c,d
e,f,g,h
When I print:
1,2,3,4
5,6,7,8
a,b,c,d
e,f,g,h ²²²²ר─
Upvotes: 0
Views: 2779
Reputation: 16530
regarding:
printf("%s", content);
the code that filled in the contents of content
failed to NUL terminate that array of characters.
(and the allocated memory doesn't have enough room to append a NUL char)
so the call to printf()
will keep outputting characters until it finds a NUL char.
That is the underlying reason for the junk characters being output.
Upvotes: 0
Reputation: 4003
Your string is not null terminated. You need to allocate enough space to hold the last null character, something like temp = realloc(array, (size + 1) * sizeof(char));
and at the end do something like content[size] = '\0'
. However, using realloc
is probably the worst way to do what you're trying to do.
I'd use stat
to find the file's size, then use mmap
to map the file to memory and then malloc
to the size of the file, and then memcpy
to the malloc
ed memory. realloc
is evil, performance wise.
Here is an alternative that greatly outperforms the original code:
#include <stdlib.h>
#include <stdio.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc,char** argv){
if (argc != 2){
printf("Usage: %s {filename}\n",argv[0]);
return 1;
}
int fd = open(argv[1], O_RDONLY);
// @todo: check if fd is valid
struct stat st;
int ret = fstat(fd,&st);
// @todo: check ret
void* mapped_memory = mmap(NULL,st.st_size,PROT_READ,MAP_SHARED,fd,0);
// @todo: check mapped_memory that is not null
char* str = (char*)malloc(sizeof(char)*(st.st_size + 1));
// @todo: check that str is not null
memcpy(str,mapped_memory,st.st_size);
str[st.st_size] = '\0';
printf("%s",str);
free(str);
munmap(mapped_memory,st.st_size);
close(fd);
return 0;
}
Upvotes: 1
Reputation: 11921
The statement ch = (char)fgetc(fs);
in the loop also try to print EOF
, which you shouldn't.
Just Replace that block of code with
while ( (ch = fgetc(fs)) != EOF) { /* fetch the char & check the condition */
putchar(ch);
size++;
content = myRealloc(content, size);
content[size - 1] = ch;
}
size++;
content = myRealloc(content, size);
content[size - 1] = '\0';
print("%s", content);
Also check the manual page of fgetc()
it returns int
. So make ch
type as int
.
int fgetc(FILE *stream);
Also print("%s", content);
should be printf("%s", content);
unless you didn't define print()
.
Finally & most importantly once job is done, don't forgot to free the dynamically allocated memory by calling free()
function.
Upvotes: 1
Reputation: 177
Add the null terminated character at the end:
int size = 0;
int ch = 0;
char* content = 0;
FILE* fs = fopen(file, "r");
//getting file's content and put it into a string
while ((ch = fgetc(fs)) != EOF)
{
size++;
content = myRealloc(content, size);
content[size - 1] = (char)ch;
}
size++;
content = myRealloc(content, size);
content[size - 1] = '\0';
print("%s", content);
Edit: Also, as pointed out by @achal, you are trying to add the EOF character since when you read it you are already in the while loop. I modified my code accordingly.
Upvotes: 4