【问题标题】:Doubly Linked List of Structures - Overwriting结构的双向链表 - 覆盖
【发布时间】:2016-03-01 17:44:14
【问题描述】:

所以我试图用 C++ 编写一个在双向链表上执行基本操作的程序。我遇到的主要问题是,每次我向列表中添加一个新元素时,我为新元素输入的 id 字段都会覆盖所有其他元素的 id 字段。 id 字段是唯一这样做的字段,这让我非常困惑。我相信我的错误可能在于我使用指针的某个地方,因为这是我在 C++ 中使用它们来管理列表的第一个程序(Ada 中的指针对我来说似乎要简单得多)。我已经通过 GDB 多次运行我的程序,但似乎仍然无法确定导致问题的原因。这让我相信这可能是我的逻辑错误。

这是我的主要内容:

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

using namespace std;



int 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 << endl;
         }
         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

这是我的文件 list.h:

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


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

最后是我的文件 list.cpp 中的 AddItem 函数:

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

using namespace std; 

rec * first = NULL;
rec * last = NULL;




int AddItem( rec r )
//Return: 1 if a success, 0 if failed.
//No duplicate id's, sort by lastname
{
   rec * ptr = NULL;
   rec * current;

   rec * myStruct = new rec;
   myStruct -> id = r.id;
   strcpy(myStruct -> firstname, r.firstname);
   strcpy(myStruct -> lastname, r.lastname);

   ptr = first;

   //Check for duplicate id's, currently commented out due to id's being overwritten
   //while (ptr)
   //{
   //   if (ptr -> id == myStruct -> id)
   //   {
   //       return 0;
   //   }
   //   ptr = ptr -> next;
   //}

   //ptr = first;

   if (first == NULL) //Empty
   {
      first = myStruct;  //Inserts node into empty list
      last = myStruct;
      myStruct -> prev = NULL;
      myStruct -> next = NULL;
      return 1;
   }
   else if (myStruct -> lastname > last -> lastname) //Add to end of list
   {
      last -> next = myStruct;
      myStruct -> prev = last;
      last = myStruct;
      return 1;
   }
   else if (myStruct -> lastname && myStruct -> lastname < first -> lastname) //Add to beginning of list
   {
      ptr = first;
      first = myStruct;
      myStruct -> next = ptr;
      ptr -> prev = myStruct;
      return 1;
   }
   else
   {
      current = first;
      while (current)
      {
         if (myStruct -> lastname > current -> lastname && myStruct -> lastname <= current -> next -> lastname)
         {
            ptr = current -> next;
            current -> next = myStruct;
            myStruct -> prev = current;
            myStruct -> next = ptr;
            ptr -> prev = myStruct;
            return 1;
         }
         else
         {
            current = current -> next;
         }
   }
   return 0;
}

我确信这段代码中还有其他错误和一些草率的编程,但我计划在解决这个覆盖问题后修复这些错误并使程序更整洁/更高效,因为它也阻碍了我测试我的程序的其他部分。在此先感谢,并为冗长的帖子感到抱歉。

Update1:​​意识到我需要换行后

myStruct -> id = r.id;

到一个字符串拷贝,如:

strcpy(myStruct -> id, r.id);

我现在收到分段错误。我会想象我的指针有些东西搞砸了。我回去工作,感谢到目前为止的所有帮助!

Update2:经过更多的编辑和更多的错误,我的程序可以运行了!我现在正在清理和优化程序。感谢大家的宝贵建议!

【问题讨论】:

  • 它是 C++,所以使用 OOP。用 C++ 编写 C 风格的代码很糟糕。
  • 我对 OOP 不熟悉,但我在一个从 C 过渡到 C++ 的课程中​​,我们目前正在使用两者的组合。到目前为止,我们从 C++ 中介绍的只是对象,但那是在给出这个任务之后,所以我们被要求不要使用它们。
  • "但我正在从 C 过渡到 C++ 的课程中​​" -- 老实说,我看不到任何过渡。你写的基本上还是C
  • 坏主意。 C 和 C++ 是不同的语言。一个基本的列表将是 OOP 的一个很好的介绍。
  • 如果你真的要从 C 过渡到 C++,你至少会开始使用 std::string,而不是 char*strcpy 等。

标签: c++ pointers doubly-linked-list


【解决方案1】:

所有 id 对象都具有相同的值 - idbuffer 的第一个字符的地址。

主要

cin >> idbuffer;
r.id = idbuffer;
       ^^^^^^^^^

然后进一步AddItem

int AddItem( rec r )
//Return: 1 if a success, 0 if failed.
//No duplicate id's, sort by lastname
{
   rec * ptr = NULL;
   rec * current;

   rec * myStruct = new rec;
   myStruct -> id = r.id;
                    ^^^^^
   //...

您应该动态分配将由id 指向的内存,并在那里复制带有 id 的实际字符串。或者您应该将数据成员id 声明为字符数组。

例如main

cin >> idbuffer;
r.id = new char[std::strlen( idbuffer ) + 1];
std::strcpy( r.id, idbuffer ); 

AddItem

rec * myStruct = new rec( r );

更好的方法是使用std::string 类型的对象。

【讨论】:

  • 那么错误主要出在哪里?我们的教授向我们提供了主文件,据我所知,我是班上唯一遇到此问题的人。
  • @Lareaper 您至少应该动态分配内存并将代表 id 的字符串复制到该内存中。在这种情况下,每个 id 都有自己的值 - 分配内存的地址。
  • 所以我可以通过为每个新 ID 动态分配新内存来防止这种情况,对吗?编辑:我刚刚意识到我一直在将 id 视为一个整数。哇,我觉得自己很愚蠢。是时候对我的代码进行一些更改了!
  • @Lareaper "据我所知,我是班上唯一遇到此问题的人。" 这是因为写入未初始化的指针是未定义的行为.该程序可能“工作”、崩溃、不崩溃但给出错误结果、工作 1000 次但尝试 1001 次失败、在您所有朋友的计算机上工作但在您的计算机上失败、仅在您的计算机上工作而对其他所有人都失败,等等。跨度>
  • @PaulMcKenzie 我应该将指针初始化为 NULL,对吗?
猜你喜欢
  • 2019-05-02
  • 2012-05-20
  • 1970-01-01
  • 2015-12-27
  • 2013-12-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-05
相关资源
最近更新 更多