hangman console game in c - c

#include<stdio.h>
#include<string.h>
#include<time.h>
#include<stdlib.h>
typedef struct dic {
int index;
char string[10];
struct dic *next;
}node;
main() {
FILE *fp;int indexrand;node *head;node *mainhead;
char s[10],question[10],answer[10];char check;
int count=-1,i,j,k,len,flag;head=(node *) malloc(sizeof(node));
mainhead=head;
fp=fopen("dictionary.txt","r");
while((fgets(s,10,fp))!=NULL) {
strcpy(head->string,s);
count++;
(head->index)=count;
head->next=(node *)malloc(sizeof(node));
head=head->next;
}
fclose(fp);
head->next=NULL;
srand(time(NULL));
indexrand=rand()%(count+1);
printf("%d\n",indexrand);
for(head=mainhead;(head->next)!=NULL;head=head->next)
if((head->index)==indexrand)
strcpy(question,(head->string));
printf("%s\n",question);
len=strlen(question);
printf("%d\n",len);
for(i=0;i<len-1;i++)
answer[i]='_';
answer[i]='\0';
printf("%s\n",answer);
printf("6 chances to go\n");
for(i=0,k=6;k>0;i++) {
flag=0;
printf("%d\n",i);
scanf("%c",&check);
for(j=0;j<(len-1);j++) {
if(question[j]==check) {
flag++;
answer[j]=check;
}
}
if(flag>0)
printf("%d chances to go\n",k);
if(flag==0) {
k--;
printf("no common letters...%d chances to go\n",k);
}
printf("%s\n",answer);
}
}
The file dictionary.txt has only one word per line.
While running the code, for every attempt from the user (i.e after user enters a character) the statement no common letters...%d chances to go\n",k is being displayed even if the flag > 0 condition is satisfied.
How do I correct this?

The line
scanf("%c",&check);
is reading characters the user types, including the newline.
You probably just want to read the first character on the line: use fgets() to read the whole line, and then set check = line[0].

printf("%d\n",i);
scanf("%c",&check);
Because of these statements,scanf is taking \n as a parameter and so printing "no common letters..." every time.Replace the above code with
printf("%d",i);
scanf("\n%c",&check);

I think you want to pass a string to scanf, so try it :
scanf("%s",&check);

Related

C Programming - Using Parallel Arrays to enter Names, Exercise Marks and Compute Average of Exercise Marks and Display

I'm doing self-study on C Programming, and I have been recommended the following C Program by my colleagues to study further, where you can enter the Name and Age and it displays and uses Insert, Delete, Display, and Exit menu options.
I'm trying to convert it to my current study stream logic scenario where I need to enter the Name, Exercise Mark 1 (up to 3), and then it computes the Average and gets displayed while employing the Insert, Delete, Display, Update (updating the scores only, not the names), Delete and Exit.
Any guidance please on how to learn this code and understand the logic, and apply it to the 2nd scenario will be much appreciated.
Here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 50
//using parallel arrays as fields in the list
typedef struct list{
char name[MAX][31];
int age[MAX];
int last;
}LIST;
LIST L;//L structure is global
void save();
void retrieve();
void makenull();
void insert(char n[31],int a);
void del(char n[31]);
void display();
int locate(char n[31]);
int isfull();
int isempty();
int menu();
int main(){
char nm[31];
int ag;
makenull();
retrieve();
while(1){
switch(menu()){
case 1: system("cls");printf("Insert Mode\n");
printf("Input Name: ");scanf("%s",nm);
printf("Input Age: ");scanf("%d",&ag);insert(nm,ag);break;
case 2: system("cls");printf("Delete Mode\n");
printf("Input Name: ");scanf("%s",nm);del(nm);break;
case 3: display();break;
case 4: save();exit(0);
default: printf("\n1-4 lang!\n");system("pause");
}
}
return 0;
}
void makenull(){
L.last = -1;
}
void insert(char n[31],int a){
if (isfull()){
printf("List is full.\n");
system("pause");
}
else {
L.last++;
strcpy(L.name[L.last],n);
L.age[L.last]=a;
}
}
void del(char n[31]){
int p;
if (isempty()){
printf("List is empty.\n");
system("pause");
}
else {
p=locate(n);
if (p==-1){
printf("Not found.\n");
system("pause");
}
else{
for(int i = p;i<L.last;i++){
strcpy(L.name[i],L.name[i+1]);
L.age[i]=L.age[i+1];
}
L.last--;
printf("Successful delete operation.\n");
system("pause");
}
}
}
void display(){
int i;
system("cls");
printf(" Name Age \n");
for(i=0;i<=L.last;i++)
printf("%d.) %s %d\n",i+1,L.name[i],L.age[i]);
system("pause");
}
int locate(char n[31]){
int i;
for (i=0;i<=L.last;i++)
if(strcmp(L.name[i],n)==0)
return i;
return -1;
}
int isfull(){
if (L.last==MAX-1)
return 1;
else
return 0;
}
int isempty(){
return(L.last==-1);
}
int menu(){
int op;
system("cls");
printf("MENU\n");
printf("1. Insert\n");
printf("2. Delete\n");
printf("3. Display\n");
printf("4. Exit\n");
printf("\nSelect(1-4): ");
scanf("%d",&op);
return(op);
}
void save(){
FILE *fp;
int i;
fp=fopen("Practice4.dbf","w+");
if (fp==NULL){
printf("File Error.\n");
system("pause");
}
else{
for (i=0;i<=L.last;i++)
fprintf(fp,"%s %d\n",L.name[i],L.age[i]);
}
fclose(fp);
}
void retrieve(){
FILE *fp;
char n[31];
int i,a;
fp=fopen("Practice4.dbf","r+");
if (fp==NULL){
printf("File Error.\n");
system("pause");
}
else {
while(!feof(fp)){
fscanf(fp,"%s %d\n",n,&a);
insert(n,a);
}
}
fclose(fp);
}
Your code isn't properly formatted and there are no comments. I can't give you a direct answer with some code in it, but summing up all my comments (and of course I deleted them), this is what I've to say:
Consider this scenario-
if your .dbf has more than MAX 50 elements, then your while (!feof(fp)) inside retrieve() will keep calling insert() and insert() will keep executing its if () { } block.
You should put something like while (!feof(fp) && L.last < MAX) to prevent that situation and you'll need to further modify your code in insert(). Another thing is, this code doesn't have any update() function and scores variable. You'll need to add scores in your struct as well as there must be scores fields in your .dbf.
Now, for a moment let's say everything else is good to go in your code, then you should follow these following steps:
Declare variables
char nameInput[31];
float ex_marks[3], sum = 0, avr = 0;
in main().
Add another case 5 in your switch () block inside main() and translate and convert the following pseudocode into C code:
Read name in nameInput
locate()
if found then
3.a for i = 0 to 2
Read marks in ex_marks[i]
sum = sum + ex_marks[i]
3.b Calculate avr = sum / 3
3.c Display name and avr
else
Display name is not in the list.
exit
Also read about why is while(!feof()) always wrong?

Inserting at the end of queue in C

I am trying to insert node at the end of queue and facing below error . This is simple fundamental error while compiling the code but making my life hard.
#include<stdio.h>
#include<stdlib.h>
typedef struct UNIX {
char str[20];
struct UNIX *next;
}examp;
examp *head=NULL;
int insert_last(char *s)
{
examp *new,*slide;
slide=head;
new = (examp *)malloc(sizeof(examp));
if(!new)
return(EXIT_FAILURE);
while(slide->next!=NULL)
slide=slide->next;
slide->next=new;
new->str=s;
new->next=NULL;
if(head==NULL)
{ head=new;
return 1;
}
return 1;
}
void display (void);
int main()
{
insert_last("hello ");
insert_last("how ");
insert_last("have ");
insert_last("you ");
insert_last("been ");
insert_last("! ");
display();
}
void display(void)
{
examp *slide;
slide=head;
while(slide->next!=NULL)
{ printf("%s ",slide->str);
slide=slide->next;
}
}
Error :stack_queue.c:27:10: error: assignment to expression with array type
new->str=s;
Update : Using strncpy reolved the error , but code is not working as expected and stopping unexpectedly.
You can't assign to a static array like that. Consider using strcpy or strncpy to copy the contents of the character string instead.
You cannot assign a string to an array! An array have its own memory, you can write or read elements in the array, but cannot assign an address.
You can eventually copy the string s contents to the array:
strncpy(new->str, s, 19);
new->str[19] = '\0'; //Close the string in case of overflow.
We used strncpy to limit the copied characters to the array size (19 chars + the ending '\0').
You can try it. Only replace in new->str=s; to strcpy(new->str, s); (ie. s will be copy in to new->str)
#include<stdio.h>
#include<stdlib.h>
typedef struct UNIX {
char str[20];
struct UNIX *next;
}examp;
examp *head=NULL;
int insert_last(char *s)
{
examp *new,*slide;
slide=head;
new = (examp *)malloc(sizeof(examp));
if(!new)
return(EXIT_FAILURE);
while(slide->next!=NULL)
slide=slide->next;
slide->next=new;
strcpy(new->str, s);
new->next=NULL;
if(head==NULL)
{ head=new;
return 1;
}
return 1;
}
void display (void);
int main()
{
insert_last("hello ");
insert_last("how ");
insert_last("have ");
insert_last("you ");
insert_last("been ");
insert_last("! ");
display();
}
void display(void)
{
examp *slide;
slide=head;
while(slide->next!=NULL)
{ printf("%s ",slide->str);
slide=slide->next;
}
}
As already stated you will have to use strcpy (or strncpy) in order to assign the string.
Asides from that I wanted to mention two things:
Do not forget to free your memory allocated by malloc. Create a method to free a single node (examp) then you can also provide a method to destroy the whole list.
I would suggest to rename the variable new to avoid confusion (pure C compiler may deal with it, but C/C++ compiler will most likely get into trouble).
Considering your update:
Take a look at the following line
while(slide->next!=NULL)
At this time slide does not even exist (it is NULL), still you perform an operation on the pointer. This is the reason why the program crashes.
Your error is in the first call insert_last("hello "):
int insert_last(char *s)
{
examp *new,*slide;
slide=head;
new = (examp *)malloc(sizeof(examp));
if(!new)
return(EXIT_FAILURE);
while(slide->next!=NULL)
slide=slide->next;
when you call it first time, head is NULL, so slide becomes NULL, but you don't check it, and call it in
while(slide->next!=NULL)
Here slide is null for the frst function call

Inserting in Linked List

I'm having a small difficulty inserting a full sentence containing all characters in my string when I'm building a Linked List.
I would like to be able to insert a string like: word_#_2003_#_definition
But when I'm running my code in my main() method it continues repeating the choices to do like it never stops asking me to enter an option. Hope it's clear.
Here's my struct:
struct node
{
char data[100];
struct node *previous; // Points to the previous node
struct node *next; // Points out to the next node
} *head, *last;
Here's my function to insert a node:
void insert_beginning(char words[99])
{
struct node *var, *temp;
var=(struct node *)malloc(sizeof(struct node)); //explination about the (node *)
strncpy(var->data, words,99);
if (head==NULL)
{
head=var;
head->previous=NULL;
head->next=NULL;
last=head;
}
else
{
temp=var;
temp->previous=NULL;
temp->next=head;
head->previous=temp;
head=temp;
}
}
And this is in my main() method:
int main()
{
char loc[99];
char words[99];
int i, dat;
head=NULL;
printf("Select the choice of operation on link list");
printf("\n1.) Insert At Begning\n2.) Insert At End\n3.) Insert At Middle");
printf("\n4.) Delete From End\n5.) Reverse The Link List\n6.) Display List\n7.)Exit");
while(1)
{
printf("\n\n Enter the choice of operation you want to do ");
scanf("%d",&i);
switch(i)
{
case 1:
{
printf("Enter a word you want to insert in the 1st node ");
scanf(" %s",words);
insert_beginning(words);
display();
break;
}
Any ideas on how to do it?
The code is highly questionable:
return codes are never checked. You must check return codes,
especially if you are using scanf
You need to empty the whole buffer with scanf otherwise you will continue
reading old contents for the next command
A better alternative is to use sscanf
You must initialize your variables, for instance last, but there are additional
cases of variables that do not get initialized
Your data types are not consistently defined, this will create security problems
sometimes 99 characters and sometimes 100.
insert_beginning should not return void, the memory allocation can fail
Your code in main() should probably look more like:
int main()
{
char loc[99];
char words[99];
int i, dat;
head = NULL;
printf("Select the choice of operation on link list");
printf("\n1.) Insert At Beginning\n2.) Insert At End\n3.) Insert At Middle");
printf("\n4.) Delete From End\n5.) Reverse The Link List\n6.) Display List\n7.) Exit\n");
while(1)
{
printf("\nEnter the choice of operation you want to do: ");
if (scanf("%d", &i) != 1)
{
fprintf(stderr, "Failed to read a number: exiting\n");
return 1;
}
switch(i)
{
case 1:
{
printf("Enter a word you want to insert in the 1st node: ");
if (scanf("%98s", words) != 1)
{
fprintf(stderr, "Failed to read words; exiting\n");
return 1;
}
insert_beginning(words);
display();
break;
}
...
}
...
}
...
}
return 0;
}
As discussed in the comments, you are not checking the return status from scanf(), so you don't know when it is failing, and when it fails to read a number, it leaves the argument (i) alone, so you go back to the same option again, and rinse and repeat.
Elementary debugging techniques (not shown):
Print the values you get from your inputs. Print the value of i after the scanf() error checking. Print the value of words after the scanf() error checking.
Step through with a debugger.
Create a function to dump (print) your key data structures:
static void dump_data_structure(FILE *fp, char const *tag, data_structure const *data)
{
...code to dump the structure to the specified file stream,
...identified by tag (so you can tell which call it is you are looking at)
}
Use the structure dumper extensively while debugging. Keep it for use later when modifying the code. If done right, it can be enormously helpful.

How to approach and optimize code in C

I am new to C and very much interested in knowing how to approach any problem which has more than 3 or 4 functions, I always look at the output required and manipulate my code calling functions inside other functions and getting the required output.
Below is my logic for finding a students record through his Id first & then Username.
This code according to my professor has an excessive logic and is lacking in many ways, if someone could assist me in how should I approach any problem in C or in any other language it would be of great help for me as a beginner and yes I do write pseudo code first.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct{
int id; //Assuming student id to be unique
int age;
char *userName; //Assuming student userName to be unique
char *dept;
}student; // Alias "student" created for struct
student* createstruct(); // All function prototype declared
student* createArray();
void addstruct(student* s2);
void searchChar(student* s2,int num);
void searchInt(student* s2,int num);
student* createstruct() // function createStruct() to malloc data of struct student.
{
student *s;
s = (student*)malloc(sizeof(student));
s->userName = (char*)malloc(sizeof(char)*32);
s->dept = (char*)malloc(sizeof(char)*32);
printf("please enter id ");
scanf("%d",&s->id);
printf("please enter age ");
scanf("%d",&s->age);
printf("please enter userName ");
scanf("%31s",s->userName);
printf("please enter department ");
scanf("%31s",s->dept);
printf("\n");
return s;
}
student* createArray()
{
student *arr; //declaration of arr poiter, type struct student
arr = (student*)malloc(sizeof(student)*10); // memory allocated for a size of 10
return arr;
}
void addstruct(student *s2) // function for adding data to the structures in array
{
int i,num;
student* s1;
printf("please enter the number of records to add:");
scanf("%d",&num);
printf("\n");
if(num>0 && num<11)
{
for(i=0;i<num;i++) // if user want to enter 5 records loop will only run 5 times
{
s1 = createstruct();
s2[i].id = s1->id; // traversing each element of array and filling in struct data
s2[i].age = s1->age;
s2[i].userName = s1->userName;
s2[i].dept= s1->dept;
}
}
else if(num>10) // if user enters more than 10
{
for(i=0;i<10;i++) // loop will still run only 10 times
{
s1 = createstruct();
s2[i].id = s1->id;
s2[i].age = s1->age;
s2[i].userName = s1->userName;
s2[i].dept = s1->dept;
}
printf("Array is full"); // Array is full after taking 10 records
printf("\n");
}
searchInt(s2,num); // Calling searchInt() function to search for an integer in records
searchChar(s2,num); // Calling searchChar() function to search for a string in records
free(s1);
free(s2);
}
void searchChar(student* s2,int num) // function for searching a string in records of structure
{
char *c;
int i;
c = (char*)malloc(sizeof(char)*32);
printf("please enter userName to search ");
scanf("%31s",c);
printf("\n");
for (i=0;i<num;i++) //num is the number of struct records entered by user
{
if ((strcmp(s2[i].userName,c)==0)) //using strcmp for comparing strings
{
printf("struct variables are %d, %d, %s, %s\n", s2[i].id,s2[i].age,s2[i].userName,s2[i].dept);
break;
}
else if(i == num-1)
{
printf("nothing in userName matches: <%s>\n",c);
break;
}
}
}
void searchInt(student* s2,int num) //searchs for an integer and prints the entire structure
{
int i,z;
printf("please enter id to search ");
scanf("%d",&z);
printf("\n");
for (i=0;i<num;i++)
{
if (s2[i].id == z)
{
printf("struct variables are %d, %d, %s, %s\n\n", s2[i].id,s2[i].age,s2[i].userName,s2[i].dept);
break;
}
else if(i == num-1)
{
printf("nothing in id matches: <%d>\n\n",z);
break;
}
}
}
int main(void)
{
student *s2;
s2 = createArray();
addstruct(s2);
return 0;
}
I'm not going to go into optimizing, because if you wanted better theoretical performance you would probably go with different data structures, such as ordered arrays/lists, trees, hash tables or some kind of indexing... None of that is relevant in this case, because you have a simple program dealing with a small amount of data.
But I am going to tell you about the "excessive logic" your professor mentioned, taking your searchInt function as an example:
for (i=0;i<num;i++)
{
if (s2[i].id == z)
{
printf("struct variables are %d, %d, %s, %s\n\n", s2[i].id,s2[i].age,s2[i].userName,s2[i].dept);
break;
}
else if(i == num-1)
{
printf("nothing in id matches: <%d>\n\n",z);
break;
}
}
The thing here is that every time around the loop you're testing to see if you're at the last element in the loop. But the loop already does that. So you're doing it twice, and to make it worse, you're doing a subtraction (which may or may not be optimized into a register by the compiler).
What you would normally do is something like this:
int i;
student *s = NULL;
for( i = 0; i < num; i++ )
{
if( s2[i].id == z ) {
s = &s2[i];
break;
}
}
if( s != NULL ) {
printf( "struct variables are %d, %d, %s, %s\n\n",
s->id, s->age, s->userName, s->dept );
} else {
printf("nothing in id matches: <%d>\n\n",z);
}
See that you only need to have some way of knowing that the loop found something. You wait for the loop to finish before you test whether it found something.
In this case I used a pointer to indicate success, because I could then use the pointer to access the relevant record without having to index back into the array and clutter the code. You won't always use pointers.
Sometimes you set a flag, sometimes you store the array index, sometimes you just return from the function (and if the loop falls through you know it didn't find anything).
Programming is about making sensible choices for the problem you are solving. Only optimize when you need to, don't over-complicate a problem, and always try to write code that is easy to read/understand.

Hash Table: it doesn't save correctly [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
What my program do..
read a text file of format
store name 1
itemcode quantity
itemcode quantity
.
.
store name 2
itemcode quantity
itemcode quantity
.
.
When you Run my code you will Ask to Enter a task.
there are three options
L itemcode quantity
entering the above sequence will print all the stores which contains that item with the given quantity.
U itemcode quantity storename
this option takes three arguments itemcode int quantity and storename
the Function for this option just update the given store with the amount quantity.
Q
this option call my Savefile method which save the current data structure back to the file.
Problem.
There is a problem I am facing.
whenever I update file it updates successfully but when Enter Command Q to quit and save it doesn't save correctly..
save_file(char *)
it lost whole data just the first store is save..
stores.txt
carrefour_Milan
12345678 12
23456766 16
carrefour_Torino
12345678 65
67676765 12
Carrefour_Vercelli
23456766 20
and also can you help me in finding the time complexity of
int listfile(char *)
and
int updatefile(char *,int ,char *)
I mean Big O.
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define MAX_ITEM 1000
#define MAXS 129
#define MAXL 132
#define MAXC 9
FILE *fp;
typedef struct store{
char Storename[MAXS];
int quantity;
struct store *NEXT;
}STORE;
typedef struct item{
char item_code[MAXC];
struct store *Stores;
struct item *NEXT;
}ITEM;
ITEM *list_item[MAX_ITEM];
int readfile(char *fname);
int update_file(char *item_code,int qty,char *name);
int hash(char *item_code);
int save_file(char *fname);
void init();
void init(){
int i;
for( i=0;i<MAX_ITEM;i++)
list_item[i]=NULL;
}
int readfile(char *fname){
char *p,line[MAXL+1],storen[MAXL+1];
int pos;
ITEM *current=NULL,*prev=NULL;
STORE *s_cur=NULL,*s_prev=NULL;
char itemcode[MAXC];int qty;
if((fp=fopen(fname,"r"))==NULL)
return -1;
while(!feof(fp)){
if(fgets(line,MAXL+1,fp)==NULL)
break;
if((p=strchr(line,'\n'))==NULL)
;
else
*p='\0';
if(line[0]>='a' && line[0]<='z' ||line[0]>='A' && line[0]<='Z')
strcpy(storen,line);
else{
//fgets(line,MAXL,fp);
if(sscanf(line,"%s %d",itemcode,&qty)>0){
current=(ITEM *)malloc(sizeof(ITEM));
if(current==NULL)
return -1;
pos=hash(itemcode);
if(list_item[pos]==NULL){
list_item[pos]=current;
if((s_cur=(STORE *)malloc(sizeof(STORE)))==NULL)
return -1;
strcpy(s_cur->Storename,storen);
strcpy(current->item_code,itemcode);
s_cur->quantity=qty;
current->Stores=s_cur;
s_cur->NEXT=NULL;
current->NEXT=NULL;
}
else{
ITEM *q=list_item[pos];
if((s_cur=(STORE *)malloc(sizeof(STORE)))==NULL)
return -1;
while(q!=NULL){
if(strcmp(q->item_code,itemcode)==0){
STORE *temp=q->Stores,*temp_a=NULL;
if(temp==NULL){
q->Stores=s_cur;
strcpy(s_cur->Storename,storen);
s_cur->quantity=qty;
s_cur->NEXT=NULL;
}
else{
while(temp!=NULL){
temp_a=temp;
temp=temp->NEXT;
}
temp_a->NEXT=s_cur;
strcpy(s_cur->Storename,storen);
s_cur->quantity=qty;
s_cur->NEXT=NULL;
}
}
q=q->NEXT;
}
if(q==NULL){
q=current;
current->NEXT=NULL;
current->Stores=s_cur;
strcpy(s_cur->Storename,storen);
s_cur->quantity=qty;
s_cur->NEXT=NULL;
}
}
}
}
}
fclose(fp);
return 0;
}
int listfile(char *item_code,int qty){
int i;
ITEM *u=NULL;
item_code[strlen(item_code)]='\0';
if(list_item[hash(item_code)]==NULL)
return -1;
else{
u=list_item[hash(item_code)];
while(u!=NULL){
if(strcmp(u->item_code,item_code)==0){
STORE *temp=u->Stores;
while(temp!=NULL){
if(temp->quantity>=qty){
printf("STORE %s\n",temp->Storename);
}
temp=temp->NEXT;
}
}
u=u->NEXT;
}
}
return 0;
}
int update_file(char *item_code,int qty,char *name){
ITEM *u=NULL;
item_code[strlen(item_code)]='\0';
name[strlen(name)]='\0';
if(list_item[hash(item_code)]==NULL)
return -1;
u=list_item[hash(item_code)];
if(u==NULL)
return -1;
while(u!=NULL){
if(strcmp(u->item_code,item_code)==0){
STORE *temp=u->Stores;
while(temp!=NULL){
if(strcmp(temp->Storename,name)==0)
temp->quantity+=qty;
temp=temp->NEXT;
}
}
u=u->NEXT;
}
return 0;
}
int hash(char *item_code){
int sum=0,s=0;
while(item_code[s]!='\0'){
sum+=33*item_code[s];
s++;}
return sum%MAX_ITEM;
}
void clear(){
char c;
while(c!='\n')
scanf("%c",&c);
}
main(){
int y;
char fname[]="stores.txt",line[MAXL],command,z[MAXS];
char x[MAXC];
init();
if(readfile(fname)==-1)
printf("Error reading file!");
else{
do{
printf("Enter task:");
fgets(line,MAXL,stdin);
sscanf(line,"%c",&command);
switch(command){
case 'L': sscanf(line,"%c%s%d",&command,x,&y);
if(listfile(x,y)==-1)
printf("No items were found\n");
break;
case 'U':sscanf(line,"%c%s%d%s",&command,x,&y,z);
if(update_file(x,y,z)==0)
printf("Update OK\n");
else
printf("Error when updating\n");
break;
case 'Q':if(save_file(fname)==0)
printf("Done\n!");
break;
default:printf("Enter correct command\n");
break;
}
}while(command!='Q');
}
}
int save_file(char *fname){
ITEM *p=NULL,*q=NULL;
int num=0,i,j;
char str[MAXS];
if((fp=fopen(fname,"w"))==NULL)
return -1;
for( i=0;i<MAX_ITEM;i++){
if(list_item[i]==NULL)
;
else{
p=list_item[i];
while(p!=NULL){
STORE *s=p->Stores;
if(s==NULL)
;
else{
if(strcmp(s->Storename,"0000\0")!=0){
strcpy(str,s->Storename);
// puts(str);
fprintf(fp,"%s\n",str);
}
while(s!=NULL){
for( j=0;j<MAX_ITEM;j++){
if(list_item[j]==NULL)
;
else{
q=list_item[j];
while(q!=NULL){
STORE *st=q->Stores;
if(st==NULL)
;
else{
while(st!=NULL){
if(strcmp(st->Storename,str)==0 && strcmp(st->Storename,"0000\0")!=0){
printf("%s %d\n",q->item_code,st->quantity);
fprintf(fp,"%s %d\n",q->item_code,st->quantity);
strcpy(st->Storename,"0000\0");
}
st=st->NEXT;
}
}
q=q->NEXT;
}
}
}
s=s->NEXT;
}
}
p=p->NEXT;
}
}
}
fclose(fp);
return 0;
}
This is an inconsistent and unreadable mess. I suggest as first steps to refactor the layout.
Repair the indentation so it reflects the code structure. Chose a bracing style and use it consistently. Something like this
if(x){
;
}else{
foo();
}
should better look like this:
if (x) {
;
}
else {
foo();
}
That's a much better starting point for any debugging and maintenance. And there is a lot of maintenance necessary.
Your code is very inefficient. For example when reading the file, you malloc the store structure separately in both branches of the if statement, and copy the store name in three different places, again in all different code paths. Why not simply malloc the store structure and initialise it correctly before you work out where to put it?
Also in the read file function, if the hash table position corresponding to the item is not empty, the memory allocated to "current" gets leaked.
Furthermore, if you actually find a match for the item, you don't break out of the loop which means that the block of code beginning:
if(q==NULL){
q=current;
gets executed.
Lastly (for now), if a slot in the hash table is filled but there is no matching itemcode then the item won't get put into the hash table. Look at your code. At what point do you assign "current" to any part of the chain that starts at "list_item[pos]"? You don't. Doing "q = current" just stores one value in another variable. What you need is something like:
current->next = list_item[pos];
list_item[pos] = current;
To add it on at the beginning of the list.
I suggest you fix your file reading function before worrying about your file writing function.
P.s. an upvote and a request for more comments may get you some more help. Depending on how busy I am and whether others can also be bothered to help.

Resources