2

I have the following function that should loop and take multiple lines from the user (names and dates). The user needs to enter an empty line to stop the loop.

 while ((line = getLineFromUser()) != NULL) {
    token = getNameAndDate(&concert, line);

however, when I get to the last line in the loop, the getchar() waits for the user input (which is good for me, because it means that I finished getting the previous line), but ch gets '\n' as soon as I enter the next line (not specifically an empty line). as anyone encountered this before? Everything else seems to work fine until the last getchar(). if needed, I will provide the other functions as well.

this is the getLineFromUser function:

char *getLineFromUser() {
    int ch;
    char *line;

    int logSize, phySize;
    logSize = 0, phySize = 2;
    line = (char *)malloc(sizeof(char) * phySize);
    checkAllocation(line);

    while ((ch = getchar()) != '\n' && ch != EOF) {
        if (logSize == phySize) {
            phySize *= 2;
            line = (char *)realloc(line, sizeof(char) * phySize);
            checkAllocation(line);
        }
        line[logSize] = ch;     // get char into the str
        logSize++;
    }
    if (logSize == 0) {
        free(line);
        line = NULL;
    } else {
        line = realloc(line, sizeof(char) * logSize + 1);
        checkAllocation(line);
        line[logSize] = '\0';
    }
    return line;
}

and this is the declaration:

char* getLineFromUser();
jmoerdyk
  • 5,544
  • 7
  • 38
  • 49
Eli Freid
  • 33
  • 7
  • 1
    This depends on the definition of `getLineFromUser`, which seems mysterious to me. What does it use its argument for? – rici May 26 '22 at 15:43
  • because I needed to handle line by line, and didn't want to lose any chars from the buffer, I used getchar() in the main function above, checked that it's not '\n' (meaning empty line) and sended the char to the function to create a string with ch as the first char in the string, this is why the getLineFromUser gets ch as an argument – Eli Freid May 26 '22 at 16:04
  • @Oka I changed my code to look like the code steve mentioned below, and inside the getLine function, I changed ch from char to int, but I still run into the same problem, I will edit my question and add the getLine function to provide more information – Eli Freid May 26 '22 at 16:07
  • Yes, please provide a complete [Minimal, Reproducible Example](https://stackoverflow.com/help/minimal-reproducible-example) that details a program we can compile, including the code that drives these functions: `main`, headers and all. The preliminary advice, in lieu of an answer, is to use [`fgets`](https://en.cppreference.com/w/c/io/fgets) or [`getline`](https://man7.org/linux/man-pages/man3/getline.3.html) to read lines of input. – Oka May 26 '22 at 16:07
  • Aside: `sizeof (char)` is guaranteed to be `1`, and can be omitted from multiplicative calculations for brevity. Do not [cast the return of `malloc`](https://stackoverflow.com/a/605858/2505965) (or `realloc`) in C. – Oka May 26 '22 at 16:14
  • @chqrlie I posted the basic idea of the code, sense it has some mallocs and other stuff – Eli Freid May 26 '22 at 16:17
  • @chqrlie ok, I will change it back, just a second – Eli Freid May 26 '22 at 16:18

3 Answers3

0

I would suggest revising your getLineFromUser function slightly so that you can call it more like this:

char *line, *token;
    
while ((line = getLineFromUser()) != NULL) {
    if(is_empty(line)) break;
    token = getNameAndDate(line);
}

Trying to treat the newlines separately from the lines is a recipe for complexity, confusion, and bugs.

Steve Summit
  • 45,437
  • 7
  • 70
  • 103
  • thanks for your answer! unfortunately I still get the same problem after changing my code. I tried to handle the '\n' from the getLine function as you mentioned I should, however after the user enters a second line, the getchar() still gets a '\n' even thou the buffer is empty (I assume its empty because it awaits for my input). inside the getLine function, I loop with while(ch = getchar() != '\n' && ch != EOF) – Eli Freid May 26 '22 at 15:58
0

Your code seems fine except for these remarks:

  • line = realloc(line, sizeof(char) * logSize + 1); is inconsistent: you should either write realloc(line, logSize + 1) or realloc(line, sizeof(char) * (logSize + 1)). There is no consequence here since sizeof(char) is 1 by definition.

  • you return NULL at end of file and for an empty line, so the caller cannot tell the difference. This might be a problem elsewhere in the code.

The main loop should stop as soon as an empty line is entered, or at end of file:

while ((line = getLineFromUser()) != NULL) {
    token = getNameAndDate(&concert, line);
}

You did not post the rest of the calling function: it should not have ch = getchar(); before nor after this loop.

chqrlie
  • 131,814
  • 10
  • 121
  • 189
  • first of all, thank you for your help! I don't have any other functions that uses `getchar()` before or after the main while. however I tested this snippet of code on another environment and it seems to work well, for some reason it doesn't work on my environment . can it be compiler related issue? – Eli Freid May 26 '22 at 16:35
  • @EliFreid: it is unlikely to be a compiler issue, but it could be a side effect of your environment's handling of user input. What environment is that? – chqrlie May 26 '22 at 16:55
  • I am using Clion on windows and on macOS, and still experience this issue – Eli Freid May 27 '22 at 09:00
  • @EliFreid: how do you perform your tests? From inside Clion or from a shell prompt in a terminal window? – chqrlie May 27 '22 at 09:30
  • from inside the Clion, after some more checking it seems to be an issue with the toolchain, I will try some different toolchains and If it will sort the issue I will update – Eli Freid May 27 '22 at 11:10
0

update: the bug was solved.

after adding a printf(<someString>); inside of the main loop it seems to have fixed the bug, I tested it with multiple strings and chars and it seems that as long as I use printf(); it does something to "flush" the buffer and gets rid of the \n.

Eli Freid
  • 33
  • 7
  • *it seems that as long as I use `printf();` it does something to "flush" the buffer and gets rid of the `\n`* Sorry to say, but that's not the way it works, so your bug isn't really fixed, and it will probably be back again some day, for as random a reason as this one. – Steve Summit May 27 '22 at 19:44