Reputation: 73
I've been searching on how to allocate a dynamic buffer using fgets
, but I can't seem to get it on this example. The file has two numbers of unknown length separated by a white-space. For every line it reads each character until ' '
and \n
and prints it.
char *ptr;
char line[MAX];
while(fgets(line, sizeof line , fp) != NULL){
ptr = line;
for(i=0; i<2; i++){
while(*ptr && (*ptr) != ' '){
if(*ptr == ' ')
break;
k = (*ptr) - '0';
if(k != -38) // wont print '\n'
printf("%d", k);
ptr++;
}
while(*ptr && (*ptr) != '\n') {
if(*ptr == ' '){
ptr++;
continue;
}
k = (*ptr) - '0';
printf("%d", k);
ptr++;
}
}
}
Can someone give me an idea on how to make
line
dynamic while still usingptr
that way?
Upvotes: 1
Views: 12876
Reputation: 518
On systems with glibc >= 2.7, or POSIX.1-2008 support, what I think you want can be accomplished using:
char *line;
while (fscanf(f, "%m[^\n]\n", &line) == 1) {
/* do stuff with line */
free(line);
}
This works great on my Linux systems, but over in the Windows universe, Microsoft Visual C++ supports neither %m, nor any equivalent that I can find.
Upvotes: 4
Reputation: 47925
I think what you want is something like this:
size_t linelen = 80;
char *line = malloc(linelen);
while(magic_reallocating_fgets(&line, &linelen, fp) != NULL) {
/* ... do whatever you want with line ... */
}
But then, of course, the $64,000 question is, what does magic_reallocating_fgets
look like? It's something like this:
char *magic_reallocating_fgets(char **bufp, size_t *sizep, FILE *fp) {
size_t len;
if(fgets(*bufp, *sizep, fp) == NULL) return NULL;
len = strlen(*bufp);
while(strchr(*bufp, '\n') == NULL) {
*sizep += 100;
*bufp = realloc(*bufp, *sizep);
if(fgets(*bufp + len, *sizep - len, fp) == NULL) return *bufp;
len += strlen(*bufp + len);
}
return *bufp;
}
That's not really complete code, it's almost pseudocode. I've left two things for you as exercises:
It has no error-checking on the malloc
and realloc
calls.
It's kinda grossly inefficient, in that it makes not one but two extra passes over each line it reads: to count the characters, and again to look for a '\n'
. (It turns out fgets
's interface isn't ideal for this kind of work.)
Upvotes: 4
Reputation: 357
You cannot change the size of an array during run time in C. It is illegal. This is because arrays are allocated from the stack. To have the size be dynamic you would have to declare a pointer, and allocate the memory for it dynamically. This data is allocated from the heap.
You can change the size of allocated memory by using realloc
.
int lineLen = 80;
char *line;
line = (char *)malloc(sizeof(char) * 80);
if (line == NULL) {
// Something went horribly wrong
exit(1);
}
while (fgets(line, lineLen, fp)) {
// Do something to find the size
line = (char *)realloc(line, sizeof(char) * newLen);
if (line == NULL) {
// Something went horribly wrong
exit(1);
}
}
However, allocating and reallocating memory is a rather expensive operation. As a result, you may be more effective by just choosing a big buffer size, if you can do that safely. If you have a short loop then it may not be significant enough to worry about, but it is probably not advisable to be constantly changing your buffer's size.
Upvotes: 0