I am trying to learn how to dynamically allocate memory for very long lines when I'm reading a file. I search on here and web and I tried some code.
Firstly, here is my first non-dynamic code:
char line[256];
file = fopen(inputFileName, "r");
// Here, of course I checked file is opened or not.
while (fgets(line, sizeof(line), file)) {
// do some operations
}
// Closing operations
This works for me when I reading files. But here is line must be equal or less than 255 characters. So, I want to read for example 300 character length line from file.
I tried following code:
size_t maxl = 256;
//char line[256];
char *line = malloc(maxl * sizeof(char));
if(!line){
printf("Memory not allocated!!\n");
return -2;
}
file = fopen(inputFileName, "r");
while (fgets(line, sizeof(line), file)) {
while(line[strlen(line) - 1] != '\n' || line[strlen(line) - 1] != '\r'){
char *tmp = realloc (line, 2 * maxl);
//fgets(line, sizeof(line), file);
if (tmp) {
line = tmp;
maxl *= 2;
}
else{
printf("Not enough memory for this line!!\n");
return -3;
}
}
// do some operations
}
I tried to implement answers in this question actually: Reading a line from file in C, dynamically
But it always enter "Not enough memory" part of the code. So, what am I doing wrong?
Thank you already for your answers and advises.
Edit: Code is updated depend on first comments.
Edit 2: Code is always read same 3 characters from the file.
Imagine that the file is like:
abcdabcdabcd...
The line
variable is always "abc" even after re-allocation operation.
Here are some corrections you need to do:
char *tmp = realloc (line, 2 * maxl);
to char *tmp = realloc (line, 2 * maxl * sizeof(char);
(just a suggestion!).fseek(file,0,SEEK_SET);
will seek to the beginning of the file inputFileName
.sizeof(line)
will always be a constant value as you are computing the size of a character pointer, not the string length. So, change while (fgets(line, sizeof(line), file)) {
to while (fgets(line, maxl, file)) {
.//fgets(line, sizeof(line), file);
inside the if (tmp)
block because you would want to read the string from file again after reallocation.line[strlen(line) - 1] != '\n' || line[strlen(line) - 1] != '\r'
is logically incorrect. You may want to enter the loop only if the last character of the line
is neither '\n'
nor '\r'
. So you must use a &&
there instead of ||
.Here is the modified code:
size_t maxl = 256;
//char line[256];
char *line = malloc(maxl * sizeof(char));
if(!line){
printf("Memory not allocated!!\n");
return -2;
}
file = fopen(inputFileName, "r");
while (fgets(line, maxl, file)) {
while(line[strlen(line) - 1] != '\n' && line[strlen(line) - 1] != '\r'){
char *tmp = realloc (line, 2 * maxl * sizeof(char));
fseek(file,0,SEEK_SET); //or wherever you want to seek to
if (tmp) {
line = tmp;
maxl *= 2;
fgets(line, maxl, file);
}
else{
printf("Not enough memory for this line!!\n");
return -3;
}
}
printf("%s\n",line); //just to check
}
The problems in your code were:
sizeof(line)
number of characters only and not maxl
number of characters.if(tmp)
).Now, why that Not enough memory..
was printing?
It was because your loop was running multiple times and the reallocated memory size (maxl
value) was increasing like 256, 512, 1024, 2048, ..., 65536, ...
When this size becomes large enough for the compiler to deny reallocation, you had that error string printed. If you like, try to debug your version of the code or print the value of maxl
in each iteration of inner while
loop.