我制作了一个程序,它是一个通过软件操作的小型库。当我添加两本书然后删除第一本书时,由于count--
函数中的del()
,第二本书与第一本书的bookid相同。我不能依赖打印计数作为bookid。有更好的选择吗?
#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();
}
答案 0 :(得分:1)
一种方法是拥有两个全局计数器:一个具有存储的书籍数量,另一个具有下一个(唯一的)书籍ID,正如Tyler McHenry指出的那样。删除书籍时,减少书籍数量,但不会减少下一本书籍。
我注意到当一本书被删除时,你将其余的书条目移到一起(“压缩”它们),这样你的数组总是“密集”。因此,另一种解决方案是向书籍结构添加“已删除”标志。现在,在删除书籍时不会压缩条目,但是添加书籍时,代码必须在数组中搜索空位。此外,bookid只是阵列中的位置。 (顺便说一句,如果您对大小进行硬编码,比如数组的大小,请执行一次。)
#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;我
在sort()中使用selection sort而不是在那里使用一遍例程(在所有情况下都不起作用)。印刷书籍也应该跳过任何无效的书籍。
答案 1 :(得分:0)
一些指示:
使用fgets代替获取,更安全 因为你可以指定max buf len
在add()中没有分配书籍ID, 所以它将 - 由于全球化 - 保持0
为什么你需要书籍ID?您 有一个40的数组,使用该数组 index as id。
答案 2 :(得分:0)
您的第一个问题似乎是您实际上从未将bookid
结构的book
字段设置为任何内容。它最终会在每个book结构中都有一些任意值,如果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++;
现在,如果您在调用add
之后调用del
,这仍然存在问题,因为在该代码所在的单迭代循环中,i
始终设置为{ {1}}。因此,正如您所注意到的,如果count
经常发生变化,那么您将分配重复的ID。一种解决方案是在count
函数的顶部定义一个静态变量(在函数调用之间保留其值),指示下一个book id应该是什么,如下所示:
add
请注意,我用顶部的简单边界检查替换了你的循环。
这样,您添加的每本书都会获得自己的唯一标识符,该标识符不一定与其在数组中的位置或添加时存在的书籍数量相对应。此方法不会重复使用以前删除的书籍的ID,但这可能是一种理想的行为。