2

I am working through a problem in the C ansi programming book. I am asking the user for input until there is no end of line. However, i'd like to have the characters moved to the next line once 10 characters have been reached. However, the newline character only works after hitting enter. Shouldn't a new line be outputted once i == 10?

#include <stdio.h>
#define MAXLINE 10


// count number of chars, once it reaches certain amount

int main() 
{
    int i,c;

    for (i=0;(c=getchar()) != EOF; i++)
    {
        if (c == '\n'){
            i = 0;
        }

        else if (i == MAXLINE){
            printf("\n");
        }

    }
    //printf("%d\n",i);

}

Thank you.

Colorful Codes
  • 577
  • 4
  • 16
  • 2
    The input is not flushed into the input stream till you hit enter anyway. It is line- or even fully buffered. https://www.gnu.org/software/libc/manual/html_node/Buffering-Concepts.html – Eugene Sh. May 26 '20 at 20:05

1 Answers1

1

"Shouldn't a newline be outputted once i == 10?"

No. Because the console input is buffered by default. getchar() will not return the next character in stdin before it found a newline character '\n' in stdin. The newline is required to flush the buffer.

There are implementation-based solutions possible to flush the input immediately and not waiting for the newline. For example getche() in conio.h under Windows/DOS or the cbreak() option and using getch() instead of getchar() in the curses-library for Linux.

Also your counting is incorrect, with i = 0; and if (i == MAXLINE) after 11 characters will a newline be placed in the output, not after 10. This is because you start at 0, not 1. Use either i = 1 or if (i == (MAXLINE - 1)) instead.


If you are on Windows/DOS, try:

#include <stdio.h>
#include <conio.h>             // Necessary to use getche().

#define MAXLINE 10


// count number of chars, once it reaches certain amount

int main (void) 
{
    int i, c;

    for (i = 0; (c = getche()) != EOF; i++)
    {
         if (i == (MAXLINE - 1))
         {
             printf("\n");             
             i = -1;          // Counter is reset. To break out of the loop use CTRL + Z.
         }
    }

    //printf("%d\n",i);
}

If the counter reset is a bit hard to understand for you, the code above is basically equivalent to:

#include <stdio.h>
#include <conio.h>             // Necessary to use getche().

#define MAXLINE 10


// count number of chars, once it reaches certain amount

int main (void) 
{
    int i, c;

    for (i = 1; (c = getche()) != EOF; i++)
    {
         if (i == MAXLINE)
         {
             printf("\n");
             i = 0;          // Counter is reset. To break out of the loop use CTRL + Z.
         }
    }

    //printf("%d\n",i);
}

For Linux use the cbreak() and getch() from the ncurses-library:

#include <stdio.h>
#include <ncurses.h>            

#define MAXLINE 10


// count number of chars, once it reaches certain amount
int main (void) 
{
    cbreak();
    echo();

    initscr();

    int i, c;

    for (i = 1; (c = getch()) != ERR; i++)
    {
         if (i == MAXLINE)
         {
             printf("\n");
             refresh();
             i = 0;          // Counter is reset. To break out of the loop use CTRL + D.
         }
    }

    //printf("%d\n",i);

    endwin();
}

Note: To use the ncurses-library, you need to add the -lnurses option at invoking the compiler.

Furthermore, you need to use initscr() and endwin() to open and close the curses terminal window.

  • How would I use this solution? This site https://fresh2refresh.com/c-programming/c-file-handling/getche-function-c/ just say that getche() will echo out the character input. Isn't that already happening? – Colorful Codes May 26 '20 at 21:21
  • 1
    @ColorfulCodes No, It isn't. That's what I said. If you use Windows, `#include ` and replace `getchar()` by `getche()`. – RobertS supports Monica Cellio May 26 '20 at 22:14
  • 1
    @ColorfulCodes Maybe I was get you wrong with your previous comment. Yes, you actually see what you input into the console with `getchar()`, but it isn´t used in the program itself until the newline line is found in `stdin` - Made by a press to [Enter]/[Return] f.e.. `getche()` combines both, echoing the input but also returning the character immediately. – RobertS supports Monica Cellio May 27 '20 at 07:31
  • 1
    @ColorfulCodes Also updated my answer with an example. I´ve forgot to mention that your counter is incorrect if you want to print a newline after every 10 characters. – RobertS supports Monica Cellio May 27 '20 at 07:37
  • Actually, this code doesn't work for me but I'll keep your answer as checked since it still gave me new information and somewhere else to look. This doesn't work on Linux. I've tried ncurses.h and curses.h also using -lcurses when compiling the code after installation. I appreciate the help. Hopefully my comment will help other Linux users. – Colorful Codes May 29 '20 at 02:38
  • @ColorfulCodes I didn´t knew your were working on Linux. My thought was that you are using Windows since you responded to the `getche()` approach as I said it was for Windows-only. Else I had not provide the Windows example. You never said a word about which implementation you use explicitly. I updated my answer and provided the Linux approach. `cbreak()` is to flush the buffer immediately after a character has been provided and `echo()` is for echoing the input immediately to the console. – RobertS supports Monica Cellio May 29 '20 at 12:22
  • @ColorfulCodes Maybe take a look at [this](https://stackoverflow.com/questions/1798511/how-to-avoid-pressing-enter-with-getchar) question as well. – RobertS supports Monica Cellio May 29 '20 at 15:57