简体   繁体   English

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

[英]While performing operations will the bookid's get changed?

I have made a program which is a small library operated via software. 我做了一个程序,它是一个通过软件操作的小型图书馆。 When I add two books and then delete the first book the second book gets the same bookid as the first book because of count-- in the del() function. 当我添加了两本书,然后删除第一本书的第二本书得到相同的BOOKID的,因为第一本书count--del()函数。 I cannot rely on printing the count as the bookid. 我不能依靠将计数打印为书本。 Is there a better option? 有更好的选择吗?

#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();
}

One way is to have two global counters: one has the number of books stored, the other gives the next (unique) book id, as Tyler McHenry points out. 正如泰勒·麦克亨利(Tyler McHenry)所指出的,一种方式是拥有两个全局计数器:一种具有存储的书籍数量,另一种提供下一个(唯一的)书籍ID。 When you delete a book, decrement the number of books, but never decrement the next book id. 删除书籍时,请减少书籍的数量,但不要减少下一本书的ID。

I notice that when a book is deleted, you move the rest of the book entries together ("compress" them) so your array is always "dense". 我注意到,删除一本书后,您将其余的书本条目一起移动(“压缩”它们),因此数组始终是“密集的”。 So another solution is to add a "deleted" flag to the book structure. 因此,另一种解决方案是在书籍结构中添加“已删除”标志。 Now you don't compress the entries when a book is deleted, but when a book is added, the code must search for an empty place in the array. 现在,当删除一本书时,您无需压缩条目,但是当添加一本书时,代码必须在数组中搜索空白位置。 Also the bookid is just the position in the array. 书号也只是数组中的位置。 (By the way, if you hard-code sizes, like the size of an array, do it once.) (顺便说一句,如果您硬编码大小(例如数组的大小),请执行一次。)

#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() now just marks the book as invalid. del()现在仅将书标记为无效。 The main part of del() looks like this. del()的主要部分如下所示。

gets(ch); 得到(CH); int idToDelete = atoi(ch); int idToDelete = atoi(ch); // find which structure it belongs to for(i=0;i //找到它属于哪个结构(i = 0; i

Use a selection sort in sort() instead of the one-pass routine (which doesn't work in all cases) which is there. 在sort()中使用选择排序 ,而不要使用在那里的单遍例程(并非在所有情况下都有效)。 Printing books should skip any book that is not valid, too. 打印书籍也应跳过任何无效的书籍。

some pointers: 一些指针:

use fgets instead of gets, its safer because you can specify max buf len 使用fgets而不是gets,它更安全,因为您可以指定max buf len
in add() there is no book id assigned, so it will - due to being global - remain 0 在add()中,没有分配书号,因此-由于是全局的-它将保持为0
why do u need book id? 为什么需要书号? you have an array of 40, use the array index as id. 您有40个数组,请使用数组索引作为id。

Your first problem seems to be that you are never actually setting the bookid field of the book structure to anything. 您的第一个问题似乎是您从未真正将book结构的bookid字段设置为任何内容。 It will end up having some arbitrary value in each book struct, which will make it pure luck if del ever works correctly. 它最终将在每个书本结构中具有一些任意值,如果del能够正常工作,这将使其很幸运。

Your problem is in here: 您的问题在这里:

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++;

Take a look at this code, and show me where you set the value of b[i].bookid . 看一下这段代码,然后告诉我在哪里设置b[i].bookid的值。 The answer is nowhere. 答案无处。 So try changing the last few lines to: 因此,尝试将最后几行更改为:

b[i].bookid = i;
printf("Dear User,the book has succesfully been added.The book id is %d", b[i].bookid);
count++;

Now, this still has a problem if you ever call add after calling del , because in the single-iteration loop that that code is in, i is always set to count . 现在,如果您在调用del之后再调用add ,仍然会遇到问题,因为在该代码所在的单迭代循环中, i始终设置为count So, as you noticed, if count ever changes, which it will frequently, you will assign duplicate IDs. 因此,正如您所注意到的,如果count经常发生变化,那么您将分配重复的ID。 One solution is to define, at the top of the add function, a static variable (which retains its value between calls to the function) indicating what the next book id should be, like so: 一种解决方案是在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();
}

Note that I replaced your loop with a simple bounds check at the top. 请注意,我在顶部用简单的边界检查替换了循环。

This way, every book you add gets its own, unique identifier that does not necessarily correspond to its position in the array or the number of books that existed at the time it was added. 这样,您添加的每本书都会获得自己的唯一标识符,该标识符不一定与其在数组中的位置或添加时存在的书的数量相对应。 This method will not re-use IDs of previously deleted books, but that is probably a desirable behavior. 此方法不会重复使用以前删除的图书的ID,但这可能是理想的行为。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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