C: Using scanf to accept a predefined input length char[] - c

I'm writing a C program that needs to accept user input of up to 100 characters, but the user is allowed to input less than that limit. I'm trying to implement this idea with a while loop that continues to accept char input until the user presses enter (ascii value of 13), at which point the loop should break. This is what I've written:
char userText[100]; //pointer to the first char of the 100
int count = 0; //used to make sure the user doens't input more than 100 characters
while(count<100 && userText[count]!=13){ //13 is the ascii value of the return key
scanf("%c", &userText[count]);
count++;
}
Launching from the command line, if I enter a few characters and then press enter, the prompt simply goes to a new line and continues to accept input. I think the problem lies with my lack of understanding how scanf receives input, but I'm unsure of how to change it. What can I do to make to loop break when the user presses enter?

Because you read into &userText[count] and then do count++, so you loop condition userText[count]!=13 is using the new value of count. You can fix it with:
scanf("%c", &userText[count]);
while(count<100 && userText[count]!='\n'){
count++;
scanf("%c", &userText[count]);
}
And as Juri Robl and BLUEPIXY are pointing out, '\n' is 10. 13 is '\r', which isn't what you want (most likely).

while(count<100 && scanf("%c", &userText[count]) == 1 && userText[count]!='\n'){
count++;
}

You should probably check against \n (=10) not 13. Also you check against the wrong count, it is already one to high.
int check;
do {
check = scanf("%c", &userText[count]);
count++;
} while(count<100 && userText[count-1]!='\n' && check == 1);
userText[count] = 0; // So it's a terminated string
On the other hand you could use scanf("%99s", userText); which allows up to 99 chars input (and one at the end for the 0).
The check for check == 1 looks for an error in reading, for example an EOF.

Related

Why does a while loop run infinitely instead of waiting for more input from fgets()?

Boy, this darn thing is stumping me. I want to create a loop that verifies if a user has entered an int (and not some other data type). To do this, I get the first character of the user's input using fgets(), and then I check if that character is a digit (that is the minimum part of my task for the code to break).
char input[2];
int main(){
printf("Please enter the minimum value the random number can be: ");
fgets(input, sizeof(input), stdin);
printf("%c", input[0]);
if(!isdigit(input[0])){
int escape = 0;
while(escape == 0)
printf("Try again: ");
fgets(input, sizeof(input), stdin); //This will now overwrite whatever was in 'input'
if (isdigit(input[0])) //Will keep looping back to the fgets(), asking for new input each time until you enter a number.
escape = 1;
flushInpt();
}
In the above code (assuming all the right libraries are #included), it should ask for input (which it does) then check if the first character of that input is a digit (which it does) and if it is not a digit it should enter a while loop where it prints "Try again: " with a new fgets() that waits for the user to put in new input. It stays inside that while loop until they input a digit as the first char, at which point it breaks out of the loop (this is the part it does not do).
But whenever I input a non-digit the first time, it enters the while loop as expected, but then infinitely prints "Try again: " over and over again without ever stopping at the getsf() statement to wait for new input? My question is why does it loop infinitely?
I have verified as well that the flushInpt() function is not the culprit, as the problem occurs whether that call is in the loop or not. In case you were wondering, flushInpt is just a basic loop function that walks through the input buffer and removes anything that might be there.
char ch;
void flushInpt(){
while ((ch = getchar()) != '\n' && ch != EOF)
continue;
}
You're missing curly braces:
while(escape == 0)
{ //<--
printf("Try again: ");
fgets(input, sizeof(input), stdin); //This will now overwrite whatever was in 'input'
if (isdigit(input[0])) //Will keep looping back to the fgets(), asking for new input each time until you enter a number.
escape = 1;
flushInpt();
} //<--
I guess this block is your while loop.

Entering while loop repeatedly before stopping at getchar()

I'm writing a simple C program in which I want to validate my user's input for integers from 1-9.
The logic for my code seems fine but for some reason if I type "lll" for my input (or any other random input not between 1-9), it will show the error message inside the while loop a couple of times before actually stopping at the getchar() once again.
/**
* Validate user input and reprompt if invalid
* #return input - Users valid input
*/
int validateUserInput() {
int firstInput = getchar() - 48;
int secondInput = getchar();
while(secondInput != 10 || firstInput >= 10 || firstInput <= 0 ){
printf("Invalid Input. Please try again. \nEnter a number between (1-9): ");
firstInput = getchar() - 48;
secondInput = getchar();
}
return firstInput;
}
The logic is that:
Invalid Input - If the second input != 10 which means that the second char is something other than the enter key.
Invalid Input - If the first char subtracted 48 is higher than 9 or less than 1 then it's too high.
The logic seems fine to me but here's some output when I enter random characters:
Enter a number between 1-9: lllll
Invalid Input. Please try again.
Enter a number between 1-9: Invalid Input. Please try again.
Enter a number between 1-9: Invalid Input. Please try again.
Enter a number between 1-9: Invalid Input. Please try again.
Enter a number between 1-9: Invalid Input. Please try again.
Enter a number between 1-9: Invalid Input. Please try again.
Enter a number between 1-9:
Why does it repeat that message so many times before actually letting me enter input again? This is all that's wrong with my program.
Your logic is fine. But the invalid characters you input still remain in the input buffer. So, the subsequent calls to getchar() read them.
Whenever you hit an invalid input, you want to ignore them all. You can read them out using a loop like this:
while(secondInput != 10 || firstInput >= 10 || firstInput <= 0 ){
printf("Invalid Input. Please try again. \nEnter a number between (1-9): ");
int i;
while((i=getchar()) != '\n' && i != EOF);
...
Having said that it's generally hard to use getchar() and scanf() family functions to correctly read interactive input and do error checking. A better way would be to read lines (such as fgets()) and parse/error check them.
Because you entered 5 chars. 5x L. You are checking only one char, but by what did you wrote I guess you want to check whole input charr array. So then you cant use getChar().

Check the input of the scanf

I want to write code that checks if the user enters correct input, i.e 1, 2, 3 or 4. Otherwise, the message "input error" is printed. If the user enters a letter for example, since the input variable in the scanf is char type, it works too.
But in the case of multiple characters, I throught about the following solution: I try to enter all the characters into a char array and to check how many members into it. I wrote the following code:
char option;
int countIn;
char inArray[10];
do { //while option!=4
scanf("%c", &option);
while (countIn < 10 && scanf("%c", &option) != -1 && option != '\n') {
inArray[countIn] = option;
countIn++;
}
if (countIn > 1) { option = 10; }
else { option = inArray[0]; }
countIn = 0;
} while (option != '4');
The problem is when I enter 1 for example, the program works well, but for the second loop iteration, the scanf doesn't work and the program does automatically the part 1 again and again.
what did I do wrong?
Replace both scanf() calls with:
scanf(" %c", &option);
Note the space in the format string, which tells scanf to consume all the whitespaces. The reason why it seems to skip is the newline left in the input buffer by previous input.
From scanf():
ยท A sequence of white-space characters (space, tab, newline,
etc.; see isspace(3)). This directive matches any amount of
white space, including none, in the input.
Note that even though EOF is typically defined as -1, it's not safe to assume so. I would strongly suggest to use EOF instead of -1.

How to terminate a loop when a letter entered in C?

In my task I need to use a loop and get an input between 1-5, if i get any other input i need to keep iterating until i get 1-5.
Could you please tell me what am i doing wrong?
Part of my code:
int rateSelected, weeklyHours;
printf("Enter the number corresponding to the desired pay rate or action:\n");
printf("1) %.2lf$/hr 2) %.2lf$/hr\n", RATE1, RATE2);
printf("3) %.2lf$/hr 4) %.2lf$/hr\n", RATE3, RATE4);
printf("5) Quit\n");
while ((scanf("%d", &rateSelected)) != EOF && rateSelected != 5)
{
if (rateSelected > 5 || isalpha(rateSelected) ==1){
printf("please enter a number between 1-5:\n");
continue;
}
printf("Now enter your weekly hours:\n");
scanf("%d", &weeklyHours);
ChoosePayRate(rateSelected, weeklyHours);
}
tnx
The problem is your use of %d format specifier. When letters are entered instead of digits, scanf returns zero to indicate that nothing is read. If you would like to allow entering letters along with digits, you should either add a read of a string when scanf returns zero, or always read into a string buffer, and then use sscanf or atoi to convert the string to integer.
You better use fgets() and strtol() for this. Scanf and the line-buffering of stdio is not very helpful together...
char line[LINE_MAX];
do {
fgets(line, sizeof(line), stdin);
} while(!isdigit(line[0]));
int choice = strtol(line, NULL, 10);
isalpha(rateselected) will never be true because you are storing an int in rateselected.
scanf("%d",rateselected) allready takes care of catching character input, and returns 0 if that is the case. So you should change the isalpha test to a rateselected == 0 test.
Also, scanf will never return EOF. It will return 0, and then you need to test feof(stdin) to see if you really hit the end of input. (which would correspond to a ctrl-Z for keyboard input).
Remove the isalpha(rateSelected).
isalpha() checks if the value passed as parameter is an alphanumeric character - but you are passing the int value which you have just read.
However, this is still not sufficient - you would need to catch the return value from scanf() to check if scanf() has actually read an int. But if no int was entered, the characters are not discarded so that the next scanf() will again try to convert them, which leads to an endless loop.
Better use the solution provided by #dasblinkenlight.
Use this:
int e;
while ((e = scanf("%d", &rateSelected)) != EOF)
{
scanf("%*[^\n]"); // this clean your input buffer
if (e==0 || rateSelected>5 || rateSelected<1) {
printf("please enter a number between 1-5:\n");
continue;
}
instead of
while ((scanf("%d", &rateSelected)) != EOF && rateSelected != 5)
{
if (rateSelected > 5 || isalpha(rateSelected) ==1){
printf("please enter a number between 1-5:\n");
continue;
}

Insert values through getchar

I am unable to insert a value into ptr char array:
int main() {
char S[MAX_STRING_LENGTH],*str;
int total,j=0,i=0;
char ptr[16],c;
scanf("%d",&total);
for(i=0;i<total;i++){
c=getchar();
do{
ptr[j]=(char)tolower(c);
j++;
c=getchar();
}while(c!='\n' && j<15 );
ptr[j]='\0';
printf("j=%d , %s",j,ptr);
}
}
The reason for this I know:
I put do-loop exit on '\n' and I'm using enter('\n') itself after inserting value in total.
That way it is exiting loop without insertion of value.
How can I correct it?
What you are doing is kind of unsafe. First of all depending on the operating system you may have to terminate on '\r' not only on '\n'. Second you never check the size of the input to be within 15 symbols. Please note I say 15 symbols because it is usually good practise to leave one cell for the zero terminating character.
If the input does not contain whitespaces(space or tab) I would advice you to use scanf("%s") as it is less error-prone. Also you will eliminate the need for a while loop.
If that is not the case, you should add a check for '\r' as well and also you will have to remove the newline character that you type after the total value. Like so:
scanf("%d", &total);
getchar();
This is needed because otherwise the newline after total will be the first char you read in your while loop and thus you will exit on the first iteration of the cycle.
If you debug your program you will see that this happens.
Because scanf did scan \n in the input stream but it didn't store it in &total . The next time you getchar() it will get it \nwhich cause the do-while only can execute once.
add
getchar();
after scanf.
input stream :
the next you getchar() will from here
|
|
A A A A A A \n A A A A A A
^
|
the variable total store string before this
During scanf you will enter some no(no of characters) say 10 and will hit enter. Now this '\n\ will not be read by scanf and it's there in input stream. During first iteration, getchar() will read this '\n' and will terminate the loop after first iteration. So better put a getchar() after scanf() so as no make inputstream to empty. apart from this,
You haven't put any check beyond array index limit. It maybe the case user keep entering the characters and you endup trying to insert beyond 16 places.
while(c != '\n' && j < 15);
Will solve your problem.

Resources