Input number resets to 0 after scanf - c

I have a weird issue. I ask a user to enter a number between 1 and 15. Then I would ask the user would the like to get the factorial value of the number using either recursive or a for loop.
When they answer that question the inputted value goes to 0. If I remove the question for testing purpose the value stays the value the user inputted.
#include <stdio.h>
int recursive(int);
int nonRecursive(int);
int main()
{
/* Variables */
int numberSelected, returnedValue;
char answer;
do
{
/* Request a number between 1 and 15 */
printf("Please enter a number between 1 and 15: ");
scanf("%d", &numberSelected);
printf("%d\n", numberSelected); /* This prints out the user's number */
}while(numberSelected < 1 || numberSelected > 15); /* Loops if the value is not between 1 and 15 */
/* Ask user if they want to return a recursive value or a value calculated manually */
printf("Would you like a recusive value of the number you entered? Y or N: ");
scanf("%s", &answer);
if(answer == 'y' || answer == 'Y')
{
printf("%d\n", numberSelected); /* Here it resets to 0 */
returnedValue = recursive(numberSelected); /* Returns the recursive value */
printf("The recursive value of %d is %d\n", numberSelected, returnedValue);
}
else
{
printf("%d\n", numberSelected); /* Here it resets to 0 also*/
returnedValue = nonRecursive(numberSelected); /* Returns the value from for loop */
printf("The non recursive value of %d is %d\n", numberSelected, returnedValue);
}
return 0;
}
/* Get value using recursive */
int recursive(int n)
{
if (n == 0)
return 1; // Base case
else
return n * recursive(n - 1);
}
/* Get value using for loop */
int nonRecursive(int n)
{
int i;
int fact = 1;
for(i = 1; i <= n; i++)
{
fact *= i;
}
return fact;
}
Thank you for the help

scanf("%s", &answer);
is wrong. %s is for reading strings (null-terminated sequence of characters), but answer has only room for 1 character, so out-of-bound write will occur when strings with one or more characters is read. It may break data around that.
The line should be
scanf(" %c", &answer);
Use %c, which reads single character.
Add a space before %c to have scanf() ignore whitespace characters.

Related

Function that prompts user for integer value and checks for valid input

I currently am stuck on a small part of an assignment I need to do.
One requirement of the assignment is
"Call a function that prompts the user for each of the values of the coefficients a, b, and c for the quadratic equation and returns the value entered, with error checking for a valid input (scanf returned a value)."
and I can't figure out how to do this. I can easily prompt the user for input and I can check if it is valid input, but I don't know how to turn this into a function. My current code is:
{
if (isalpha(a))
{
printf("INPUT ERROR!\n");
printf("Enter a value for a: ");
scanf("%d", &a);
}
} //this is how I would normally check the input
int main(void) //start of main() function definition
{
int a, b, c, n, D; //declares integer variables a, b, c, n, and D
float root1, root2; //declares float variables root1 and root2
do //do while loop starts here
{
printf("Enter a value for a: "); //prompts user to input integer for variable 'a'
scanf("%d", &a); //reads an integer from the keyboard and stores in the variable 'a'
printf("%d\n", a); //returns value of integer that was input for variable 'a'
printf("Enter a value for b: "); //prompts user to input integer for variable 'b'
scanf("%d", &b); //reads an integer from the keyboard and stores in the variable 'b'
printf("%d\n", b); //returns value of integer that was input for variable 'b'
printf("Enter a value for c: "); //prompts user to input integer for variable 'c'
scanf("%d", &c); //reads an integer from the keyboard and stores in the variable 'c'
printf("%d\n", c); //returns value of integer that was input for variable 'c'
...}
Sorry for any formatting mistakes, but that is basically the part of the program I am stuck with.
My question is, how can I combine the first function with everything in the do/while loop to make one big function that I can call three times?
I don't know how I'd be able to switch out all the instances of a for b and c using a function, as I've never really had to use a function like this before.
Function that prompts user for integer value and checks for valid input
If users only entered valid integer text on a line-by-line basis, then code is easy:
// Overly idealized case
fputs(prompt, stdout);
char buf[50];
fgets(buf, sizeof buf, stdin);
int i = atoi(buf);
But users are good, bad and ugly and **it happens. If code wants to read a line, parse it for an in-range int, and detect a host of problems, below is code that vets many of the typical issues of bogus and hostile input.
I especially interested in detecting overly long input as hostile and so invalid as a prudent design against hackers. As below, little reason to allow valid input for a 32-bit int with more than 20 characters. This rational deserve a deeper explanation.
End-of-file
Input stream error
Overflow
No leading numeric test
Trailing non-numeric text
Excessive long line
First a line of input is read with fgets() and then various int validation tests applied. If fgets() did not read the whole line, the rest is then read.
#include <limits.h>
#include <ctype.h>
// Max number of `char` to print an `int` is about log10(int_bit_width)
// https://stackoverflow.com/a/44028031/2410359
#define LOG10_2_N 28
#define LOG10_2_D 93
#define INT_DEC_TEXT (1 /*sign*/ + (CHAR_BIT*sizeof(int)-1)*LOG10_2_N/LOG10_2_D + 1)
// Read a line and parse an integer
// Return:
// 1: Success
// 0: Failure
// EOF: End-of-file or stream input error
int my_get_int(int *i) {
// Make room for twice the expected need. This allows for some
// leading/trailing spaces, leading zeros, etc.
// int \n \0
char buf[(INT_DEC_TEXT + 1 + 1) * 2];
if (fgets(buf, sizeof buf, stdin) == NULL) {
*i = 0;
return EOF; // Input is either at end-of-file or a rare input error.
}
int success = 1;
char *endptr;
errno = 0;
long value = strtol(buf, &endptr, 10);
// When `int` is narrower than `long`, add these tests
#if LONG_MIN < INT_MIN || LONG_MAX > INT_MAX
if (value < INT_MIN) {
value = INT_MIN;
errno = ERANGE;
} else if (value > INT_MAX) {
value = INT_MAX;
errno = ERANGE;
}
#endif
*i = (int) value;
if (errno == ERANGE) {
success = 0; // Overflow
}
if (buf == endptr) {
success = 0; // No conversion
}
// Tolerate trailing white-space
// Proper use of `is...()` obliges a `char` get converted to `unsigned char`.
while (isspace((unsigned char ) *endptr)) {
endptr++;
}
// Check for trailing non-white-space
if (*endptr) {
success = 0; // Extra junk
while (*endptr) { // quietly get rest of buffer
endptr++;
}
}
// Was the entire line read?
// Was the null character at the buffer end and the prior wasn't \n?
const size_t last_index = sizeof buf / sizeof buf[0] - 1;
if (endptr == &buf[last_index] && buf[last_index - 1] != '\n') {
// Input is hostile as it is excessively long.
success = 0; // Line too long
// Consume text up to end-of-line
int ch;
while ((ch = fgetc(stdin)) != '\n' && ch != EOF) {
;
}
}
return success;
}
Sample usage
puts("Enter a value for a: ", stdout);
fflush(stdout); // Insure output is seen before input.
int a;
if (my_get_int(&a) == 1) {
printf("a:%d\n", a);
}
My question is, how can I combine the first function with everything in the do/while loop to make one big function that I can call three times?
Well, the function need not be big. The things to factor out are the prompt string and the variable to read - the latter can be left in the calling main() and assigned from a return value. Regarding how you would normally check the input, I recommend leaving this checking to scanf() and just test its return value.
#include <stdio.h>
#include <stdlib.h>
int input(char *prompt)
{ // prompts user to input integer
// reads an integer from standard input and returns it
int a, s; // leave it to scanf to check the input:
while (printf("%s", prompt), fflush(stdout), s = scanf("%d", &a), !s)
{
printf("INPUT ERROR!\n");
do s = getchar(); while (s != '\n' && s != EOF); // consume bad input
}
if (s == EOF) puts(""), exit(0); // no more input
return a;
}
In main() you can then just do
a = input("Enter a value for a: ");
b = input("Enter a value for b: ");
c = input("Enter a value for c: ");
(without a loop).
scanf() already processes the input for you according to the format specifier (%d) so you just need to understand how scanf works and use it to check and build your function :)
When you write scanf("%d", &a); the program expects you write an integer because of the %d specifier, and if an integer is read, the program writes it into variable a.
But the function scanf also has a return value, ie, you can do check = scanf("%d", &a); and check will have a value of 0 or 1 in this case. This is because the return value records how many values have been successfuly read. If you entered dsfugnodg there's no number so it would return 0. If you entered 659 32 it would read the 1st value successfully and return 1.
Your function would look something like:
#include <stdio.h>
int getAndPrint(char label)
{
int n = 0, val = 0;
do {
printf("Enter a value for %c: ", label);
n = scanf("%d", &val);
if (n == 0) {
printf("Error, invalid value entered.\n");
/* Consume whatever character leads the wrong input
* to prevent an infinite loop. See:
* https://stackoverflow.com/questions/1669821/scanf-skips-every-other-while-loop-in-c */
getchar();
}
} while (n == 0);
printf("%c = %d\n", label, val);
return val;
}
int main()
{
int a, b, c;
a = getAndPrint('a');
b = getAndPrint('b');
c = getAndPrint('c');
printf("a=%d, b=%d, c=%d\n", a, b, c);
}
See also:
Scanf skips every other while loop in C
I think the following code is you wanted:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h> // for isalpha
void InputAndCheck(int * pValue, const char * pName)
{
do
{
printf("Enter a value for %s: ", pName);
scanf("%d", pValue);
if (isalpha(*pValue))
{
printf("INPUT ERROR!\n");
continue;
}
else
{
break;
}
} while (1);
// clear the input buffer
fflush(stdin);
return;
}
int main()
{
int a, b, c;
InputAndCheck(&a, "a");
InputAndCheck(&b, "b");
InputAndCheck(&c, "c");
printf("a=%d;b=%d;c=%d;\r\n",a,b,c);
return 0;
}
What you are looking for is an introduction to functions.
Here is one : https://www.tutorialspoint.com/cprogramming/c_functions.htm
This is a very important building block in programming and you should definitely learn to master that concept.
functions will allow you to execute some code in different contexts over and over, just changing the context (the parameters).
It is declared like this
int add(int first, int second){
//here we can use first and second
printf("first: %d\n", first);
printf("second: %d\n", second);
//and eventually return a value
return first+second;
}
Now when using we are reusing our previous code to excute a task which result will vary depending of the arguments we pass.
printf("1+2 = %d\n", add(1, 2));
-->3
printf("2+2 = %d\n", add(2, 2));
-->4
Example solution for your task:
//this will handle validation
int validateInput(int input){
if(isalpha(input)){
printf("INPUT ERROR!\n");
return 0;
}
return 1;
}
//this will prompt the user and return input only if the input is valid
int askForCoefficient(unsigned char coefficientName){
int valid = 0;
int value = 0;
while(!valid){
printf("Enter a value for %c: ", coefficientName);
value = scanf("%d", &value);
valid = validateInput(value);
}
printf("%d\n", value);
return value;
}

Re-prompting a user until he/she enters a positive integer value greater than 1

I'm solving CS50 (problemset 1) i.e water.c. It asks user to write a program that prompts the user for the length of his or her shower in minutes (as a positive integer) and then prints the equivalent number of bottles of water (as an integer).
1 min of shower = 12 bottles consumed
MAIN PROBLEM: The problem is that we have to ensure that the user inputs a positive number of minutes otherwise it keeps on re-prompting his back to input/scanf statement. As long as he enters he enters length<=0, I can re-prompt him back using while(length<=0) condition but as he enters a character i.e abc123 in input my code keeps on executing. Any solutions??
>
#include <stdio.h>
int main()
{ int length=0;
int min=12;
int bottle=0;
printf("Enter length of his or her shower in minutes");
scanf("%d", &length);
while (length <= 0){
printf("Enter length of his or her shower in minutes");
scanf("%d", &length);
}
bottle= (min*length);
printf("%d", bottle);
return 0;
}
You can solve this by reading a string first, and then extracting any number:
#include <stdio.h>
int main(void)
{
int length = 0;
char input[100];
while(length <= 0) {
printf("Enter length: ");
fflush(stdout);
if(fgets(input, sizeof input, stdin) != NULL) {
if(sscanf(input, "%d", &length) != 1) {
length = 0;
}
}
}
printf("length = %d\n", length);
return 0;
}
Program session:
Enter length: 0
Enter length: -1
Enter length: abd3
Enter length: 4
length = 4
Crucially, I always check the return value from scanf, the number of items successfully converted.
If you don't care about Inputs like 1f then the Above Answers are ok For you, but if you do not want to accept this kind of Input, then the following approach does something like that:
#include<stdio.h>
int checkInput(void);
int main(void){
int number = checkInput();
printf("\nYour number is\t%d\n",number);
return 0;
}
int checkInput(void){
int option,check;
char c;
do{
printf("Please type a number:\t");
if(scanf("%d%c",&option,&c) == 0 || c != '\n'){
while((check = getchar()) != 0 && check != '\n' && check != EOF);
printf("\tI sayed a Number please\n\n");
}else{
if ( option < 1){
printf("Wrong input!\n");
}else{
break;
}
}
}while(1);
return option;
}
Output:
Please type a number: 1f
I sayed a Number please
Please type a number: f1
I sayed a Number please
Please type a number: -1
Wrong input!
Please type a number: 1
Your number is 1
You don't need the first prompt outside the loop because you have already initialised length to zero, so the loop will prompt at least once.
On most platforms other then Wndows, you need to flush stdout to show text not terminated with a newline.
scanf will return so long as a newline character is buffered and %d alone will not consume the newline, so you need to ensure that any remaining characters up to and including the newline are flushed to prevent an endless loop.
It is good practice to check the return value from scanf() since it makes no guaranteed about not modifying its arguments even when a conversion fails.
It is not clear why min is a variable here sine it is initialised but never re-assigned, but presumably that may be the case in the final program?
#include <stdio.h>
int main( void )
{
int length = 0 ;
int min = 12 ;
int bottle = 0 ;
while( length <= 0 )
{
int converted = 0 ;
printf( "Enter length of his or her shower in minutes: " ) ;
fflush( stdout ) ;
converted = scanf( "%d", &length ) ;
if( converted != 1 )
{
length = 0 ;
}
while( (c = getchar()) != '\n' && c != EOF ) { } // flush line buffer
}
bottle = min * length ;
printf( "%d", bottle ) ;
return 0;
}
int min = 0;
do {
printf("Enter minutes: ");
scanf("%i", &min);
} while(min <= 0);
//programs resumes after this.

Turning my array into a function and making 2nd function to print it

Im trying to create a program that has 2 options, view and compute. Right now im trying to figure how to turn my array where i will input my values into a function, so i can go in and out several times to store the values. I also want to view to be a function where i can view the values several times.
i've managed to get the computing part to work in my main, now i need to turn it into a function. Secondly how do i create a second function to view it?
My code is a bit mess please bear with me.
#include <stdio.h>
#define LENGTH 10
int enterMeasurements();
int main(void)
{
char input;
int nrMeasurements=0;
int arrayTable[LENGTH] = {0};
//main menu
do
{
char input;
printf("\nMeasurement tool 1.0\n");
printf("V for (View)\n");
printf("E for (Enter Values)\n");
printf("C for (Compute Values)\n");
printf("R for (Reset Values)\n");
printf("Q for (Quit)\n");
printf("\nEnter input: ");
scanf(" %c", &input);
if(input == 'v' || input == 'V')
{
// function to print array values
printf("[ ]\n");
}
else if(input == 'e' || input == 'E')
{
// enter values here
nrMeasurements = enterMeasurements(arrayTable,nrMeasurements); // my function for entering values
}
else if (input == 'c' || input == 'C')
{
// enter function to calc min, max and avg and prints it.
printf("[ min max avg ]\n");
}
else if (input == 'r' || input == 'R')
{
// enter function that erase the entire array.
printf("[ erase array ]\n");
}
}
while (input !='q' && input != 'Q');
return 0;
}
int enterMeasurements()
{
int enterMeasurements(int arrayTable[], int nrMeasurements)
{
int i;
for (i = 0; i < LENGTH; i++)
{
printf("Enter Measurement #%i (or 0): ", i+1);
scanf("%d", &arrayTable[i]);
if (arrayTable[i] == 0 )
break;
}
return i;
}
To help you get started (you should really read a beginners book on the subject) I will show you the printArray function.
First of all the printArray function needs to know the actual array to print. it also needs to know the number of elements in the array. This can be accomplished in two ways: Global variables (which no-one is really recommending) or with function arguments.
You first need to tell the compiler that the function takes arguments:
void printArray(int *array, size_t numElements)
The above line tells the compiler that the printArray function takes two arguments: One which is called array and is a pointer to int (arrays "decays" to pointers to their first element when passed to functions), and one argument that is named numElements and is of type size_t (which is a good type for sizes and number of elements and similar things). The function is declared to return nothing with the void keyword.
The declared arguments can then be used inside the function like any other variables in the scope of the function, and are in fact just like any other local variable defined inside the function. So you can then use them like e.g.
void printArray(int *array, size_t numElements)
{
for (size_t i = 0; i < numElements; ++i)
{
printf("array[%d] = %d\n", i, array[i]);
}
}
To call this function you need to pass the array and the number of elements, much like you pass arguments to any other function like scanf or printf:
printArray(arrayTable, i);
Note that the function doesn't return anything, which means you can't use it in printf, or any other expression that expects a value.
You should of course also make your forward function prototype declaration match the actual function definition.
Alex, continuing from your last comment, to display a menu that will allow you to add values to your array, delete values from your array and view the array (along with the max, min and average of the values), can do something similar to the following. Note: the command line isn't a windowed user interface, so your menu operations are more like a printed receipt of your transactions with it. (you can do nice text windows and stationary menus, but that generally requires an text library, such as ncurses which is well beyond the scope of your question.
As explained in the comment, your basic approach is simply to create a loop that repeats continually. It will display your menu and allow you to enter your selection from a list, e.g.:
======== Program Menu =========
V) View the Array.
I) Insert New Value.
D) Delete Existing Value.
N) Display Minimum Value.
X) Display Maximum Value.
A) Display Average of Values.
S) Display Sum of Values.
Q) Quit.
Selection:
After the user enters the selection, to make the comparison easier, the user's input in converted to lower-case. Also note, that the input is read as a string using fgets (a line-oriented input function) which makes taking user input much easier than having to worry about whether the '\n' remains in the input buffer (stdin) just waiting to cause problems for your next input. (you can use the scanf family of functions, but YOU are the one responsible for accounting for each character entered by the user (and emptying the input buffer).
Reading input with fgets will read up to and including the '\n', so their is no chance of the '\n' being left unread in stdin. Also note that fgets will read a string or characters, where you are only interested in the first. That is easily handled simply by referencing the first character in the buffer. (e.g. if you are reading user-input into a buffer called buf, you can simply use buf[0] to access the first character, or simply *buf for that matter)
After the user input is read, the first character is passed to a switch statement, where each case of the statement is compared against the first character. If the character matches a case, then the actions associated with that case are taken, ending with the break (you can read about fall-through processing if the break is omitted on your own)
As mentioned in the comment, if you simply need to break out of one loop, then break is all you need. However here, your switch statement is inside the loop. A single break will only get you out of the switch but not the outside for loop. To break out of nested loops, use the goto statement. (you could also add more variables and set some type of exit flag, but why? This is what the goto was meant to do. (there are some cases where a flag is equally good as well)
In each case within the switch, you are free to call whatever code is needed to handle that menu selection. You will note we simply call short helper functions from within the switch to print the array, insert values, remove values, etc. You can put all the code in the switch if you like, it just rapidly become unreadable.
Putting that altogether, you can do something like the following:
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <ctype.h>
enum { MAXN = 64 }; /* constant - max numbers of vals & chars */
void showmenu ();
void prnarray (int *a, int n);
int addvalue (int *a, int n, int newval);
int delvalue (int *a, int n, int index);
int minvalue (int *a, int n);
int maxvalue (int *a, int n);
int sumvalues (int *a, int n);
int main (void) {
int vals[MAXN] = { 21, 18, 32, 3, 9, 6, 16 }, /* the array */
n = 7;
for (;;) { /* loop until user quits or cancels, e.g. ctrl+d */
showmenu(); /* show the menu */
char buf[MAXN] = "";
fgets (buf, MAXN, stdin); /* read user input */
/* convert to lower-case for comparison of all entries */
switch (tolower (buf[0])) { /* 1st char is entry */
case 'v' : prnarray(vals, n);
break;
case 'i' : printf ("\n enter the new value: ");
if (fgets (buf, MAXN, stdin) &&
isdigit (buf[0])) {
n = addvalue (vals, n, atoi (buf));
}
break;
case 'd' : printf ("\n enter the index to delete: ");
if (fgets (buf, MAXN, stdin) &&
isdigit (buf[0])) {
n = delvalue (vals, n, atoi (buf));
}
break;
case 'n' : printf ("\n Mininum of '%d' values is : %d\n",
n, minvalue (vals, n));
break;
case 'x' : printf ("\n Maxinum of '%d' values is : %d\n",
n, maxvalue (vals, n));
break;
case 'a' : printf ("\n Average of '%d' values is : %.2lf\n",
n, (double)sumvalues (vals, n)/n);
break;
case 's' : printf ("\n Sum of '%d' values is : %d\n",
n, sumvalues (vals, n));
break;
case 'q' : printf (" that's all folks...\n");
goto done;
default : if (!buf[0]) { /* check for manual EOF */
putchar ('\n'); /* tidy up */
goto done;
}
fprintf (stderr, "error: invalid selection.\n");
}
}
done:; /* goto label - breaking 'for' and 'switch' */
return 0;
}
void showmenu ()
{
fprintf(stderr, "\n ======== Program Menu =========\n\n"
" V) View the Array.\n"
" I) Insert New Value.\n"
" D) Delete Existing Value.\n"
" N) Display Minimum Value.\n"
" X) Display Maximum Value.\n"
" A) Display Average of Values.\n"
" S) Display Sum of Values.\n"
"\n"
" Q) Quit.\n"
"\n"
" Selection: ");
}
void prnarray (int *a, int n)
{
int i;
printf ("\n there are '%d' values in the array:\n\n", n);
for (i = 0; i < n; i++)
printf (" array[%2d] : %d\n", i, a[i]);
}
int addvalue (int *a, int n, int newval)
{
if (n == MAXN) {
fprintf (stderr, "error: all '%d' values filled.\n", n);
return n;
}
a[n++] = newval;
return n;
}
int delvalue (int *a, int n, int index)
{
if (index < 0 || index > n - 1) {
fprintf (stderr, "error: index out of range.\n");
return n;
}
int i;
for (i = index + 1; i < n; i++)
a[i-1] = a[i];
a[i] = 0;
return --n;
}
int minvalue (int *a, int n)
{
int i, min = INT_MAX;
for (i = 0; i < n; i++)
if (a[i] < min)
min = a[i];
return min;
}
int maxvalue (int *a, int n)
{
int i, max = INT_MIN;
for (i = 0; i < n; i++)
if (a[i] > max)
max = a[i];
return max;
}
int sumvalues (int *a, int n)
{
int i, sum = 0;
for (i = 0; i < n; i++)
sum += a[i];
return sum;
}
(note: there are always additional validation checks you can add to test whether you have read all the input the user provided, etc.. But given the crux of your question I'll leave that learning to you)
Example Use/Output
$ ./bin/menusimple
======== Program Menu =========
V) View the Array.
I) Insert New Value.
D) Delete Existing Value.
N) Display Minimum Value.
X) Display Maximum Value.
A) Display Average of Values.
S) Display Sum of Values.
Q) Quit.
Selection: v
there are '7' values in the array:
array[ 0] : 21
array[ 1] : 18
array[ 2] : 32
array[ 3] : 3
array[ 4] : 9
array[ 5] : 6
array[ 6] : 16
======== Program Menu =========
V) View the Array.
I) Insert New Value.
D) Delete Existing Value.
N) Display Minimum Value.
X) Display Maximum Value.
A) Display Average of Values.
S) Display Sum of Values.
Q) Quit.
Selection: i
enter the new value: 77
======== Program Menu =========
V) View the Array.
I) Insert New Value.
D) Delete Existing Value.
N) Display Minimum Value.
X) Display Maximum Value.
A) Display Average of Values.
S) Display Sum of Values.
Q) Quit.
Selection: v
there are '8' values in the array:
array[ 0] : 21
array[ 1] : 18
array[ 2] : 32
array[ 3] : 3
array[ 4] : 9
array[ 5] : 6
array[ 6] : 16
array[ 7] : 77
Look things over and let me know if you have any questions. Also, as you are just learning, make sure you are compiling your code with compiler warnings enabled and that you don't consider your code reliable until it compiles without warning. That means you should be compiling with at least the -Wall -Wextra flags set. If you are using gcc and the command line, then it would be:
gcc -Wall -Wextra -O2 -o simplemenu simplemenu.c
To compile the code in simplemenu.c into an executable named simplemenu with the -O2 optimizations applied. If you are really wanting to eliminate all warnings, add -pedantic as well. For codeblock or other IDE, look through the compiler menu options, they all provide a place to input all of the options you would like. Good luck with your code.
Procedural Approach Without Functions & Input With scanf
OK, now that we know how far we need to backup, let's look at rewriting the code in a bare minimum, top-down approach without using functions and taking user input with scanf (which will cause you more grief, especially taking mixed character and numeric input, but it can be done, if you account for the '\n' left in stdin)
First a note about taking input with scanf. When you ask for user input, like with the menu selection, and the user enters V and presses Enter, the input buffer stdin contains "V\n" (the '\n' as the result of pressing Enter). When you then use scanf to read a character (e.g. char sel; scanf ("%c", &sel);) the 'V' is taken from stdin and stored in sel leaving '\n' in stdin. If you then attempt to read another character (e.g. char nextch; scanf ("%c", &nextch);) it will appear that scanf has skipped reading nextch because it never allow you to enter a value. What has actually happened is scanf ("%c", &nextch); has read the '\n' that remained in stdin as your next character and is quite content with the value of 0xa (10 decimal) in nextch.
You must always account for the '\n' when using scanf. You have two options, 1) leave a space before the conversion specifier (e.g. scanf (" %c", &nextch); or 2) use the assignment suppression operator '*' (e.g. scanf ("%c%*c", &nextch);), the second %*c telling scanf to read and discard the following character without adding the conversion to the match count (which is the integer value returned by scanf). Which brings up the most important point of all, always check the return of scanf. (otherwise, you have no clue whether you have an actual value to work with or just garbage) I will leave the reading of man scanf to you for further details on the effect of the space before the conversion specifier, and the assignment suppression operator.
The return for scanf (the match count) is the number of successful conversions performed based on the number of conversion specifiers contained within the format string (e.g. scanf (" %c %d", &somechar, &someint); contains 2 conversion specifiers %c and %d, so the return for scanf after successful conversion of both would be 2. If a matching or conversion failure occurs, the return will be less than 2 and if an error condition is encountered reading from the stream (stdin in this case) EOF is returned (generally a value of -1) All of this, and more, is why scanf is NOT the preferred method for taking user input in C. (that being said, it is what most tutorials, and most teachers, make the poor choice to expose new C programmers to without an understanding of the pitfalls)
With that out of the way, if you work through the example below, you will see that I have simply moved the code from the functions to within the if ... else if ... else framework. (look at the one-to-one relationship from where I call functions from the switch in the first example and the code below) This should also show why breaking the code up into logical functions, improves readability and improves code re-use. Compare the use of the switch statement with the if ... else if ... else daisy chain. Both are fine, but to me, the switch is more easily readable at a glance.
You should make sure you understand both versions as they are both basic entry level approaches to using C. Take your time going through each and if you have questions that you cannot answer by consulting one of the references provided in the tag-wiki link, just ask.
#include <stdio.h>
#include <stdlib.h> /* for atoi */
#include <limits.h> /* for INT_MIN/INT_MAX */
enum { MAXN = 64 }; /* constant - max numbers of vals & chars */
int main (void) {
int vals[MAXN] = { 21, 18, 32, 3, 9, 6, 16 }, /* the array */
n = 7;
for (;;) {
char c;
/* show the menu */
fprintf(stderr, "\n ======== Program Menu =========\n\n"
" V) View the Array.\n"
" I) Insert New Value.\n"
" D) Delete Existing Value.\n"
" N) Display Minimum Value.\n"
" X) Display Maximum Value.\n"
" S) Display Sum of Values.\n"
" A) Display Average of Values.\n"
"\n"
" Q) Quit.\n"
"\n"
" Selection: ");
/* read selection (inside of if is OK), check EOF or quit */
if (scanf (" %c", &c) == EOF || c == 'q' || c == 'Q') {
printf ("\n that's all folks...\n");
break;
}
if (c == 'v' || c == 'V') { /* view array code */
printf ("\n there are '%d' values in the array:\n\n", n);
int i;
for (i = 0; i < n; i++)
printf (" array[%2d] : %d\n", i, vals[i]);
}
else if (c == 'i' || c == 'I') { /* insert value code */
if (n == MAXN) {
fprintf (stderr, "error: all '%d' values filled.\n", n);
continue;
}
int newval = 0;
printf ("\n enter the new value: ");
if (scanf (" %d", &newval) == 1) {
vals[n] = newval;
n++;
}
else
fprintf (stderr, "error: invalid input.\n");
}
else if (c == 'd' || c == 'D') { /* delete value code */
int i, index = 0;
printf ("\n enter the index to delete: ");
if (scanf (" %d", &index) != 1) {
fprintf (stderr, "error: invalid input.\n");
continue;
}
if (index < 0 || index > n - 1) {
fprintf (stderr, "error: index out of range.\n");
continue;
}
for (i = index + 1; i < n; i++)
vals[i-1] = vals[i];
vals[i] = 0;
n--;
}
else if (c == 'n' || c == 'N') { /* display minimum code */
int i, min = INT_MAX;
for (i = 0; i < n; i++)
if (vals[i] < min)
min = vals[i];
printf ("\n Mininum of '%d' values is : %d\n",
n, min);
}
else if (c == 'x' || c == 'X') { /* display maximum code */
int i, max = INT_MIN;
for (i = 0; i < n; i++)
if (vals[i] > max)
max = vals[i];
printf ("\n Maxinum of '%d' values is : %d\n",
n, max);
}
else if (c == 's' || c == 'S') { /* compute sum code */
int i, sum = 0;
for (i = 0; i < n; i++)
sum += vals[i];
printf ("\n Sum of '%d' values is : %d\n",
n, sum);
}
else if (c == 'a' || c == 'A') { /* compute avg code */
int i, sum = 0;
double avg = 0.0;
for (i = 0; i < n; i++)
sum += vals[i];
avg = (double)sum/n;
printf ("\n Average of '%d' values is : %.2lf\n",
n, avg);
}
else /* if not matched, then invalid selection */
fprintf (stderr, "error: invalid selection.\n");
}
return 0;
}
(the operation and output from both program versions will be identical)

Scanf more values C

i need help with short Code in C. I must read floats on input line seperated with space and input is ended with float 0 or EOF.
How to do this if i dont know how many numbers or in input, or how it works and ask to EOF if i am reading just numbers and not chars?
Thanks for any response.
example of input in one line:
12 11 10 45 50 12 EOF
12 10 11 45 0
int main(void)
{
float num;
float sum = 0;
do{
scanf("%f", num);
sum += num;
} while(EOF || num == 0);
return 0;
}
From the man page of scanf -
scanf returns the number of items successfully matched and assigned
which can be fewer than provided for, or even zero in the event of an
early matching failure. The value EOF is returned if the end of input
is reached before either the first successful conversion or a matching
failure occurs.
This means that scanf will return EOF only when it encounters EOF as the first input when it is called because EOF must be preceded with a newline '\n' else it won't work (depending on the OS). You must also account for the matching failure scanf may encounter.
#include <stdio.h>
int main(void) {
float num;
float sum = 0;
int val;
while((val = scanf("%f", &num)) != EOF && val == 1) {
sum += num;
}
if(val == 0) {
printf("matching failure. input is not a float.\n");
}
else {
printf("end of input.\n");
}
return 0;
}
From scanf reference:
On success, the function returns the number of items of the argument
list successfully filled. This count can match the expected number of
items or be less (even zero) due to a matching failure, a reading
error, or the reach of the end-of-file.
If a reading error happens or the end-of-file is reached while
reading, the proper indicator is set (feof or ferror). And, if either
happens before any data could be successfully read, EOF is returned.
If an encoding error happens interpreting wide characters, the
function sets errno to EILSEQ.
So, you may rewrite your do-while loop to something like
int retval;
while((retval = scanf("%f", &num)) != EOF && retval > 0 && num != 0) {
sum += num;
}
if(retval == 0) {
printf("input read error.\n");
}
to match your constraints.
Also note you need to prefix your variable with & when passing it to scanf(), since the function expects a pointer to deal with (you need to pass variable address).
EDIT:
see this topic concerning EOF problems in Windows
You can re write your code like this
int main(void)
{
float num;
float sum = 0;
do
{
scanf("%f", &num);
sum += num;
} while((!feof(stdin)) && (num != 0));
printf("%f", sum);
return 0;
}
Here feof indicates end of input stream.
The following may be a slightly more robust way to do this:
#include <stdio.h>
#include <string.h>
int main(void) {
int sum=0;
int num;
char *p;
char buf[1000];
fgets(buf, 1000, stdin);
p = strtok(buf," ");
while(p!=NULL) {
if(sscanf(p, "%d", &num) == 1) sum+=num;
p = strtok(NULL, " ");
}
printf("the sum is %d\n", sum);
}
Test:
> testme
1 2 3 4 0
the sum is 10
> testme
1 2 3 4 ^D
the sum is 10
Note - you have to enter ctrl-D twice to get the desired effect when you are at the end of a line.
you can get your doubt clear by reading "C programming a modern approach by K N King"
This book provides proper clarification on this topic
Test the result of scanf() for 0, 1 or EOF.
Test the value scanned for 0.0.
int main(void) {
float num;
float sum = 0;
int cnt;
while ((cnt = scanf("%f", &num)) == 1) {
if (num == 0.0) break;
sum += num;
}
// cnt should be EOF, 0 or 1
if (cnt == 0) {
printf("Input is not a number\n");
}
else {
printf("Sum %f\n", sum);
}
return 0;
}
Although, in general, scanf() returns values EOF, 0, 1, ... "number of format specifiers", a value of 0 occurs rarely. Example input is "+".

trying to run two parts of program second part can't input string

I am trying to get both parts of this program to work as you can see I have split it with first part (question 1) and second part (question 2). The problem is first part runs fine just when the second part starts I can not input any string and it just seems to skip through the code without letting me input the string.
If I delete the first part (question 1) of the program then everything works fine and I can input the string. What interrance is causing this issue.
int main()
{
first();
second();
}
//Question 1
int first()
{
/* dataarray.c */
float data[20] = {
50.972438, 93.765053, 9.252207, 1.851414, 16.717533,
71.583113, 97.377304, 20.352015, 56.309875, 0.072826,
23.986237, 36.685959, 80.911919, 86.621851, 53.453706,
96.443735, 29.845786, 18.119300, 31.079443, 52.197715 };
/* The number of elements in the data array */
int data_size = 20;
int pos;
int j;
int i;
int k;
printf("Question 1\n");
for(i=0;i<data_size;i++)
{
printf("\nArray %i is %f ",i,data[i]); //Initial arrays print statement
}
printf("\n\nArray number to delete:"); //User Choose one to delete
scanf("%i",&pos);
k =0;
for(j = 0; j< pos;j++)
{
printf("\n Array %i is now %f ",k,data[j]);
k++;
}
k=pos;
for(j=pos+1;j<data_size;j++)
{
printf("\n Array %i is now to %f ",k,data[j]); //Shows array changed to
k++;
}
data_size = data_size - 1; //Decreases data size
}
//Question 2
int second()
{
printf("\n\nQuestion 2\n");
int a,b,check=0;
char str[20];
printf("\nEnter a String:\n"); //User inputs word to check if its palindrome
gets(str);
for(b=0;str[b]!=0;b++); //Starts at 0 increment till the last length
b=b-1;
a=0;
while(a<=b)
{
if(str[a]==str[b]) //String a is forwards b is backwards
{
a=a+1;
b=b-1;
check=1; //If check = 1 then a palindrome
}
else
{
check=0; //If check = 0 then it not a plaindrome
break; //Loop break
}
}
if(check==1)
printf("It is a Palindrome:"); //Statement printed if check = 1
else
printf("It is not a Palindrome\n"); // Else if 0 this statement is printed
}
When you call scanf in part one, I presume you enter a number followed by a newline. scanf consumes the number, but the newline is left in the buffer. The gets() in part 2 then sees the newline and returns a blank line. An easy solution is to do
scanf( "%i\n", &pos );
BTW, never use gets. Use fgets instead.

Resources