Getting stuck in getIntLimited function - c

i have a problem in getting stuck in getIntLimited function. In adjustQuantity i need it to check if user entered the right number, not more or less than needed and not letters. I didn't do that to "Stock" option, only in "Check" option. But my first problem is that i have to type the number twice to get a response from it and the second is that i can't get out of the getIntLimited loop.
Here's the image of the output:
and the part of my code:
void GroceryInventorySystem(void){
struct Item Items[MAX_ITEM_NO];
int opt, records;
int loop = 0;
welcome();
while(!loop){
if(opt == 3){
adjustQuantity(Items, records, CHECKOUT);
saveItems(Items, DATAFILE, records);
if(0 == saveItems(Items, DATAFILE, records)){
printf("Could not update data file %s\n", DATAFILE);
}
pause();
}
}
int getInt(void){ // Check if user entered the character and breaks, returns the value if a number //
char letter = 'x';
int value;
while(1){
scanf("%d%c", &value, &letter);
if(letter != '\n'){
printf("Invalid integer, please try again: ");
flushKeyboard();
}else{
return value;
}
}
}
int getIntLimited(int lowerLimit, int upperLimit){ // Check if user typed the value higher/lower and repeats. Returns the value if user entered the right number //
int Value;
while(1){
Value = getInt();
if(Value <= lowerLimit || Value >= upperLimit){
printf("Invalid value, %d < value < %d: ", lowerLimit, upperLimit);
}else{
return Value;
}
}
}
void adjustQuantity(struct Item item[], int NoOfRecs, int stock) {
int check, sku, index, opt;
char tostock[] = "to stock", tocheck[] = "to checkout";
printf("Please enter the SKU: ");
scanf("%d", &sku);
check = locateItem(item, NoOfRecs, sku, &index);
if (check == 0) {
printf("Item not found!\n");
} else {
displayItem(item[index], FORM);
if (stock == STOCK) {
printf("Please enter the quantity %s; Maximum of %d or 0 to abort: ", tostock, MAX_QTY - item[index].quantity);
scanf("%d", &opt);
if (opt == 0) {
printf("--== Aborted! ==--\n");
} else {
item[index].quantity += opt;
printf("--== Stocked! ==--\n");
}
} else {
printf("Please enter the quantity %s; Maximum of %d or 0 to abort: ", tocheck, item[index].quantity);
scanf("%d", &opt);
if (opt == 0) {
printf("--== Aborted! ==--\n");
} else if (item[index].quantity < opt){
opt = getIntLimited(item[index].quantity, 0);
} else {
item[index].quantity -= opt;
printf("--== Checked out! ==--\n");
if (item[index].quantity <= opt) {
printf("Quantity is low, please reorder ASAP!!!\n");
}
}
}
}
}

i did a mistake in opt = getIntLimited(0, item[index].quantity); it should be the opposite like this opt = getIntLimited(item[index].quantity, 0); now it exits out of the loop whenever i type the right number in between 0 and 5 .
I also putted opt = getIntLimited(0, item[index].quantity); instead of scanf, and removed else if statements

Related

while loop not breaking even with break C programming

Trying to make a GPA calculator.
Here is my code:
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
int main()
{
float fgpa, grade, n;
char reply;
n = 1;
grade = 1;
printf("--- GPA Calculator ---");
while(fgpa < 1 || fgpa > 4)
{
printf("\n\nEnter your current GPA: ");
scanf("%f", &fgpa);
if(fgpa < 1 || fgpa > 4)
printf("Invalid Input! Please re-enter value.");
}
printf("\nUsing the following table to convert grade to points\n\nA+ = 4.0\nA = 4.0\nB+ = 3.5\nB = 3\nC+ = 2.5\nC = 2.0\nD+ = 1.5\nD = 1\nF = 0\n");
while(grade > 0, n++)
{
printf("\nEnter points for module %.0f, enter \"0\" if there are no more additional modules: ", n);
scanf("%f", &grade);
printf("%f", grade);
fgpa = (fgpa + grade) / n;
}
fgpa = fgpa* n / (n-1);
n--;
printf("\n\nNumber of modules taken: %.0f\nFinal GPA: %.1f", n, fgpa);
return 0;
}
I've tried using if(grade = 0) break; but its still not breaking the loop even when the grade is correctly read 0.
picture of 0 being read correctly but loop still continuing
There are multiple problems in the code:
fgpa is uninitialized so the first test in the loop has undefined behavior.
you should also test the return value of scanf() to detect invalid or missing input.
while (grade > 0, n++) is incorrect too: you should instead always read the next grade and test its value and break from the loop before incrementing n.
Your averaging method seems incorrect too: you do not give the same weight to every module.
It seems more appropriate for your purpose to use for ever loops (for (;;)), unconditionally read input, check for scanf() success and test the input values explicitly before proceeding with the computations.
Here is a modified version:
#include <stdio.h>
// flush the rest of the input line, return EOF at end of file
int flush(void) {
int c;
while ((c = getchar()) != EOF && c != \n')
continue;
return c;
}
int main() {
float fgpa;
float grade;
int n = 1;
char reply;
printf("--- GPA Calculator ---");
for (;;) {
printf("\n\nEnter your current GPA: ");
if (scanf("%f", &fgpa) == 1) {
if (fgpa >= 1 && fgpa <= 4)
break;
}
} else {
if (flush() == EOF) {
fprintf(stderr, "unexpected end of file\n");
return 1;
}
}
printf("Invalid Input! Please re-enter value.\n");
}
printf("\nUsing the following table to convert grade to points\n\n"
"A+ = 4.0\nA = 4.0\nB+ = 3.5\nB = 3\nC+ = 2.5\n"
"C = 2.0\nD+ = 1.5\nD = 1\nF = 0\n");
for (;;) {
printf("\nEnter points for module %d, enter \"0\" if there are no more additional modules: ", n);
if (scanf("%f", &grade) == 1) {
if (grade <= 0)
break;
printf("%f\n", grade);
fgpa = fgpa + grade;
n = n + 1;
} else {
if (flush() == EOF)
break;
printf("Invalid Input! Please re-enter value.\n");
}
}
fgpa = fgpa / n;
printf("\n\nNumber of modules taken: %d\nFinal GPA: %.3f\n", n, fgpa);
return 0;
}

Remove user in array Struct program

I'm working in a struct array program to make some simple user applications. Below is a compilable code, it is not the full code, but it shows that the function to remove a user is not working. I'm new to C and I am not sure about how to do this user remotion. I thought about something related to a null array, but it didn't work. The program asks to enter the name, so the user will be removed.
#include<stdio.h>
#include <stdlib.h>
#include <string.h>
#define max_users 50
int num = 0; //variable to count the number of users
typedef struct
{
char name[50];
int age;
}user;
user number[max_users];
user aux[max_users];
user read_user()
{
user user;
printf("\nEnter your name: ");
scanf("%s", &(user.name));
printf("\nEnter your age: ");
scanf("%d",&(user.age));
return user;
}
void printUser(user user)
{
printf("\n-----------------------\n");
printf("\nName: %s", user.name);
printf("\nAge: %d", user.age);
}
void enterUser()
{
number[num] = read_user();
printUser(number[num]);
num++;
}
void printAllUsers()
{
for(int i = 0; i < num; i++)
{
printUser(number[i]);
}
}
void performUserRemotion(char name[])
{
char null[50] = {"\0"};
for (int i = 0; i < num; i++) {
if (strcmp(name, number[i].name) == 0)
{
strcpy(number[i].name, null);
printf("\n*** User removed ***");
i--;
}
else
{
printf("\n*** No user ***");
break;
}
}
}
void removeUser()
{
char name_search[50];
int i;
printf("Enter the user to be removed: ");
scanf("%s", &name_search);
performUserRemotion(name_search);
}
int main()
{
int choice;
while(1)
{
printf("\n\nRECORD: ");
printf("\n1) Enter User");
printf("\n2) Remove User");
printf("\n3) Print all users");
printf("\n4) Exit");
printf("\n\nEnter the command >> ");
scanf(" %d", &choice);
switch(choice)
{
case 1:
enterUser();
break;
case 2:
removeUser();
break;
case 3:
printAllUsers(num);
break;
case 4:
printf("\n*** Exit ***\n");
exit(0);
break;
}
}
}
In the function below I planned to remove all the information about the user, so when I enter 3) Print all users, the user removed does not appear anymore and the array is reduced by 1.
void performUserRemotion(char name[])
{
char null[50] = {"\0"};
for (int i = 0; i < num; i++) {
if (strcmp(name, number[i].name) == 0)
{
strcpy(number[i].name, null);
printf("\n*** User removed ***");
i--;
}
else
{
printf("\n*** No user ***");
break;
}
}
}
Pictures A and B are the user's registrations. Picture C is when you enter the command to remove a user, in this case, I registered 'user' and 'name' and wanted 'user' to be removed, so when I enter 3) Print all users, the screen only shows 'name'.
The program still has some basic problems, such as it can't read a name with space, but I will work on it later. The main problem is that I can't perform the remotion of a user.
The logic of removing a user is wrong, because when you print all users, you print the whole content of the array. So to remove a user, you must have somewhere num = num - 1;.
A simple way is to find the index of the user to remove, and then consistently erase every record with next one:
void performUserRemotion(char name[])
{
char null[50] = { "\0" };
int i;
// find the name
for (i = 0; i < num; i++) {
if (strcmp(name, number[i].name) == 0)
{
break;
}
}
if (i == num) {
printf("\n*** No user ***");
}
else {
// remove the user from the array
for (; i < num - 1; i++) {
memcpy(number + i, number + i + 1, sizeof(*number));
}
num -= 1;
printf("\n*** User removed ***");
}
}
You still have a number of minor problems like unused variables, so when everything will work, you should ask for a full review on Code Review

Why non-integer inputs cause infinite loop?

When I enter a non-integer value it cause an infinite loop. Do I need to replace scanf? If so how can I do that.
int num=1;
if(num==1){
int slct;
printf("\n\tWelcome");
printf("\n1. Login\n2. Register\n3. Account\n4. Exit\n");
SELECTION: ;
printf("\n\tEnter a number:");
scanf("%d",&slct);
if (slct == 1){}
else if (slct == 2){}
else if (slct == 3){}
else if (slct == 4){
return 0;
} else {
goto SELECTION;
}
}
You need to check the return value of scanf and flush the input:
#include <stdbool.h>
#include <stdio.h>
int main()
{
bool done = false;
while (!done) {
printf("\n\tWelcome\n");
printf("1. Login\n");
printf("2. Register\n");
printf("3. Account\n");
printf("4. Exit\n\n");
printf("Enter a number:");
int selection;
int result = scanf("%d", &selection);
if (EOF == result) {
done = true;
}
else if (1 != result) {
printf("You did not enter a valid number\n");
int c;
while ((c = getchar()) != '\n' && c != EOF) {}
done = (c == EOF);
}
else if (1 == selection) {
printf("You chose login\n");
}
else if (2 == selection) {
printf("You chose register\n");
}
else if (3 == selection) {
printf("You chose account\n");
}
else if (4 == selection) {
done = true;
}
else {
printf("Please pick a number between 1 and 4\n");
}
}
}
The format string in scanf("%d",&slct); is %d which means you want to read a number.
When you enter something else than a number, scanf returns 0 to indicate that zero numbers were read.
If the scanf encounters and end-of-file when attempting to read the input (enter control-D) then it returns the special value EOF.
Also, scanf does not consume the incorrect input, so you need to explicitly flush it.

Searching through struct array for string entered by user

This is just a function from my program that is supposed to search for the string or integer the user enters in the struct array. What I'm trying to do is add an error message and the ability to try again when that entered string or integer is not found in the struct array. It searches just fine if you enter the correct string or integer but nothing happens if you don't. I'm trying to change that but can't find the solution.
I've tried for a while now with one of the cases in my switch statement but I need to do it for all three. But so far I've only tried on case 3.
search(struct items aItems[], int *num_items)
{
int choice_of_search, b=0, found_word=0, search_num, i=0, j=0, k=0;
char search_phrase[20]; struct items search[MAX];
printf("Choose what to search for? (1) Item number, (2) Name and (3) Balance. ");
scanf("%d", &choice_of_search);
while(choice_of_search < 1 || choice_of_search > 3)
{
printf("Wrong choice!\n");
printf("Choose what to search for? (1) Item number, (2) Name and (3) Balance. ");
scanf("%d", &choice_of_search);
}
switch(choice_of_search)
{
case 1:
printf("Item number?\n");
scanf("%d", &search_num);
for(i = 0; i < *num_items; i++)
{
if(search_num == aItems[i].itemnumber)
{
printf("Item number found!\n");
search[found_word]=aItems[i];
found_word+=1;
}
}
break;
case 2:
printf("Name?\n");
scanf("%s", search_phrase);
for(i = 0; i < *num_items; i++)
{
if(strstr(aItems[i].name, search_phrase))
{
printf("Name found!\n");
search[found_word]=aItems[i];
found_word+=1;
}
}
break;
case 3:
printf("Balance?\n");
scanf("%d", &search_num);
for(i = 0; i < *num_items; i++)
{
if(search_num == aItems[i].balance)
{
printf("Balance found!\n");
search[found_word]=aItems[i];
found_word+=1;
}
else
{
printf("Balance not found! Try again.\n");
printf("Balance?\n");
scanf("%d", &search_num);
}
}
break;
}
while(b < found_word)
{
printf("Item number: %d Name: %s Balance: %d\n", search[b].itemnumber, search[b].name, search[b].balance);
b++;
}
}
Maybe this can help
int done;
...
...
case 3:
done = 0;
while(1);
{
printf("Balance?\n");
scanf("%d", &search_num);
for(i = 0; i < *num_items; i++)
{
if(search_num == aItems[i].balance)
{
printf("Balance found!\n");
search[found_word]=aItems[i];
found_word+=1;
done = 1;
}
}
if (done) break;
printf("Balance not found! Try again.\n");
}
break;
But notice that the code isn't user friendly as it doesn't allow the user a way to stop the search without a match. So maybe you should consider adding a "Would you like try again" option.
A simple approach could be
printf("Balance not found! Would like to try again?.\n");
scanf(" %c", &some_char);
if (some_char != 'y') break;

How do I use a for loop to retrieve from the user the indicated number of items indicated?

int a = 1;
printf("Enter the number of items from 1 and 10: \n");
while (a <= 10)
{
scanf("%d", &a);
if (a >= 1 && a <= 10)
{
printf("Thank You!\n");
break;
}
else
{
printf("Wrong input! Try Again.\n");
continue;
}
}
To be more detailed about what I'm asking lets say that the user enters 3 (for 3 items) how would I use the for loop to retrieve that information so I can further finish the code.
You should keep in mind following points:
Get the no.of choice before starting loop
Check the condition in loop with no. of choices.
Only one loop is enough for your task.
I think you need this:
int a = 1;
bool bFlag = true;
int price[10];
printf("Enter the number of items from 1 and 10: \n");
while(bFlag){
scanf("%d", &a);
if (a >= 1 && a <= 10)
{
printf("Thank You!\n");
break;
}
else
{
printf("Wrong input! Try Again.\n");
continue;
}
}
for (int i = 0; i< a; i++)
{
printf("Enter price for item %d = ", i);
scanf("%d",&price[i]);
}

Resources