-4

I have the following piece of code:

while (fgets(line,1024,file))
{
    getchar();
    printf(line);
    i++;
    line = (char*)realloc(line, sizeof(char)*sizes[i]);
}

and for some reason when I printf the line, it prints two lines. How can it be?

full code:

int main()
{
    FILE * file = fopen("C:/Users/user/Desktop/a.txt","r");
    char c;
    int count=0;
    int words=0;
    int* sizes = (int*)calloc (count+1,sizeof(int));

    if (file)
    {
        do
        {
            c= getc(file);
            words++;

            if (c=='\n'|| c==EOF)
            {
                sizes[count]=words+1;
                count++;
                words=0;
                if (c=='\n')
                    sizes = (int*)realloc(sizes,(count+1)*sizeof(int));
            }
        }while (c!=EOF);

        rewind(file);
        char* line = (char*)malloc(sizeof(char)*(sizes[0]));

        int i=0;
        while (fgets(line,1024,file))
        {
                getchar();
                printf("%s",line);
                i++;
                line=(char*)realloc(line,sizeof(char)*sizes[i]);
        }

        printf(line);

        free(line);

        /*for (int i=0; i<8; i++)
        {
            printf("%d\n",sizes[i]);
        }*/

        free(sizes);
        fclose(file);
    }

    getchar();

    return 0;
}

as you see, I count each line's length, put it into array, than allocate a string according to the line's length.

David Frye
  • 498
  • 4
  • 10
ByoTic
  • 333
  • 1
  • 4
  • 16
  • 5
    You should use `printf("%s", line);`. Otherwise, if `line` contains any characters that are valid `printf` formats, you will run into problems. – R Sahu Aug 13 '14 at 19:52
  • 4
    1) This question seems less like a useful question to upvote and showcase on this site long-term, and more like a one-off that a few minutes of debugging could solve for you. 2) It would be nice for you to provide an [MCVE](https://stackoverflow.com/help/mcve) either way. – David Frye Aug 13 '14 at 19:54
  • @R Sahu I tried it, it made no difference. @David Frye, tried to debug it more than few minutes. I can show more of the code, just ask for it... I thought this was enough as this is the part with the weird behavior (As far as I know fgets NEVER insert to the string more than one line) – ByoTic Aug 13 '14 at 19:57
  • 1
    Why do you call `getchar()` immediately after calling `fgets()`? – Keith Thompson Aug 13 '14 at 20:04
  • @user3050072: Honestly, I shouldn't have to ask for it. I will, and I suppose I just _did_, but it would be nice if we were provided with a sample of code that would, say, _compile_. What is going on with `i`? What does a sample input file look like? That sort of thing. I know that the [MCVE](https://stackoverflow.com/help/mcve) page is probably not displayed as prominently as it should be around here, but please do consider it in the future. – David Frye Aug 13 '14 at 20:06
  • edited, I hope it will be clearer now. – ByoTic Aug 13 '14 at 20:09
  • 1
    " I tried it, it made no difference." -- What part of "**if** line contains any characters that are valid printf formats" don't you understand? Enter a line containing a '%' and it will certainly make a difference. – Jim Balter Aug 13 '14 at 20:15
  • I DID understand, and I said it was not the case. – ByoTic Aug 13 '14 at 20:18
  • `char c;` should be `int c;` to properly detect `EOF`. – chux - Reinstate Monica Aug 13 '14 at 20:21
  • 4
    "fgets is not stopping after \n" - it is. – The Paramagnetic Croissant Aug 13 '14 at 20:21
  • `printf(line);` after the `while` loop should be deleted. – chux - Reinstate Monica Aug 13 '14 at 20:23

4 Answers4

1

You have an extra

printf(line);

after the while loop, causing the last line to be printed twice.

if you change the print inside tho loop to

printf("read[%d]: %s", i, line);

it will be more obvious. the same i won't be printed twice. the output may appear to have a line breakn in the middle if you have a strange control sequence like \v\r but it's still the same "line" being printed

Ryan Haining
  • 35,360
  • 15
  • 114
  • 174
  • Maybe, but it's not what I'm talking about, It is printing two different lines from the file each iteration. – ByoTic Aug 13 '14 at 20:12
  • 1
    you're gonna have to show the input file then, because it isn't. – Ryan Haining Aug 13 '14 at 20:12
  • did you compile it? I inserted a random text... Maybe it has to do with the fact I compile it as a cpp file? I don't think so – ByoTic Aug 13 '14 at 20:14
  • @user3050072 yeah I compiled and ran it. is your text file just text? if it has some weird control characters in it then *maybe* you could get the same line to print twice. how are you generating the random text? – Ryan Haining Aug 13 '14 at 20:15
  • for some reason it is printing twice each iteration – ByoTic Aug 13 '14 at 20:16
  • I think you have characters in your text file that aren't as visible. if I make a text file with a pattern like `\v\r` then the output will appear on two separate lines – Ryan Haining Aug 13 '14 at 20:19
  • @user3050072 does it work if you make a small text file yourself by hand? – Ryan Haining Aug 13 '14 at 20:22
  • By the way, why is that working? I mean, in the last line, fgets reaches EOF and should return null, but instead it is continuing into the loop's block. How is that possible? – ByoTic Aug 13 '14 at 21:52
  • 1
    @user3050072 `fgets` and similar functions won't signal EOF until you try to read past the end of the file. the last line will be fine, but when you try to read after that it wil fail – Ryan Haining Aug 13 '14 at 22:27
1

if you just press "enter" at getchar there will be one line. if you type 1 letter and enter there will be 2 lines. if you type 2 letters and enter there will be 3 lines

see where i m going. your input breaks at "enter" but getchar is happy with one character and the other is in the buffer which it gets in the next loop.

sample output:

total 192
1 <---------input
-rw-rw-r-- 1 nranjan3 nranjan3  1032 Jun 11  2013 parseCreateList.c
-rw-rw-r-- 1 nranjan3 nranjan3   462 Jun 14  2013 mpSpRec.c
12 <---------input
-rwxrwxr-x 1 nranjan3 nranjan3  8681 Jun 14  2013 mpSpRec.exec
-rw-rw-r-- 1 nranjan3 nranjan3   162 Jul 29  2013 mtTrace.log
-rw-rw-r-- 1 nranjan3 nranjan3  1280 Jul 29  2013 iccLogger.c
123 <---------input
-rwxrwxr-x 1 nranjan3 nranjan3  6662 Aug 20  2013 k.out
-rw-rw-r-- 1 nranjan3 nranjan3  1465 Aug 21  2013 stNewProcPar.c
-rwxrwxr-x 1 nranjan3 nranjan3 11624 Aug 21  2013 masterP
-rw-rw-r-- 1 nranjan3 nranjan3   321 Nov 25  2013 memTest.c

now instead of getchar you add this, it will work and show 1 line irrespective how many letters you type

while (getchar() != '\n');
Nish
  • 379
  • 2
  • 9
0

If you are asking about the extra new line in your code then you need to go for probably to remove the getchar() function. cause due to this it simply waits in new line and when you put enter then you can see the next line from the file. However you looks like that extra line in your output. so exchange the Function:

getchar();

with:

getch();

I hope you probably get the answer.

Avinash
  • 497
  • 1
  • 6
  • 19
  • It's not what I'm talking about. line should be a line from a text file, and when I malloc the line, I know for sure i malloc it with the correct size, but instead it is printing TWO lines from the file. – ByoTic Aug 13 '14 at 20:01
  • 1
    There are (at least) two functions called `getch()`. One is Windows-specific, the other is part of `[n]curses`. Neither seems appropriate in this case. – Keith Thompson Aug 13 '14 at 20:04
  • I tried that code. Only last line it is printing extra and i don't seem to be there are any problem with normal getch() function. – Avinash Aug 13 '14 at 20:18
0

char c; should be int c;. Since EOF must be different to all possible chars, if you use char c; then either you never find EOF, or you get false positives, depending on your system's format of char.

Moving on:

while (fgets(line,1024,file))

Replace 1024 with sizes[i]. This will prevent a buffer overflow.

{
    getchar();

The getchar() discards the first character of the next line. However if the next line was blank then it means the entire next line is discarded. Then your line counts will be out of sync with the lines you are reading (causing undefined behaviour if you were still using 1024 in fgets, which could explain why you see bogus output).

i++;

You should break out of the loop if i >= count.

As others have mentioned, printf(line); after the loop will mean the last line prints twice (and is garbled if it contained any % characters).

Finally, don't cast malloc. As well as making your code more robust it will make it easier to read. You don't need sizeof(char) either since that is always 1.

NB. It'd be much better to just read the lines as you go, instead of making two passes over the file.

Community
  • 1
  • 1
M.M
  • 138,810
  • 21
  • 208
  • 365