Hi I need to prompt a user for some input and then validate it. The input must only be validated if it is a positive integer and not greater then 23. The only problem I am having with this is when the user enters a non-numerical input like "hello." The code below does not successfully detect that any input is non-numerical and though I have tried many methods to do this, none of them seem to work. Below is the closest I seem to have gotten by taking the input as a string then converting it to an integer, however it still does not work. Any help would be appreciated.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int main(void) {
int height;
char input[50];
int cont = 0;
while (cont == 0) {
printf("Please provide a non-negative integer no greater than 23.\n");
scanf("%s", &input);
height = atoi(input);
if (height <= 23 && height >= 0) {
cont = 1;
} else {
//do nothing
}
}
printf("Valid Input.\n");
return 0;
}
The atoi() function has no provision for returning an error indicator. Instead, you can use the strtol() function:
char *end;
height = strtol(input, &end, 10);
if (end == input) {
// no digits were entered
puts("Invalid input.");
continue;
}
#include <stdio.h>
int main(void) {
int height;
while(1){
printf("Please provide a non-negative integer no greater than 23.\n");
//if(2==scanf("%d%c", &height, &nl) && nl == '\n' && 0<= height && height <= 23)//more limited for "number\n"
if(1==scanf("%d", &height) && 0<= height && height <= 23)
break;
//Clear of invalid input
while(getchar()!='\n')
;
}
printf("Valid Input(%d).\n", height);
return 0;
}
I am assuming that you have to consider the whole input into the consideration rather than only certain parts like "12jjj" and "23h" as invalid.
In my opinion, since 23 is only 2 char, so there is no harm in checking the length of the string and the individual characters.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
bool ValidateInput (char * input, int &output)
{
if (strlen(input) > 2)
return false;
for (int index = 0; index < strlen (input); index++)
{
if ((input[index] < '0') || input[index] > '9')
return false;
}
output = atoi(input);
return true;
}
int main(void) {
int height;
char input[50];
int cont = 0;
while (cont == 0) {
printf("Please provide a non-negative integer no greater than 23.\n");
scanf("%s", input);
if (ValidateInput (input, height))
break;
}
printf("Valid Input.\n");
return 0;
}
I hope this helps.
Related
I write this program to do validation of selection (integer type variable) that entered by users. But the problem is after a valid input, the next invalid input (e.g: character type variable) will not be stored in the integer variable (selection). How can I solve this?
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#pragma warning (disable:4996)
void main()
{
int selection;
while (1)
{
while (1)
{
printf("Enter Your Selection (0-4) > ");
scanf("%d", &selection);
rewind(stdin);
if (!selectionCheck(&selection, 0, 4))
printf("Invalid\n");
else break;
}
printf("Success\n");
}
system("pause");
}
int selectionCheck(int *input, int min, int max)
{
char str[100] = "";
itoa(*input, str, 10);
if (isdigit(str[0]))
{
if (*input < min || *input > max)
return 0;
else return 1;
}
else
{
return 0;
}
}
Some notes:
1) You aren't checking the scanf() return value, and this is very usable: the negative return means that the entered characters can't be converted to int (because of "%d" format), and the return value equal 0 means that the input is empty (no characters entered).
2) In case that the user entered wrong character(s) (not digit(s)), the input buffer will remain busy until you read it in other way. Good idea is to use additional scanf("%s") here to read any characters as string, so buffer will be empty after this call. Using rewind() is not enough here.
3) There is no need to additional checking of input in selectionChecking() for isdigit(), because "%d" format in scanf() doesn't allow to read anything else but number.
4) There is no need to pass pointer to selection value in selectionChecking() call - it will be enough to pass it as value.
So, try this below:
// declaration of 'selectionCheck()'
int selectionCheck(int input, int min, int max);
void main()
{
int selection;
while (1)
{
while (1)
{
printf("Enter Your Selection (0-4) > ");
int ret = scanf("%d", &selection);
if (ret < 0) // invalid characters on input
{
printf("Invalid characters\n");
scanf("%s"); // empty buffer, reading it as string and putting readed characters to nowhere ;)
continue; // go to top of loop
}
if (ret == 0) // empty input
{
printf("No (empty) input\n");
continue; // go to top of loop
}
// here 'ret' is greather than 0, so valid number was entered
if (selectionCheck(selection, 0, 4)) // is value between 0 and 4 ?
break; // yes, success, break current loop!
printf("Invalid value\n");
}
printf("Success\n");
}
system("pause");
}
int selectionCheck(int input, int min, int max)
{
if (input < min || input > max)
return 0;
else
return 1;
}
Of course, you can write 'selectionCheck()' more condensed:
int selectionCheck(int input, int min, int max)
{
return (input < min || input > max) ? 0 : 1;
}
or simply:
int selectionCheck(int input, int min, int max)
{
return (input >= min && input <= max);
}
Edit: Since I understand that I need to provide more info to make it clear for you guys, I added the main function and the getchoice and also two images of the program running. My problem is that after entering the endword, I want to see the menu first and then make a choice, whereas it prompts me to give an input without showing the menu.
This function is part of a bigger program, but this is where a problem occurs.
It reads words inputed, places them into an array, until the keyword ****END is entered. However, when this keyword is entered, it doesn't go immediatelly in the specified if clause (you will see that in the code). I'm a newbie and it could be something really obvious, but any help is greatly appreciated.
#include <string.h>
#define M 50
#define N 15
void getText(char a[M][N])
{
int i, j;
char temp[N];
for (i = 0; i < 50; i++) {
for (j = 0; j < 15; j++) {
if (i == 49 && j == 14) {
printf("Maximum length of text reached.\n");
}
scanf("%s\n", temp);
if (strcmp(temp, "****END") == 0) {
printf("You entered the endkey.\n");
return;
}
strcpy(a[i], temp);
}
}
}
int main(){
int input;
while(1){
input = getChoice();
if(input == 1){
getText(text);
}
else if(input == 2){
getDictionary();
}
else if(input == 3){
correctText();
}
else if(input == 4){
saveText();
}
else if(input == 5){
getStats();
}
else if(input == 6){
break;
}
}
return 0;
}
int getChoice(){
int temp;
printf("Choose function:\n1: Enter text\n2: Enter dictionary\n3: Correct text\n4: Save text\n5: Get text statistics\n6: Exit program\n");
scanf("%d", &temp);
return temp;
}
Entered the endword and now it waits for input instead of showing the menu.
I inputed 2 for the second program function, then it showed the menu and proceeded to function 2.
Apart from the unnecessary double-nested loop, this line
scanf("%s\n", temp);
should be
scanf("%s", temp);
Usually, you should not try to match trailing whitespace with scanf, and the format specifier %s automatically filters out leading whitespace (but note that %c does not).
There are other faults and the code presented was originally incomplete, but notably the input length for %s must be restricted to prevent buffer overflow.
#include <stddef.h> // size_t
#include <ctype.h> // isspace()
#include <stdio.h> // scanf(), puts()
#include <string.h> // strcmp()
// see https://stackoverflow.com/questions/2653214/stringification-of-a-macro-value
#define STRINGIFY(x) #x
#define STRING(x) STRINGIFY(x)
#define LINES 50
#define COLS 15
char const *end = "****END";
// throw away everything until a newline is found
void clear(FILE *stream)
{
int ch;
while ((ch = getc(stream)) != EOF && ch != '\n');
}
size_t getText(char dst[LINES][COLS + 1])
{
size_t i = 0;
for (; i < LINES; i++) {
char temp[COLS + 1] = { 0 };
scanf("%" STRING(COLS) "s", temp); // "%15s" at runtime.
int ch;
// if the next character is not whitespace ...
if ((ch = getchar()) != EOF && !isspace(ch)) {
puts("Warning: Input too long, was truncated!");
clear(stdin);
}
if (strcmp(temp, end) == 0) {
puts("You entered the endkey.");
return i;
}
strcpy(dst[i], temp);
}
return i;
}
int main(void)
{
// COLS + 1 ... we need space for the terminating newline character.
char foo[LINES][COLS + 1];
size_t n = getText(foo);
for (size_t i = 0; i < n; ++i)
puts(foo[i]);
}
The %s conversion specifier should never be used without specifying a width to limit the characters that get stored:
char foo[10];
scanf("%9s");
First, I apologize if the question doesn't make sense as my English isn't that good...
My question is, how do we print out different things depending on the user input?
What I'm trying to do is: when user inputs integer, the program prints out the inputted number. When the user inputs something that's not integer (like symbols and characters), the program prints out "not integer".
my current idea (pseudo-code) is as follows:
`int main(){
int value;
printf("Enter numbers");
scanf("%d", &value);
if(value is integer){
printf("%d", value);
} else {
printf("not integer");
}
return 0;
}`
what gets me is the scanf; by using %d, I'm assuming that the user will input an integer values, but the user can input values that are not integers so I can't make a comparison using the if statement if( value is integer). How can I make a comparison that will determine whether the inputted value is integer or not?
I don't know if this is a good thing or not.
You can use ASCII to check if the input type is an integer or not
(between 48 - 57 in ASCII)
it will be like this
char value;
int flag = 0; //to check true or false (0 means false, and 1 means true)
printf("Enter numbers");
scanf("%c", &value);
for(int i = 48; i <= 57; i++){
if(value == i){
flag = 1;
break;
}
}
if(flag == 1){
printf("%c", value);
} else {
printf("not integer");
}
How do you print different things depending the user input?
Step 1: Read the line of user input
char buf[100];
if (fget(buf, sizeof buf, stdin)) {
// something was entered
Step 2: test the string
char *end;
long value = strtol(buf, *end);
// If the end is the same as the beginning, no conversion occurred.
if (end == buf) {
puts("not integer");
}
printf("%ld\n", value);
}
}
Additional code could look for input that occurred after the integer. Also code could test for a large number that overflowed the long range.
The code is as follows. It caters for different situations like inputting negative numbers and decimal numbers:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int main() {
char input[20];
int wrongFlag = 0;
scanf("%s", input);
if (input[0] == '0' && strlen(input) > 1) {
wrongFlag = 1;
//for number starts with 0, and string length>1 eg: 010
}
for (int i = 0; i < strlen(input); i++) {
if (i == 0 && (input[i] == '-' && strlen(input) > 2 && input[i + 1] == '0')) {
//check first round only: negative number with length >2 and starts with 0 eg: -010.
wrongFlag = 1;
continue;
}
if (i != 0 && !isdigit(input[i])) {
//check following rounds, check if it is not digit
wrongFlag = 1;
break;
}
}
if (wrongFlag) {
printf("Not integer");
}
else {
printf("integer");
}
return 0;
}
Try this it works for me.
#include<stdio.h>
#include<string.h>
int main()
{
int i;
char value[50];
int len;
printf("Enter maximum 50 digits\n");
/* enter the values you wanted*/
printf("Enter the value: ");
gets(value);
len = strlen(value);
/*it will iterate upto the end of the user input*/
for(i=0;i<len;i++)
{
if(48<value[i] && value[i]<=57)
{
if(i==(len-1))
printf("It's an integer");
}
else{
printf(" Not an integer");
break;
}
}
return 0;
}
everyone!
I hope someone can help me figure out something in C language.
This is my first seriously homework in IT, I have no experience and I'm learning in e-studies, so teacher help isn't very available.
I need to develop console application in C language. User need to input 10 integer numbers, if insert number isn't integer, need to output error and again re-enter new number until all 10 integer numbers will be inserted.
Everything works in case if I say that these 10 numbers can't be 0 (I make this to be sure that my if-else statement working), but won't work when I want that every input number will be check if it is integer or not.
How can I do it right.
Please help
so far my code look like this:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int i;
float f;
int numbers[10];
for (i = 0; i < 10; i++)
{
scanf ("%d", &numbers[i]);
if (numbers[i] != 0)
{
scanf ("*%d", &numbers[i]);
}
else
{
printf ("\nError!Entered number is't integer \n");
printf ("\nPlease insert number again \n");
scanf("%*d", &numbers[i]);
}
}
}
#include <stdio.h>
int main(void) {
int i = 0;
int val;
char ch;
int numbers[10];
while(i < 10) {
val = scanf("%d", numbers + i); // read the integer into a[i]
if(val != 1) {
while((ch = getchar()) != '\n') // discard the invalid input
; // the null statement
printf("Error! Entered number is not an integer.\n");
printf("Please enter an integer again.\n");
val = scanf("%d", numbers + i);
continue;
}
++i;
}
// process the numbers array
return 0;
}
I write this line again
val = scanf("%d", numbers + i);
Now it works how I need. Great - thanks a lot
There are several techniques you might use:
Read the number as a string and reject if it contains characters not suitable for an integer. The use sscanf() to convert the string to integer.
Read the number as a float and reject if it is out of integer range or it has a non-integer value.
Read the input character by character and build up an integer value. If invalid characters appear, reject the value.
scanf returns the number of input items successfully matched and assigned. You can check this value for 1 for each call of scanf. If the value is 0, then you should discard the input to clear the stdin buffer and read input again.
#include <stdio.h>
#include <ctype.h>
int main(void) {
int i = 0;
int val;
char ch;
int numbers[10];
while(i < 10) {
// read an integer and the first non-numeric character
val = scanf("%d%c", numbers + i, &ch);
// if the number of items assigned by scanf is not 2 or if
// the first non-numeric character is not a whitespace, then
// discard the input and call read input again.
// for example input of type 32ws are completely discarded
if(val != 2 || !isspace(ch)) {
while((ch = getchar()) != '\n') // discard the invalid input
; // the null statement
printf("Error! Entered number is not an integer.\n");
printf("Please enter an integer again.\n");
continue;
}
++i;
}
// process the numbers array
return 0;
}
Although I am not entirely clear on the details of your question, here is an outline of code similar to what you want:
int main(void)
{
int i;
int numbers[10];
int sum = 0;
for(i=0; i<10; ++i)
{
printf("Enter #%d:\n", i+1);
scanf("%d", numbers+i);
if (numbers[i] % 2 == 0) // Then Number is even
{
sum += numbers[i];
}
}
printf("The sum of only the even numbers is %d\n", sum);
getch();
return 0;
}
To read an int, suggest fgets() then sscanf() or strtol()
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int i;
int numbers[10];
for (i = 0; i < 10; ) {
char buffer[50];
if (fgets(buffer, sizeof buffer, stdin) == NULL) break;
int n; // number of `char` parsed
if (sscanf(buffer, "%d %n", &numbers[i], &n) != 1 || buffer[n] != '\0') {
printf("Error! Entered number is not an integer.\n");
printf("Please enter an integer again.\n");
continue;
}
i++;
}
return 0;
}
The strtol() approach. This detects overflow issues:
if (fgets(buffer, sizeof buffer, stdin) == NULL) break;
char *endptr;
errno = 0;
long num = strtol(buffer, &endptr, 10);
if (errno || num < INT_MIN || num > INT_MAX) Handle_RangeError();
if (buffer == endptr || *endptr != '\n') Handle_SyntaxError();
numbers[i] = (int) num;
Recommend making a int GetInt(const char *prompt) function that can be used repeatedly.
User input is evil. Do not trust it until well vetted.
I've searched in and out of these forums but am still having trouble. My understanding of C is still very basic. I'm creating a small program that takes 3 numerical values entered by the user and then calculates the highest. I nailed that.
I now want to ensure that the user enters only integer values. I managed to get the prog to keep prompting the user to re-enter the value until it is within the specified numerical range (for example, any number between 1 and 1000 inclusive, piece of cake) but that's not good enough. I used 3 while loops to test each value, but this only works as long as the input is of type integer.
The trick is I cant use built in functions. It needs to be manual (sorry, poor choice of words) I tried to use char variables and x = getchar(); to get the ASCII value and test it in a condition but I can't get it working in a loop. (while/ do-while)
I also tried using a "for loop" and array variables but once again am struggling to get it to keep prompting the user.
I've also tried to test the value returned by scanf to see if its integer but my knowledge level of correct C syntax is level: noob. Either my loops don't loop or they loop infinitely.
Here is some sample code:
int x, y, z =0;
printf("Enter the first number:\n");
scanf("d", &x);
while (condition) /* Here is where I need to determine that the entered val is false */
{
printf("Wrong input. Re-enter a valid value.\n");
x =0;
scanf("%d", &x); /*user re-prompted */
}
I'm getting the idea that I'll have to use ASCII and a loop, but I just can't get to it. Also, the values entered get sent to a function for comparing and are then returned.
Could someone give me some advice and a few tips please?
Much thanks
You would have to use something like fgets, and strtol:
long someValue;
char *bufEnd = NULL;
char buf[128]; // max line size
do {
printf("enter a value: ");
fgets(buf, 128, stdin);
someValue = strtol(buf, &bufEnd, 10); // base 10
} while (bufEnd == buf || *bufEnd != '\n');
printf("got value: %li", someValue);
What we are doing here is we are tapping into strtol's capability to tell us where it stopped parsing, by passing in bufEnd.
Then, we are making sure that bufEnd doesn't point to the beginning of buf (in which case, it didn't start with a number), and also checking to make sure that bufEnd points to \n, or the end of the line (making sure that the user didn't enter something like 123abc, which strtol would interpret as 123). You may wish to trim buf of whitespace characters first, however.
You're absolutely on the right track with "scanf()". Just check the return value. If you don't get the expected #/values, then you got invalid input:
char found = FALSE;
int ival;
double x;
while (!found)
{
printf("Please enter a valid integer: ");
if (scanf("%d", &ival) !=1) {
printf ("Invalid! Please re-enter!\n");
continue;
}
printf("Please enter a valid floating point number: ");
if (scanf("%lf", &x) !=1) {
printf ("Invalid! Please re-enter!\n");
continue;
}
found = TRUE;
}
Here's my solution. It safe against buffer overflow and straightforward .
#include <stdio.h>
#define LEN 10
int main() {
int a;
char str[LEN];
fgets( str, LEN, stdin );
while ( !sscanf( str, "%d", &a ) )
fgets( str, 10, stdin );
printf("Num is : %d\n", a);
return 0;
}
#include <stdio.h>
#include <limits.h>
#include <ctype.h>
int getInteger(int* err){
int ch;
int n;//int32
int takeNum, sign;
long long int wk;//long long int as int64
wk=0LL;
*err = 0;
takeNum = 0;//flag
sign = 1;//minus:-1, other:1
/* //skip space character
while(EOF!=(ch=getchar()) && (ch == ' ' || ch == '\t' || ch == '\n'));
ungetc(ch, stdin);
*/
while(EOF!=(ch=getchar())){
if(ch == '-'){
if(takeNum != 0){//in input number
*err = 1;
break;
}
if(sign == -1){//already sign
*err = 2;
break;
}
sign = -1;
continue;
}
if(ch >= '0' && ch <= '9'){//isdigit(ch) in ctype.h
if(takeNum == 0)
takeNum = 1;
wk = wk * 10 + (ch - '0')*sign;
if(INT_MAX < wk || INT_MIN > wk){//overflow
*err = 3;
break;
}
continue;
}
if(ch != '\n'){//input other [-0-9]
*err = 4;
}
break;
}
if(takeNum == 0){//not input number
*err = 5;
} else {
n=wk;
}
while(ch != '\n' && EOF!=(ch=getchar()));//skip to newline
return n;
}
int getValue(const char* redoprompt, int low, int high){
int num, err=0;
while(1){
num = getInteger(&err);
if(err || low > num || high < num)
printf("%s", redoprompt);
else
break;
}
return num;
}
#define max(x,y) ((x)>(y))? (x) : (y)
int main(){
const char *error_message = "Wrong input. Re-enter a valid value.\n";
int x, y, z, max;
x = getValue(error_message, 1, 1000);
y = getValue(error_message, 1, 1000);
z = getValue(error_message, 1, 1000);
max = max(max(x,y), z);
printf("max:%d\n", max);
return 0;
}