I'm writing a code that I want to make sure the User only inputs an integer between 1-10 and stores that value in a 2D array. I'm trying to use pointers to do complete this task.
#include <stdio.h>
int main()
{
//Declaration of a 2D array
int movie_Scores [8][5];
//Declaration of a pointer variable which points to the address of the 1st element
int *p;
p=&movie_Scores;
//Array of pointers to strings and initializtion
char movie_Names[][100] = {"1. Movie 1",
"2. Movie 2",
"3. Movie 3",
"4. Movie 4",
"5. Movie 5",
"6. Movie 6",
"7. Movie 7",
"8. Movie 8"
};
for(int i=0; i<5; i++)
{
printf("Judge %d, rate each movie from 1-10:\n\n", i+1);
for(int j=0;j<8;j++)
{
printf("\n%s\t:", movie_Names[j]);
scanf("%d", (p+i+(j*5)));
while(*(p+i+(j*5))<1 || *(p+i+(j*5))>10)
{
printf("Enter number between 1-10:\n");
printf("\n%s\t:", movie_Names[j]);
scanf("%d", (p+i+(j*5)));
}
}
}
}
Currently my code takes the input and directly stores it into the array without checking if the value entered is between 1-10.
Input functions do not test for valid range. (In fact, that is a known failing of scanf. See here and here for the eyes-glaze-over reasons.) You need to test the value after you get it.
int value;
if (!scanf( "%d", &value )) fooey();
if ((value < 1) or (value > 10)) fooey();
Getting input in C is actually a rather obnoxious thing to do. You can write yourself a helper function to put all the messy stuff in one spot, then you can use it elsewhere.
Also, use better variable names, and don’t introduce gratuitous variables.
for(int judge_number=0; judge_number<5; judge_number++)
{
printf("Judge %d, rate each movie from 1-10:\n", judge_number+1);
for(int movie_number=0; movie_number<8; movie_number++)
{
int rating;
for (;;)
{
printf("%s\t:", movie_Names[movie_number]);
scanf("%d", &rating);
if ((rating >= 1) and (rating <= 10)) break;
printf("Rating must be an integer in 1 to 10.\n");
}
movie_Scores[movie_number][judge_number] = rating;
}
}
EDIT: BTW, I would be remiss if I didn’t mention today’s magic numbers 5 and 8.
You should not use magic numbers. Instead, provide a named value somewhere.
#define NUMBER_OF_MOVIES 8
#define NUMBER_OF_JUDGES 5
Then you can use those identifiers anywhere you need them:
int movie_Scores [NUMBER_OF_MOVIES][NUMBER_OF_JUDGES];
And:
for (int judge_number=0; judge_number<NUMBER_OF_JUDGES; judge_number++)
Et cetera.
First, I'd write a function that reads an int and checks it against an input, returning 1 if an acceptable int was read, and 0 if one was not.
int read_int_from_range(int *n, int start, int end) {
int r = scanf("%d", n);
return r == 1 && *n >= start && *n <= end;
}
Now, you can call this and check it and use that to loop until you get "valid" input in another function if you want, or simply exit with an error message if that's the desired behavior.
The problem of how to verify that the user actually entered an integer has already been answered in this question:
Validate the type of input in a do-while loop C
Therefore, the question remains how to verify that the integer that the user entered is also in the range 1 to 10.
In order to do this, all you need is an if statement. However, if you want the user to be automatically re-prompted for input, then you will also need a loop.
In my solution below, I use the function get_int_from_user from my solution to the question mentioned above, with a slight modification, so that it accepts printf-style input. This function automatically verifies that the user entered a valid integer, and if not, it automatically reprompts the user for input.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <limits.h>
#include <errno.h>
#include <stdarg.h>
#define NUM_JUDGES 3
#define NUM_MOVIES 8
int get_int_from_user( const char *prompt, ... );
int main( void )
{
//Declaration of a 2D array
int movie_scores[NUM_JUDGES][NUM_MOVIES];
//Array of pointers to strings and initializtion
char *movie_names[] = {
"1. <Movie 1>",
"2. <Movie 2>",
"3. <Movie 3>",
"4. <Movie 4>",
"5. <Movie 5>",
"6. <Movie 6>",
"7. <Movie 7>",
"8. <Movie 8>"
};
for( int i = 0; i < NUM_JUDGES; i++ )
{
printf( "Judge %d, rate each movie from 1-10:\n\n", i+1 );
for( int j = 0; j < NUM_MOVIES; j++ )
{
//repeat until the input is in the range 0 to 10
for (;;)
{
int score;
score = get_int_from_user( "%s: ", movie_names[j] );
if ( 0 <= score && score <= 10 )
{
//score is good, so write it to the 2D array and
//break out of the loop
movie_scores[i][j] = score;
break;
}
printf( "Error: The score must be in the range 0 to 10!\n" );
}
}
printf( "\n" );
}
//input is complete, so now it is time to print back the data to the user
printf( "\nThe following data was entered:\n\n" );
for ( int i = 0; i < NUM_JUDGES; i++ )
{
printf( "Judge %d: ", i+1 );
for ( int j = 0; j < NUM_MOVIES; j++ )
{
printf( "%d ", movie_scores[i][j] );
}
printf( "\n" );
}
}
int get_int_from_user( const char *prompt, ... )
{
//loop forever until user enters a valid number
for (;;)
{
char buffer[1024], *p;
long l;
va_list vl;
//prompt user for input
va_start( vl, prompt );
vprintf( prompt, vl );
va_end( vl );
//get one line of input from input stream
if ( fgets( buffer, sizeof buffer, stdin ) == NULL )
{
fprintf( stderr, "Unrecoverable input error!\n" );
exit( EXIT_FAILURE );
}
//make sure that entire line was read in (i.e. that
//the buffer was not too small)
if ( strchr( buffer, '\n' ) == NULL && !feof( stdin ) )
{
int c;
printf( "Line input was too long!\n" );
//discard remainder of line
do
{
c = getchar();
if ( c == EOF )
{
fprintf( stderr, "Unrecoverable error reading from input!\n" );
exit( EXIT_FAILURE );
}
} while ( c != '\n' );
continue;
}
//attempt to convert string to number
errno = 0;
l = strtol( buffer, &p, 10 );
if ( p == buffer )
{
printf( "Error converting string to number!\n" );
continue;
}
//make sure that number is representable as an "int"
if ( errno == ERANGE || l < INT_MIN || l > INT_MAX )
{
printf( "Number out of range error!\n" );
continue;
}
//make sure that remainder of line contains only whitespace,
//so that input such as "6sdfj23jlj" gets rejected
for ( ; *p != '\0'; p++ )
{
if ( !isspace( (unsigned char)*p ) )
{
printf( "Unexpected input encountered!\n" );
//cannot use `continue` here, because that would go to
//the next iteration of the innermost loop, but we
//want to go to the next iteration of the outer loop
goto continue_outer_loop;
}
}
return l;
continue_outer_loop:
continue;
}
}
This program has the following behavior:
Judge 1, rate each movie from 1-10:
1. <Movie 1>: abc
Error converting string to number!
1. <Movie 1>: 4abc
Unexpected input encountered!
1. <Movie 1>: 12
Error: The score must be in the range 0 to 10!
1. <Movie 1>: 1
2. <Movie 2>: 2
3. <Movie 3>: 3
4. <Movie 4>: 4
5. <Movie 5>: 5
6. <Movie 6>: 6
7. <Movie 7>: 7
8. <Movie 8>: 8
Judge 2, rate each movie from 1-10:
1. <Movie 1>: 8
2. <Movie 2>: 7
3. <Movie 3>: 6
4. <Movie 4>: 5
5. <Movie 5>: 4
6. <Movie 6>: 3
7. <Movie 7>: 2
8. <Movie 8>: 1
Judge 3, rate each movie from 1-10:
1. <Movie 1>: 10
2. <Movie 2>: 10
3. <Movie 3>: 10
4. <Movie 4>: 10
5. <Movie 5>: 10
6. <Movie 6>: 10
7. <Movie 7>: 10
8. <Movie 8>: 10
The following data was entered:
Judge 1: 1 2 3 4 5 6 7 8
Judge 2: 8 7 6 5 4 3 2 1
Judge 3: 10 10 10 10 10 10 10 10
Note that for demonstration purposes, I have reduced NUM_JUDGES form 5 to 3.
As far as I know, the only option is to simply use scanf. If the number is less than 1 or more than 10, you can print something like "Please enter a number from 1 to 10. and use scanf again until you get a number between 1 and 10.
Related
I have this program:
#include <stdio.h>
int main(){
int val;
printf("Enter any number: ");
scanf("%d",&val);
printf("The number incremented is %d\n",val+1);
printf("Enter any number again: ");
scanf("%d",&val);
printf("The number decremented is: %d\n",val-1);
return 0;
}
It works completely fine if i give it an integer input, but when its a different input, the program goes crazy and runs without accepting the second input. (the second output is -1). is there a fix to this?
I have tried to test the program with number and non-number inputs, For the non number one in the first input, as the description said, the program continued and didnt accept the second input.
Edit: I did not mention the desired output of the program, sorry about that.
If the output is non-integer then it will return with err code 1.
If you want the function to return -1; in the case of the user entering invalid input, then you should check the return value of scanf, for example like this:
#include <stdio.h>
int main( void )
{
int val;
printf( "Enter any number: ");
if ( scanf( "%d", &val ) != 1 )
{
printf( "Invalid input!\n" );
return -1;
}
printf( "The number incremented is %d\n", val+1 );
printf( "Enter any number again: " );
if ( scanf( "%d", &val ) != 1 )
{
printf( "Invalid input!\n" );
return -1;
}
printf( "The number decremented is: %d\n", val-1 );
return 0;
}
This program has the following behavior:
Enter any number: abc
Invalid input!
Enter any number: 5
The number incremented is 6
Enter any number again: abc
Invalid input!
Enter any number: 5
The number incremented is 6
Enter any number again: 10
The number decremented is: 9
However, this solution is not perfect. For example, if the user enters 5abc in the first line, then the first scanf successfully reads 5, but the second scanf will fail:
Enter any number: 5abc
The number incremented is 6
Enter any number again: Invalid input!
If you don't want this counter-intuitive behavior, then it would probably be best not to use the function scanf for line-based user input, but to rather use the functions fgets and strtol instead, for example like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <limits.h>
#include <errno.h>
int get_int_from_user( const char *prompt );
int main( void )
{
int val;
val = get_int_from_user( "Enter any number: ");
printf( "The number incremented is %d\n", val+1 );
val = get_int_from_user( "Enter any number again: ");
printf( "The number decremented is: %d\n", val-1 );
return 0;
}
int get_int_from_user( const char *prompt )
{
//loop forever until user enters a valid number
for (;;)
{
char buffer[1024], *p;
long l;
//prompt user for input
fputs( prompt, stdout );
//get one line of input from input stream
if ( fgets( buffer, sizeof buffer, stdin ) == NULL )
{
fprintf( stderr, "Unrecoverable input error!\n" );
exit( EXIT_FAILURE );
}
//make sure that entire line was read in (i.e. that
//the buffer was not too small)
if ( strchr( buffer, '\n' ) == NULL && !feof( stdin ) )
{
int c;
printf( "Line input was too long!\n" );
//discard remainder of line
do
{
c = getchar();
if ( c == EOF )
{
fprintf( stderr, "Unrecoverable error reading from input!\n" );
exit( EXIT_FAILURE );
}
} while ( c != '\n' );
continue;
}
//attempt to convert string to number
errno = 0;
l = strtol( buffer, &p, 10 );
if ( p == buffer )
{
printf( "Error converting string to number!\n" );
continue;
}
//make sure that number is representable as an "int"
if ( errno == ERANGE || l < INT_MIN || l > INT_MAX )
{
printf( "Number out of range error!\n" );
continue;
}
//make sure that remainder of line contains only whitespace,
//so that input such as "6sdfj23jlj" gets rejected
for ( ; *p != '\0'; p++ )
{
if ( !isspace( (unsigned char)*p ) )
{
printf( "Unexpected input encountered!\n" );
//cannot use `continue` here, because that would go to
//the next iteration of the innermost loop, but we
//want to go to the next iteration of the outer loop
goto continue_outer_loop;
}
}
return l;
continue_outer_loop:
continue;
}
}
This program has the following behavior:
Enter any number: 5abc
Unexpected input encountered!
Enter any number: abc
Error converting string to number!
Enter any number: 5
The number incremented is 6
Enter any number again: 10
The number decremented is: 9
Note that my second program is more sophisticated than the first program, because it keeps on prompting the user for input until the user enters a valid int, whereas the first program simply prints an error message and returns -1.
I took the function get_int_from_user from this answer of mine to another question. See that answer for more information on the extensive input validation that the function performs.
The first scanf is looking for an integer if it doesn't get an integer it does nothing,
The secoind scanf is looking for an integer if it doesn't get an integer it does nothing.
If the first scanf does nothing, nothing changes, so the second identical scanf presented with the same environment will also do nothing.
one way to fix this is to tell the second scanf to discard the garbage characters.
scanf("%*[^0-9]%d",&val);
Subsequent edits to the question made that solution unsuitable.
#include <stdio.h>
int main(){
int val;
char junk[2];
printf("Enter any number: ");
if( scanf("%d%1[\n]",&val,&(junk[0])) < 2)
{
puts("numbers only please");
return 1;
}
printf("The number incremented is %d\n",val+1);
printf("Enter any number again: ");
if( scanf("%d%1[\n]",&val,&(junk[0])) < 2)
{
puts("numbers only please");
return 1;
}
printf("The number decremented is: %d\n",val-1);
return 0;
}
I am just a beginner to C language. I am trying to write a programme that take marks of four subjects. But in case if user provides a wrong input such as alphabets then it should print "Please Enter Number" and should again ask the marks of same subject.
Here is my code..
// Programme to add marks of four subject and to calculate percentage.
#include <stdio.h>
#include<ctype.h>
int main()
{
float sub_marks, total_marks, temp, check = 0;
printf("\nPragramme to add marks of four subject and to calculate percentage.\n\n");
for (int i = 1; i <= 4; i++) //Running loop four times to enter marks of four subjects.
{
printf("Enter Marks of Subject %d: ", i);
scanf("%f", &sub_marks);
if (sub_marks > 100) //condition for what to do if marks are greater then 100
{
printf("\n**MARKS CONNOT BE GREATER THEN 100**\n\n");
i--;
}
else
{
temp = temp + sub_marks; //addind marks to get total marks
}
}
printf("\n\nTotal Marks: 400");
printf("\n\nObtained marks: %.2f", temp);
printf("\n\nPercentage: %.2f%%\n\n", temp / 4);
return 0;
}
I did try a lot but ended up with output..
Pragrame to add marks of fout subject and to calculate percentage.
Enter Marks of Subject 1: 65
Enter Marks of Subject 2: y
**PLEASE ENTER NUMBER.**
Enter Marks of Subject 3:
**PLEASE ENTER NUMBER.**
Enter Marks of Subject 4:
**PLEASE ENTER NUMBER.**
After entering alphabet it dosen't let the user to input for the rest of the loops. Instead it should ask "Enter Marks of Subject 1:"
I achived above output by placing below code after else.
while (sub_marks >= 0)
{
remainder = sub_marks % 10;
if (!isdigit(remainder))
{
printf("Please enter Number");
break;
}
}
Unfortunately, the C standard library does not offer any easy way to read a floating-point number from the user, and to automatically keep asking the user until the input is valid. However, you can write such a function yourself, using the functions fgets and strtof.
In the code snippet below, I wrote a variadic function
float get_float_from_user( const char *prompt, ... )
which you can call like printf to print a string. It will repeatedly prompt the user for input using this string, until the input is valid. Once the input is valid, the function will return the user input converted to a float. You can call the function for example like this:
sub_marks = get_float_from_user( "Enter Marks of Subject %d: ", i );
If you replace the call to scanf with the line above, then your program should work as desired, after additionally fixing the following bug:
You must initialize temp to 0. The line
float sub_marks, total_marks, temp, check = 0;
will not initialize temp to 0. It will only initialize check to 0. If you want to initialize all 4 variables to 0, then you should instead write the following:
float sub_marks = 0, total_marks = 0, temp = 0, check = 0;
However, it would probably be better to change the name of temp to sum, as that describes the purpose of the variable better. Also you are not using the variables total_marks and check at all, so you can remove them. Therefore, you may want to change that line to the following:
float sub_marks, sum = 0;
Note that I am deliberately not initializing sub_marks, as that is not necessary (initializing sum is necessary, though).
However, since you are not using sub_marks outside the loop, it would probably be better to declare it inside the loop, in order to limit its scope.
Also, changing the loop counter i inside the loop is considered bad programming practice. A cleaner solution would be to create an additional loop inside the loop, so that the inner loop will only stop when the input is in the desired range.
Here is the code which does everything mentioned above:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include <stdarg.h>
float get_float_from_user( const char *prompt, ... )
{
for (;;) //loop forever until user enters a valid number
{
char buffer[1024], *p;
float f;
va_list vl;
//prompt user for input
va_start( vl, prompt );
vprintf( prompt, vl );
va_end( vl );
//get one line of input from input stream
if ( fgets( buffer, sizeof buffer, stdin ) == NULL )
{
fprintf( stderr, "unrecoverable error reading from input\n" );
exit( EXIT_FAILURE );
}
//make sure that entire line was read in (i.e. that
//the buffer was not too small)
if ( strchr( buffer, '\n' ) == NULL && !feof( stdin ) )
{
int c;
printf( "line input was too long!\n" );
//discard remainder of line
do
{
c = getchar();
if ( c == EOF )
{
fprintf( stderr, "unrecoverable error reading from input\n" );
exit( EXIT_FAILURE );
}
} while ( c != '\n' );
continue;
}
//attempt to convert string to number
errno = 0;
f = strtof( buffer, &p );
if ( p == buffer )
{
printf( "error converting string to number\n" );
continue;
}
//make sure that no range error occurred
if ( errno == ERANGE )
{
printf( "number out of range error\n" );
continue;
}
//make sure that remainder of line contains only whitespace,
//so that input such as "6sdfh4q" gets rejected
for ( ; *p != '\0'; p++ )
{
if ( !isspace( (unsigned char)*p ) )
{
printf( "unexpected input encountered!\n" );
//cannot use `continue` here, because that would go to
//the next iteration of the innermost loop, but we
//want to go to the next iteration of the outer loop
goto continue_outer_loop;
}
}
return f;
continue_outer_loop:
continue;
}
}
int main()
{
float sum = 0;
printf( "\nProgram to add marks of four subjects and to calculate average.\n\n" );
for ( int i = 1; i <= 4; i++ )
{
float sub_marks;
//loop forever until input is in the desired range
for (;;)
{
sub_marks = get_float_from_user( "Enter marks of subject %d: ", i );
if ( sub_marks < 0.0 )
{
printf( "Marks cannot be negative!\n" );
continue;
}
if ( sub_marks > 100.0 )
{
printf( "Marks cannot be greater than 100!\n" );
continue;
}
//input is in acceptable range, so break out of infinite loop
break;
}
sum += sub_marks;
}
printf( "\n" );
printf( "Total marks: 400\n" );
printf( "Obtained marks: %.2f\n", sum);
printf( "Average: %.2f%%\n", sum / 4.0 );
printf( "\n" );
return 0;
}
The program above has the following behavior:
Program to add marks of four subjects and to calculate average.
Enter marks of subject 1: This is a test.
error converting string to number
Enter marks of subject 1: 70
Enter marks of subject 2: 80abc
unexpected input encountered!
Enter marks of subject 2: 80
Enter marks of subject 3: 110
Marks cannot be greater than 100!
Enter marks of subject 3: 90.7
Enter marks of subject 4: abc85
error converting string to number
Enter marks of subject 4: 85
Total marks: 400
Obtained marks: 325.70
Average: 81.43%
The function get_float_from_user is a slight modification of my function get_int_from_user from the second code snippet of this answer of mine to another question.
I've tried to put everything together as much as possible, but it's hard to read input correctly, managing everything that users can throw at you. This version is not perfect!
EDIT: As Andreas Wenzel pointed out: This solution has the following issues:
If the user enters a line that is so long that it doesn't fit into the input buffer, then your program won't handle the input properly. Ideally, you should check for the newline character in the input buffer.
The function sscanf has undefined behavior if the input is out of range of a float. This cannot be prevented when using the function sscanf. Therefore, it is generally not a good idea to use that function for input validation. The function strtof is better, as the behavior is well-defined for an out of range error.
The main thing is that you were computing the "average", not the "percentage".
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
int main(void)
{
printf("Program to add marks of four subjects and to calculate the average.\n\n");
float total_marks = 0;
for (int i = 1; i <= 4; i++) { // Running loop four times to enter marks of four subjects.
bool valid = false;
while (!valid) {
printf("Enter mark of subject %d: ", i);
char line[256];
if (fgets(line, 256, stdin) == NULL) {
printf("\n**INPUT ERROR OR EOF**\n\n");
exit(EXIT_FAILURE);
}
float mark;
int n;
if (sscanf(line, "%f %n", &mark, &n) != 1) {
printf("\n**ENTER A FLOATING POINT VALUE**\n\n");
}
else if (line[n] != 0) {
printf("\n**DON'T ADD ANYTHING AFTER THE NUMBER**\n\n");
}
else if (mark < 0 || mark > 100) {
printf("\n**MARKS MUST BE BETWEEN 0 AND 100**\n\n");
}
else {
valid = true;
total_marks += mark; // add marks to get total
}
}
}
printf("Total Marks: %.2f\n", total_marks);
printf("Average: %.2f\n\n", total_marks / 4);
return EXIT_SUCCESS;
}
Here's my code. When it asked for my first input on the command line, I entered '5cde'. Then it printed '5', and it didn't ask for any more inputs before termination.
How is this okay? Is there a way to see how scanf is working internally as I run this program? I really want to know what exactly is going on behind the scenes. I'm not sure how the input buffer works, and if I should even be messing with it. Or should I just use a different io function instead? Because scanf seems pretty unsafe to me.
int i;
scanf("%d", &i);
printf("%d", i);
scanf("%d", &i);
scanf("%d", &i);
scanf("%d", &i);
scanf("%d", &i);
The behavior of the function scanf when the conversion specifier d is used is the following
d Matches an optionally signed decimal integer, whose format is the same as expected for the subject sequence of the strtol function
with the value 10 for the base argument. The corresponding argument
shall be a pointer to signed integer
So for this input buffer
5cde
the first call of scanf reads the character 5 because it represents a valid integer number and the position in the input buffer moves to the right to the character 'c'.
When the next and subsequent calls of scanf failed because the symbol 'c' is not a valid digit. The position in the input stream stays the same.
You should check whether call of scanf was successful> For example
if ( scanf("%d", &i) == 1 )
{
printf("%d\n", i);
}
else
{
// remove the invalid input
scanf( "%*[^\n]%*c" );
}
Here is a demonstration program.
#include <stdio.h>
int main( void )
{
enum { N = 3 };
printf( "Enter %d numbers.", N );
for ( int i = 0; i < N; i++ )
{
printf( "\t%d: ", i + 1 );
int value;
while ( !( scanf( "%d", &value ) == 1 ) )
{
scanf( "%*[^\n]%*c" );
puts( "Invalid input. Try again" );
printf( "\t%d: ", i + 1 );
}
printf( "You inputted %d\n", value );
}
}
Its output might look like
Enter 3 numbers.
1: 1A
You inputted 1
2:
Invalid input. Try again
2: B
Invalid input. Try again
2: 2C
You inputted 2
3:
Invalid input. Try again
3: 3
You inputted 3
That is the user entered the following sequence of strings
1A
B
2C
3
You should check the result of each scanf call. It returns the number of items successfully read (or EOF in case of failure) so in your case it should return 1 or otherwise something went wrong.
Please also note that each time you hit enter during input, there's a trailing line feed character added to stdin which needs to be discarded, if you were for example to read a string after reading a number. This should be addressed early on in your C book, if it's any good.
Overall scanf is to be regarded as a quick & dirty function for simplistic programs and not something to be used in real production code, so you don't really need to worry about leaning all the details of it. Using fgets and reading everything as strings is much better (and faster) practice.
Every time you ask for input, the user will also press Enter.
Therefore, get input as a string, then turn that string into a number. As there are several steps to reading a number and verifying it as correct, you can even write a convenient function to help.
void fatal_error( const char * message )
{
fprintf( stderr, "%s\n", message );
exit( 1 );
}
int get_int( const char * prompt, int min, int max, const char * error_message )
{
char s[ 100 ];
int n, count;
printf( "%s ", prompt );
fflush( stdout );
if ( !fgets( s, sizeof(s), stdin ) // user's input
or (sscanf_s( s, "%d %n", &n, &count ) != 1) // convert to int
or (count != strlen( s )) // no "123abc" stuff allowed
or (n < min)
or (n > max) )
fatal_error( error_message );
return n;
}
int main()
{
int n = ask_int( "n?", 1, 100, "n is not optional, and must be in [1,100]" );
int age = ask_int( "How old are you?", 0, INT_MAX, "You cannot be negative years old." );
etc
Say if I want to ask the user to enter one input or two inputs or three.
For example:
int num_1, num_2, num_3;
printf("Enter input" );
Now I'm struggling to find how to scan either one, two or three.
If I do this:
scanf("%d %d %d", &num_1, &num_2, &num_3);
it won't work if the user inputs only one or two inputs.
So how do I do it?
You should use a cycle and an array for the inputs, for example:
/* array where the inputs will be stored. It has the maximum
number of elements (3), assuming you want to use static arrays */
int inputs[3];
int n_inputs, i;
/* ask the user how many values he wants to put */
printf("Number of inputs: \n");
if(scanf("%d", &n_inputs) != 1) {
fprintf(stderr, "scanf fail!\n");
exit(EXIT_FAILURE);
}
/* ask for the inputs values */
printf("inputs [%d]: \n", n_inputs);
for(i = 0; i < n_inputs; i++) {
if(scanf("%d", &inputs[i]) != 1) {
fprintf(stderr, "scanf fail!\n");
exit(EXIT_FAILURE);
}
}
*edited to add scanf basic error handling.
Use a simple for loop and an array:
#include <stdio.h>
int main() {
int arr[3];
for (int i = 0; i < 3; i++) {
if (scanf("%d", &arr[i]) != 1) {
return 1;
}
}
return 0;
}
You can use loop for multiple input. First take the number of input, then loop through that.
For example:
int n, i;
printf("Please enter the input threshold: ");
scanf("%d", &n);
int arr[n];
for (i = 0; i < n; i++) {
printf("Enter number #%d: ", i+1);
scanf("%d", &arr[i]);
}
The following program will read exactly one line of input using fgets and read up to MAX_INPUTS (defined as 3) numbers from that line using strtol.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#define MAX_INPUTS 3
#define MAX_LINESIZE 80
int main( void )
{
long inputs[MAX_INPUTS];
int num_inputs;
char line[MAX_LINESIZE], *p;
//prompt user for input
printf( "Please enter up to %d numbers: ", MAX_INPUTS );
//attempt to read one line of input
if ( fgets( line, sizeof line, stdin ) == NULL )
{
fprintf( stderr, "error reading line\n" );
exit( EXIT_FAILURE );
}
//verify that entire line was read in
if ( strchr( line, '\n' ) == NULL )
{
fprintf( stderr, "line too long\n" );
exit( EXIT_FAILURE );
}
//read one number per loop iteration
for (
num_inputs = 0, p = line;
num_inputs < MAX_INPUTS;
num_inputs++
)
{
char *q;
errno = 0;
//attempt to convert next number
inputs[num_inputs] = strtol( p, &q, 10 );
//break out of loop if unable to find another number
if ( p == q )
break;
//make p point to end of inputted number
p = q;
//make sure that entered number is representable as "long int"
if ( errno == ERANGE )
{
fprintf( stderr, "number is out of range\n" );
exit( EXIT_FAILURE );
}
}
//output the inputted data
printf( "You entered %d inputs. The values are:\n", num_inputs );
for ( int i = 0; i < num_inputs; i++ )
{
printf( "%ld\n", inputs[i] );
}
}
This is what happens when I run this program:
Please enter up to 3 numbers: 80 30
You entered 2 inputs. The values are:
80
30
Size of array <=1000 and reverse a array in C programming & problem is in printing.
For example output is:
7654321
I want:
7 6 5 4 3 2 1
The first line take input about the number of elements in the array. The second prints the reverse of the array.
#include <stdio.h>
int main()
{
int k, i;
scanf("%d",&k); //no of integers in array
int a[1000]; //size given in question
for(i=0;i<=1000;i++)//accepting input
scanf("%d",&a[i]);
for(i=k-1;i>=0;i--)//for reversing string
printf("%d",a[i]);//my problem
//code
return 0;
}
Apart from your question the program is invalid.
The valid range of indices for the array declared in the program is [0, 1000).
However in this loop
for(i=0;i<=1000;i++)//accepting input
scanf("%d",&a[i]);
you are trying to access the element with the index equal to 1000 though the array does not have such an element.
If your compiler supports variable length arrays then you could declare an array with the number of elements entered by the user.
In this case the program can look like
#include <stdio.h>
int main( void )
{
size_t n;
printf( "Enter the size of an array (0 - exit): " );
if ( scanf( "%zu", &n ) == 1 && n != 0 )
{
int a[n];
for ( size_t i = 0; i < n; i++ ) scanf( "%d", &a[i] );
putchar( '\n' );
for ( size_t i = n; i != 0; i-- ) printf( "%d ", a[i-1] );
putchar( '\n' );
}
}
The program output might look like
Enter the size of an array (0 - exit): 10
9 8 7 6 5 4 3 2 1 0
Pay attention to the call of printf
printf( "%d ", a[i-1] )
^^^
It can be substituted to the following two function calls
for ( size_t i = n; i != 0; i-- )
{
printf( "%d", a[i-1] );
putchar( ' ' );
}