C, can not read input - c

#include <stdio.h>
#include <stdlib.h>
int main()
{
int i,j;//count
int c;//for EOF test
int menu;
unsigned int firstSize = 12811;
unsigned int lastSize;
char * text=malloc(firstSize);
if(text == NULL){
printf("\n Error. no Allocation.");
exit(-1);
}
printf("\n for input 1e,for autoinput press 2.");
scanf("%d",&menu);
if(menu==1){
printf("enter text..");
c = EOF;
i = 0;
lastSize = firstSize;
while (( c = getchar() ) != '\n' && c != EOF)
{
text[i++]=(char)c;
//if i reached maximize size then realloc size
if(i == lastSize)
{
lastSize = i+firstSize;
text = realloc(text, lastSize);
}
}
This is the part of code which is where the problem lies.
Output when I type 1 for the scanf is:
for input 1e,for autoinput press 2.
1
enter text..
It does not let me to give input for the getchar().
But when I delete scanf for menu and use menu=1;, I can easily give input for the getchar() and it gives me output correctly:
printf("\n for input 1e,for autoinput press 2.");
scanf("%d",&menu);
instead of that
printf("\n for input 1e,for autoinput press 2.");
//scanf("%d",&menu);
menu=1;
Is it about printf scanf issues that I don't know about? In java, before taking second input, we need to put some blank. Is it like that?

The problem is that you press Enter after entering a number for your scanf. The number is consumed by the scanf while the newline character generated by the enter key press resides in the standard input stream(stdin).
When the execution of the program reaches the while loop:
while (( c = getchar() ) != '\n' && c != EOF)
getchar() sees the newline character, grabs it, assigns it to c and then, the loop doesn't execute as the condition(c != '\n') is false. This is what you were unexpecting.
You can add
while (( c = getchar() ) != '\n' && c != EOF);
anywhere between the scanf and your getchar() to clear the stdin.
An alternative way would be to use scanf("%d%*c",&menu); as suggested by #user3121023 in the comments. %*c instructs scanf to read and discard a character. It will discard the newline character if the user had typed in a number and then pressed enter for the scanf.
Other stuff:
c = EOF; isn't required. Neither is the cast here: text[i++]=(char)c;. You also do not need two variables lastSize and firstSize. You should also check the return value of realloc.

Related

While GetChar != EOF terminating inconsistently

I have these two blocks of code, the aim of both of which is to get some user inputs, to make a cryptography script.
int keyPrompt(){
/* this prompts the user for the Caesar encryption key */
int c;
printf("Enter key value between 1-9: ");
while((c=getchar()) != EOF && c != '\n'){
return c;
}
}
int cryptPrompt(){
/* this asks the user whether they want to encrypt or decrypt */
int d;
printf("Do you want to encrypt or decrypt?(E/D): ");
while((d=getchar()) != EOF && d != '\n'){
/*
if(d == 'E'){
return 1;
}
else if (d == 'D' ){
return -1;
}
*/
return d;
}
}
The problem I'm having is that when I run the file, the first while loop behaves as I expect it to: I enter a value, hit enter and it goes to the next line. With the second while loop, when it executes the function, it skips asking the user for an input and simply goes straight to the next line of good, not storing any return value.
Any idea why it's doing this?
Consider what this code does:
int keyPrompt(){
/* this prompts the user for the Caesar encryption key */
int c;
printf("Enter key value between 1-9: ");
while((c=getchar()) != EOF && c != '\n'){
return c;
}
}
After printing the prompt, it reads an input character. If that character is an EOF or a newline, it exits the loop and falls off the end of the function (without a return, which leads to undefined behavior if the returned value is not ignored). If its NOT an EOF or newline, it returns the character.
In no case will the while loop ever actually loop.
Consider what happens if you call this code and enter a key+newline. The key will be read and returned, and the newline will be left in the input buffer. Now consider what happens if you call another function like this -- the first thing it will read is the newline left over from the keyPrompt function...

Flushing standard input buffer in C

This code is a simplification from a larger project I'm working on and it sums up the problem in a simple example. I am obtaining input from the user, their name, and then clearing the buffer from any input that did not fit in the C-string. The problem is that After entering the name, the user has to push enter twice for the program to respond, and because I am using getchar() to flush the buffer there is just a clear misunderstanding in the logic of the loop I created. How can I keep the user from entering Enter twice, in otherword what am I missing? Thanks!
#include "stdafx.h"
#include <stdio.h>
#include <string.h>
#define BUFFSIZE 10
int main(void)
{
unsigned char name[BUFFSIZE];
printf("ENTER YOUR NAME: ");
fgets(name, BUFFSIZE, stdin);
name[strcspn(name, "\n")] = '\0';
//flush the input buffer
int flush;
while (flush = getchar() != '\n' && flush != EOF);
printf("Your name is: %s!\n ", name);
printf("Press enter to continue...");
getchar();
return 0;
}
The problem in your program is that you don't distinguish the two cases: a) the user's input fit into the buffer versus b) the input didn't fit. What distinguishes these cases is the presence of the newline character in the buffer. That information is destroyed when you overwrite that character:
fgets(name, BUFFSIZE, stdin);
name[strcspn(name, "\n")] = '\0';
What we need here is something like:
size_t nlcspn = strcspn(name, "\n");
bool incomplete = name[nlcspn] == 0;
name[nlcspn] = 0;
Now we have an incomplete flag to test. Only when this flag informs that the input didn't contain a newline, then we can go ahead and complete the "get line" operation of fgets with a little loop that scans until a newline is received. (In that case, some error recovery might also be a good idea, like informing the user that the input had been too long, and creating an opportunity to rectify that).
Another thing to note is that fgets returns a value which should be checked. If it returns a null pointer, it means that the stream ended before any input was consumed. The problem is that in that case, fgets doesn't put anything into the array. The array retains its previous value, which may be previously read input, or an indeterminate value ("garbage") due to uninitialized contents.
First, the remainder of the line should not be consumed if there is no remainder, otherwise an additional line will be skipped over. Secondly, assignment has a lower precedence than most operations, meaning that flush = is evaluated after
getchar() != '\n' && flush != EOF.
When comparing the result at assignment explicit parenthesis should be added:
flush = getchar() != '\n' to (flush = getchar()) != '\n'
Alternatively the assignment can be moved outside of the conditional, see below.
The following edit uses strlen to get the final character, and moves the assignment into the loop.
#include <stdio.h>
#include <string.h>
#define BUFFSIZE 10
int main(int argc, char *argv[])
{
char name[BUFFSIZE];
size_t len;
int c;
printf("ENTER YOUR NAME: ");
fgets(name, BUFFSIZE, stdin);
len = strlen(name);
if (name[len - 1] == '\n')
name[len - 1] = '\0';
else
do
c = getchar();
while (c != '\n' && c != EOF);
printf("Your name is: %s!\n ", name);
printf("Press enter to continue...");
getchar();
return 0;
}
My wild guess just reading your code is that the error is here :
while (flush = getchar() != '\n' && flush != EOF);
You want to getchar() until the output buffer is '\n' or EOF, right ? Then try this :
while (flush = getchar() != '\n' || flush != EOF);

EOF not working as expected (C)

I'm trying to use the EOF function but it doesn't work as I expect it. In the debugger mode it doesn't detect the second "scanf" function and just carries on. It keeps on missing out the "scanf" function now and then. Code is posted below
int main() {
char tempString;
int i = 0;
printf("Enter your letter\n");
scanf_s("%c", &tempString);
while (tempString != EOF) {
printf("You entered:%c\n", tempString);
scanf_s("%c", &tempString);
}
}
I have also tried it using the getchar() function but the same thing occurs, code is posted below:
int main() {
char tempString;
int i = 0;
printf("Enter your letter\n");
while ((tempString = getchar()) != EOF) {
printf("You entered:%c\n", tempString);
}
}
Thanks for reading
EDIT:
Firstly you omitted the length argument required by scanf_s for %c and %s formats.
Second, the %c format takes the next character from the input buffer. At the second (and subsequent) entries there was a newline left in the input buffer from the first input. Adding a space before the %c format specifier cleans off that leading whitespace.
Other formats, such as %s and %d do ignore leading whitespace, but not %c.
Thirdly, with scanf the use of EOF is not the way to go, you should control the loop with the return value from scanf which tells you the number of items successfully read.
This program starts by using scanf_s. The second entry ignores the newline after the first entry.
Then it moves to using getchar. In this test the function return value is int, so that's my data type here. That way EOF (-1) won't conflict with any required character data. Note that getchar starts by reading the newline left after the previous scanf_s (which only ignores leading whitespace.
#include <stdio.h>
int main(void)
{
char ch_scanf; // char type
int ch_getchar; // int type
printf("Using scanf_s\n");
if (scanf_s(" %c", &ch_scanf, 1) == 1) { // consumes any leading whitespace
printf("scanf_s value: %d\n", ch_scanf);
}
if (scanf_s(" %c", &ch_scanf, 1) == 1) { // consumes any leading whitespace
printf("scanf_s value: %d\n", ch_scanf);
}
printf("\nUsing getchar\n");
while ((ch_getchar = getchar()) != EOF) {
printf("getchar value: %d\n", ch_getchar);
}
return 0;
}
Sample session:
Using scanf_s
A
scanf_s value: 65
B
scanf_s value: 66
Using getchar
getchar value: 10
C
getchar value: 67
getchar value: 10
^Z
Finally if you want to use the standard library function scanf without MSVC ticking you off, you can do it like this
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
try this
#include <stdio.h>
int main(void) {
char tempString;
printf("Enter your letter\n");
while (scanf_s("%c%*c", &tempString, 1) != EOF) {//%*c for consume newline, 1 is buffer size
printf("You entered:%c\n", tempString);
}
return 0;
}
int tempString;//int for check EOF
printf("Enter your letter\n");
while ((tempString = getchar()) != EOF) {
printf("You entered:%c\n", tempString);
getchar();//consume newline
}
The behaviour of scanf() function in C
Is to read the input from the keyboard buffer till it encounters EOF (ie; till we
press enter key)
In general, it is not advisable to use "%c" in C to read an input character because
The value is collected in keyboard buffer till we hit enter and we could not restrict user entering single character
So, the best way to obtain a character is by using getchar() function.
In the program you have provided you can use any other character to check for end and not EOF since it is used in scanf() implementation to mark the input end.
You may other keys like esc to check for the end
#include <stdio.h>
#include <stdlib.h>
#define esc 27
int main()
{
char ch;
while((ch = getchar()) != esc) {
//print the entered character here
}
}
To know in depth about scanf() implementation look into this scanf() source code

Entering more characters skips prompts

well I have a buffer of I'm assuming 10 characters. I notice when I enter 9 characters though it will skip prompt EX.
Enter a p value:
123456789
Enter a q value:
Enter a k value:
But if I put in 8 or less it will accept it normally as the program is intended, even if the user inputs letters or special characters.
My code:
#include <stdio.h>
#include <math.h>
#include <limits.h>
#include <ctype.h>
int main()
{
char pbuffer[10], qbuffer[10], kbuffer[10];
int p=0, q=0, k=0;
int r, i, Q, c, count, sum;
char a[3];
a[0]='y';
while(a[0]=='y' || a[0]=='Y')
{
printf("Enter a p value: \n");
fgets(pbuffer, sizeof(pbuffer), stdin);
p = strtol(pbuffer, (char **)NULL, 10);
printf("Enter a q value: \n");
fgets(qbuffer, sizeof(qbuffer), stdin);
q = strtol(qbuffer, (char **)NULL, 10);
printf("Enter a k value: \n");
fgets(kbuffer, sizeof(kbuffer), stdin);
k = strtol(kbuffer, (char **)NULL, 10);
while(p<q+1)
{
Q=p;
sum=0;
count=0;
while(Q>0)
{
count++;
r = Q%10;
sum = sum + pow(r,k);
Q = Q/10;
}
if ( p == sum && i>1 && count==k )
{
printf("%d\n",p);
}
p++;
a[0]='z';
}
while((a[0]!='y') && (a[0]!='Y') && (a[0]!='n') && (a[0]!='N'))
{
printf("Would you like to run again? (y/n) ");
fgets(a, sizeof(a), stdin);
}
}
return 0;
}
fgets will read in as many characters as it can until it hits either a newline, EOF, or the size of the buffer. It also saves one extra character for a string-terminating \0. So, if you type in 123456789\n and have a 10-character buffer, fgets knows that it can only fit 9 characters in that buffer, so it reads in the first 9 and appends a NULL, giving you 123456789\0 in your buffer, and \n still in STDIN. Then, you call fgets a second time. It doesn't wait for input, because there is already a \n in STDIN, so it reads up to that \n, which happens to be only one character. So, your second buffer is now \n\0, and STDIN is now empty.
Either make your buffers large enough to store the strings that you're going to input, or flush STDIN after every fgets. Likely something like:
while((c = getchar()) != '\n' && c != EOF)
/* Ignore the character */ ;
Add this line after the fgets
scanf("\n");
Instead of reading into a char buffer first, you could use scanf(), e.g. scanf("%d", &p) could replace both fgets() and strtol().
Actually fgets retains the \n character when the size argument provided to it is less than the characters entered. In your case you provided value 10 as size to fgets.
so When you enter 9 characters, it fills the buffer with them and waits for an enter from you to stop reading. And when you press the enter it just puts the null character in the end of it and forward the enter to next prompt and hence skipping it.
check the examples in the answer to a question https://stackoverflow.com/a/11180652/1386897.
Flush the stdin after to the calls to fgets using
int c;
while((c = getchar()) != '\n' && c != EOF);
The reason why fgets dosen't wait for the user to enter data is because fgets knows that the buffer is full (9 chars and one space for \0) and appends a \0 in the end of the string and leaves the \n in the stdin which is taken by the next fgets

Why is getchar() reading '\n' after a printf statement?

I'm prompting the user to enter the length of an array, initializing a char[] array with this input, and then prompting the user to type a message to enter into the char[] array.
I'm reading the first character of the user's message with getchar().
However, getchar() is reading the new-line escape '\n' before it is reading any user input. It seems to be getting '\n' from the previous printf statement that prompts the user...
Here is the relevant code:
#include <stdio.h>
int main(void) {
int len = 0,
originalLen = 0;
printf("\n\nWhat is the length of the array? ");
scanf("%d", &originalLen);
char str[originalLen]; // intitializing the array
printf("Enter a message to enter into the array: ");
char target = getchar();
str[len] = target;
// why is getchar() reading '\n'?
if (target == '\n') {
printf("\n...what happened?\n");
}
return 0;
} // end of main
It's because the previous scanf does not read the newline after the number.
This can be solved two ways:
Use e.g. getchar to read it
Add a space after the scanf format (e.g. scanf("%d ", ...))
You can use getchar in a loop to flush out stdin before reading the next character.
while((target = getchar()) != '\n' && target != EOF)
When you enter the number and hit the ENTER key, a number and a character are placed in the input buffer, they are namely:
The entered number and
The newline character(\n).
The number gets consumed by the scanf but the newline remains in the input buffer, which is read by getchar().
You need to consume the \n before calling getchar() by using:
scanf("%d ", &originalLen);
^^^
This tells scanf to read the number and an additional character, which is \n.

Resources