c programming: stopping endless loops [closed] - c

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
I have been trying to get my head around validating the code, a.k.a stopping the program from breaking and entering the endless loops but I find it quite difficult.
So far I have come across multiple points in the program where the user can break it by entering the wrong input for example with the main menu if the user enters a letter or symbol instead of a number the program enters the endless loop, so a basic guide on validating would be helpful.
#include <stdio.h>
#include <stdlib.h>
struct packet{
int source;
int destination;
int type;
int port;
char data[50];
};
void main ()
{
struct packet s[50]; //Array for structure input
int choice;
int customerCount = 0, ii = 0;
while (customerCount <= 50){
printf("What would you like to do?\n");
printf("\t1) Add a packet.\n");
printf("\t2) s all packets.\n");
printf("\t3) Save packets.\n");
printf("\t4) Clear all packets.\n");
printf("\t5) Quit the programme.\n");
scanf("%i", &choice);
switch (choice)
{
case 1: printf("\n****Adding a packet*****\n");
printf("Where is the packet from?\n");
scanf("%i", &s[customerCount].source);
printf("Where is the packet going?\n");
scanf("%i", &s[customerCount].destination);
printf("What type is the packet?\n");
scanf("%i", &s[customerCount].type);
printf("What is the packet's port?\n");
scanf("%i", &s[customerCount].port);
printf("Enter up to 50 characters of data.\n");
scanf("%s", s[customerCount].data);
customerCount++;
break;
case 2: printf("\nDisplaying Infomation\n");
for(ii = 0; ii < customerCount; ii++) {
printf("\nSource: %d", s[ii].source);
printf("\nDestination: %d", s[ii].destination );
printf("\nType : %d", s[ii].type);
printf("\nPort : %d", s[ii].port);
printf("\nData: %s\n---\n", s[ii].data);
}
break;
case 3: break;
case 4: break;
case 5: break;
default: printf("\nThis is not a valid choice, please choose again\n\n");
break;
}
}
}

scanf returns the number of arguments it successfully scanned.
Checking for proper input and rejecting bad input can be as simple as:
printf("Where is the packet from?\n");
while(scanf("%i", &s[customerCount].source) != 1)
{
while(getchar() != '\n')
continue;
}
This is not very robust, however, and something like validating user input should be very robust. Assume the user will always enter wrong input... it's sad but true.

Related

Unexpected random characters printed by library management program [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
I am working on a school project where I have to make a program that let the user enter information about new books, delete books or display all registered books.
The unexpected behavior is when I choose to display all books : THE SECOND BOOK'S TITLE ALWAYS print some strange random characters or about 15 empty lines while the rest remain normal.
#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <stdlib.h>
typedef struct {
int Pages,RlsYear,AtrNbr; //"Pages" stands for "the number of pages", "RlsYear" stands for "Release Year"
char Title[128],Genre[128],Authors[256];
}book;
int main()
{
int i,nb;
char ch1,Tmp[128],cln;
book* b = malloc(1 * sizeof(book));
nb=0;
puts("\n Enter your choice : ");
ch1=getch();
while (ch1 != EOF && ch1 != 'q')
{
switch(ch1) {
case 'n': // N to enter a new book
case 'N':
{
printf("\n enter the book's Title : ");
gets(b[nb].Title);
printf(" enter the book's Genre : ");
gets(b[nb].Genre);
printf(" how many pages does the book have ? ");
scanf("%d",&b[nb].Pages);
gets(cln); //i added those "gets(cln)" to avoid problems from "scanf" so you can just ignore them
printf(" when was the book released (year)? ");
scanf("%d",&b[nb].RlsYear);
gets(cln);
printf(" how many authors does this book have ? ");
scanf("%d",&b[nb].AtrNbr);
gets(cln);
strcpy(b[nb].Authors,"");
for(i=0;i<b[nb].AtrNbr;i++)
{
printf("\t\t enter the %d author : ",i+1);
gets(Tmp);
strcat(b[nb].Authors,Tmp);
strcat(b[nb].Authors," | ");
}
nb=nb+1;
book* B = realloc(b, nb+1 * sizeof(book));
b = B;
}
break;
case 'i': // I to display registered books
case 'I':
{
for(i=0;i<nb;i++)
printf("\n %s",b[i].Title);
}
break;
default:
printf("unknown choice !");
break;
}
puts("\n Enter your choice : ");
ch1=getch();
}
return 0;
}
I solved the problem when i changed the b.Title size from 128 to 60.
Apparently the problem appears when the b.Title size passes 80.
Can someone explain please? i'm more confused now

Function that reads the file doesn't work. Interactive menu problem

Im having some problems making my newly started project to work (also im a beginner).
For some reason option number 4 in my interactive menu doesn't work and just takes a default route (doesn't output whats inside a file (file directory is fine.).
At this point i've read every forum searching for answer but couldn't modify my code in any way that would work.
So I decided to ask you for help.
Here is my code:
#include <stdio.h>
#include <stdlib.h>
#define kFileLocation "/Users/patrykpiwowarczyk/Desktop/STUDIA/FoCP/Kodowanie/TestProjektSemestralnyAngielski/TestProjektSemestralnyAngielski/authors.txt"
void options();
void start(void);
void score(void);
void optionz(void);
void author(void);
void pexit(void);
int main(void)
{
char ch;
int num;
char option;
while (1) {
printf("****Your English Learning Index Cards****\n\n");
printf("Enter 1-5 of the following options: \n\n");
options();
scanf("%c", &option);
switch (option) {
case '1':
break;
case '2':
break;
case '3':
break;
case '4':
author();
break;
case '5':
pexit();
break;
default:
printf("Please insert number ranging from 1-5 though... No cheating! \n\n");
printf("Press ENTER key to Continue\n");
}
}
return 0;
}
void options()
{
printf("1. Start Game \n");
printf("2. View Scoreboard \n");
printf("3. Options \n");
printf("4. Author \n");
printf("5. Exit \n\n");
}
void author()
{
char c;
FILE *authorsFile;
if ((authorsFile = fopen("/Users/patrykpiwowarczyk/Desktop/STUDIA/FoCP/Kodowanie/TestProjektSemestralnyAngielski/TestProjektSemestralnyAngielski/authors.txt","r")) == NULL)
{
printf("FAILED to read the file, maybe check directory?\n");
exit(1);
}
while ((c = fgetc(authorsFile)) != EOF)
{
printf("%c", c);
}
fclose(authorsFile);
}
void pexit()
{
puts("Your progress has been saved, see you next time.");
exit(0);
}
if you could help me in any way I would appreciate it soo much..
Greetings, Patryk Piwowarczyk.
PS: the #define kFileLocation is a leftover from my other tries. Omit it.
Based on your comments, I conclude the following:
The problem was that scanf correctly wrote the digit into the variable option the first time it was called. However, the second time scanf was called, it immediately returned the newline character from the previous menu selection, instead of waiting for the user to enter another digit. Whenever scanf returned a newline, the default case was triggered.
Therefore, the problem can be best solved by changing the scanf call to the following:
scanf(" %c", &option);
By adding a space to the start of the format string, you instruct scanf to discard all whitespace characters before reading the character. That way, you can insure that a newline will never be written into the option variable.
The problem of scanf reading newline characters instead of discarding them has been discussed in more detail in this question.

Prompt error when user enters a char instead of an expected int

I'm making a menu that lists options 1-3. The user is expected to enter an integer.
scanf("%d", &select_option)
How do I prompt error when user enters a char (for example "a", or "asd" for long strings, or a mixture like "1a2") instead of an expected int? Thanks.
Note: When the user enters a 'char' like 'a', 'asd', the code goes into an infinite loop for some reason.
Here's my program (minimal example):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
printf("Favourite sports? \n");
printf("1. Tennis\n");
printf("2. Badminton\n");
printf("3. Basketball\n");
printf("4. Exit program.\n");
printf("Enter your choice (1-4): ");
scanf("%d", &select_option);
while(select_option != 4)
{
switch(select_option)
{
case 1:
printf("You like tennis! Nice! \n");
break;
case 2:
printf("You like badminton! Nice!");
break;
case 3:
printf("You like basketball! Nice!");
break;
default:
system("clear");
printf("Invalid option. Please re-enter your choice (1-4).\n");
}//end switch
printf("Favourite sports? \n");
printf("1. Tennis\n");
printf("2. Badminton\n");
printf("3. Basketball\n");
printf("4. Exit program.\n");
printf("Enter your choice (1-4): ");
scanf("%d", &select_option);
}//end while
}//end main
You could do this:
#include <stdio.h>
int main(void) {
int v;
int ret = scanf("%d", &v);
if(ret == 1)
printf("OK, %d\n", v);
else
printf("Something went wrong!\n");
return 0;
}
where I took advantage of the return value of scanf(), and based on that value, I made an assumption. This will fail for the case of "1a2", but will succeed for "12" and "a".
However, this is a broad question and personally the way I would go for it is:
Use fgets() to read input.
Discard newline.
Convert string to integer (with strtol() for example).
Validate input.
I am assuming u are a beginner. You can use Switch Case which is used usually for creating menus and depending on the choice of the user executes the particular case.
I will show u a small example.
#include<stdio.h>
#include<conio.h>
int main()
{
int n;
printf("Select the sports u want to do\n");
printf("1.Tennis\n2.Karate\n3.Football\n");
scanf("%d",&n);
Switch(n)
{
case 1:printf("You chose Tennis\n");
break; //To prevent from all cases being executed we use
//break which helps from coming out of a loop
case 2:printf("You chose Karate\n");
break;
case 3:printf("You chose Football\n");
break;
default:printf("Please enter an appropriate number !");
//Cases which dont match with the input are handled by default !
}
}
Also to make the user enter input until he wants to exit add a while loop with a variable !
I hope this helps!

Parameters not passing correctly back to main

Source outline: User selects option either to 1. Make Bugatti; 2. Create Bugatti; or 3. Exit program. After each option is complete, the user should be returned back to the menu to select another option.
(Note: the user cannot display the car until it is created, hence the if statement in case 2)
The problem: User's inputs for createCar() function are not being returned back into main() (specifically to case 2 - Display Bugatti) and is displaying some large, odd values, instead of the user's inputs. I know it has something to do with the values not being stored into memory/called back to main().
Also, the while statements in createCar() function are completely being disregarded when I use parameters for some reason.
I would appreciate answers in code to make things easier to resolve personally if possible, thanks!
#include <stdio.h>
#include <math.h>
#define now 2017
//Function headers
void printMenu(void);
void createCar(int *speed, int *year, int *bhp, int *age);
int main(void)
{
//Variables
int userInput;
int topSpeed, yearMade, horsepower, carAge;
/***Loop program to return to menu after option is completed***/
for(;;)
{
//Print menu and get input from user
printMenu();
scanf("%i", &userInput), fflush(stdin);
//Validate input
while(userInput < 1 || userInput > 3)
{
printf("\nWrong input, please retry...\n");
scanf("%i", &userInput), fflush(stdin);
}
//Make decisions after user's choice
switch(userInput)
{
//Option 1: Create car then return to menu
case 1:
createCar(&topSpeed, &yearMade, &horsepower, &carAge);
continue;
//Option 2: Read car details (if created) then return to menu
case 2:
if(topSpeed == NULL)
{
printf("\nYou must first create a car, please retry...\n\n");
continue;
}
printf("\n----Bugatti Veyron----\n");
printf("Top Speed: %i km/h\nYear made: %i\nAge: %i years old\nHorsepower: %i bhp\n", &topSpeed, &yearMade, &horsepower, &carAge);
printf("----------------------\n");
continue;
//Option 3: Kill program
case 3:
exit(1);
}
}
return 0;
}
//Function: Display menu
void printMenu(void)
{
printf("-----------------------------------------\n");
printf("[Bob's Custom Car Creation Complex v1.0]\n");
printf("1. Create Bugatti\n2. Display Bugatti\n3. Exit\n");
printf("-----------------------------------------\n");
}
//Function: Make a car + validate inputs
void createCar(int *speed, int *year, int *bhp, int *age)
{
//Prompt user for top speed + validate input
printf("Enter the top speed of your Bugatti:");
scanf("%i", &speed), fflush(stdin);
while(speed <=0)
{
printf("You cannot have a top speed of nothing silly :-D\nPlease retry...\n");
scanf("%i", &speed), fflush(stdin);
}
//Prompt user for year mate + validate input
printf("What year is your Bugatti produced?:");
scanf("%i", &year), fflush(stdin);
while(year <=0)
{
printf("You cannot own a Bugatti that is from the future laddy!!\nPlease retry...\n");
scanf("%i", &year), fflush(stdin);
}
//Calculate age of car
age = now - year;
//Prompt user for horsepower + validate input
printf("How much horsepower does your Bugatti have?:");
scanf("%i", &bhp), fflush(stdin);
while(bhp <=0)
{
printf("A Bugatti with no engine... doesn't sound too promising :-O\nPlease retry...\n");
scanf("%i", &bhp), fflush(stdin);
}
}
You have to dereference the age and year pointer to get/set its value.
//Calculate age of car
*age = now - *year;
You have to remove the '&' at the scanf() in createVar, because speed, year and bhp are already pointers to int.
Enabling compiler warnings and resolving them would avoid you troubles!

Having an issue with structs and the program not saving inputs. I am inexperienced [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
The compiler doesn't come up with any errors...It is supposed to be a basic phonebook with 5 slots for people. For some reason everything seems to work but it doesn't save the information. What did I do wrong?
typedef struct contact{
char fname[10];
char lname[10];
int pnumber;
};
struct contact p1;
struct contact p2;
struct contact p3;
struct contact p4;
struct contact p5;
int go =0;
int phonebook(struct contact person,int use);
int main(){
while(go == 0){
int contact;
int choice;
int location;
printf("first what position in your contacts would you like to change?(1-5)\n");
scanf("%d",&location);
printf("what would you like to do?\n1. add a contact\n2. change a contact\n3. print a
contact\n4. Quit\n");
scanf("%d",&choice);
switch(location){
case 1:
phonebook(p1,choice);
break;
case 2:
phonebook(p2,choice);
break;
case 3:
phonebook(p3,choice);
break;
case 4:
phonebook(p4,choice);
break;
case 5:
phonebook(p5,choice);
break;
default:
printf("that was not a valid option\n");
}
}
system("PAUSE");
return EXIT_SUCCESS;
}
int phonebook(struct contact person,int use){
switch(use){
case 1:
if(person.pnumber>0){
printf("you already have a contact there\n");
}
else{
printf("What is the contact's first name?\n");
scanf("%s", &person.fname);
printf("\nWhat is the contact's last name?\n");
scanf("%s", &person.lname);
printf("\nWhat is the contact's phone number?\n");
scanf("%d", &person.pnumber);
}
break;
case 2:
if(person.pnumber == 0)
printf("No contact is saved in this position\n");
else{
printf("What is the contact's first name?\n");
scanf("%s", &person.fname);
printf("\nWhat is the contact's last name?\n");
scanf("%s", &person.lname);
printf("\nWhat is the contact's phone number?\n");
scanf("%d", &person.pnumber);
}
break;
case 3:
printf("\nName:%s\n%s \nNumber:%d \n",&person.fname,&person.lname,&person.pnumber);
break;
case 4:
go = 1;
break;
default:
printf("that wasn't an option. Please pick a valid option next time.\n");
}
}
You have a simple problem: the C language uses "call by value", so your phonebook() function gets a copy of the struct. Then the phonebook() function changes the copy, but the changes aren't saved anywhere.
The way you fix this: you have to make your phonebook() function take a pointer to a struct, and then it can use the pointer to modify the struct.
int phonebook(struct contact *pcontact, int use)
{
// ... stuff omitted ...
printf("What is the contact's first name?\n");
scanf("%s", pcontact->fname); // "fname" works as a pointer
printf("\nWhat is the contact's phone number?\n");
scanf("%d", &pcontact->pnumber); // must take address of integer "pnumber"
// ... rest of phonebook() omitted ...
// example of calling phonebook():
case 1:
phonebook(&p1, choice);
http://www.lysator.liu.se/c/bwk-tutor.html#pointers
You are passing person by value, not by reference, so phonebook is making changes to a copy of the contact struct.
Try
int phonebook(struct contact *person,int use);

Resources