LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   C: behaviour of getchar() after a print statement that ends in a whitespace??? (https://www.linuxquestions.org/questions/programming-9/c-behaviour-of-getchar-after-a-print-statement-that-ends-in-a-whitespace-819120/)

jay73 07-10-2010 02:28 PM

C: behaviour of getchar() after a print statement that ends in a whitespace???
 
Maybe a beginner's question but then I have been learning C for only two days...

How do I make getchar() skip a leading space? The situation I am looking is this: I print a prompt that ends in a space
printf("Input: ");
and then when I use getchar() to read the text that was typed after the prompt, it appears to process the trailing space as a leading space that belongs to the input.
Could anyone explain why? And how can the space be skipped, preferably without inserting code that explicitly checks whether I'm reading the first character or not. I have already found out that I can skip such a space using scanf
scanf (" %c", &ch);
where the leading space in the format string eliminates leading spaces from the input string. That is the sort of thing I have in mind.

Sergei Steshenko 07-10-2010 04:00 PM

Quote:

Originally Posted by jay73 (Post 4029370)
Maybe a beginner's question but then I have been learning C for only two days...

...when I use getchar() to read the text that was typed after the prompt, it appears to process the trailing space as a leading space that belongs to the input. ...

'getchar' is buffered, i.e. new characters are seen only after you enter newline ('\n').

So, if, for example, you want to enter 'a', in fact you need to enter 'a', '\n'. So after the first call to 'getchar' you'll get 'a' (that's what you expect), but on the second call (suppose, you wanted to enter 'b') instead of 'b' you'll first get the '\n' you've entered after 'a', and only on the third call you'll get 'b', but again you'll have yet another '\n' in the buffer.

Try 'fread' instead.

wje_lq 07-10-2010 07:16 PM

Quote:

Originally Posted by Sergei Steshenko (Post 4029420)
Try 'fread' instead.

That won't help. The problem is not fread() versus getchar(); you need to use termios to make your data unbuffered. Then you can use either getchar() or fread().

To observe how fread() acts buffered under ordinary circumstances, run this shell script:
Code:

cat > 1.c <<EOD; rm -f 1; gcc -Wall -Werror 1.c -o 1; ./1
#include <stdio.h>

int main(void)
{
  int          linefeed_count;

  unsigned char buffer[4];

  fprintf(stderr,"a prompt: ");

  linefeed_count=0;

  for(;;)
  {
    if(fread(buffer,1,1,stdin)<1)
    {
      break;
    }

    printf("got 0x%02X",buffer[0]);

    if((buffer[0]>=' ') && (buffer[0]<='~'))
    {
      printf(" %c",buffer[0]);
    }

    printf("\n");

    if(buffer[0]=='\n')
    {
      linefeed_count++;
    }

    if(linefeed_count>=2)
    {
      break;
    }
  }

  return 0;

} /* main() */
EOD

If you run the program and enter "x", and press the <Enter> key, and then "b", and press the <Enter> key, you'll get output like this:
Code:

a prompt: x
got 0x78 x
got 0x0A
y
got 0x79 y
got 0x0A


Sergei Steshenko 07-11-2010 07:15 AM

Quote:

Originally Posted by wje_lq (Post 4029520)
That won't help. The problem is not fread() versus getchar(); you need to use termios to make your data unbuffered. Then you can use either getchar() or fread().
...

Well, we still have 'man 2 read' :).

wje_lq 07-11-2010 06:57 PM

We need termios for this. We really, really do.
Quote:

Originally Posted by Sergei Steshenko (Post 4029801)
Well, we still have 'man 2 read' :).

Well, you're right, we do, but it won't help here. We still get the same output with the same input, but run against this shell script:
Code:

cat > 1.c <<EOD; rm -f 1; gcc -Wall -Werror 1.c -o 1; ./1
#include <stdio.h>
#include <unistd.h>

int main(void)
{
  int          linefeed_count;

  unsigned char buffer[4];

  fprintf(stderr,"a prompt: ");

  linefeed_count=0;

  for(;;)
  {
    if(read(STDIN_FILENO,buffer,1)<1)
    {
      break;
    }

    printf("got 0x%02X",buffer[0]);

    if((buffer[0]>=' ') && (buffer[0]<='~'))
    {
      printf(" %c",buffer[0]);
    }

    printf("\n");

    if(buffer[0]=='\n')
    {
      linefeed_count++;
    }

    if(linefeed_count>=2)
    {
      break;
    }
  }

  return 0;

} /* main() */
EOD


jay73 07-13-2010 01:06 AM

Thanks for your suggestions but I'm afraid I don't see how they answer my question. Like I said, the problem is that part of my output is being considered as input:
Code:

printf("Input: ");  //print "Input: " prompt
char ch = getchar();  //read input entered at the prompt

If I run the code and enter, say, an 'a', I would expect ch to hold the value 'a'. But it doesn't, it contains a space. The only reason I can think of is that somehow the trailing space of the prompt (there is a space after the colon) is being treated as input. But why?

Wim Sturkenboom 07-13-2010 01:27 AM

It does not take that trailing space (or at least I'm 99.99% sure that it does not)

Code:

#include <stdio.h>

int main(int argc, char *argv[])
{
char ch;

    printf("Input: ");
    ch=getchar();

    printf("ch = 0x%X\n", ch);
    return 0;
}

Code:

wim@btd-techweb01:~/progs/lq819120$ gcc -Wall lq819120.c -o lq819120
wim@btd-techweb01:~/progs/lq819120$ ./lq819120
Input: A
ch = 0x41
wim@btd-techweb01:~/progs/lq819120$

Your problem might be that your terminal uses a characterset that uses multiple bytes instead of single byte ASCII (not sure what it is called).

jay73 07-13-2010 02:09 AM

Hi Wim,

Terminal uses UTF.8. When I run your piece of code, I also get 41 hex so the problem must lie elsewhere. I think I'll need to take a better look at the code that was producing the problem. It seems quite likely that some method call before the printf statement leaves a new line in the buffer.


All times are GMT -5. The time now is 11:07 PM.