I\'ve got a C program that I\'m trying to write which intends to reverse the lines of a file. I am still very inept at C (though I come from a Java background), so I am very lik
buffer
The trouble is that you keep storing the pointer buffer
in str[i]
, but buffer
only contains the last line read.
You will have to make copies of the lines read, maybe using strdup()
:
str[i++] = strdup(buffer);
There's error checking to worry about, but conceptually, that's one simple way to deal with it.
Could you please clarify as to why that is? The declaration of
fgets()
beingchar *fgets()
, I got the impression that it momentarily returns a pointer to the line currently read from the file!
Actually, fgets()
returns one of two values:
buffer
, the pointer to the string passed to the function.In particular, it does not create new storage for you automatically. If you want that, you probably need to look at readline() from POSIX.
So, your calls to fgets()
use the same array, buffer
, each time, so that each successive line read overwrites the previous one. That's why you need to copy each line somehow, and why I suggested strdup()
as an easy way to do that.
The function strdup()
is part of POSIX but not standard C. However, it is easily implemented:
char *strdup(const char *str)
{
size_t len = strlen(str) + 1;
char *dup = malloc(len);
if (dup != 0)
memmove(dup, str, len);
return(dup);
}
You should avoid goto
when possible, which is easily done with this code. Your dual-purpose error message actually ends up confusing the user who omits the argument, or supplies too many arguments. Provide two separate error messages, one for the incorrect number of arguments to the program, and one for failing to open the file.
if (argc != 2)
{
fprintf(stderr, "Usage: %s file\n", argv[0]);
exit(1);
}
fp = fopen(argv[1], "r");
if (fp == 0)
{
fprintf(stderr, "%s: failed to open file %s (%d: %s)\n",
argv[0], argv[1], errno, strerror(errno));
exit(1);
}
Note that errors should be reported on stderr
, not stdout
; that's what the error output channel is for.
In you code you are making each index of str array to point to same array buffer. Thats is why you are getting same value (value in buffer) for evey index in str array. You can use code using array like this
#define MAX_LINES 100
#define MAX_CHAR 80
int main(int argc, char *argv[])
{
if(argc != 2)
goto out;
FILE *fp;
char str[MAX_LINES][MAX_CHAR];
char buffer[MAX_CHAR];
char *revstr[MAX_CHAR];
int curr_line = 0, i = 0, j =0;
fp = fopen(argv[1],"r");
out:
if (fp == NULL && argc != 2){
printf("File cannot be found or read failed.\n");
return -1;
}
/* printf("This part of the program reverses the input text file, up to a maximum of 100 lines and 80 characters per line.\n The reversed file, from the last (or 100th) line to the first, is the following:\n\n"); */
/* fgets reads one line at a time, until 80 chars, EOL or EOF */
while(curr_line < MAX_LINES && ((fgets(buffer, MAX_CHAR, fp)) != NULL)){
//str[i] = buffer;
memcpy(str[i], buffer, strlen(buffer));
curr_line++;
++j;
++i;
}
for(i = 0; i < 4; ++i)
printf("%s \n", str[i]);
printf("END OF PROGRAM RUN.");
return 0;
}
Also you are not modifying variable currn_line