acreil 发表于 2014-9-14 14:15:24

链表查询问题,懂得帮我看下。

本帖最后由 acreil 于 2014-9-16 20:44 编辑

写的一个链表,比较复杂。
有个检查序列是不是重复的函数,当链表有两条以上的记录的时候,在检查到重复,退出的时候,程序会崩溃。。。
附上代码图。






这个是查询函数



调用代码。


把网盘地址附上。。只有一个main.cpp文件,,应用台程序。。。麻烦大家看下。
http://pan.baidu.com/s/1bnvTgf1

musilintan 发表于 2014-9-14 15:15:26

代码多的话就把工程整个发过来,网盘或者附件什么的都可以。你发的这些代码看不出有什么逻辑错误。不调试很难找出错误。尤其是你那个退出代码,只给一部分,很难理解你是打算做什么。。。

acreil 发表于 2014-9-14 21:44:59

重新把文件附上了,大家帮忙看下。。。有不足的地方也请指出。

musilintan 发表于 2014-9-15 09:37:37

本帖最后由 musilintan 于 2014-9-15 09:40 编辑

book* insert(book* head)
{
      string num;
    string price;
    book *temp = head;
      if (head != NULL)
      {
                while (temp->next)
                {
                        temp = temp->next;
                }
      }
    book *temp_next = NULL;
    do
    {
      cout << "请输入书籍的编号:";
      cin >> num;
      while (check_int(num))
      {
            
            cout << "你输入的格式有错误,请重新输入."<<endl;
            cout << "请输入书籍的编号:";
            cin >> num;
      }
                while (find_num(head, num))
                {

                        cout << "已存在编号,请重新输入." << endl;
                        cout << "请输入书籍的编号:";
                        cin >> num;
                }
      if (num == "0")
      {
                        if (temp)
                        {
                              return head;
                        }
                        else if (temp->next==NULL)
                        {
                              return head;
                        }
                        else
                        {
                              temp_next->next = NULL;
                              return head;
                        }
      }
      cout << "请输入书籍的价格:";
      cin >> price;
      while (check_float(price))
      {
            cout << "你输入的格式有错误,请重新输入."<<endl;
            cout << "请输入书籍的价格:";
            cin >> price;
      }
      if (num == "0")
      {
                        if (temp == NULL)
                        {
                              return head;
                        }
                        else if (temp_next == NULL)
                        {
                              return head;
                        }
                        else
                        {
                              temp_next->next = NULL;
                              return head;
                        }
                }
      temp_next = new book;
      temp_next->num = atoi(num.c_str());
      temp_next->price = (float)atof(price.c_str());
                temp_next->next = NULL;                        //这里
                if (head == NULL)
                {
                        temp = temp_next;
                        head = temp;
                }
                else if (temp->next == NULL)
                {
                        temp->next = temp_next;
                }
                else
                {
                        temp = temp->next;
                        temp->next = temp_next;
                }
    } while (true);
}

你的思路没问题,引起错误的原因是再查询函数里面。而最终的病因是因为创建的新节点的next指针没有制NULL导致的。所以在查询的时候会出现无限查询,直到差出链表的范围,最终报错。
程序本身的整体思路很好,只是链表方面的思路比较乱,多看看别人的代码,提高空间很大。
创建节点时需要注意2点:
1.当前节点和上一个节点的联系有没有建立。
2.当前节点的next指针有没有为NULL。
上面的注意事项针对的是链表尾插法。
不过,要是养成下面这个习惯,就会在以后编程中,为你减少很多不必要麻烦。
这是你的代码:
class book
{
public:
    int num;
    float price;
    book *next;
};
改进后:
class book
{
public:
    int num;
    float price;
    book *next;
      
public:
      book()
      {
                num = -1;
                price = 0.0;
                next = NULL;
      }
};

加一个初始化进去,这样做以后就不用考虑next指针是否为NULL了。在创建链表的时候,会自动将next制空。结构体同样可以这样做。

elvo 发表于 2014-9-15 10:36:18

        if (num == "0")
                {
                        if (temp)
                        {
                                return head;
                        }
                        else if (temp->next == NULL)
                        {
                                return head;
                        }
                        else
.....
这段代码你想做什么?输入0则返回head么??


我看了一下你的程序,修改了一些,,如下:

//main.cpp
//ConsoleApplication
//
//Created by 廖庆飞 on 14/9/9.
//Copyright (c) 2014年 廖庆飞. All rights reserved.
//

#include<iostream>
#include<string>

using namespace std;

class book
{
public:
    int num;
    float price;
    book *next;
};

book* creat();
book* delete_node(book*);
int delete_all(book*);
void find(book*);
bool find_num(book*,string);
book* insert(book*);
book* sort(book*);
bool check_int(string);
bool check_float(string);
int showbook(book*);

int main(int argc, const char * argv[])
{
        string str;
        int i;
        book *head = NULL;
        while (true)
        {
                cout << "1.重建图书2.添加图书3.删除图书4.图书排序5.图书查找6.显示图书7.屏幕清除0.程序退出" << endl;
                cin >> str;
                while (check_int(str))
                {

                        cout << "你输入的格式有错误,请重新输入." << endl;;
                        cout << "请输入选项编号:";
                        cin >> str;
                }
               
                if (str == "0")
                {
                        delete_all(head);
                        return 0;
                }
               
                i = atoi(str.c_str());
               
                switch (i)
                {
                case 1:
                        if (head == NULL)
                        {
                                head = creat();
                        }
                        else
                        {
                                delete_all(head);
                                head = creat();
                        }
                        break;
                case 2:
                        head = insert(head);
                        break;
                case 3:
                        head = delete_node(head);
                        break;
                case 4:
                        head = sort(head);
                        break;
                case 5:
                        find(head);
                        break;
                case 6:
                        showbook(head);
                        break;
                case 7:
                        system("cls");
                        break;
                default:
                        cout << "对不起,没有这个选项." << endl;
                        break;
                }
        }
       
    return 0;
}
//--------------------create---------------------------------
book *creat()
{
    string num;
    string price;
    book *head = NULL;
        book *temp = NULL;
    book *tail = head;
    while(tail!=NULL && tail->next !=NULL) //找到链表的尾
        {
            tail = tail->next;
    }
   
    do
    {
      cout << "请输入书籍的编号:";
      cin >> num;
      while (check_int(num))
      {
            
                        cout << "你输入的格式有错误,请重新输入." << endl;;
            cout << "请输入书籍的编号:";
            cin >> num;                        //输入格式错误后重新输入
      }
      
                while (find_num(head,num))
                {

                        cout << "已存在编号,请重新输入." << endl;
                        cout << "请输入书籍的编号:";
                        cin >> num;
                }
               
                if (num == "0")
                {
                        if(head)
                        {
                                return head;
                        }
                        cout<<"没有创建新图书"<<endl;
                        return NULL;               
                }
      cout << "请输入书籍的价格:";
      cin >> price;
      while (check_float(price))
      {
                        cout << "你输入的格式有错误,请重新输入." << endl;
            cout << "请输入书籍的价格:";
            cin >> price;
      }
                if (price == "0")
                {
                        if(head)
                        {
                                return head;
                        }
                        cout<<"没有创建新图书"<<endl;
                        return NULL;               
                }
      temp=new book;
      temp->num = atoi(num.c_str());
      temp->price = (float)atof(price.c_str());
      temp->next = NULL;
      if (head == NULL)
      {
              head=temp;
              tail=head;
      }
                       
      else
      {
            tail->next=temp;
            tail=temp;
      }
    } while (true);
}

//---------------------------------------------check_int

//检测输入的字符是否为数字字符
//若是返回false,否则返回true
bool check_int(string str)
{
    for (unsigned i = 0; i < str.length();i++)
    {
                if (str > '9' || str < '0')
      {
            return true;
      }
    }
    return false;
}

///--------------------------------------------check_float
bool check_float(string str)
{
    int ax = 0;//用来控制小数点的个数
    for (unsigned i = 0; i < str.length(); i++)
    {
      if (str == '.')
      {
            ax += 1;
      }
      if (ax > 1)
      {
            return true;
      }
      if (str > '9' || str < '.' || str == '/')//由于0到.之间的ASSCII只有一个'/'所把'/'字符排除
      {
            return true;
      }
    }
    return false;
}

//-----------------------------------------------showbook
int showbook(book *head)
{
    if (head == NULL)
    {
      cout << "没有图书信息." << endl;
      return 0;
    }
    while (head)
    {
                cout << "编号:\t" << head->num << "\t" << "价格:\t" << head->price << endl;
      head = head->next;
    }
    return 0;
}
//-------------------------------------------delete_node
book *delete_node(book* head)
{
    if (head == NULL)
    {
      cout << "没有数据." << endl;
      return head;
    }
    string str;
    cout << "请输入查找的编号:";
    cin >> str;
    while (check_int(str))
    {
      
                cout << "你输入的格式有错误,请重新输入." << endl;
      cout << "请输入查找的编号:";
      cin >> str;
    }
    if (str == "0")
    {
      return head;
    }
    int num = atoi(str.c_str());
    book* temp = head;
    book*temp_two = NULL;
    if (head->num == num)
    {
      temp = head->next;
      delete head;
      head = temp;
      cout << "删除完成";
      return head;
    }
    else
    {
      while (head)
      {
            temp_two = temp->next;
            if (temp_two->num == num)
            {
                if (temp_two->next == NULL)
                {
                  delete temp_two;
                  temp->next = NULL;
                  return head;
                }
                temp->next = temp_two->next;
                delete temp_two;
                cout << "删除完成." << endl;
                return head;
            }
            else
            {
                temp = temp_two->next;
            }
      }
    }
    cout << "没有查找到输入的相关数据." << endl;
    return head;
}
//======---------------------------------------delete_all 0
int delete_all(book* head)
{
    if (head == NULL)
    {
      cout << "没有数据." << endl;
      return 0;
    }
    else
    {
      book *temp = NULL;
      while (head)
      {
            temp = head->next;
            delete head;
            head = temp;
      }
    }
    if(head == NULL)
            cout << "删除成功." << endl;
           else
                   cout<<"删除失败"<<endl;
    return 0;
}
///------------------------------------------------find
void find(book* head)
{
    if (head == NULL)
    {
      cout << "没有数据." << endl;
      return;
    }
    string str;
    cout << "请输入查找的编号:";
    cin >> str;
    while (check_int(str))
    {
      
                cout << "你输入的格式有错误,请重新输入." << endl;
      cout << "请输入查找的编号:";
      cin >> str;
    }
    if (str == "0")
    {
      return;
    }
    int num = atoi(str.c_str());
    while (head)
    {
      if (head->num == num)
      {
            cout << "图书编号:" << head->num << endl;
            cout << "图书价格:" << head->price << endl;
            return;
      }
      else
      {
            head = head->next;
      }
    }
    cout << "没有查找到相关数据." << endl;
    return;
}

//=--------------------------------------------find_num
//寻找链表中是否存在输入序列
//若是返回true,否则false
bool find_num(book* head,string str)
{
        if (head == NULL)
        {
                return false;
        }
       
        int num=atoi(str.c_str());
        book *temp = head;
        while (temp)
        {
                if (temp->num == num)
                {
                        return true;
                }
                temp = temp->next;
        }
        return false;
}
//----------------------------------------insert这里和create内部实现基本一样,是否考虑封装一下
book* insert(book* head)
{
        string num;
    string price;
    book *temp=NULL;
    book *tail = head;
        if (head != NULL)
        {
                while (tail->next)
                {
                        tail = tail->next;//寻找链表尾
                }
        }
       
   do
    {
      cout << "请输入书籍的编号:";
      cin >> num;
      while (check_int(num))
      {
            
                        cout << "你输入的格式有错误,请重新输入." << endl;;
            cout << "请输入书籍的编号:";
            cin >> num;                        //输入格式错误后重新输入
      }
      
                while (find_num(head,num))
                {

                        cout << "已存在编号,请重新输入." << endl;
                        cout << "请输入书籍的编号:";
                        cin >> num;
                }
               
                if (num == "0")
                {
                        if(head)
                        {
                                return head;
                        }
                        cout<<"没有创建新图书"<<endl;
                        return NULL;               
                }
      cout << "请输入书籍的价格:";
      cin >> price;
      while (check_float(price))
      {
                        cout << "你输入的格式有错误,请重新输入." << endl;
            cout << "请输入书籍的价格:";
            cin >> price;
      }
                if (price == "0")
                {
                        if(head)
                        {
                                return head;
                        }
                        cout<<"没有创建新图书"<<endl;
                        return NULL;               
                }
      temp=new book;
      temp->num = atoi(num.c_str());
      temp->price = (float)atof(price.c_str());
      temp->next = NULL;
      if (head == NULL)
      {
              head=temp;
              tail=head;
      }
                       
      else
      {
            tail->next=temp;
            tail=temp;
      }
    } while (true);
}

///----------------------------------------------------------sort4
book* sort(book* head)
{
    if (head == NULL)
    {
                cout << "没有数据" << endl;
      return NULL;
    }
        /*
    book *p=head, *p1=NULL, *p2=NULL, *p3=NULL,*temp;
        p1 = p->next;
        p2 = p1->next;
        if (p > p1)   //这个地址有什么可排列的。。。
        {
                temp = p;
                p = p1;
                p = temp;
                head = p;
                if (p2 == NULL)
                {
                        return head;
                }
                p = p->next;
                p1 = p1->next;
                p2 = p2->next;
        }
        do
        {
                if (p1 > p2)
                {
                        p3 = p2->next;
                        temp = p1;
                        p1 = p2;
                        p2 = temp;
                        p->next = p1;
                        p1->next = p2;
                        p2->next = p3;
                }
                p = p->next;
                p1 = p1->next;
                p2 = p2->next;
        } while (p3);
        */
        //实现一个按序号排列冒泡
       
        book * tempf = head; //链表前面节点
        book * tempb = head; //链表 后面节点
        int temp;
        while(tempb=tempf){
                while(tempb){
                        if(tempf->num > tempb->num)
                        {
                                temp =tempb->num;
                                tempb->num = tempf->num;
                                tempf->num = temp;
                        }
                        tempb=tempb->next;    //指向下一个节点
                }
                tempf=tempf->next;
        }       
        cout<<"结束排列!"<<endl;
    return head;
}

acreil 发表于 2014-9-16 20:28:39

musilintan 发表于 2014-9-15 09:37
你的思路没问题,引起错误的原因是再查询函数里面。而最终的病因是因为创建的新节点的next指针没有制NU ...

嗯,看明白了,是在插入方法里面忘记对next赋NULL,导致在下一次的输入,在检查重复,调用了未知指针。

acreil 发表于 2014-9-16 20:42:55

elvo 发表于 2014-9-15 10:36
if (num == "0")
                {
                        if (temp)


刚开始写链表,有些方法确实用得比较笨。。
页: [1]
查看完整版本: 链表查询问题,懂得帮我看下。