[英]While performing operations will the bookid's get changed?
我做了一個程序,它是一個通過軟件操作的小型圖書館。 當我添加了兩本書,然后刪除第一本書的第二本書得到相同的BOOKID的,因為第一本書count--
在del()
函數。 我不能依靠將計數打印為書本。 有更好的選擇嗎?
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
static int count;
struct book
{
int bookid;
char name[30];
char author[30];
float price;
};
struct book b[40];
void add(void);
void del(void);
void sort(void);
void price(void);
void print(void);
void main(void)
{
char choice;
while(1)
{
clrscr();
printf("Enter a choice:\n 1.Add a book.\n 2.Delete a book.\n 3.Sort books by price.\n 4.To print all books details.\n 5.To print the names of the books whose price is less than 1000.\n 6.Exit\n");
choice=getche();//doing by getch() as getche makes the program rough as it is printed
switch(choice)
{
case'1':add();break;
case'2':del();break;
case'3':sort();break;
case'4':print();break;
case'5':price();break;
case'6':exit(0);
default:printf("Enter a valid choice.");break;
}
}/*switch ends*/
}
void add(void)
{
int i;
char ch[30];
clrscr();
for(i=count;i<40;i++)
{
printf("Enter books name:\n");
gets(b[i].name);
printf("Enter author's name\n");
gets(b[i].author);
printf("Enter price:\n");
gets(ch);
b[i].price=atoi(ch);
printf("Dear User,the book has succesfully been added.The book id is %d",i);
count++;
break;
} /* for ends*/
getch();
}
void print(void)
{
int i;
clrscr();
for(i=0;i<count;i++)
{
printf("Bookid=%d,Name=%s,Author=%s,Price=%f\n",b[i].bookid,b[i].name,b[i].author,b[i].price);
}
getch();
}
void del(void)
{
int i,j;
char ch[10];
clrscr();
printf("Enter book id:");
gets(ch); // how do i put it into the structure as i dont know that which structure it belongs to
for(i=0;i<count;i++) //searching
{
if(b[i].bookid==atoi(ch))
{
for(j=i;j<count;j++)
{
b[j]=b[j+1];
}//for j ends
} //if ends
} /* for of i ends */
count--;
getch();
}
//void del(void)
//{
// int i;
// char ch[10];
// clrscr();
//printf("Enter book id:");
// gets(ch);
// for(i=0;i<40;i++)
// {
// b[i]=b[i+1];
//
// }
// count--;
// printf("Dear user,delete succesful");
//getch();
//}
void sort(void)
{
int i;
float temp;
for(i=0;i<40;i++)
{
if(b[i].price>b[i+1].price)
{
temp=b[i].price;
b[i].price=b[i+1].price;
b[i+1].price=temp;
}
}/*for ends*/
printf("Dear user,the books are sorted by price.\n");
getch();
}
void price(void)
{
int i;
clrscr();
for(i=0;i<count;i++)
{
if(b[i].price<1000)
{
printf("%d.%s\n",i+1,b[i].name);
}
}
getch();
}
正如泰勒·麥克亨利(Tyler McHenry)所指出的,一種方式是擁有兩個全局計數器:一種具有存儲的書籍數量,另一種提供下一個(唯一的)書籍ID。 刪除書籍時,請減少書籍的數量,但不要減少下一本書的ID。
我注意到,刪除一本書后,您將其余的書本條目一起移動(“壓縮”它們),因此數組始終是“密集的”。 因此,另一種解決方案是在書籍結構中添加“已刪除”標志。 現在,當刪除一本書時,您無需壓縮條目,但是當添加一本書時,代碼必須在數組中搜索空白位置。 書號也只是數組中的位置。 (順便說一句,如果您硬編碼大小(例如數組的大小),請執行一次。)
#define MAXSTR (30)
struct book
{
int bookid;
int valid; // 1 is valid, 0 is empty or deleted
char name[MAXSTR];
char author[MAXSTR];
float price;
};
#define MAXBOOKS (40)
struct book b[MAXBOOKS];
int findEmpty()
{
int i;
for (i=0; i < MAXBOOKS; i++) {
if (! b[i].valid) return i;
}
return -1; // no more space
}
void add(void)
{
int i = findEmpty();
char ch[MAXSTR];
if (i < 0) return; // no room for more books
clrscr();
printf("Enter books name:\n");
fgets(b[i].name, MAXSTR, stdin);
printf("Enter author's name\n");
fgets(b[i].author, MAXSTR, stdin);
printf("Enter price:\n");
fgets(ch, MAXSTR, stdin);
b[i].price=atoi(ch);
/* Assign the empty location found to this book */
b[i].bookid = i;
/* mark that it is valid */
b[i].valid = 1;
printf("Dear User,the book has succesfully been added.The book id is %d", b[i].bookid);
getch();
}
del()現在僅將書標記為無效。 del()的主要部分如下所示。
得到(CH); int idToDelete = atoi(ch); //找到它屬於哪個結構(i = 0; i
在sort()中使用選擇排序 ,而不要使用在那里的單遍例程(並非在所有情況下都有效)。 打印書籍也應跳過任何無效的書籍。
一些指針:
使用fgets而不是gets,它更安全,因為您可以指定max buf len
在add()中,沒有分配書號,因此-由於是全局的-它將保持為0
為什么需要書號? 您有40個數組,請使用數組索引作為id。
您的第一個問題似乎是您從未真正將book
結構的bookid
字段設置為任何內容。 它最終將在每個書本結構中具有一些任意值,如果del
能夠正常工作,這將使其很幸運。
您的問題在這里:
printf("Enter books name:\n");
gets(b[i].name);
printf("Enter author's name\n");
gets(b[i].author);
printf("Enter price:\n");
gets(ch);
b[i].price=atoi(ch);
printf("Dear User,the book has succesfully been added.The book id is %d",i);
count++;
看一下這段代碼,然后告訴我在哪里設置b[i].bookid
的值。 答案無處。 因此,嘗試將最后幾行更改為:
b[i].bookid = i;
printf("Dear User,the book has succesfully been added.The book id is %d", b[i].bookid);
count++;
現在,如果您在調用del
之后再調用add
,仍然會遇到問題,因為在該代碼所在的單迭代循環中, i
始終設置為count
。 因此,正如您所注意到的,如果count
經常發生變化,那么您將分配重復的ID。 一種解決方案是在add
函數的頂部定義一個靜態變量(在調用函數之間保留其值),該靜態變量指示下一個書本ID應該是什么,如下所示:
void add(void)
{
static int nextBookId = 0;
int i = count;
char ch[30];
/* Do not overrun the array */
if (count >= 40) return;
clrscr();
printf("Enter books name:\n");
gets(b[i].name);
printf("Enter author's name\n");
gets(b[i].author);
printf("Enter price:\n");
gets(ch);
b[i].price=atoi(ch);
/* Assign the next unique book ID to this book, then increment nextBookId,
which will retain its incremented value next time you call add() */
b[i].bookid = nextBookId++;
printf("Dear User,the book has succesfully been added.The book id is %d", b[i].bookid);
count++;
getch();
}
請注意,我在頂部用簡單的邊界檢查替換了循環。
這樣,您添加的每本書都會獲得自己的唯一標識符,該標識符不一定與其在數組中的位置或添加時存在的書的數量相對應。 此方法不會重復使用以前刪除的圖書的ID,但這可能是理想的行為。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.