How Can I Fix My Infinite Loop So That It Runs Infinitely? - c

I was trying to create a program that runs infinitely until you type "exit". When a user types "donate", the program will prompt "Great! How much?". The program will keep on asking to donate until the donation money is greater than $100 (the target). The program will also have to ask you to "work here", if the user types "work here", the program will display how much has been donated.
The issue is when I type "donate" below the target, the program stops after I type in the donation money. The same issue occurs when I type "work here".
Here's my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char**argv)
{
int total=0;
int target=100;
char descision[20];
int amount=0;
while(1)
{
printf("***Welcome! Are you looking to donate or do you work here?\n");
scanf("%s", descision);
if(strcmp(descision, "donate") == 0)
{
printf("Great! How much? $");
scanf("%s", amount);
total += amount;
}
else if(strcmp(descision, "work here") == 0)
{
printf("Total donated so far: %d", total);
}
else if(strcmp(descision, "exit"))
{
printf("Bye!!!\n");
exit(0);
}
if(total > target)
{
printf("We already met our target but thanks!");
exit(0);
}
}
return 0;
}

printf("***Welcome! Are you looking to donate or do you work here?\n");
scanf("%19[^\n]", &descision[0]); // <-- you need to give base address ampersand of first cell
if(strcmp(descision, "donate") == 0)
{
printf("Great! How much? $");
scanf("%d", &amount); // <-- Give ampersand address character
total += amount;
}
Explanation of scanf("%19s[^\n]", &descision[0]);
Your decision array is of size 20, thus you need the last cell to accommodate '\0' called null termination which tells printf when string ends. Thus "[19s]" means read upto 19 characters(will discard any number of characters above 19 count, hence you will avoid issues of overwriting memory beyond the allocation/your expectation) and [^\n] means read until it finds '\n' i.e when you hit Enter Key '\n' is generated behind.

Related

How can I resolve Code will be never executed error

I am making a program that reads input from a user then check the validity,
but for the while statement in the validateInput function I am getting an warning
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
int ValidateUser(char *);
int ValidateInput(int);
FILE *database;
struct{
int year;
int unit;
float gpa;
char semester;
char grade;
char name[40];
}student;
int ValidateInput(int x)
{
while (x != 1 || x != 2 || x != 3) // code that causing a warning
return x;
}
int ValidateUser(char *input)
{
int result;
result = strcmp(input, student.name);
if (result == 0)
{
return 1;
}
else
{
while (result != 0)
{
printf("The Username you entered does not exit. Please enter correct name.");
}
}
return 1;
}
int main()
{
printf("\t----------------------------------------------------------\n");
printf("\t|\t\t\t\t Santa Monica College\t\t\t\t\t |\n");
printf("\t----------------------------------------------------------\n\n");
printf("\t\tWelcome to Santa Monica Student Record System.\n\n");
printf("Please Enter Your Option\n");
printf("\t1.View GPA/GRADE\n");
printf("\t2.Add New GPA\n");
printf("\t3.Modify Information\n");
int choice;
scanf("%d", &choice);
char UserName[40];
if(choice == 1)
{
printf("Please enter your name\n");
scanf("%s", UserName);
ValidateUser(UserName);
printf("The GPA of %s is %f , %c ", student.name, student.gpa, student.grade);
}
else if (choice == 2)
{
printf("Please enter your name\n");
scanf("%s", UserName);
ValidateUser(UserName);
}
else if (choice == 3)
{
printf("Please enter your name\n");
scanf("%s", UserName);
ValidateUser(UserName);
}
else
{
ValidateInput(choice);
}
return 0;
}
The ide was suggesting to add parentheses around x-values in the argument of while statement in the ValidateUser to make it silence
I've done some research on this warning and I found that the condition I made is not true so that's why I am getting it, but I am not quite sure what the problem is.
Can someone help me out with this???
In validateUser(), your program will reach the
while (result != 0)
only in the event that the while condition is initially true, so if it reaches the loop, it will enter it. The body of the loop does not modify result, so if it enters the loop, it will loop indefinitely.
Ultimately, if the first branch of the if / else is taken, then the function returns from within that branch, and if the second branch is taken then control never exits that branch. Either way, the
return 1;
at the end of that function cannot be reached. Of course, that's just a symptom. The infinite loop is the main problem.
It's unclear what behavior you actually want here, but what would be most in keeping with the name of the function would be for it to only evaluate whether the specified user name is valid, returning a result that conveys either "yes" or "no". There is no particular reason why such a function would need to loop at all.
You put while (result != 0) inside function ValidateUser(char *input) and never put a way to get out of the loop, resulting in the return value below it never running.
To fix this, you would need to add a break; somewhere in the loop to indicate that you are ready to leave the current loop, or make result = 0;
The difference between the two is that break; will indicate that the rest of the loop doesn't need to run and will jump out of the loop, or use result=0; to run the rest of the code in the loop and then jump out of it

While loop misbehaving,

i am pretty new to c, i m trying to make the user input a number, but if they input a letter or word it shows a warning and asks for input again, my code works fine if the user puts in a number but it goes into an infinite loop if the user inputs something invalid, here is my code
#include <stdio.h>
int main(void) {
float salary;
int status = 0;
while (status == 0)
{
printf(" Please input your yearly salary to calculate taxes: \n");
status = scanf(" %f", &salary);
if (status == 0)
printf("invalid input!\n");
}
printf("%.2f\n", salary);
return 0;
}
i thought that i was something to do with the buffer left over from the first scanf , but adding a space " %f" didnt work, i tried using fflush(stdin) after then scanf also didnt work. i m not sure what else i can try.
thanks in advance for any help.
You need to clear the buffer or it will keep evaluating it and cause the endless loop. Add one line after your invalid input: scanf("%*[^\n]")
#include <stdio.h>
int main(void) {
float salary;
int status = 0;
while (status == 0)
{
printf(" Please input your yearly salary to calculate taxes: \n");
status = scanf(" %f", &salary);
if (status == 0)
printf("invalid input!\n");
scanf("%*[^\n]");
}
printf("%.2f\n", salary);
return 0;
}
This will work. You can see a better explanation here: Scanf and loops
The problem is that scanf won't advance the file stream. You ask it to read a floating point value and it isn't able to, so it doesn't consume the input.
For example, let's say your input is "foo", which isn't a number. Your scanf call isn't able to successfully read anything and returns 0. Then, in the next iteration, "foo" is still waiting to be read from stdin.
Try changing your if condition to something like
if (status == 0) {
char foo[256];
fgets(foo, sizeof(foo), stdin);
printf("Invalid input! Expected a nmuber, got: %s", foo);
}
Notice how the entire input is read from stdin by the gets call.

Program fails to receive second input

It's just a code to receive user inputs in C program, but fails to do so and accepts null space as input. I have tried fgets() as well and the same thing keeps happening. Please advice on how to fix.
#include <math.h>
#include <stdio.h>
//#include <string.h>
#define len 16
int main(void)
{
/* Enter your code here. Read input from STDIN. Print output to STDOUT */
int n,i=0,j=0;
printf("enter the number of cards:");
n = getchar();
//scanf("%d",&n);
int c1[len][n],card[len][n];
char buf[len];
printf("Enter card number:");
gets(buf);
system("Pause");
return (0);
}
"...code to receive user inputs in c program, but fails to do so and accepts null space as input..."
The reasons your existing code has problems is covered well in the comments under your post.
Consider a different approach: Define the following:
char inBuf[80] = {0};//
int numCards = 0;//Pick variable names that are descriptive (n is not)
int cardNum = 0;
bool isnum;
Then use it in conjunction with printf() etc.
printf("enter the number of cards:");
if(fgets(inBuf, sizeof(inBuf), stdin))//will read more than just a single char, eg. "12345"
{
int len = strlen(inBuf);
isnum = true;
for(int i=0;i<len;i++)
{
if(!isdigit(inBuf[i]))
{
isnum = false;
break;
}
}
if(isnum)
{
numCards = atoi(inBuf);
}
else
{
printf("input is not a number\n"
}
}
printf("Enter card number:");
if(fgets(inBuf, sizeof(inBuf), stdin))
{
...
Repeat variations of these lines as needed to read input from stdin, with modifications to accommodate assignment statements based on user input i.e. an integer (this example is covered), a floating point number, a string (eg. a persons name)
Although there is more that you can do to improve this, it is conceptually viable for your stated purpose...

Find Biggest Number in C, by N number of inputs

So I have this code:
#include <stdio.h>
int main()
{
char peopleName[5][20],peopleAge[5];
int i;
int maxAge=0, maxName=-1;
for(i=0;i<5;i++)
{
printf("Name & Age %d :",i+1);
scanf("%s",&peopleName[i]);
scanf("%d",&peopleAge[i]);
if(peopleAge[i]>maxAge)
{
maxAge=peopleAge[i];
maxName=i;
}
}
printf("%s %d", peopleName[maxName],peopleAge[maxAge]);
}
This code finds from 5 people the oldest one. I want to change from 5 people to N number of people, whatever the number I input myself. (For example I put 7, and I can insert seven names and ages and so on).
The question has two parts: How does the user specify how many persons are entered? And how do I store the data?
The second part is easy: No matter how many persons you are going to consider, if you just want to know who is the oldest, it is enough to keep the name and age of the currently oldest person. (Of course, if there is a tie and many people are, say, 80 years old, you just get to keep the first match.)
Not storing anything also simplifies the first question. You could ask the user to specify the number of persons beforehand and that's find if you have few people. If you have a list of many people, the user would have to count the by hand and then enter the count. Miscounting is very likely.
A better way is to indicate the end of input by another means, for example by a negative age or by two dashes as name. There is also the possibility that the input runs out, for example when redirecting input from a file or when pressing one of Ctrl-Z or Ctrl-D, depending on your platform, after the input.
The example below read the input line-wise and then scans that line. The loop while (1) is in theory infinite, in practice execution breaks out of the loop when the input runs out – fgets return NULL –, when a blank line is read or when the input isn't in the format single-word name and age.
#include <stdio.h>
int main(void)
{
char oldest[80] = "no-one";
int max_age = -1;
int count = 0;
puts("Enter name & age on each line, blank line to stop:");
while (1) {
char line[80];
char name[80];
int age;
if (fgets(line, sizeof(line), stdin) == NULL) break;
if (sscanf(line, "%s %d", name, &age) < 2) break;
if (age > max_age) {
strcpy(oldest, name);
max_age = age;
}
count++;
}
printf("The oldest of these %d people is %s, aged %d.\n",
count, oldest, max_age);
return 0;
}
You can do this -
int n; // number of people
scanf("%d",&n); // take input from user
char peopleName[n][20],peopleAge[n]; // declare 2-d array
for(i=0;i<n;i++)
{
// your code
}
Also this statement -
scanf("%s",&peopleName[i]); // pass char * as argument to %s
should be -
scanf("%19s",peopleName[i]); // one space is left for null character
You can use malloc to allocate buffer dynamically.
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char (*peopleName)[20];
int *peopleAge;
int i;
int maxAge=0, maxName=-1;
int dataNum;
printf("How many people? :");
if(scanf("%d",&dataNum)!=1)return 1;
peopleName=malloc(sizeof(char[20])*dataNum);
peopleAge=malloc(sizeof(int)*dataNum);
for(i=0;i<dataNum;i++)
{
printf("Name & Age %d :",i+1);
scanf("%s",peopleName[i]);
scanf("%d",&peopleAge[i]);
if(peopleAge[i]>maxAge)
{
maxAge=peopleAge[i];
maxName=i;
}
}
printf("%s %d", peopleName[maxName],peopleAge[maxName]);
free(peopleName);
free(peopleAge);
return 0;
}
Also please note that:
You should pass char*, not char(*)[20], for %s in scanf
peopleAge[maxAge] may be out of bounds. maxName (or other name but same role) should suit here.

C programming minor issue with interactive menu when input a floating value

My program works well with invalid inputs such as char, number out of range, but a problem happens when a floating point value such as 1.2 is entered. The program prints menu again, and asks user for input before printing error message. What I try to fix is don't print menu again, but still struggle. For example,
Make your selection: 1.1
[Here is menu content]
Make your selection: That selection isn't valid. Please try again.
#include <stdio.h>
#define QUIT 0
int menu();
int main(void)
{
int choice;
char c;
choice = menu();
while(choice != QUIT) //execute so long as choice is not equal to QUIT
{
choice = menu();
}
}
int menu(void)
{
int option;
printf("Text Encoder Service\n\n");
printf("1.\tEnter name of input file (currently 'Secret.txt')\n");
printf("2.\tEnter name of output file (currently not set)\n");
printf("3.\tEnter number of characters data should be shifted (currently +7)\n");
printf("4.\tEncode the text\n\n");
printf("0.\tQuit\n\n");
printf("Make your selection: ");
while( (scanf(" %d", &option) != 1) /* non-numeric input */
|| (option < 0) /* number too small */
|| (option > 4)) /* number too large */
{
fflush(stdin); /* clear bad data from buffer */
printf("That selection isn't valid. Please try again.\n\n");
printf("Your choice? ");
}
return option;
}
I finally could validate floating input. Thanks your advices so much! This is my new code. What else do you think an invalid input?
int menu(void)
{
int option, parsed_inputs;
char overcount_char;
parsed_inputs = 1;
printf("Text Encoder Service\n\n");
printf("1.\tEnter name of input file (currently 'Secret.txt')\n");
printf("2.\tEnter name of output file (currently not set)\n");
printf("3.\tEnter number of characters data should be shifted (currently +7)\n");
printf("4.\tEncode the text\n\n");
printf("0.\tQuit\n\n");
printf("Make your selection: ");
parsed_inputs = scanf_s("%d%c", &option, &overcount_char);
while( parsed_inputs > 1 ) /* number too large */
{
if((overcount_char != '\n') || (option < 0) || (option > 4))
{
fflush(stdin); /* clear bad data from buffer */
printf("That selection isn't valid. Please try again.\n\n");
printf("Your choice? ");
scanf_s("%d%c", &option, &overcount_char);
}
else
break;
}
return option;
}
An input of 1.1 leads to the following:
The string is read into an internal buffer.
It is then matched against the given format string.
On the first non-match, the scanf() call is stopped and it returns the number of successfully scanned values.
Let's test it:
#include <stdio.h>
int main(int argc, char ** argv)
{
while (1) {
int option;
int n = scanf(" %d", &option);
printf("%d %d\n", n, option);
if (n <= 0) break;
}
}
This program reads one line.
Suppose I enter 123 132.
Then the following happens:
* As the format string starts with a space, all leading whitespace is consumed. In this case, there is none.
* Then the 123 is consumed and put into option.
* As the format string is over now, parsing is stopped, n=1 and option=123.
* In the next loop run, the same happens, giving n=1 and option=123.
But: Suppose I enter 123.321 or 123#321.
Then the following happens:
* As the format string starts with a space, all leading whitespace is consumed. In this case, there is none.
* Then the 123 is consumed and put into option.
* As the format string is over now, parsing is stopped, n=1 and option=123.
* In the next loop run, there is no whitespace to skip. .321 resp. #321 is tried to be matched to %d, but these are no valid ints. Thus, we get n=0 and option keeps its old value.
* As no characters are consumed from the input stream (the one used is put back again), the same happens over and over again - that's why I put if (n <= 0) break;.
So you see that the behaviour has nothing to do with floating point, as it doesn't matter if we use . or # to "disturb".
We change our program to
#include <stdio.h>
int main(int argc, char ** argv)
{
while (1) {
int option; char c;
int n = scanf("%d%c", &option, &c);
printf("%d %d %d %c\n", n, option, c, c);
if (n <= 0) break;
}
}
and run it, inputting 4.235#6x7.
Then we get
* n=2, option=4 and c='.' at the first run
* n=2, option=235 and c='#' at the 2nd run
* n=2, option=6 and c='x' at the 3rd run
* n=2, option=7 and c='\n' (newline) at the 3rd run
and are prompted for further input.
This makes you open to the option
(parsed_inputs = scanf("%d%c", &option, &overcount_char)) < 1
and then check what overcount_char contains, whenever parsed_inputs is > 1.
I think you should put scanf() before the while loop and explicitly check "option" variable in the while loop.
What happening is that, here scanf() will always return the value 1, because scanf() returns no. of arguments read successfully. Hence this while loop will run forever. For further information check this link->http://www.cplusplus.com/reference/cstdio/scanf/
Hope this helps!

Resources