How to scan in multiple characters at once in C? - c

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

Related

How to detect non-integer input in C

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;
}

Error with code: Segmentation Fault, Core dumped

I am having an issue with the output of my code, which is trying to return an array backwards in c using pointers. Do you guys have any solutions to the error I am getting?
Sample input:
Please enter the array size: 3
Please enter 3 elements:
4, 5, 7
Segmentation fault (core dumped)
Code:
#include <stdio.h>
int main(void){
int size, i;
int *pointer;
int arr[size];
printf("Please enter the array size: ");
scanf("%d/n", &size);
pointer = &arr[0];
printf("Please enter %d elements: \n", size);
for(i = 0; i < size; i++){
scanf("%d", arr[i]);
pointer++;
}
pointer = &arr[size - 1];
printf("The reversed array is \n");
for(i = size; i > 0; i--){
printf("%d", arr[i]);
pointer--;
}
return 0;
}
The task is not simple for beginners like you and me.
As I have understood the user can enter any number of integers in one line and all entered integers in the line must be outputted like
You entered 2
In this case neither array nor character array nor integer array will help. And in fact you need not to define an array if you want only to output numbers stored in the input buffer.
In this case you can just use the standard function getchar. Using the function in a loop you can read all numbers placed by the user in one line in the I/O buffer.
Here is a sample program. It is a little complicated because I allow the user to enter sign symbols.
There is no check in the program whether the user entered not a digit or a sign. You can develop the program further. The program demonstrates an approach to solve the task.
#include <stdio.h>
#include <ctype.h>
int main( void )
{
const int Base = 10;
printf( "Enter a seria of integer numbers in one line: " );
int c;
int sign = 0;
int num = 0;
do
{
c = getchar();
if (c == EOF || c == '\n' )
{
if (sign)
{
printf( "You entered %d\n", num );
}
}
else if (isblank( ( unsigned char )c ))
{
if (sign)
{
printf( "You entered %d\n", num );
sign = 0;
num = 0;
}
}
else
{
if (c == '-' || c == '+')
{
if (sign)
{
printf( "You entered %d\n", num );
num = 0;
}
sign = c == '-' ? -1 : 1;
}
else if (isdigit( ( unsigned char )c ))
{
c -= '0';
if (sign == 0) sign = 1;
if (sign == 1)
{
num = Base * num + c;
}
else
{
num = Base * num - c;
}
}
}
} while (c != EOF && c != '\n');
}
The program output might look for example like
Enter a seria of integer numbers in one line: 1 -1 +12-12+13 +14 -15
You entered 1
You entered -1
You entered 12
You entered -12
You entered 13
You entered 14
You entered -15
If you want to enter several lines of numbers and output numbers that are present in each line then the program can look the following way
#include <stdio.h>
#include <ctype.h>
int main( void )
{
const int Base = 10;
size_t i = 0;
while (1)
{
printf( "Enter a seria of integer numbers in one line (or press just Enter to exit): " );
int c = getchar();
if (c == EOF || c == '\n') break;
ungetc( c, stdin );
printf( "Line %zu contains the following numbers:\n", i++ );
int sign = 0;
int num = 0;
do
{
c = getchar();
if (c == EOF || c == '\n')
{
if (sign)
{
printf( "You entered %d\n", num );
}
}
else if (isblank( ( unsigned char )c ))
{
if (sign)
{
printf( "You entered %d\n", num );
sign = 0;
num = 0;
}
}
else
{
if (c == '-' || c == '+')
{
if (sign)
{
printf( "You entered %d\n", num );
num = 0;
}
sign = c == '-' ? -1 : 1;
}
else if (isdigit( ( unsigned char )c ))
{
c -= '0';
if (sign == 0) sign = 1;
if (sign == 1)
{
num = Base * num + c;
}
else
{
num = Base * num - c;
}
}
}
} while (c != EOF && c != '\n');
putchar( '\n' );
}
}
The program output might look for example like
Enter a seria of integer numbers in one line (or press just Enter to exit): 1 -2 3 +4
Line 0 contains the following numbers:
You entered 1
You entered -2
You entered 3
You entered 4
Enter a seria of integer numbers in one line (or press just Enter to exit): 11-12 13+14
Line 1 contains the following numbers:
You entered 11
You entered -12
You entered 13
You entered 14
Enter a seria of integer numbers in one line (or press just Enter to exit):
As the program just outputs entered numbers then actually there is no need to build an object of the type int like
num = Base * num + c;
You could just output adjacent digits in a line.
int array[100];
int n;
scanf("%d", &n);
for(int i=0; i<n; i++) {
scanf("%d", &array[i]);
}
for(int i=0; i<n; i++) {
printf("You entered %d \n", array[i]);
}
We use the array to get all of the values, and just print them out at the end.
In C and C++ it does not matter if the values are separated by space or a newline, so you can get every integer in a single line if separated by spaces.
output
3
1 2 3
You entered 1
You entered 2
You entered 3
C makes this very easy, but you need to leverage some library functions. At the most simple:
use fgets() and strpbrk() to obtain and verify a line of text
use strtok() and strtol() to parse and verify integer values.
What you do with those values is up to you. Following your example prompt, let’s just print them.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int error( const char * message, const char * value )
{
fprintf( stderr, "%s%s\n", message, value );
return 1;
}
int main()
{
printf( "Input: " );
// Get all input on a single line
char text[1000];
fgets( text, sizeof(text), stdin );
// Verify that the entire line of input was obtained
char * nl = strpbrk( text, "\r\n" );
if (!nl) return error( "Line too long!", "" );
*nl = '\0';
puts( "Output:" );
// For each whitespace-delimited (spaces, tabs) token in the line:
for (char * token = strtok( text, " \t" ); token; token = strtok( NULL, " \t" ))
{
// Attempt to convert it to an integer
char * nok;
int n = strtol( token, &nok, 10 );
if (*nok) return error( "Invalid integer value: ", token );
// Success!
printf( "You entered %d\n", n );
}
return 0;
}
Notice also how it is OK to create a little helper function (error()). You can make helpers as complex or simple as you need. For this helper, all we need was to complain with one or two strings and return an “error happened” exit code that main() can pass right to the shell.
fgets can be used to read a line.
strtol can parse integers and report overflow and invalid input.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <limits.h>
int parselint ( char *line, int *value, char **end) {
long int number = 0;
errno = 0;
number = strtol ( line, end, 10);
if ( *end == line) {// nothing was parsed. no digits
size_t span = strcspn ( *end, "-+0123456789"); // characters to next int
if ( ! span) {
span = 1;
}
fprintf ( stderr, "problem parsing: %.*s\n", (int)span, line);
*end += span; // advance pointer to next int
return 0;// return failure
}
if ( ( errno == ERANGE && ( number == LONG_MAX || number == LONG_MIN))
|| ( errno != 0 && number == 0)) {// parsing error from strtol
fprintf ( stderr, "problem %.*s", (int)(*end - line), line);
perror ( " ");
return 0;
}
if ( number > INT_MAX || number < INT_MIN) {
fprintf ( stderr, "problem %.*s ", (int)(*end - line), line);
fprintf ( stderr, "out of int range\n");
return 0;
}
*value = number;//assign number to pointer
return 1;//success
}
int main ( void) {
char line[4096] = "";
char *parse = line;
int number = 0;
fgets ( line, sizeof line, stdin);
line[strcspn ( line, "\r\n")] = 0; // remove newline
while ( *parse) {
if ( 1 == parselint ( parse, &number, &parse)) {
printf ( "you entered %d\n", number);
}
}
return 0;
}

How to deal with wrong input in C?

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;
}

Yes and no while loop not validating if incorrect string is entered in C

When correct option is selected the program loops fine but if the user selects a wrong choice the program keeps looping at the wrong answer. I tried many other solutions but none seem to be working.________________________________________________________________________________________
#include<stdlib.h>
#include<string.h>
#include<stdio.h>
#include <math.h>
#define correct 1
#define incorrect 0
int main(void)
{
int y, flags = incorrect;
size_t r = 0;
char s ='y';
int v;
char courses[5][100];
char list_courses[5][100] = {"CSE1100",
"CSE1101",
"CSE1102",
"ITE1100",
"ITE1101"};
do{
printf("Enter Courses :\n Courses available: \n CSE1100 \n CSE1101 \n ITE1100\n ITE1101\n");
scanf("%s", courses[r]);
getchar();
r++;
for(int i = 0;i < 5; i++)
{
y = strcmp(&list_courses[i][0],courses[i]);
if(y == 0)
{
flags = correct;
}
}
while(flags != correct)
{
for(size_t p = 0; p <r ; p++)
{
printf("%s incorrect choose from list of courses \n CSE1100 \n CSE1101 \n ITE1100\n ITE1101\n", courses[p]);
printf("try again!:\n", courses[p]);
scanf("%s", courses[p]);
getchar();
}
}
for(int i = 0;i < 5; i++)
{
y = strcmp(&list_courses[i][0],courses[i]);
if(y == 0)
{
flags = correct;
}
}
printf("Would you like to enter another course? (y or n) \n");
s = getchar();
}while(s == 'y');
}
The loop for(size_t p = 0; p <r ; p++) seems redundant, as it does not seem appropriate to print the error message several times.
The lines
scanf( "%s", courses[r] );
getchar();
will not work if the user enters more than one word of input. In that case, the getchar function call will not consume the newline character from the input stream. Also, it is always possible that scanf will fail, so you should always check the return value of that function. Additionally, you should always restrict the number of characters written to the buffer, otherwise, if the user enters too much data, this will cause a buffer overflow, and your program may crash. Therefore, is better to use the following code:
int c;
if ( scanf( "%99s", courses[r] ) != 1 )
{
//TODO: handle error
}
do
{
c = getchar();
} while ( c != '\n' && c != EOF );
Also, instead of using
#define correct 1
#define incorrect 0
and using these values with a variable named flags, it would seem easier to use the data type bool and introduce a variable input_valid, which defaults to false. You must #include <stdbool.h> in order to use this data type.
Also, if the user enters a wrong value, you are duplicating most of the input code. This is unnecessary. You should instead repeat the loop iteration.
Solving the problem would be easier if you first only attempt to read a single course from the user:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#define NUM_COURSES 5
int main(void)
{
bool input_valid = false;
const char * const list_courses[NUM_COURSES] = {
"CSE1100",
"CSE1101",
"CSE1102",
"ITE1100",
"ITE1101"
};
while ( !input_valid )
{
char input[100];
int c;
//prompt user for input
printf(
"Courses available:\n"
" CSE1100\n"
" CSE1101\n"
" CSE1102\n"
" ITE1100\n"
" ITE1101\n"
"\n"
"Enter Course: "
);
//attempt to read one word of user input
if ( scanf( "%99s", input ) != 1 )
{
fprintf( stderr, "unexpected input failure!\n" );
exit( EXIT_FAILURE );
}
//discard remainder of input line
do
{
c = getchar();
} while ( c != '\n' && c != EOF );
//determine whether course entered was valid or not
for( int i = 0; i < NUM_COURSES; i++ )
{
if ( strcmp(input, list_courses[i] ) == 0)
{
input_valid = true;
break;
}
}
//if invalid, print error message
if ( !input_valid )
printf( "Invalid choice! Try again.\n\n" );
}
printf( "Input was valid.\n" );
}
This program has the following behavior:
Courses available:
CSE1100
CSE1101
CSE1102
ITE1100
ITE1101
Enter Course: CSE1103
Invalid choice! Try again.
Courses available:
CSE1100
CSE1101
CSE1102
ITE1100
ITE1101
Enter Course: CSE1102
Input was valid.
If you want the user to be able to enter multiple courses, then you will need an additional outer loop and you will need a place to store all the courses that the user has selected. In your code, you have allocated 100 bytes for storing every course. However, this is rather wasteful, as all you have to remember is an index between 0 and 4, because there are only 5 courses in the array list_courses. You only need a single byte to store such a small number, so a char would be sufficient. But let's not be too thrifty and use an int instead (which is 4 bytes on most common platforms):
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#define NUM_COURSES 5
int main(void)
{
int selected_courses[NUM_COURSES];
int num_selected_courses = 0;
int c;
const char * const list_courses[NUM_COURSES] = {
"CSE1100",
"CSE1101",
"CSE1102",
"ITE1100",
"ITE1101"
};
do
{
bool input_valid = false;
int selected_course;
int d;
while ( !input_valid )
{
char input[100];
//prompt user for input
printf(
"Courses available:\n"
" CSE1100\n"
" CSE1101\n"
" CSE1102\n"
" ITE1100\n"
" ITE1101\n"
"\n"
"Enter Course: "
);
//attempt to read one word of user input
if ( scanf( "%99s", input ) != 1 )
{
fprintf( stderr, "unexpected input failure!\n" );
exit( EXIT_FAILURE );
}
//discard remainder of input line
do
{
d = getchar();
} while ( d != '\n' && d != EOF );
//determine whether course entered was valid or not
for( int i = 0; i < NUM_COURSES; i++ )
{
if ( strcmp(input, list_courses[i] ) == 0)
{
input_valid = true;
selected_course = i;
break;
}
}
//if invalid, print error message
if ( !input_valid )
printf( "Invalid choice! Try again.\n\n" );
}
//input was valid, so add course
selected_courses[num_selected_courses] = selected_course;
num_selected_courses++;
//if we have already reached the maximum number of
//courses, then don't ask again
if ( num_selected_courses == NUM_COURSES )
break;
//ask user whether he wants to add another course
printf("Would you like to enter another course? (y or n)\n");
c = d = getchar();
//add spacing
printf( "\n" );
//discard remainder of input line
while ( d != '\n' && d != EOF )
d = getchar();
} while ( c == 'y' );
printf( "You have selected the following courses:\n" );
//print courses selected by user
for ( int i = 0; i < num_selected_courses; i++ )
printf( "%s\n", list_courses[selected_courses[i]] );
}
This program has the following behavior:
Courses available:
CSE1100
CSE1101
CSE1102
ITE1100
ITE1101
Enter Course: CSE1101
Would you like to enter another course? (y or n)
y
Courses available:
CSE1100
CSE1101
CSE1102
ITE1100
ITE1101
Enter Course: ITE1102
Invalid choice! Try again.
Courses available:
CSE1100
CSE1101
CSE1102
ITE1100
ITE1101
Enter Course: ITE1100
Would you like to enter another course? (y or n)
y
Courses available:
CSE1100
CSE1101
CSE1102
ITE1100
ITE1101
Enter Course: CSE1102
Would you like to enter another course? (y or n)
n
You have selected the following courses:
CSE1101
ITE1100
CSE1102
Note that this solution is not perfect, because it allows the user to select the same course twice. If you want, you can add an additional check to prevent this.

How to store courses added from a y/n loop to a char in c

The code prints the list of courses the user entered using a for loop. Is there a way in which the list of courses can be saved to a single char file like
printf("%s", listofcourses);
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#define NUM_COURSES 5
int main(void)
{
int selected_courses[NUM_COURSES];
int num_selected_courses = 0;
int c;
const char * const list_courses[NUM_COURSES] = {
"CSE1100",
"CSE1101",
"CSE1102",
"ITE1100",
"ITE1101"
};
do
{
bool input_valid = false;
int selected_course;
int d;
while ( !input_valid )
{
char input[100];
//prompt user for input
printf(
"Courses available:\n"
" CSE1100\n"
" CSE1101\n"
" CSE1102\n"
" ITE1100\n"
" ITE1101\n"
"\n"
"Enter Course: "
);
//attempt to read one word of user input
if ( scanf( "%99s", input ) != 1 )
{
fprintf( stderr, "unexpected input failure!\n" );
exit( EXIT_FAILURE );
}
//discard remainder of input line
do
{
d = getchar();
} while ( d != '\n' && d != EOF );
//determine whether course entered was valid or not
for( int i = 0; i < NUM_COURSES; i++ )
{
if ( strcmp(input, list_courses[i] ) == 0)
{
input_valid = true;
selected_course = i;
break;
}
}
//if invalid, print error message
if ( !input_valid )
printf( "Invalid choice! Try again.\n\n" );
}
//input was valid, so add course
selected_courses[num_selected_courses] = selected_course;
num_selected_courses++;
//if we have already reached the maximum number of
//courses, then don't ask again
if ( num_selected_courses == NUM_COURSES )
break;
//ask user whether he wants to add another course
printf("Would you like to enter another course? (y or n)\n");
c = d = getchar();
//add spacing
printf( "\n" );
//discard remainder of input line
while ( d != '\n' && d != EOF )
d = getchar();
} while ( c == 'y' );
printf( "You have selected the following courses:\n" );
//print courses selected by user
for ( int i = 0; i < num_selected_courses; i++ )
printf( "%s\n", list_courses[selected_courses[i]] );
}
Is there a way in which the list of courses can be saved to a single char file
I assume that with "a single char file" you mean a single string.
Currently, you are storing the IDs (which are int indexes into the array list_courses) of all the courses that the user has selected, in the array selected_courses. At the end of the program, these IDs are individually read and converted into text, and printed to the screen. If you instead want to write them to a string, and then use
printf( "%s", string );
on that string afterwards, then this is possible (although I don't understand why you want to do that):
You can change the lines
//print courses selected by user
for ( int i = 0; i < num_selected_courses; i++ )
printf( "%s\n", list_courses[selected_courses[i]] );
to:
//this buffer must be made large enough, otherwise a buffer overflow
//will occur
char string[200];
//set first character to null to make string empty
string[0] = '\0';
//fill string with list of courses
for ( int i = 0; i < num_selected_courses; i++ )
{
//add a comma and a space if this is not the first in the list
if ( i != 0 )
strcat( string, ", " );
//add course to string
strcat( string, list_courses[selected_courses[i]] );
}
//print the string
printf( "String contents: %s\n", string );
The program now has the following behavior:
Courses available:
CSE1100
CSE1101
CSE1102
ITE1100
ITE1101
Enter Course: CSE1100
Would you like to enter another course? (y or n)
y
Courses available:
CSE1100
CSE1101
CSE1102
ITE1100
ITE1101
Enter Course: CSE1102
Would you like to enter another course? (y or n)
y
Courses available:
CSE1100
CSE1101
CSE1102
ITE1100
ITE1101
Enter Course: ITE1100
Would you like to enter another course? (y or n)
n
You have selected the following courses:
String contents: CSE1100, CSE1102, ITE1100

Resources