How to detect carriage return in C? - c

For my homework we are supposed to write a checksum that continues to display checksums until a carriage return is detected (Enter key is pressed). My checksum works fine and continues to prompt me for a string to convert it to a checksum, but my program is supposed to end after I press the enter key. In my code, I set up a while loop that continues to calculate the checksums. In particular I put:
while(gets(s) != "\r\n")
Where s in a string that the user has to input. I've also tried this with scanf, and my loop looked like:
while(scanf("%s",s) != '\n')
That did not work as well. Could anyone please give me some insight onto how to get this to work? Thanks

The gets(s) returns s. Your condition compares this pointer to the adress of a constant string litteral. It will never be equal. You have to use strcmp() to compare two strings.
You should also take care of special circumstances, such as end of file by checking for !feof(stdin) and of other reading errors in which case gets() returns NULL.
Please note that gets() will read a full line until '\n' is encountered. The '\n' is not part of the string that is returned. So strcmp(s,"\r\n")!=0 will always be true.
Try:
while (!feof(stdin) && gets(s) && strcmp(s,""))

In most cases the stdin stream inserts '\n' (newline or line-feed) when enter is pressed rather than carriage-return or LF+CR.
char ch ;
while( (ch = getchar()) != '\n` )
{
// update checksum using ch here
}
However also be aware that normally functions operating on stdin do not return until a newline is inserted into the stream, so displaying an updating checksum while entering characters is not possible. In the loop above, an entire line will be buffered before getchar() first returns, and then all buffered characters will be updated at once.

To compare a string in C, which is actually a pointer to an array of characters, you need to individually compare the values of each character of the string.

Related

Is getchar() gets a character from input? [duplicate]

I am confused by a program mentioned in K&R that uses getchar(). It gives the same output as the input string:
#include <stdio.h>
main(){
int c;
c = getchar();
while(c != EOF){
putchar(c);
c = getchar();
}
}
Why does it print the whole string? I would expect it to read a character and ask again for the input.
And, are all strings we enter terminated by an EOF?
In the simple setup you are likely using, getchar works with buffered input, so you have to press enter before getchar gets anything to read. Strings are not terminated by EOF; in fact, EOF is not really a character, but a magic value that indicates the end of the file. But EOF is not part of the string read. It's what getchar returns when there is nothing left to read.
There is an underlying buffer/stream that getchar() and friends read from. When you enter text, the text is stored in a buffer somewhere. getchar() can stream through it one character at a time. Each read returns the next character until it reaches the end of the buffer. The reason it's not asking you for subsequent characters is that it can fetch the next one from the buffer.
If you run your script and type directly into it, it will continue to prompt you for input until you press CTRL+D (end of file). If you call it like ./program < myInput where myInput is a text file with some data, it will get the EOF when it reaches the end of the input. EOF isn't a character that exists in the stream, but a sentinel value to indicate when the end of the input has been reached.
As an extra warning, I believe getchar() will also return EOF if it encounters an error, so you'll want to check ferror(). Example below (not tested, but you get the idea).
main() {
int c;
do {
c = getchar();
if (c == EOF && ferror()) {
perror("getchar");
}
else {
putchar(c);
}
}
while(c != EOF);
}
Strings, by C definition, are terminated by '\0'. You have no "C strings" in your program.
Your program reads characters (buffered till ENTER) from the standard input (the keyboard) and writes them back to the standard output (the screen). It does this no matter how many characters you type or for how long you do this.
To stop the program you have to indicate that the standard input has no more data (huh?? how can a keyboard have no more data?).
You simply press Ctrl+D (Unix) or Ctrl+Z (Windows) to pretend the file has reached its end.
Ctrl+D (or Ctrl+Z) are not really characters in the C sense of the word.
If you run your program with input redirection, the EOF is the actual end of file, not a make belief one
./a.out < source.c
getchar() reads a single character of input and returns that character as the value of the function. If there is an error reading the character, or if the end of input is reached, getchar() returns a special value, represented by EOF.
According to the definition of getchar(), it reads a character from the standard input. Unfortunately stdin is mistaken for keyboard which might not be the case for getchar. getchar uses a buffer as stdin and reads a single character at a time. In your case since there is no EOF, the getchar and putchar are running multiple times and it looks to you as it the whole string is being printed out at a time. Make a small change and you will understand:
putchar(c);
printf("\n");
c = getchar();
Now look at the output compared to the original code.
Another example that will explain you the concept of getchar and buffered stdin :
void main(){
int c;
printf("Enter character");
c = getchar();
putchar();
c = getchar();
putchar();
}
Enter two characters in the first case. The second time when getchar is running are you entering any character? NO but still putchar works.
This ultimately means there is a buffer and when ever you are typing something and click enter this goes and settles in the buffer. getchar uses this buffer as stdin.

Where to use this while loop?

I've just started to learn c programming. I don't know weather this question is silly or not.
Where do i use
while(getchar()! ='\n') ;
When using scanf function in some program the above mentioned while loop is used whereas some other program doesn't use the while loop after the scanf function.
So, where should i use this while loop and where not to?
Use the loop to clean up the rest of a line after an error
You use code similar to the loop in the question when you think there is debris left on a line of input after you (attempted to) read some data from standard input but the operation failed.
For example, if you have:
int n;
if (scanf("%d", &n) != 1)
…recover from error here?…
The error recovery should check for EOF (it is correct to use feof() here — but see while (!feof(file)) is always wrong for how not to use feof()), and if you didn't get EOF, then you probably got a letter or punctuation character instead of a digit, and the loop might be appropriate.
Note that you should always check that the scanf() operations — or any other input operation — succeeded, and the correct check for the scanf() family of functions is to ensure you got the expected number of successful conversions. It is not correct to check whether scanf() returned EOF; you can can get 0 returned when there's a letter in the input queue and you ask for a number.
Beware EOF
Incidentally, the loop in the question is not safe. It should be:
int c;
while ((c = getchar()) != EOF && c != '\n')
;
If the loop in the question gets EOF, it continues to get EOF, and isn't going to do anything useful. Always remember to deal with it. Note the use of int c; too — getchar() returns an int and not a char, despite its name. It has to return an int since it returns every valid character code and also returns a distinct value EOF, and you can't fit 257 values into an 8-bit quantity.
While loop syntax :
while (condition test)
{
// C- statements, which requires repetition.
// Increment (++) or Decrement (--) Operation.
}
while(getchar()! ='\n') ;
Here your condition is getchar()!='\n'.
First getchar() will execute . It will ask input from user. This function returns the character read as an unsigned char cast to an int or EOF on end of file or error. While loop keep continue executing until return value will not match with '\n'
scanf() example : scanf("%s", &str1);
With scanf you can ask user for enter input one time only For more than one input you have to place scanf in loop.
Where as you ask to enter input to user in while loop condition So It will keep asking input from user until EOF signal occur.
When the scanf() format string does not cause it to read the newline from the input buffer.
Most simple format specifiers will not read the newline. However if you use %c, any character may be read, including newline, in which case the loop will need modification:
while( ch != '\n' && getchar() != '\n' ) ;
Where ch is the variable receiving the %c input.
Because console input is normally line-buffered, failing to consume the newline will cause subsequent stdin reading functions to return immediately without waiting for further input, which is seldom what is intended.
You would not use such a loop in cases where multiple fields are entered in a single line but processed in separate scanf() (or other stdin function) calls.

scanf in a while loop reads on first iteration only

NOTE: Please notice this is not a duplicate of Why is scanf() causing infinite loop in this code? , I've already seen that question but the issue there is that he checks for ==0 instead of !=EOF. Also, his problem is different, the "infinite loop" there still waits for user input, it just does not exit.
I have the following while loop:
while ((read = scanf(" (%d,%d)\n", &src, &dst)) != EOF) {
if(read != 2 ||
src >= N || src < 0 ||
dst >= N || dst < 0) {
printf("invalid input, should be (N,N)");
} else
matrix[src][dst] = 1;
}
The intention of which is to read input in the format (int,int), to stop reading when EOF is read, and to try again if an invalid input is received.
The probelm is, that scanf works only for the first iteration, after that there is an infinite loop. The program does not wait for user input, it just keeps assuming that the last input is the same.
read, src, and dst are of type int.
I have looked at similar questions, but they seem to fail for checking if scanf returns 0 instead of checking for EOF, and the answers tells them to switch to EOF.
You need to use
int c;
while((c=getchar()) != '\n' && c != EOF);
at the end of the while loop in order to clear/flush the standard input stream(stdin). Why? The answer can be seen below:
The scanf with the format string(" (%d,%d)\n") you have requires the user to type
An opening bracket(()
A number(For the first %d)
A comma(,)
A number(For the last %d)
The space(First character of the format string of your scanf) and the newline character(\n which is the last character of the format string of your scanf) are considered to be whitespace characters. Lets see what the C11 standard has to say about whitespace characters in the format string of fscanf(Yes. I said fscanf because it is equivalent to scanf when the first argument is stdin):
7.21.6.2 The fscanf function
[...]
A directive composed of white-space character(s) is executed by reading input up to the first non-white-space character (which remains unread), or until no more characters can be read. The directive never fails
So, all whitespace characters skips/discards all whitespace characters, if any, until the first non-whitespace character as seen in the quote above. This means that the space at the start of the format string of your scanf cleans all leading whitespace until the first non-whitespace character and the \n character does the same.
When you enter the right data as per the format string in the scanf, the execution of the scanf does not end. This is because the \n hadn't found a non-whitespace character in the stdin and will stop scanning only when it finds one. So, you have to remove it.
The next problem lies when the user types something else which is not as per the format string of the scanf. When this happens, scanf fails and returns. The rest of the data which caused the scanf to fail prevails in the stdin. This character is seen by the scanf when it is called the next time. This can also make the scanf fail. This causes an infinite loop.
To fix it, you have to clean/clear/flush the stdin in each iteration of the while loop using the method shown above.
scanf prompts the user for some input. Assuming the user does what's expected of them, they will type some digits, and they will hit the enter key.
The digits will be stored in the input buffer, but so will a newline character, which was added by the fact that they hit the enter key.
scanf will parse the digits to produce an integer, which it stores in the src variable. It stops at the newline character, which remains in the input buffer.
Later, second scanf which looks for a newline character in the input buffer. It finds one immediately, so it doesn't need to prompt the user for any more input.

It seems I must first press enter before getchar() gets EOF

I'm starting to learn about EOF and I've written the following simple program :
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void main()
{
int i=0;
while(getchar()!=EOF)
{
i++;
}
printf("number of characters : %d \n",i);
}
The thing is, when I write a string, press enter and then press Ctrl+Z the output is the number of the characters I wrote plus 1 (for the EOF). However, if I write a string and, without changing line, press Ctrl+Z the while loop does not terminate. Why is that?
First things first, EOF is signalled only when Ctrl + Z is at the very beginning of a line. With that on mind:
On your first try with your input (10 characters) and then Enter, you actually push your input\n to the input stream, which gets read character by character through getchar, and there are 11 characters now with the addition of that new line at the end thanks to your Enter.
On the new line, you then use the Ctrl + Z combination to signal the EOF, and you indeed do that properly there; signal the EOF and get 11 as the result.
It's strange that you were expecting to see 10 here. What if you were to have an input of multiple lines? Would you like it to not count for new lines? Then you could use something like:
int onechar;
while ((onechar = getchar( )) != EOF)
{
if (onechar != '\n')
i++;
}
Or even more further, are you always expecting a single line of input? Then you might want to consider changing your loop condition into following:
while(getchar( ) != '\n')
{
i++;
}
Oooor, would you like it to be capable of getting multi-line input, as well as it to count the \n characters, and on top of all that, just want it to be able to stop at Ctrl + Z combinations that are not necessarily at the beginning of a line? Well then, here have this:
// 26 is the ASCII value of the Substitute character
for (int onechar = getchar( ); onechar != EOF && onechar != 26; onechar = getchar( ))
{
i++;
}
26, as commented, is the Substitute character, which, at least on my machine, is what the programme gets when I use Ctrl + Z inappropriately. Using this, if you were to input:
// loop terminated by the result of (onechar != 26) comparison
your input^Z
You would get 10 as the result and if you were to input:
// loop terminated by the result of (onechar != EOF) comparison
your input
^Z
You would get 11, counting that new-line which you did input along with all the other 10 characters before that. Here, ^Z has been used to display the Ctrl + Z key combination as an input.
Input uses buffers. The first getchar requests a system-level read. When you press enter or ctrl-z the read returns the buffer to the program. When you press enter the system also adds a newline character to the buffer before returning it. Eof is not an actual character but results from reading an empty buffer.
After the control is returned to the program, getchar sequentially reads each character in the returned buffer and when it's finished it requests another read.
In the first case, getchar reads the buffer including the newline character. Then since the buffer is empty getchar requests another read which is interrupt by pressing ctrl-z, returning an empty buffer and resulting in EOF.
In the second case, pressing ctrl-z simply returns the buffer and after getchar is finished reading it, it requests another read which isn't finished since you never press ctrl-z or enter again.
It's not your while loop that never finishes but merely the read call. Try to press ctrl-z twice in the second case.
I saw here topic related to this. What you need to do is to set pts/tty into non-cannonical mode and do it with somekind of TCSANOW(do attr changes immediately).
You do it using functions from termios.h , operating on struct termios;

regarding inputing enter key

char ch;
ch=getch();
printf("%d",ch);
When I input enter key then the output displayed is
13
But ascii code for new line is 10, so why 13 is displayed?
The following code runs infinite time on inputting enter key
char *ch=malloc(100);
do
{
*ch=getch();
ch++;
}while(*(ch-1)!='\n');
In some systems, "Enter" is really two characters: Carriage Return followed by Line Feed.
End-of-line is always represented by '\n' in C, regardless of whether the underlying system represents it as \n, \r or \r\n, or something else. The value of '\n' is probably 13 on your system.
C doesn't require ASCII, but ASCII has a carriage return character and a line feed character. Don't use the numeric values for any of them, since C doesn't require ASCII - always use the character literal '\n' for portability.
getch() is not a standard C function, so who knows what you're trying to do with it, but when using the C standard I/O, library, you're testing for end of line, not for some specific key like Enter, and you do that by testing for '\n'. Obviously if you're using those functions on a file, it wouldn't make any sense to talk about keys.
I am assuming you are using Windows OS. When you press the enter key, then '\r' character also called carriage return or CR is read by the getch function. See key-codes. You are comparing this with the newline character '\n' which obviously evaluates to false and you continue looping. So you should do this instead:
char *ch = malloc(100);
// check ch for NULL
do {
*ch = getch();
ch++;
} while(*(ch-1) != '\r'); // compare with carriage return
ASCII value of '\r' is 13 and that explains your output.getch function is not standard and not portable. Also, it has been deprecated. You should use the standard getchar function instead. Additionally, read this - Why doesn't pressing enter return '\n' to getch()?

Resources