2013-03-07 5 views
0

У меня возникли проблемы с синтаксисом с помощью программы с двойным соединением, которую я пишу для образовательных целей. Я создал структуру в моем файле заголовка, и моя основная программа, похоже, в порядке, но реализация моих функций в файле .cpp дает мне огромные трудности. У меня возникли проблемы с рассмотрением трех случаев включения записи в список. В частности, распределение памяти, инициализация заголовка и хвоста списка, а также порядок инструкций меня смущает, поскольку передается копия записи, которая будет добавлена ​​в мой список.Внедрение с двойным связыванием

Мой заголовок файла выглядит следующим образом:

struct rec 
{ 
    char * id; 
    char firstname[15]; 
    char lastname[15]; 
    struct rec* prev; 
    struct rec* next; 
}; 


int AddItem (rec r); 
int DeleteItem (char* delid); 
void PrintList (int order); 

Мой .cpp файл, где трудность заключается, заключается в следующем:

#include <iostream> 
#include "list.h" 
#include <string.h> 
using namespace std; 

// These pointers refer to the head and tail of the list. 
rec* first = NULL; 
rec* last = NULL; 

int AddItem(Rec r) 
{ 

    rec* newRecEntry; 
    rec* current = NULL; 
    rec* previous = NULL; 

    // Check for duplicate id 
    current = first; 
    while (current) 
    { 
    if(strcmp(current -> id, r.id) == 0) 
     { 
     return 0; 
     } 
    else 
     // Create a new node 
     { 
     newRecEntry = new Rec; 
     newRecEntry->id = new char[strlen(r.id)+1]; 
     strcpy(newRecEntry->id, r.id); 
     strcpy(newRecEntry->firstname,r.firstname); 
     strcpy(newRecEntry->lastname,r.lastname); 
     newRecEntry->next = NULL; 
     newRecEntry->prev = NULL; 
     } 
     // Find the appropriate position for the node and insert accordingly 
     // Check to see if the list is empty 
     if (first == NULL) 
     { 
     first = newRecEntry; 
     last = newRecEntry; 
     } 
     else if (r.lastname>last.lastname) 
     { 




     else 
     { 

    return 0; 
} 

/*int DeleteItem(char* ID) 

Я должен иметь возможность вставить в начало, середину и конец списка. Удалите элемент из списка на основе идентификатора и распечатайте список в порядке возрастания или убывания на основе ввода пользователем, но сначала я просто хотел бы обработать добавление элементов в указанный список. Мои определения функции заключаются в следующем, а также содержит некоторые ошибки

lists.cpp

#include <iostream> 
#include "list.h" 
#include <string.h> 
using namespace std; 

// These pointers refer to the head and tail of the list. 
    rec* first = NULL; 
    rec* last = NULL; 

int AddItem(Rec r) 
{ 

    rec* newRecEntry; 
    rec* current = NULL; 
    rec* previous = NULL; 

    // Check for duplicate id 
    current = first; 
    while (current) 
    { 
    if(strcmp(current -> id, r.id) == 0) 
     { 
     return 0; 
     } 
    else 
    // Create a new node 
     { 
     newRecEntry = new Rec; 
     newRecEntry->id = new char[strlen(r.id)+1]; 
     strcpy(newRecEntry->id, r.id); 
     strcpy(newRecEntry->firstname,r.firstname); 
     strcpy(newRecEntry->lastname,r.lastname); 
     newRecEntry->next = NULL; 
     newRecEntry->prev = NULL; 
     } 
     // Find the appropriate position for the node and insert accordingly 
     // Check to see if the list is empty 
     if (first == NULL) 
     { 
     first = newRecEntry; 
     last = newRecEntry; 
     } 
     else if (r.lastname>last.lastname) 
     { 




     else 
     { 

    return 0; 
} 

/*int DeleteItem(char* ID) 
{ 
    rec 
} 
*/ 



/*void printList(int order) 
{ 
loop 
{ 
    cout << ptr -> Id << " "; 
    cout << ptr -> firstname << " "; 
    cout << ptr -> lastname << " "; 
    cout << ptr -> prev << " "; // address of previous 
    cout << ptr << " "; // address of item 
    cout << ptr -> next << " "; // address of next item 
} 

} 

Main выглядит следующим образом:

#include <iostream> 
#include "list.h" 
#include <string.h> // <string> 

using namespace std; 

void main (void) 
{ 
    int choice, printorder; 
    char idbuffer[100]; 
    rec r; 


do 
{ 
    cout << "Enter your choice 1 Add, 2 Delete, 3 Print, 0 quit "<<endl; 
    cin >> choice; 

    switch (choice) 
    { 
     case 1: //AddItem 
     cout << "\nEnter ID "; 
     cin >> idbuffer; 

     r.id = idbuffer; 
     cout << "\nFirst Name "; 
     cin >> r.firstname; 
     cout << "\nLast Name "; 
     cin >> r.lastname; 
     if (AddItem (r)) 
     { 
      cout << "\nSuccess!\n"; 
     } 
     else 
     { 
      cout << "\nItem failed to be added\n"; 
     } 

     break; 
     case 2: //Delete 
     cout << "\nEnter id :"; 
     cin >> idbuffer; 
     if (DeleteItem (idbuffer)) 
     { 
      cout << "\nDelete OK\n"; 
     } 
     else 
     { 
      cout << "\nDelete Failed for " << idbuffer; 
     } 
     break; 
     case 3: // Print 
     cout << "Enter order 0 - Ascending, 1 - Descending\n"; 
     cin >> printorder; 
     PrintList (printorder); 
     break; 
     case 0: // quit 
     break; 


     default: // bad choice 
     break; 
    } // end switch 

} 
while (choice != 0);// end do while 
} // end main 
+0

Y U использовать 'strcpy'? :( –

+2

Это код C с некоторым 'cout', а не C++. Если вы хотите использовать C++, вы должны использовать' std :: string' вместо 'char []'. – us2012

+1

@ us2012 Мне нужно использовать микс кода для образовательных целей.Я знаю, что это C и потенциально сложнее, но у меня нет другого выбора. –

ответ

0

Это может показаться не нравится, но даже эта функция

int AddItem(Record entry) 
{ 
    Record* newRecordPointer; 
    newRecordPointer=new Record; 
    strcpy(newRecordPointer->firstName,entry.firstName); 
    strcpy(newRecordPointer->lastName,entry.lastName); 
    newRecordPointer->ID=new char[strlen(entry.ID)+1]; 
    strcpy(newRecordPointer->ID, entry.ID); 
    return 0; 
} 

пытается сделать слишком много вещей.

Напишет описание псевдокода добавления элемента в список:

  1. создатьнового узла
  2. заселить в нового узла с значений, предусмотренных
  3. прилагаетсянового узла в списке

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

Это также полезно, чтобы написать ваши ожидания ясно:

  1. перед тем AddItem называется:
    • он нужен список, чтобы работать на
    • мы не имеем класс список контейнеров, просто записи, поэтому мы должны передать Record
    • скажем, мы хотим добавить наш новый товар послеRecord прошел в
  2. после AddItem называется:
    • независимо Record мы прошли в, его Next должен указывать на новый узел
    • новый узла Previous должен указывать на узел передается в
    • и т.д. и т.п.(Это стандартная двусвязные вставки списка поведения)
  3. записку позже: мы не описали, как мы храним пустой список
    • если это циклический список, пустой список будет Record чьи Next и Previous члены указывают на себе
    • , если это линейная, то они могут быть оба NULL вместо
    • это может быть просто указатель NULL, а затем добавить первый узел в пустой список нужно больше усилий

Так, скажем, минимальную функцию, которая могла бы работать на:

void AddItem(Record *insert_after, Record value) 
{ 
    Record *new_node = CreateRecord(); 
    CopyRecordValues(new_node, &value); 
    AttachAfter(insert_after, new_node); 
} 

Обратите внимание, что если мы сочиняли реальный C++ первые две строки могли бы просто использовать конструктор копирования Record *new_node = new Record(value), но это займет больше изменений, чем для достижения идиоматического кода на C++, с которого мы начали.


Теперь, учитывая, что вы можете:

  • выполнять эти три функции? (CreateRecord и CopyRecordValues уже обработаны в вашем текущем коде)
  • пишите эквивалентный псевдокод для других операций и переведите его самостоятельно?
+0

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

+0

Итак, у вас есть глобальный первый и последний. Таким образом, вы можете игнорировать ** list ** noun (у вас уже есть) и добавить вместо этого _check для duplicate_ verb. – Useless

0

Попробуйте изменить это:

int AddItem(Record entry); 

К этому:

Record* AddItem(Record entry, Record *insertion_point = NULL); 

Если insertion_point является NULL, то можно предположить, что Record начало нового списка.

Теперь у вас достаточно информации, чтобы установить указатели Next и Previous и вернуть вновь созданный узел.

+0

С тех пор я сделал это изменение. Хотя я пытаюсь включить все три случая в процедуру AddItem. Могу ли я использовать это, чтобы охватить другие случаи? –

0

Прежде всего, вы должны определить первый и конечный элементы.

Возможность является

  • Элемент с Previous назначен NULL является первым.
  • Элемент с Next назначен на NULL.

Для простоты я удалить некоторые поля Record, это не самое лучшее, будьте осторожны, вы должны сделать много обработки ошибок и заботиться исключений:

struct Record 
{ 
    int id; 
    Record* Next; 
    Record* Previous; 
}; 

Record *CreateList(int id) 
{ 
    Record *rec = new Record; 
    rec->id = id; 
    rec->Next = NULL; 
    rec->Previous = NULL; 
    return rec; 
} 

void AddItemAfter(Record *item, int id) 
{ 
    if (!item) 
     return; 

    Record* newRecordPointer = new Record; 
    newRecordPointer->id = id; 
    newRecordPointer->Next = NULL; 
    newRecordPointer->Previous = NULL; 

    newRecordPointer->Next = item->Next; 
    item->Next = newRecordPointer; 
    newRecordPointer->Previous = item; 
} 

void ShowList(Record *list) 
{ 
    Record *ptr = list; 
    while (ptr) 
    { 
     cout << ptr->id << endl; 
     ptr = ptr->Next; 
    } 
} 

int main() 
{ 
    Record *list = CreateList(1); 

    AddItemAfter(list, 2); 
    AddItemAfter(list, 3); 

    ShowList(list); 
} 
+0

Моя основная программа запрашивает у пользователя, какую операцию выполнить, и если пользователь вводит 1, пользователь будет передавать информацию, которая будет передана процедуре добавления. Пользователь поставляет идентификатор, имя и фамилию. –