3

I tried this code

#include <stdio.h>

int main() {
    int num;
    printf("Enter a number: ");
    scanf("%d", &num);

    printf("You entered: %d. Next, let's print on the same line: ", num);
    printf("This is the output on the same line.\n");

    return 0;
}

And my output is this:

Enter a number: 10
You entered: 10. Next, let's print on the same line: This is the output on the same line.

But I want this output instead:

Enter a number: 10You entered: 10. Next, let's print on the same line: This is the output on the same line.

Basically I do not want the cursor to skip a line after I provide an input.

Jabberwocky
  • 48,281
  • 17
  • 65
  • 115
  • 4
    Do you type `10`? That's the `10` that you see after `Enter a number: ` – mch May 23 '23 at 07:15
  • 1
    You can't do this easily with `scanf` in a standard way. As a beginner you shouldn't bother. – Jabberwocky May 23 '23 at 07:17
  • Usually terminals are mixing stdin and stdout (e.g., you see a mix of what the program prints and what you typed), but some online compilers have them separate: https://godbolt.org/z/EbT13cqv4 Here you can see that the output is in 1 line, but it misses the `10` that you typed. – mch May 23 '23 at 07:33
  • stdin is, by default, line buffered, so you need to change the terminal to send you a character at a time (on Linux `cfmakeraw()` for instance). The next problem how do you know after typing `0` that the number is done? You could use `scanf("%c", ...)` to read a character at a time . You can use `sscanf()` or `strtol()` to convert a string to number, or you can writer your own function to add a digit to an existing number ( `value = 10 * value + digit`) – Allan Wind May 23 '23 at 07:35
  • Another approach is to reposition the cursor using ansi control codes. `scanf("%d")` ignores leading white space so you will need to a use "%8[^\n]" read the input including white space, then figure out how long that string is with`strlen()`. You can save the current position before the `scanf()` call, and restore it after, then move right however many bytes of your string you read - 1 possible for the newline. – Allan Wind May 23 '23 at 08:07
  • 1
    The issue you have here is that your operating system's terminal driver is *echoing* everything you type. (If it didn't, you couldn't see the `1` and `0` as you typed them.) So if you don't want it to echo the newline that you type, you're going to have to turn off all echoing. Then, since you probably do want to see the `1` and `0` as you type them, you're going to have to do the echoing yourself, for characters other than newline. And you'll probably have to turn off "canonical mode" also. It'll be quite a project if you've never worked with the terminal driver before. – Steve Summit May 23 '23 at 12:10

3 Answers3

2

Here is the answer that I outlined above using ANSI escape codes if your terminal supports it:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define CSI "\033["
#define FORWARD "C"
#define RESTORE "\0338"
#define SAVE "\0337"
#define str(s) str2(s)
#define str2(s) #s

#define STR_LEN 10 // int(log10(INT_MAX))

int main() {
    char str[STR_LEN+1];
    printf("Enter a number: ");
    printf("%s", SAVE);
    scanf("%" str(STR_LEN) "[^\n]", str);
    printf("%s%zu%s", RESTORE CSI, strlen(str), FORWARD);
    char *p;
    int num = strtol(str, &p, 10);
    printf("You entered: %d. Next, let's print on the same line: ", num);
    printf("This is the output on the same line.\n");
}

and here is the expected output:

Enter a number: 10You entered: 10. Next, let's print on the same line: This is the output on the same line.

I probably wouldn't use it. For instance, if you enter multiple lines of input you will end up with stray data on the screen.

You should check the return value from strtol() and further ensure that the value fits with an int (i.e. between INT_MIN and INT_MAX).

Allan Wind
  • 23,068
  • 5
  • 28
  • 38
  • @Jabberwocky Done. ANSI escape codes are widely supported (AFAIK). – Allan Wind May 23 '23 at 09:04
  • Yes, they are. But they _may_ not be supported, you should make that clear as the OP is a beginner. BTW your code doesn't work here (Windows 10) but the terminal is supposed to support ANSI escape sequences, not sure what's going on... – Jabberwocky May 23 '23 at 09:11
  • 1
    @Jabberwocky Save/restore is a "private" which I guess is an extension. Changed it to the DEC version.`\e7` and `\e8` which also works here. – Allan Wind May 23 '23 at 09:14
2

It's not really a programming problem but at user/console problem. If the user hits enter after typing something, a new line character will get added to stdin.

Depending on OS, you can instead enter EOF. How to enter the value of EOF in the terminal. Ctrl+D or Ctrl+Z depending on OS.

After which the behavior should be as shown here: https://godbolt.org/z/88h5MhTzr. Note that I haven't touched your code.

There are other non-standard console I/O functions that can be used to get the behavior you want even when the user presses enter, but that's not really worth studying since console I/O over stdin is very dated and overall problematic. Professional programs without GUI using the console tend to take input over command line arguments instead, which is less error prone and easier to sanitize.

Lundin
  • 195,001
  • 40
  • 254
  • 396
2

On most platforms, when reading user input from stdin, the user's input will be echoed to the screen. This includes the newline character.

If you want more control of whether input is echoed to the screen, you will have to use platform-specific functionality.

For example, on Microsoft Windows, you can use the _getch function, which will read a single keystroke from the user without echoing it. Then, you can make your program only print that keystroke to the screen if that keystroke fulfills a certain condition (for example if it is not a newline character). For more flexibility, you can use the function ReadConsoleInput instead of _getch.

On Linux, you can use the ncurses library for the same purpose.

Andreas Wenzel
  • 22,760
  • 4
  • 24
  • 39