0

I am trying to use fgets and fputs to copy-paste a file. I wrote in two ways, one in for loop, the other in while loop. While loop works perfectly, but for loop acts weird.

I tried to debug and wrote this:

FILE *infile = fopen("infile", "r");
FILE *outfile = fopen("forLoop_outfile", "w");
int row = 6, len = 6;
char *readbuf = malloc(len * sizeof(char));
for (int i = 0; i < row; i++)
{
    printf(" %d ", i);
    if (fgets(readbuf, len, infile) == NULL)
       perror("fgets");
    if (fputs(readbuf, outfile) == -1)
       perror("fputs");
    if (fputs(readbuf, stdout) == -1)
       perror("fputs");
}

input file:

abcde
fghij
klmno
pqrst
uvwxy
z

stdout and output file are the same:

 0 abcde 1 
 2 fghij 3 
 4 klmno 5 

as you can see, only the first 3 lines are read, and something when wrong for every 2 iteration. And debugging seems useless.

What's going wrong?

Nimantha
  • 6,405
  • 6
  • 28
  • 69
kowalski
  • 11
  • 4
  • I suspect your file has `\r\n` line breaks. – Barmar Jan 08 '22 at 15:05
  • Read the manual page for `fgets()` : since there is not enough space for the terminating '\n', it will be read in a next call to `fgets()` (solution: use a larger buffer and strip the LF) – wildplasser Jan 08 '22 at 15:05
  • Make `len` bigger and it should work. – Barmar Jan 08 '22 at 15:06
  • @wildplasser Got it!!! I need 5 + 1(`\n`) + 1(`\0`) = 7 characters to make it work. I guess it will make `\0` compulsory, so it has no space for `\n`. Thank you so much!!! – kowalski Jan 08 '22 at 15:25
  • Also: `fputs() writes the string s to stream, without its terminating null byte ('\0')` and it does **not** add a '\n'. [it is all in the fine manual] – wildplasser Jan 08 '22 at 15:30
  • @wildplasser I will read the manual again, thanks for your reminder. – kowalski Jan 08 '22 at 15:40

2 Answers2

1

Actually the input file contains

abcde\n
fghij\n
klmno\n
pqrst\n
uvwxy\n
z\n

As the length of the dynamically allocated array is equal to 6 then the first call of fgets reads only 5 characters "abcde" and appends them with the terminating zero character '\0'. The new line character '\n' is not read yet. So the next call of fgets reads this new line character '\n'.

To resolve the problem enlarge the size of the dynamically allocated array.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • This happens over and over again with beginner's code: they allocate the tiniest amount of buffer space that they imagine will be enough, but miscalculate. – Weather Vane Jan 08 '22 at 15:12
  • And one moral of the story is: when reading lines, don’t skimp on the space allocated. Consider a buffer of 2048 bytes as a minimum; you can go bigger if you prefer. – Jonathan Leffler Jan 08 '22 at 17:41
0
int row = 6, len = 10;
char *readbuf = malloc(len * sizeof(char));
for (int i = 0; i < row; i++)
{
    printf(" %d ", i);
    if (fgets(readbuf, len, infile) == NULL)
    {
       perror("fgets");
       break;
    }
    if (fputs(readbuf, outfile) == -1)
       perror("fputs");
    if (fputs(readbuf, stdout) == -1)
       perror("fputs");
}

Your lenis too small as you have also '\n' char at the end. You need to stop the execution if you failed to read the new line.

0___________
  • 60,014
  • 4
  • 34
  • 74