Изменится ли букид при выполнении операций? - PullRequest
2 голосов
/ 09 июля 2010

Я создал программу, которая представляет собой небольшую библиотеку, управляемую с помощью программного обеспечения.Когда я добавляю две книги, а затем удаляю первую книгу, вторая книга получает тот же 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();
}

Ответы [ 3 ]

1 голос
/ 29 июля 2010

Один способ состоит в том, чтобы иметь два глобальных счетчика: один хранит количество сохраненных книг, другой дает следующий (уникальный) идентификатор книги, как указывает Тайлер МакГенри.Когда вы удаляете книгу, уменьшайте количество книг, но никогда не уменьшайте идентификатор следующей книги.

Я замечаю, что когда книга удаляется, вы перемещаете остальные записи книги вместе («сжимаете» их)так что ваш массив всегда "плотный".Таким образом, другое решение заключается в добавлении «удаленного» флага в структуру книги.Теперь вы не сжимаете записи, когда книга удаляется, но когда книга добавляется, код должен искать пустое место в массиве.Также 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 () выглядит следующим образом.

gets (ch);int idToDelete = atoi (ch);// найти, к какой структуре он принадлежит (i = 0; i

Использовать selection sort в sort () вместо однопроходной процедуры (которая работает не во всех случаях), котораяПечать книг должна пропустить любую недопустимую книгу.

0 голосов
/ 20 июля 2010

Ваша первая проблема, кажется, в том, что вы на самом деле никогда не устанавливаете в поле bookid структуры 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 всегда имеет значение count. Итак, как вы заметили, если count когда-либо изменится, что будет часто, вы назначите дубликаты ID. Одним из решений является определение в верхней части функции add статической переменной (которая сохраняет свое значение между вызовами функции), указывающей, каким должен быть следующий идентификатор книги, например:

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

Обратите внимание, что я заменил ваш цикл простой проверкой границ сверху.

Таким образом, каждая добавляемая вами книга получает свой собственный уникальный идентификатор, который не обязательно соответствует ее положению в массиве или количеству книг, которые существовали на момент добавления. Этот метод не будет повторно использовать идентификаторы ранее удаленных книг, но это, вероятно, желательное поведение.

0 голосов
/ 09 июля 2010

некоторые указатели:

использовать fgets вместо get, это безопаснее, поскольку вы можете указать max buf len
в add (), для которого не назначен идентификатор книги, поэтому он будет - из-заБудучи глобальным - оставайся 0
зачем тебе идентификатор книги?у вас есть массив из 40, используйте индекс массива как идентификатор.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...