Library menu program on C language code not working - c

In my class i been assigned to make a Library menu program which includes
a structure with bookname/author/price/issue date;
then a menu with different options like addbook,display, search by author etc
i believe i got the basic idea of how to do it and i made a draft of it in codeblocks. but problem is code working but i cant get input/output of book name only (rest working i think) and i cant find the reason why. im a beginner in programming just been doing it for 2 month or so, so i would be very greatful if someone can point out whats wrong in my code.
Thanks in advance and here is my code>
#include<stdio.h>
#include<string.h>
int bookcount=0;
struct library{
char name[100];
char author[100];
float price;
char date[20];
}str[100];
int main(){
int i;
menu();
return 0;
}
int menu(){
int choice,i;
for(i=0;;i++){
printf("\nWelcome to library menu.Please enter a choice from below-");
printf("\n\nPress 1 to add book information\nPress 2 to Display book information\nPress 3 to search books by author name");
printf("\nPress 4 to list the count of books\nPress 5 to find all the books for given price\nPress 0 for exit\nChoice=");
scanf("%d",&choice);
if(choice==0)
break;
else{
switch(choice){
case 1:
addbook();
break;
case 2:
display();
break;
case 3:
searchbyauthor();
break;
case 4:
listcount();
break;
case 5:
findbyprice();
break;
default:
printf("invalid input!\n");
}
}
}
return 0;
}
int addbook(){
int n,i;
printf("\nEnter number of books to add=");
scanf("%d",&n);
for(i=0;i<n;i++){
printf("\nEnter book title=");
gets(str[bookcount].name);
printf("\nEnter book author=");
gets(str[bookcount].author);
printf("\nEnter book date=");
gets(str[bookcount].date);
printf("\nEnter book price=");
scanf("%f",&str[bookcount].price);
bookcount++;
}
return 0;
}
int display(){
int i;
for(i=0;i<bookcount;i++){
printf("\nBook no %d name=",i+1);
puts(str[i].name);
printf("\nBook no %d author=",i+1);
puts(str[i].author);
printf("\nBook no %d issue date=",i+1);
puts(str[i].date);
printf("\nBook no %d price=%f",i+1,str[i].price);
}
return 0;
}
int searchbyauthor(){
char inp[100];
int i;
printf("\nEnter Author name to search=");
gets(inp);
for(i=0;i<bookcount;i++){
if(strcmp(str[i].author,inp)==0)
printf("\nBook name=%s",str[i].name);
}
return 0;
}
int listcount(){
printf("\nnumber of books are =%d\n",bookcount);
return 0;
}
int findbyprice(){
float inp;
int i;
printf("\nEnter price to search=");
scanf("%f",&inp);
for(i=0;i<bookcount;i++){
if(str[i].price==inp)
printf("\nBook name=%s",str[i].name);
}
return 0;
}

As you didn't post any input, I needed to find out that myself, just include sampling input and output next time:
1
1
name
Let's see what your program does with stdin at this point
scanf("%d",&choice); // in menu() in loop, choice := 1, ie add book
scanf("%d",&n); // in addbook(), n := 1, ie. 1 book
gets(str[bookcount].name); // in addbook in loop, this will be and should be ""
scanf() "consume and discard all leading whitespace characters", and newline is whitespace character. So this is what happens:
scanf("%d",&choice); // reads '1' from the input, and stops BEFORE newline
scanf("%d",&n); // discards newline and reads 1 from the input and stops before newline
gets(str[bookcount].name); // because newline is still in buffer and gets
// stops at first newline, this will read empty string
// the next gets will read the `name` from stdin, as it wasn't read already
The fix is rather simple. Just scanf for lines scanf("%d\n",...); not for single variables.

Related

Is there a better way to accept full name of user in structures from the console in C language?

This is a mini project for library management system. The problem is that first fgets function for user input in case 1 falls through no matter the content but that of the subsequent ones works. I want to accept the full name of the book name and the author which contains whitespaces from the console.
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <string.h>
// Structure definition
struct library
{
char bookName[50];
char authorName[50];
int numberOfPages;
float price;
};
int main()
{
// Structure Variable declaration
struct library lib[50];
// Variables initialization
int i,j,keepcount;
i=j=keepcount = 0;
// Character arrays
char arth_nm[50],book_nm[50];
while(j!=7)
{
// Menu Selection
printf("\n\n1. Add book information\n2. Display book information\n");
printf("3. List all books of given author\n");
printf("4. List the title of specified book\n");
printf("5. List the count of books in the library\n");
printf("6. Display Highest Price Book\n");
printf("7. Exit");
printf ("\n\nSelect one of the above: \n");
scanf("%d",&j);
switch(j)
{
// Entering book details
case 1:
printf ("Enter book name: ");
fgets(lib[i].bookName, sizeof(lib[i].bookName), stdin);
printf ("Enter author name: ");
fgets(lib[i].authorName, sizeof(lib[i].authorName), stdin);
printf ("Enter pages: ");
scanf ("%d",&lib[i].numberOfPages);
printf ("Enter price: ");
scanf ("%f",&lib[i].price);
keepcount++;
break;
// All book details entered
case 2:
printf("You have entered the following information\n");
for(i=0; i<keepcount; i++)
{
printf ("Book name = %s",lib[i].bookName);
printf ("\tAuthor name = %s",lib[i].authorName);
printf ("\tPages = %d",lib[i].numberOfPages);
printf ("\tPrice = %f",lib[i].price);
printf("\n");
}
break;
// Searching for book details by using the name of the Author
case 3:
printf ("Enter author name : ");
scanf ("%s",arth_nm);
for (i=0; i<keepcount; i++)
{
if (strcmp(arth_nm, lib[i].authorName) == 0)
printf ("%s %s %d %f",lib[i].bookName,lib[i].authorName,lib[i].numberOfPages,lib[i].price);
}
break;
// Searching for book details by using the name of the book
case 4:
printf ("Enter book name : ");
scanf ("%s",book_nm);
for (i=0; i<keepcount; i++)
{
if (strcmp(book_nm, lib[i].bookName) == 0)
printf ("%s \t %s \t %d \t %f",lib[i].bookName,lib[i].authorName,lib[i].numberOfPages,lib[i].price);
}
break;
// Case for Total many of books shelved
case 5:
printf("\n No of books in library : %d", keepcount);
break;
// Case for Highest paid book
case 6:
printf ("Highest Price Book : ");
float temp = 0;
for (i=0;i<keepcount;i++)
{
if(temp < lib[i].price)
temp = lib[i].price;
}
printf("%f", temp);
break;
case 7:
exit (0);
}
}
return 0;
}
Use the fgets() statement for accepting whitespaces:
fgets(arth_nm, 50, stdin);
You should fflush(stdout) it to clear the output buffer like this:
fflush(stdout);
fgets(arth_nm, 50, stdin);
It'll help you to fix this.
yes , there is, as #Rohan Bari said, you can use fgets() , though some compilers does not supports the use of this function. Alternatively, you can use
scanf ("%[^\n]%*c", variableName);
this function takes the input till a new line or enter is pressed, i.e, it will read any character including whitesapces.i hope i've been able to help.

Bugs in C Switch Menu using a Char as Choice, Won't Read in fgets name

Im basically Writing a program that creates, reads, updates and
deletes records in a binary file.
Everything compiles correctly, no syntax errors, but I do have some
bugs.
KNOWN BUGS
1.) Imputing any strings does not work, using fgets
2.) Ctrl-D Does Work but outputs a 'default' error before it exits.
3.) Update does not work (Not my main issue at the moment as the others are more important for now.)
4?) I'm not sure if the menu is working how it's supposed to work. I
think the do while is correct, since in the menu if I select and hit
CTRL-D it does exit the program. Just wanna be sure.
Right now I just want to know why, It is skipping the courseName in
the inputs function.
Here is my code thus far
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <errno.h>
#include <string.h>
typedef struct{
char courseName [64];
char courseSched [4];
unsigned int courseHours;
unsigned int courseSize;} COURSE;
FILE *pfileCourse;
int courseNumber = 0;
//Prototypes
void inputDetails(COURSE *c);
void readCourseRecord();
void createCourseRecord();
void print_menu();
void modifyCourseInfo();
void deleteCourse();
void display(COURSE c);
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
int main(int argc, char *argv[]) {
char choice; // this is the choice
printf("Enter one of the following actions or press CTRL-D to exit\n");
printf("C - Create a new course record\n");
printf("R - Read an existing course record\n");
printf("U - Update an existing course record\n");
printf("D - Delete an existing course record\n");
do{
choice = getchar();
switch(choice) {
case 'c':
case 'C':
printf("YOU PICKED C for Create\n");
createCourseRecord();
break;
case 'r':
case 'R':
printf("This is Choice R\n");
readCourseRecord();
break;
case 'u':
case 'U':
printf("Here is where you update an existing course\n");
modifyCourseInfo();
break;
case 'd':
case 'D':
printf("here is where you Delete an existing course record\n");
deleteCourse();
break;
default:
printf("Wrong Choice!\n");
}
}while(choice != EOF);
return 0;
}
void createCourseRecord() {
COURSE data;
pfileCourse = fopen("courses.dat", "ab");
printf("Please Enter The Details of The Course\n");
inputDetails(&data);
fwrite(&data, sizeof(data), 1, pfileCourse);
fclose(pfileCourse);
printf("Course Has Been Created!\n");
}
void inputDetails(COURSE *c) {
printf("Enter a course number: \n");
scanf("%d", &courseNumber);
printf("Enter a Course Name: \n");
fgets(c->courseName, sizeof(courseName), stdin);
printf("Enter the course schedule (MWF or TR): \n");
fgets(c->courseSched, 4, stdin);
fflush(stdin);
printf("Enter the course credit hours: \n");
scanf("%d",&c->courseHours);
fflush(stdin);
printf("Enter Number of Students Enrolled: \n");
scanf("%d",&c->courseSize);
return;
}
void readCourseRecord(){
COURSE data;
int flag = 0;
int readCourseNumber = 0;
printf("Please Enter a Course Number to Display\n");
scanf("%d", &readCourseNumber);
fflush(stdin);
pfileCourse = fopen("courses.dat", "rb");
while((fread(&data, sizeof(data), 1, pfileCourse)) > 0) {
if(readCourseNumber == courseNumber)
{
display(data);
flag = 1;
}
}
fclose(pfileCourse);
if(flag == 0)
printf("Course not Found!\n");
}
void deleteCourse(){
int newCourseNum;
COURSE data;
FILE *file2;
printf("Please Enter The Course You Wish You Delete\n");
scanf("%d", &newCourseNum);
pfileCourse = fopen("courses.dat", "rb");
file2 = fopen("temp.dat", "wb");
rewind(pfileCourse);
while((fread(&data, sizeof(data), 1, pfileCourse)) > 0)
{
if(courseNumber != newCourseNum)
{
fwrite(&data, sizeof(data), 1, file2);
}
}
fclose(file2);
fclose(pfileCourse);
remove("courses.dat");
rename("temp.dat", "courses.dat");
printf("%d was Successfully deleted\n", newCourseNum);
}
void modifyCourseInfo()
{
COURSE data;
int newCourseNum, found = 0;
printf("Modify\n");
printf("Please Enter The Course You Wish You Modify\n");
scanf("%d", &newCourseNum);
pfileCourse = fopen("courses.dat", "rb+");
while ((fread(&data, sizeof(data), 1, pfileCourse)) > 0 && found == 0)
{
if (courseNumber == newCourseNum)
{
display(data);
printf("Please Enter New Details\n");
inputDetails(&data);
fseek(pfileCourse, - (long)sizeof(data), 1);
fwrite(&data, sizeof(data), 1, pfileCourse);
printf("Course Updated\n");
found == 1;
}
}
fclose(pfileCourse);
if(found == 0)
printf("ERROR: course not found\n");
}
void display(COURSE c){
printf("courseNumber:\t %d\n", courseNumber);
printf("courseName:\t %s\n",c.courseName);
printf("courseSched:\t %s\n",c.courseSched);
printf("courseName:\t %d\n",c.courseHours);
printf("courseSize:\t %d\n",c.courseSize);
}
It doesn't skip courseName, courseName just gets value '\n' because scanf function stops reading your input BEFORE white space. Scanf ignores any whitespace characters encountered before the next non-whitespace character. So you can just add
scanf("%d[^\n]", &courseNumber);
getchar();
after every scanf you have but I'd recommend you to use fgets function for every interactive input.

.exe has stopped working (Cprogramming)

I am running this program and keep getting an error after I input my name
"program1.exe has stopped working"
have no idea why any help?
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
void create();
//void edit();
//void delete();
int main()
{
char choice;
printf("\n\t\t **********************\n\n");
printf("\n\t\t Train Booking Application\n");
printf("\n\t\t **********************\n\n");
printf("Select 1 to create a booking,\tSelect 2 to Edit booking,\tSelect 3 to Delete a booking\n");
scanf("%d",&choice);
if (choice == 1){
create();
}
return 0;
}
void create(){
char Fname,Sname;
printf("Please enter your First name:\n");
scanf ("%s",Fname);
printf("Please enter your Second name:\n");
}
char is used to read one character. Use string instead.
%d is used for reading integers but you defined . Either use
int choice;
or use
scanf("%s", &choice);
try to use a switch for your selection too
switch(choice){
case 1:
create();
break;
case default:
//default statement(s)
}
Please pay attention to the compiler warnings. It will discover problems for you. Suggestion for improvements in the program comments:
#include <stdio.h>
#include <stdlib.h>
//#include <iostream> // C++ include, not needed!
void create();
int main()
{
int choice; // changed to int to match scanf("%d", char is to small to hold an `int`
printf("\n\t\t **********************\n\n");
printf("\n\t\t Train Booking Application\n");
printf("\n\t\t **********************\n\n");
printf("Select 1 to create a booking,\tSelect 2 to Edit booking,\tSelect 3 to Delete a booking\n");
scanf("%d", &choice);
switch (choice){ // switch is a better choice than nested ifs
case 1:
create();
break;
default:
printf("not implemented yet...\n");
break;
}
return 0;
}
void create(){
char Fname[256],Sname[256]; // changed to arrays to match scanf ("%s"
// char Fname, Sname with %s would destroy memory
printf("Please enter your First name:\n");
scanf ("%s",Fname);
printf("Please enter your Second name:\n");
scanf ("%s",Sname);
}
As char just store one character and your name is longer than that, try using char Fname[], for storing your entire name.

Menu type program

I have an assignment to write a program for supporting an art gallery in C. It has to be menu based program using lists. I wrote the first function of the menu and I need some help writing the other three. So I have a structure of an unique code of the painting, author's name, painting's name, price, year of the painting. I have to create a function deleting a painting using the unique code, print out all the info about every painting and modifying a painting again using said code. The data has to be in a dynamic type structure using a linked list. This is the program so far.
#include <stdio.h>
void addPainting(void);
void erasePainting(void);
void printData(void);
void modifyData(void);
int main()
{
struct paintings
{
char code[20];
char name[50];
char paintingName[50];
double price;
int year;
}painting[100];
int choice;
do
{
printf("Menu\n");
printf("To add a painting press 1.\n");
printf("To erase a painting press 2.\n");
printf("To print data for all paintings by authors alphabetically press 3.\n");
printf ("To modify data for a painting press 4.\n");
printf("To exit the program press 5.\n");
scanf("%d",&choice);
switch(choice)
{
case 1:
{
addPainting();
break;
}
case 2:
{
erasePainting();
break;
}
case 3:
{
printData();
break;
}
case 4:
{
modifyData();
break;
}
default: printf ("Wrong choice. Try again\n");
break;
}
}while (choice !=5);
void addPainting()
{
FILE *fp;
struct paintings painting;
printf("Enter code:");
scanf("%s", &painting.code);
printf("Enter the name of the author:");
scanf("%s", &painting.name);
printf("Enter the name of the painting:");
scanf("%s", &painting.paintingName);
printf("Enter price:");
scanf("%lf", &painting.price);
printf("Enter the year of creation:");
scanf("%d", &painting.year);
if ((fp=fopen("paintings","wb"))==NULL)
exit(1);
if ((fwrite (&painting,sizeof(painting),1,fp)!=1))
exit(2);
fclose(fp);
}
}
First problem: You are missing the closing brace ( } ) for the main() function. (but I am sure you knew that)
The reason for the struct size error is that you are attempting to create an instance of struct painting in the void addPainting() function, when it was created with local scope in the main function, and therefore it is not visible to the function. Create struct painting with global scope if you want to use it this way:
This will build (and run) but only for the functions defined, the others are commented out. There are other problems you will have to work out, or ask about.
EDITED to fix scanf() statements, show use of fopen()/fclose(), create and write strings using sprintf()/fputs()...
void addPainting(void);
//void erasePainting(void);
//void printData(void);
//void modifyData(void);
typedef struct //created with global scope, visible to all functions
{
char code[20];
char name[50];
char paintingName[50];
double price;
int year;
}PAINTING;
PAINTING painting[100];//array of instance of PAINTING
#define PATH "C:\\play\\painting.txt" //edit to your need
int main()
{
int choice;
do
{
printf("Menu\n");
printf("To add a painting press 1.\n");
printf("To erase a painting press 2.\n");
printf("To print data for all paintings by authors alphabetically press 3.\n");
printf ("To modify data for a painting press 4.\n");
printf("To exit the program press 5.\n");
scanf("%d",&choice);
switch(choice)
{
case 1:
{
addPainting();
break;
}
case 2:
{
//erasePainting();
break;
}
case 3:
{
//printData();
break;
}
case 4:
{
//modifyData();
break;
}
default: printf ("Wrong choice. Try again\n");
break;
}
}while (choice !=5);
}
void addPainting(void)
{
FILE *fp;
char stringToWrite[80];
//Note: this function could be prototyped with an int argument
// to be used as an index for the array arguments of your
// structure. Currently, the indexes are hard-coded to 0,
printf("Enter code:");
//scanf("%s", &painting[0].code);
scanf("%s", painting[0].code); //& not needed for char array (char *) et. al.
printf("Enter the name of the author:");
scanf("%s", painting[0].name);
printf("Enter the name of the painting:");
scanf("%s", painting[0].paintingName);
printf("Enter price:");
scanf("%lf", &painting[0].price);
printf("Enter the year of creation:");
scanf("%d", &painting[0].year);
fp = fopen (PATH, "a");//open for create/append text file (not write binary, "wb")
if(fp)
{
sprintf(stringToWrite, "Painting Code is: %s\n", painting[0].code);
fputs(stringToWrite, fp);
// do others same way...
//...
fclose(fp);
}
}

gets not taking the password

In the code below in lesson2() i have used a password to enter the function but when i enter the function it does not takes in the passord and says incorrect password.By not taking in the password,i mean to say that i have used gets but its waiting for me to input a password.please dont tell me not to use gets!
#include<stdio.h>
#include<conio.h>
#include<string.h>
#include<dos.h>
int mistakes=0,mistakes_length,len;
char temp[100];
void lesson1(void);
void lesson2(void);
void result(void);
void main(void)
{
int choice;
clrscr();
printf("Enter a lesson number to practise:1-10 \n");
scanf("%d",&choice);
switch(choice)
{
case 1:
lesson1();
result();
break;
case 2:
lesson2();
result();
break;
default:
printf("You did not entered a valid choice program quitting..\n");
exit(0);
}
getch();
}
void lesson1(void)
{
int i;
char str1[100]="testing the typing tutor if it works";
mistakes_length=5;
clrscr();
gotoxy(25,2);
puts("Welcome to lesson 1");
puts(str1);
len=strlen(str1);
for(i=0;i<len;i++)
{
temp[i]=getche();
if(strncmpi(&str1[i],&temp[i],1))//does not match
{
mistakes++;
sound(100);
delay(1000);
nosound();
}
}
getch();
}
void result(void)
{
printf("Your statsistics are as under:\nYou performed this lesson with %d mistakes\n",mistakes);
if(mistakes>=mistakes_length)
{
printf("\n Your typing is very bad");//allow anything to be typed with any mistake in lesson 1
}
if(mistakes>3&&mistakes<5)
{
printf("Bad!,You need to practise this excercise more\n");
}
if(mistakes>=1&&mistakes<=3)
{
printf("Good!you can still do better\n");
}
if(mistakes==0)
{
printf("Excellent!You are qualified for the next lesson\n");
printf("The next lessons password is \n\t\t\t:12345");
}
}
void lesson2(void)
{
char password[]="12345",str2[]="My name is khan and i am not a criminal";
int i;
mistakes=0,mistakes_length=0,
printf("Enter password:\n");
gets(temp);
if(strcmp(temp,password))
{
gotoxy(20,25);
printf("Wrong Password,Program Quitting.\n");
getch();
exit(1);
}
gotoxy(25,25);
printf("Password Accpted!");
getch();
clrscr();
gotoxy(25,2);
printf("Welcome to lesson 2\n");
printf("Type the text shown below:\n");
puts(str2);
len=strlen(str2);
for(i=0;i<len;i++)
{
temp[i]=getche();
if(strncmp(&str2[i],&temp[i],1));
{
mistakes++;
}
}
getch();
}
I think that it is the scanf and gets together making a problem!
Your problem is that prior to calling gets(), you have called scanf("%d",&choice); (in main()). The problem with this is that console input is line oriented. This means that although you are only waiting for a number to be entered the user has to enter a complete line ending in newline. The %d format specifier only consumes the digit characters leaving the rest of the line in the buffer to be used by the next console input call; which in this case is gets() which sees the newline in the buffer and returns an empty string without waiting for further input.
A solution:
scanf("%d",&choice);
while(getchar() != '\n' ) { /*no nothing*/}
I think the problem you are seeing is in fact coming from the main method.
The scanf() call that you make is only looking for "%d" rather than "%d\n".
Therefore, you enter the number 2 in order to try test 2, and must press enter before that value gets to the program. Since scanf is not trying to match it, that newline remains as part of the input stream and thus is passed directly to gets() within the next function.
Therefore, if you change the string within scanf inside the main function, you should see the code start working.
Now on another note (and I know that you asked us not to but...) you really shouldn't use gets(). In order to switch to fgets, just replace gets(temp) with fgets(temp,99,stdin). That 99 is any number that is less than the size of the temp buffer you have made, which in this case has size 100.
Try printing temp like this: printf("[%s]\n", temp); after the gets(temp); to see what is saved in temp. It may takes as input a previous given input from lesson1 function?
If this is the case, something like this maybe will fix the problem:
char other_tmp[5];
gets(other_tmp);
gets(temp);
although in such a case you should better correct the lesson1 function instead.
it supposed to work.
edit your code:
int r = gets(temp);
printf("returned: %d, Entered: %s\n", r, temp);
and post here the result

Resources