Problem with character input by getchar() or getche() - c

When I compile the C codes (from Teach yourself C, 2nd edition-Herbert Schildt) written below in Borland C++ v5.02, I get a warning message as below:
"c61.c(7,6): Conversion may lose significant digits"
What's wrong?
#include "stdio.h"
main()
{
char ch;
ch = getchar();
printf(" You typed: %c", ch);
return 0;
}
Same problem with another example:
#include "conio.h"
#include "stdio.h"
main()
{
char ch;
printf("Enter a character: ");
ch = getche();
printf("\nIts ASCII code is %d", ch);
return 0;
}

getchar() returns an int, so that it can return non-character values like EOF. So when you store the return value in a smaller datatype, like a char, you are potentially losing information.
Schildt's books are commonly considered the worst available for learning C (or C++) and this is a good example of why. You would be well advised to get a better book, such as K&R.

The prototype for getchar is:
int getchar (void);
It returns an int because it needs to return EOF which is not a character.
Expanding on that, the function needs to be able to return any valid character, as well as being able to return a special "character" indicating that you're reached the end of file (or an error has occurred).
Since a char data type can only hold one of the characters, there would be no way to indicate this end of file if all the function returned was a char. That's because, if you selected one of those char values to represent end of file, you would not be able to tell the difference between the end of file and the actual character.
For example, let's choose 'A' to indicate end of file. When you actually get back an 'A' from getchar(), how will you know whether you've reached the end of file or whether the user actually entered 'A'?
To get around this, many functions that give you back a char will actually give you an int and use one of the integer values which don't have an actual char equivalent (such as -1).
In that case (assuming an 8-bit char), you would get back either a -1 if you've reached the end of the file or a value from 0 through 255 inclusive representing the character entered.
And you need to get yourself both a more modern book and a more modern compiler:
#include <stdio.h>
int main (void) {
int ch = getchar();
if (ch != EOF)
printf("You typed: %c\n", ch);
return 0;
}
Why anyone is still using Borland is this day and age (where gcc is both just as cheap and much better) is beyond me.

What about this alternative program? It works fine.
#include <stdio.h>
main()
{
char ch;
getchar();
printf("Enter the character: ");
scanf("%c", &ch);
printf(" You typed: %c\n", ch);
return 0;
}
Please leave some comments.

Related

How does EOF act in getchar() and scanf() on Windows system?

I have two pieces of codes to test how the two console I/O functions, getchar() & scanf(), handle the EOF. But I still do not have a clear comprehension about the actual operations behind the outputs and their behaviors. Can someone explains that for me? Thanks a lot! (I am using Windows OS)
// 1st piece of Code
#include <stdio.h>
#include <ctype.h>
int main(void)
{
char ch;
while ((ch=getchar()) != EOF)
{
putchar(toupper(ch));
}
return 0;
}
If I type
abc
or
abc(ctrl+z)
The program will have the same outputs:
ABC
// 2nd piece of Code
#include<stdio.h>
int main(void)
{
int x;
while(scanf("%d",&x) != EOF)
{
/*Ctrl + z + Enter*/
printf("x=%d\n",x);
}
return 0;
}
If I type
123
The program will output:
x=123
Otherwise, if I type
123(ctrl+z)
The program will have an infinite output:
x=123
x=123
x=123
x=123
...
getchar() returns the value of the character converted to unsigned char or EOF in case of error.
The error can be "end of file" or something else; usually (for getchar()) the programmer does not care about the error, just that an error happened.
scanf() returns the number of values matched and assigned (basically the number of % in the format string) or EOF in case of error. Note that the number can be less than the number of % in case, for example, of badly formatted input
Just like for getchar() the error can be "end of file" or something else. Particularly, reading less than the number of % is not an error.
So you may prefer to test for the correct number of assignments rather than testing for error in scanf()
#include <stdio.h>
int main(void) {
int x;
while (scanf("%d", &x) != 1) {
/*Ctrl + z + Enter*/
printf("x=%d\n", x);
}
return 0;
}
The problem is that on Windows the EOF is put into the input buffer like a normal character (with the encoded value 26).
When reading character by character (with e.g. getchar) this is handled by the Windows run-time library. But it doesn't work like that with scanf because when scanf parses the input it's like another character. And as a non-digit it's an invalid character for te "%d" format, leading to your scanf Call to return 0 instead of EOF (since it's not parsed by the format).
One way to solve it is to press the Ctrl-Z sequence on its own new line.
Another (and more reliable) way to solve it is to check that scanf returns the number of formats you have in the string. In your case you should compare against 1 (as you have one format specifier).

C : How to stop the loop when getting the end of input from keyboard or file while using scanf one char at a time

void main(void)
{
char character;
do {
scanf("%c", &character);
printf("%c", character);
} while (character != EOF);
}
I'm going to process the input character by character, and I am only allowed to use scanf(). However, the while loop does not stop. Since I may need to process the input with multiple-line strings, it is impossible to add one more condition: character != '\n'.
Can somebody help me with this problem? Thanks!
You have an incorrect expectation. When scanf() encounters the end of the input before either matching an input item or recognizing a matching failure, it returns EOF. Under no circumstance does it modify the value of the datum associated with an input item that has not been matched.
You are ignoring scanf's return value, which is generally a perilous thing to do, and instead testing whether scanf records EOF in the object associated with the input item, which, in your particular case, it must not ever do.
For a start it should be int main...
Also you need to check the return value from scanf - please read the manual page.
Taking this into account, the code should look like this
#include <stdlib.h>
#include <stdio.h>
int main()
{
char character;
while (scanf("%c", &character) == 1) {
if (character != '\n) {
printf("%c", character)
}
}
return EXIT_SUCCESS;
}

stopping `scanf` when user enters "." DOT

I am messing around with the function below, I want to end input capture when user enters a DOT character. It seems that getche() is not doing what it is intentended to do:
void Encode(FILE *fp)
{
char chWord[100];
char *chP;
printf("Enter a word or a sentence, close it by a \".\"\r\n");
scanf("%s",chWord);
if (chWord != '.')
{
for (chP = chWord; *chP != '\0'; chP++) //to print each digit till end of string \0
{
printf("%d ",*chP+10);
fprintf(fp, "%d ",*chP+10);
}
}
}
UPDATE
It seems that I was not clear enough. What I am trying to do is when user enters a DOT it should act like pressing ENTER key so the program goes to next step. Some sort of simulating ENTER key.
if (chWord != '.')
should be
if (*chWord != '.')
you are comparing a char pointer to a char instead of a char to another char.
be aware that the way this code is written the input ".123" will skip the printing segment. not sure if this is desireable to you or not.
The scanf family of function accept a (negative)character set as a format specifier.
You can do scanf("%[abc]", chWord); to accept only strings composed of the letters abc.
And you can also specify which characters not to accept. So scanf ("%[^.]", chWord); will accept a string composed of anything but a dot.
Edit
I forgot to mention, that the dot will remain in the input stream buffer, so to read and ignore it during the scanf itself (rather than flush the buffer or do a getchar), just add it to the end of the format string. I.e.:
scanf ("%[^.].", chWord);
OK, backing out that whole Answer based on your update...
The answer is no, there is no way to do what you want to do with scanf, or anything in standard C for that matter. What you're trying to do is platform (and possibly compiler) specific.
If you want to treat the '.' as a enter key press you have to do the magic yourself. So, since you didn't mention if you were using any specific OS or compiler I'll give you the first example that comes to mind.
This works with Windows MS VS:
#include <Windows.h>
#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
char key = 0;
int counter = 0;
char chWord[100] = {0};
while(counter < 100) {
while(!_kbhit()) { //While no key has been hit
Sleep(1); //Sleep for 1 ms
}
key = _getch(); //Get the value of the key that was hit
if(key == '.') //if it was a .
break; //act as if it were an "enter" key and leave
else
chWord[counter] = key;
counter++;
}
chWord[99] = '\0';
printf("The string was %s\n", chWord);
return 0;
}

Help with basic reading user input in C

I am currently just learning C and for a project I need to read in integer inputs from the user. Currently I am using code that looks like this:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int a, b;
printf("Please enter your first number");
while((a = getchar()) != '\n') {
}
printf("test");
return 0;
}
Im not sure how to get the number with getchar and then store it in a variable i can use.
Also I'm using = '\n' in the while statement because I don't really understand how EOF works (as in the K&R book) because whenever i use EOF i go into this loop i cant get out of.
Thanks for any advice anyone can offer.
You can use scanf.
Have a look at this example:
printf("Please enter your first number ");
int number=0;
scanf ("%d",&number);
The scanf answer above mine is correct, but if you haven't read about addresses or format strings, it may be difficult to grok.
You can convert your character to its integer equivalent by subtracting '0' from it:
char c = getchar();
int n = c - '0';

C Prints One Char More Without Value

I am trying to print the ASCII values of 3 char-type characters. When I input the first char it doesn't print the value of the char. After the first char it starts to give the value.
#include <stdio.h>
int main() {
char ch;
int t;
while(t < 3){
scanf("%c\n", &ch);
printf("%c - %d\n", ch,ch);
t++;
}
}
http://i54.tinypic.com/2mdqb7d.png
Variable t is not automatically initialized to 0 by compiler. So You need to initialize t with 0. If printf doesn't print immediately it means the data is buffered. If you want to see immediatley you may consider flushing stdout right after printf.
I saw this several times, and don't know the root cause, but solution that works is:
scanf("\n%c", &ch);
It probably has something to do with buffered end of line character.

Resources