繁体   English   中英

在执行操作时,书生会改变吗?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM