So my program needs to consist of it forcing the user to input a string between 5-10 characters, with validation, so ensuring that the length is correct, i have this so far but completely stuck, any advice on how to validate the data type to only strings allowed to be inputted?
char x[10];
int length, i;
for(i=0;i=10;i=i+1){
printf("Please enter 5-10 Characters\n");
scanf("%s", &x);
length = strlen(x);
if (length < 5){
printf("Not Long Enough!\n");
}
if (length > 10){
printf("Too Long!\n");
}
while('x' == 'char'){
if (scanf("%s", &x) == 1){
return 0;
}else{
printf("Not a string, Try again");
gets(x);
}
}
printf("You inputted: %s\n", x);
}
Various problems in code, so will center on the title topic.
Only string between 5 and 10 characters inputted?
any advice on how to validate the data type to only strings allowed to be inputted?
Use fgets() to read a line of user input. I would use a helper function.
scanf() does not well recover from errant input. Do not use it.
Be sure to use a large enough buffer to hold the 10 characters read and the appended null character. #Weather Vane
// Return 1 on success
// Return -1 on EOF
// Return 0 on failure (too long or too short)
// `x` must be at least size `max + 1`
int read_line_min_max(char *x, size_t min, size_t max) {
if (fgets(x, max + 1, stdin) == NULL) return -1;
size_t len = strlen(x);
if (len > 0 && x[len - 1] == '\n') {
x[--len] = '\0'; // lop off potential \n
} else {
// more data to read, but saving not needed, simply consume it
int ch;
while ((ch = fgetc(stdin)) != '\n' && ch != EOF) {
len++;
}
}
return (len >= min) && (len <= max);
}
Example
#define READ_MIN 5
#define READ_MAX 10
char buffer[READ_MAX + 1];
int result;
do {
printf("Please enter 5-10 Characters\n");
result = read_line_min_max(buffer, READ_MIN, READ_MAX);
} while (result == 0);
while('x' == 'char') is unclear.
Perhaps should be while(strcmp(x, "char") != 0)
Related
I have an integer 'n' that is responsible for amount of numbers to enter later on.
I need to check for any incorrect inputs here.
The first scanf for 'n' works fine, but the second has some flaws.
The case is following:
n = 3 (e.g.) - doesn't matter
Then I want to scanf: 1 2 3 4
It will be scanned first 3 values but I need to throw out an error.
Same goes with: 1 2 3.5 - (last number is float but it still reads 3)
and with a char: 1 2 3g
if (scanf("%d", n) == 1 && getchar() == '\n') {
if (n > NMAX || n < 0) {
error = 1;
return;
}
for (int i = 0; i < n; i++) {
if (scanf("%d", p) == 1) {
The ONLY correct input is the exact same amount of integer numbers (equals to 'n') to scan in a for loop.
UPD: I can use only <stdio.h> library as well as only scanf.
Create a helper function to read an int and validate it.
The key is that to validate input, form a helper function that you can improve as needed, like using fgets() rather than scanf() once the poor "only scanf" requirement is removed.
// Sample
// Return 1 on success
// Return EOF on end-of-file
// Else return 0
int read_int(int *i, int min, int max, int line) {
long long num;
int result = scan("%18lld", &num); // Accept many out of int range input
if (result == EOF) return result; // or if (result < 0)
if (line) {
// consume the rest of the line
int ch;
while ((ch = getchar()) != '\n' && ch != EOF) {
if (!isspace(ch)) { // or `ch != ' ' && `ch != '\t' && ...
result == 0;
}
}
}
if (result == 1) {
if (num < min || num > max) {
return 0;
}
*i = (int) num;
}
return result;
}
Sample usage
if (read_int(&n, 0, NMAX, 1) != 1) {
error = 1;
return;
}
for (int i = 0; i < n; i++) {
if (read_int(&p, INT_MIN, INT_MAX, i + 1 == n) != 1) {
error = 1;
return;
}
...
Note: read_int() does not catch all errors, just many of them. Easy enough to improve, once all OP's limitations and goals are known.
Try using scansets with scanf. %1[\n] will scan up to one character that is a newline. %99[ \t] will scan up to 99 characters that are space or tab. If the character is not a newline, space or tab, it is replaced in the input stream.
If scanf with %d can't scan an int, it will return 0. scanf could also return EOF.
fgets and parse with strtol or others is the better solution.
#include <stdio.h>
int main ( void) {
char space[100] = "";
char newline[2] = "";
int number = 0;
int count = 0;
int quantity = 3;
printf ( "enter %d integers\n", quantity);
while ( 1) {
if ( 1 == scanf ( "%d", &number)) {
++count;
}
else {
printf ( "could not parse an integer\n");
break;
}
scanf ( "%99[ \t]", space);
if ( 1 == scanf ( "%1[\n]", newline)) {
if ( count == quantity) {
printf ( "scanned %d integers\n", quantity);
break;
}
else if ( count > quantity) {
printf ( "too many integers\n");
break;
}
else printf ( "enter another integer\n");
}
}
return 0;
}
Check if this works
while(n-1)
{
scanf("%d ",p);
n-=1;
}
scanf("%d",p);
//After this you can scan again to check if there is anything extra in input
//and throw error accordingly
I'm relatively new to C and would like to know how to prevent an overflow from input...
So for example, I have:
scanf("%d", &a);
Where a is an integer.
So what I could I do to prevent someone from entering a number that's larger than max integer? Due to the constraints of the problem I'm working on, you HAVE to use scanf. How do I go about restricting the input?
It is very challenging to prevent user input.
There is no magic hand to reach out and stop the user from beating away at the keyboard.
But code can limit what it reads.
scanf() is tough to limit. It may not set errno on overflow. Code can limit the number of char to say 9. That's a first step but one can not enter values like "1000000000" or "00000000000000001".
// Assume INT_MAX = 2,147,483,647.
scanf("%9d", &a);
A pedantic method would use fgetc(). An unsigned method follows. int takes a bit more.
unsigned a = 0;
int ch = fgetc(stdin);
while (isspace(ch)) {
ch = fgetc(stdin);
}
while (isdigit(ch)) {
ch -= '0';
if (a >= UINTMAX/10 && (a > UINTMAX/10 || ch > UINTMAX%10)) {
a = UINTMAX;
break; // overflow detected.
}
a = a*10 + ch;
ch = fgetc(stdin);
}
ungetc(ch, stdin); // Put back `ch` as it was not used.
But I prefer to change the goal and simply tell the user again, even if it means reading in more characters.
// 0:success or EOF
int Read_int(const char *prompt, int *dest, int min, int max) {
for (;;) {
char buf[(sizeof(int)*3 + 3)*2]; // 2x generous buffer
fputs(prompt, stdout);
if (fgets(buf, sizeof buf, stdin) == NULL) {
return EOF;
}
char *endptr;
errno = 0;
long l = strtol(buf, &endptr, 10);
// no conversion or junk at the end ....
if (buf == endptr || *endptr != '\n') {
continue;
}
if (!errno && l >= min && l <= max) {
*dest = (int) l;
return 0; // success
}
}
}
// Sample usage
int a;
Read_int("Enter an `int`\n", &a, INT_MIN, INT_MAX);
I want to write a program which reads a line of input from the user, in the following format: <Name>,<Age>,<City>
The Name can contain English letters, spaces and - only.
The Age must be an integer between 18 to 120.
The City must contain English letters and - only.
Each of them can be of size 49.
I want to store the information and print an informative error will be printed for bad input.
My code is the following:
char str[150];
char input[3][50] = { 0 };
int num = 0;
if (fgets(str, 150, stdin) != NULL) {
num = sscanf(str, "%[a-zA-Z -],%[0-9],%[a-zA-Z-]", input[0], input[1], input[2]);
}
if (num < 3) {
printf("ERROR\n");
}
The problem is that an error will not be printed for an input such as Name1$#,20,NY, Best,19,Rome123, or Best,100,Paris1$, where the city is in wrong format (with trailing characters). There is any way to solve it using sscanf?
You can use sscanf() and character classes for your purpose but there are small problems with your format string:
A-Z assumes ASCII encoding or at least an encoding where letters are contiguous.
a trailing - has a special meaning, put the dash in first position to match a dash explicitly.
there is no length prefix, so a name or city longer than 49 characters will overflow the destination array.
Rather than using fgets(), you should read the line mannually to detect overlong lines.
You can add an extra %c to check for extra characters at the end of the line. Storing the converted value is not required if you don't intend to use the field values, but you must convert the number to check if its value is in the requested range:
char str[150];
char name[50];
char city[50];
char agestr[4];
size_t i;
int c, age, pos, n;
for (i = 0; (c = getchar()) != EOF && c != '\n'; i++) {
if (i < sizeof(str) - 1)
str[i] = (char)c;
}
if (c == EOF && i == 0) {
printf("end of file\n");
return -1;
}
if (i >= sizeof(str)) {
printf("line too long\n");
return 0;
}
str[i] = '\0';
pos = 0;
/* validate the name */
if (sscanf(str + pos, "%49[-a-zA-Z ]%n", name, &n) != 1 || str[pos + n] != ',') {
printf("invalid name\n");
return 0;
}
pos += n + 1;
/* validate the age */
if (str[pos] == '0' || sscanf(str + pos, "%3[0-9]%n", agestr, &n) != 1 || str[pos + n] != ',') {
printf("invalid age\n");
return 0;
}
age = atoi(agestr);
if (age < 18 || age > 120) {
printf("age out of range: %d\n", age);
return 0;
}
pos += n + 1;
/* validate the city */
if (sscanf(str + pos, "%49[-a-zA-Z]%n", city, &n) != 1 || str[pos + n] != '\0') {
printf("invalid city\n");
return 0;
}
/* Input was validated... proceed */
I am trying to make a program that will check if the user enters a valid double number.
I know how to make it check a valid integer by doing:
if (scanf("%d%c", &inter, &newLine) != 2 || newLine != '\n')
but when it coming to checking a double type it doesn't work.
I tried:
if (scanf("%d%c", &inter, &newLine) != 2.00 || newLine != '\n')
and:
if (scanf("%d%c", &inter, &newLine) != 2.000000 || newLine != '\n')
none of those to seem to work
here is a full example of how it checks a valid integer type;
do {
num = inter % 1;
if (scanf("%d%c", &inter, &newLine) != 2 || newLine != '\n') {
printf("Invalid integer, please try again: ");
flushKeybord();
} else {
x = x + 1;
}
} while (x == 0);
the function that its calling if its invalid is simply a to clear the buffer
Yet another scanf thread. Don't use scanf for this, read the line with fgets and then parse it with sscanf or strtok, etc. See Why does everyone say not to use scanf? What should I use instead?
Besides, scanf returns the number of input items successfully matched and assigned.
// edit: use strtod for things like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char line[1024];
double d;
char *pEnd;
for(;;)
{
// here you should check if fgets returns NULL
fgets(line, sizeof line, stdin);
int len = strlen(line);
if(line[len-1] == '\n')
line[len-1] = 0;
d = strtod(line, &pEnd);
if(*pEnd == 0 && len > 0)
{
printf("Double: %lf\n", d);
return 0;
}
printf("Wrong format, try again\n");
}
return 0;
}
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;
}