1

I want to read one character at a time from standard input and operate on that. For example, input

abcdefghijklmnopqrstuvwxyz

What I want is, to operate on a (which is the first character) as soon as it has been entered (the operation on a should be done before the user enters b) and then operate on b and so on.

chqrlie
  • 131,814
  • 10
  • 121
  • 189
bigcoder
  • 21
  • 1
  • 2
  • 3
    So you want to work in non-canonical mode, take a look to [ncurses](https://www.gnu.org/software/ncurses/) on unixes or [conio](http://www.programmingsimplified.com/c/conio.h) on windoses :) – David Ranieri Aug 26 '17 at 17:03
  • Also you can take a look here https://stackoverflow.com/questions/10247591/setvbuf-not-able-to-make-stdin-unbuffered – algrid Aug 26 '17 at 18:47

3 Answers3

3

Maybe this other solution.

Taken from https://www.gnu.org/software/libc/manual/html_node/Noncanon-Example.html and https://ftp.gnu.org/old-gnu/Manuals/glibc-2.2.3/html_chapter/libc_17.html.

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <termios.h>

/* Use this variable to remember original terminal attributes. */

struct termios saved_attributes;

void
reset_input_mode (void)
{
  tcsetattr (STDIN_FILENO, TCSANOW, &saved_attributes);
}

void
set_input_mode (void)
{
  struct termios tattr;
  char *name;

  /* Make sure stdin is a terminal. */
  if (!isatty (STDIN_FILENO))
    {
      fprintf (stderr, "Not a terminal.\n");
      exit (EXIT_FAILURE);
    }

  /* Save the terminal attributes so we can restore them later. */
  tcgetattr (STDIN_FILENO, &saved_attributes);
  atexit (reset_input_mode);

  /* Set the funny terminal modes. */
  tcgetattr (STDIN_FILENO, &tattr);
  tattr.c_lflag &= ~(ICANON|ECHO); /* Clear ICANON and ECHO. */
  tattr.c_cc[VMIN] = 1;
  tattr.c_cc[VTIME] = 0;
  tcsetattr (STDIN_FILENO, TCSAFLUSH, &tattr);
}


int
main (void)
{
  char c;

  set_input_mode ();

  while (1)
    {
      read (STDIN_FILENO, &c, 1);
      if (c == '\004')          /* C-d */
        break;
      else
        putchar (c);
    }

  return EXIT_SUCCESS;
}
Luis Daniel
  • 687
  • 7
  • 18
  • This could be an answer but we don't know his OS, also, you should put the _Save the terminal attributes so we can restore them later_ part in `main` (at the very begin) instead of calling it each time a key is pressed. – David Ranieri Aug 26 '17 at 17:46
0

I think you want something like this.

#include <stdio.h>

int main ()
{
  int c;
  puts ("Enter text");
  do {
    c = getchar();
    putchar (c); //do whatever you want with this character.
  } while (c != '\0');

  return 0;
}
Luis Daniel
  • 687
  • 7
  • 18
  • 3
    Your answer is correct, but I suspect that OP wants to see those changes before pressing Enter. – David Ranieri Aug 26 '17 at 17:13
  • Yes. I want to operate on the input before pressing enter. The operation should start as soon as the character has been entered. – bigcoder Aug 26 '17 at 17:16
  • @bigcoder, Luis Daniel's code does exactly that, but those changes are non visible until you press enter because your terminal is working in canonical mode, `getch` (not standard) is what you are looking for. – David Ranieri Aug 26 '17 at 17:21
0

Since you did not specify an operating system, I am going to give a suggestion suitable for the windows operating system.

The function GetAsyncKeyState() does exactly what you ask for. You can read its documentation from this link.

As a quick example on its usage:

#include <Windows.h>

int main(void)
{
    while(1) {
        if(GetAsyncKeyState('A') & 0x8000) {
            /* code goes here */
            break;
        }
    }
    return 0;
}
machine_1
  • 4,266
  • 2
  • 21
  • 42