【问题标题】:C++ Linked List Program reading stringsC++链表程序读取字符串
【发布时间】:2014-07-15 19:31:01
【问题描述】:

嗨,现在我正在尝试重写我的代码,以便它可以将链表的每个项目作为读取名字和姓氏的字符串接收。目前我让程序工作,但是当我输入名字和姓氏时,程序将它们视为单独的元素而不是一个单一的实体。所以基本上我希望“Jack Frost”的链表长度为 1 而不是 2,然后我尝试提示用户输入名字和姓氏,以便将它们从列表中删除。希望有人可以提供帮助。我正在发布我制作的测试程序和头文件。公平警告头文件有点长。测试程序需要用名字和姓氏逐行打印完整的列表。

更新:我确实提示用户在同一行中输入名字和姓氏。由于某种原因,它们被视为两个独立的元素,我需要将它们放在一起考虑。

#ifndef H_LinkedListType
#define H_LinkedListType


#include <iostream>

                            //Definition of the node

template <typename Type>
struct nodeType
{
    Type info;
    nodeType<Type> *link;
};

template<typename Type>
class linkedListType
{
  public:
    const linkedListType<Type>& operator=(const linkedListType<Type>&); 
                                                               //Overload the assignment operator
    void initializeList(); 
                                   //Initialize the list to an empty state
                                   //Post: first = NULL, last = NULL
    bool isEmptyList();
                                   //Function returns true if the list is empty;
                                   //otherwise, it returns false
    bool isFullList();
                                   //Function returns true if the list is full;
                                   //otherwise, it returns false
    void print();
                                   //Output the data contained in each node
                                   //Pre: List must exist
                                   //Post: None
    int length();
                                   //Return the number of elements in the list
    void destroyList();
                                   //Delete all nodes from the list
                                   //Post: first = NULL, last = NULL
    void retrieveFirst(Type& firstElement); 
                                   //Return the info contained in the first node of the list
                                   //Post: firstElement = first element of the list
    void search(const Type& searchItem);
                                   //Outputs "Item is found in the list" if searchItem is in 
                                   //the list; otherwise, outputs "Item is not in the list"
    void insertFirst(const Type& newItem);
                                   //newItem is inserted in the list
                                   //Post: first points to the new list and the 
                                   //       newItem inserted at the beginning of the list
    void insertLast(const Type& newItem);
                                   //newItem is inserted in the list
                                   //Post: first points to the new list and the 
                                   //     newItem is inserted at the end of the list
                                   //     last points to the last node in the list
    void deleteNode(const Type& deleteItem);
                                   //if found, the node containing deleteItem is deleted 
                                   //from the list
                                   //Post: first points to the first node and
                                   //  last points to the last node of the updated list
    linkedListType(); 
                                   //default constructor
                                   //Initializes the list to an empty state
                                   //Post: first = NULL, last = NULL 
    linkedListType(const linkedListType<Type>& otherList); 
                                   //copy constructor
    ~linkedListType();   
                                   //destructor
                                   //Deletes all nodes from the list
                                   //Post: list object is destroyed 

  protected:
    nodeType<Type> *first;                             //pointer to the first node of the list
    nodeType<Type> *last;                              //pointer to the last node of the list 
};

template<typename Type>
void linkedListType<Type>::initializeList()
{
    destroyList();                             //if the list has any nodes, delete them
}

template<typename Type>
void linkedListType<Type>::print()
{
    nodeType<Type> *current;                             //pointer to traverse the list

    current = first;                               //set current so that it points to 
                                                   //the first node
    while(current != NULL)                             //while more data to print
    {
       cout<<current->info<<" ";
       current = current->link;
    }
}                            //end print

template<typename Type>
int linkedListType<Type>::length()
{
    int count = 0;
    nodeType<Type> *current;                             //pointer to traverse the list

    current = first;

    while (current!= NULL)
      {
       count++;
       current = current->link;
    }

    return count;
}                              // end length

template<typename Type>
void linkedListType<Type>::search(const Type& item)
{
    nodeType<Type> *current;                             //pointer to traverse the list
    bool found;

    if(first == NULL)                              //list is empty
        cout<<"Cannot search an empty list. "<<endl;
    else
    {
        current = first;                              //set current pointing to the first 
                                                      //node in the list

        found = false;                                //set found to false

        while(!found && current != NULL)                             //search the list
            if(current->info == item)                                  //item is found
                found = true;
            else
                current = current->link;                             //make current point to 
                                                                     //the next node

        if(found)
            cout<<"Item is found in the list."<<endl;
        else
            cout<<"Item is not in the list."<<endl;
   }                             //end else
}                            //end search

template<typename Type>
void linkedListType<Type>::insertLast(const Type& newItem)
{
    nodeType<Type> *newNode;                             //pointer to create the new node

    newNode = new nodeType<Type>;                             //create the new node
    newNode->info = newItem;                                  //store the new item in the node
    newNode->link = NULL;                                     //set the link field of new node
                                                              //to NULL

    if(first == NULL)                              //if the list is empty, newNode is 
                                                //both the first and last node
    {
        first = newNode;
        last = newNode;
    }
    else                                 //if the list is not empty, insert newNnode after last
    {
        last->link = newNode;                             //insert newNode after last
        last = newNode;                             //make last point to the actual last node
    }
}                            //end insertLast

template<typename Type>
void linkedListType<Type>::deleteNode(const Type& deleteItem)
{
    nodeType<Type> *current;                             //pointer to traverse the list
    nodeType<Type> *trailCurrent;                             //pointer just before current
    bool found;

    if(first == NULL)                                //Case 1; list is empty. 
        cout<<"Can not delete from an empty list.\n";
    else
    {
        if(first->info == deleteItem)                             //Case 2 
        {
            current = first;
            first = first ->link;
            if(first == NULL)                                //list had only one node
                last = NULL;
            delete current;
        }
        else                              //search the list for the node with the given info
        {
            found = false;
            trailCurrent = first;                               //set trailCurrent to point to
                                                                //the first node
            current = first->link;                              //set current to point to the 
                                                                //second node

            while((!found) && (current != NULL))
            {
                if(current->info != deleteItem) 
                {
                    trailCurrent = current;
                    current = current-> link;
                }
                else
                    found = true;
            }                                           // end while

            if(found)                                                   //Case 3; if found, delete the node
            {
                trailCurrent->link = current->link;

                if(last == current)                                     //node to be deleted was 
                                                                        //the last node
                    last = trailCurrent;                                //update the value of last

                delete current;                                         //delete the node from the list
            }
            else
                cout<<"Item to be deleted is not in the list."<<endl;
        }                             //end else
    }                             //end else
}                             //end deleteNode

#endif

这是下面的测试程序。

//This program tests various operation of a linked list

#include "stdafx.h"
#include <string>//Need to import string to the class to be able to use that type
#include <iostream>
#include "linkedList.h"

using namespace std;

int main()
{
    linkedListType<string> list1, list2;                
    int num;
    string name;//Input from the user


    //cout<<"Enter numbers ending with -999"
        //<<endl;                                       
    //cin>>num; 

    cout<<"Please enter first and last name in each line, enter end to close program" //Prompting the user to enter first and last name on each line til they specify "end"
        <<endl;
        cin>>name;

    while(name != "end")//Checks if user entered name if not it will proceed to keep prompting the user                                 
    {
        list1.insertLast(name);//inserts the name at the end of the list                        
        cin>>name;                                  
    }

    cout<<endl;                                     

    cout<<"List 1: ";                       
    list1.print();//Prints all the names line by line                                   
    cout<<endl;                                     
    cout<<"Length List 1: "<<list1.length()//Gives length of how many names are in the list 
        <<endl;                                     

    list2 = list1;                                  //test the assignment operator 

    cout<<"List 2: ";                       
    list2.print();                                  
    cout<<endl;                                     
    cout<< "Length List 2: "<< list2.length()   <<endl;                                     

    cout<< "Enter the name to be "  << "deleted: ";                             
    cin>>num;                                       
    cout<<endl;                                     

    list2.deleteNode(name);                         

    cout<<"After deleting the node, "
        << "List 2: "<<endl;                            
    list2.print();                                  
    cout<<endl;                                     

    cout<<"Length List 2: "<<list2.length()
        <<endl;                                     

    system("pause");

    return 0;   

【问题讨论】:

  • 请问你又问了什么问题?
  • 这可能有助于理解:stackoverflow.com/questions/23047052/…
  • 仅供参考:您的数据结构中的对话很糟糕,mmK。
  • @FinalContest 大量代码,而不是调试工作甚至尝试?
  • @FinalContest 重读this section from the help center 并诚实判断问题是否符合所有这些要点(尤其是调试部分)。

标签: c++ string linked-list


【解决方案1】:

cin 输入也用空格分隔,在您的示例代码中,在读取 cin&gt;&gt;name; 时的最后一个循环中,名称将对所有空格和换行符进行分隔。

改用这个:

std::string name;

std::getline(std::cin, name);

【讨论】:

  • 我不认为OP的问题在于读取字符串,而是如何在不修改链表代码的情况下将多个字段放入链表节点。
  • @ThomasMatthews 相反,我认为这是阅读的问题。如果用户天真地点击名字和姓氏之间的空格,您会得到两个不同的读取,最终成为两个不同的链接节点。虽然它应该是带有两个字段的classstruct,但它们仍然需要正确读取它们。
  • 拥有classstruct 应该很好,但我认为最好按行阅读,因为名字和/或姓氏总共可能超过 2 个单词,并且会有问题读取逻辑,即使读取所有行拆分点问题仍然存在,但至少完整名称读取正常。
  • 我尝试了这种方法,但现在它没有将任何内容计入列表,并且返回长度为 0。
  • 我读到了正确的名字,但是例外(测试 GCC 4.9.0)。在 VS2013 中可以正常插入,但删除时出错 cout&lt;&lt; "Enter the name to be " &lt;&lt; "deleted"; cin&gt;&gt;num; cout&lt;&lt;endl; list2.deleteNode(name); 读取了 num 并使用名称进行调用(此时的名称始终为 'end')
【解决方案2】:

最简单的解决方案是创建一个包含两个字符串的结构:

struct Person_Name
{
  std::string first;
  std::string last;
};

然后您可以将结构“传递”为链表中的类型:

LinkedListType<Person_Name> people;

您可能需要调整列表的“通用性”或假设,或者向 Person_Name 添加功能以使其符合列表的界面。

编辑 1:比较数据
链表可能使用operator&lt; 对列表中的节点进行排序。因此,您必须将重载运算符添加到您的结构中:

struct Person_Name
{
  std::string first_name;
  std::string second_name;
  bool operator<(const& Person_Name pn) const
  {
    if (second_name == pn.second_name)
    {
       return first_name < pn.first_name;
    }
    return second_name < pn.second_name;
  }
};

您可以以类似的方式实现operator==

【讨论】:

  • 这是一个 OP 正在构建的链表类,上面发布的代码中没有任何内容涉及比较或排序(尽管这将是存储数据的更好方法而不是一个单一的std::string).
【解决方案3】:

代替两行中的姓名和姓氏,将它们放在一行中,如下所示:

char name[256]
std::cout << "Please, enter your name: and surname";
std::cin.getline (name,256);

要拆分姓名和姓氏,请将此代码复制/粘贴到您的解决方案中。

std::vector<std::string> &split(const std::string &s, char delim, std::vector<std::string> &elems) {
    std::stringstream ss(s);
    std::string item;
    while (std::getline(ss, item, delim)) {
        elems.push_back(item);
    }
    return elems;
}

std::vector<std::string> split(const std::string &s, char delim) {
    std::vector<std::string> elems;
    split(s, delim, elems);
    return elems;
}

然后把你要写的名字和姓氏分开

vector<string> person = split(name, ' ');
person.at(0)  // the name of the person 
person.at(1)  //the surname of the person

【讨论】:

  • 请看我在一行中提示整个名称,但是在运行程序时,即使它们在一行中添加到列表中,它们仍然被视为两个不同的元素,即使我希望它们被处理作为一个。我需要在列表中输入它们
  • 通过这一行,它不会被视为两个单独的用户。 cout &lt;&lt; "enter name and surname" 没有任何意义,cin 是读取行或单词的东西。这样,您将阅读 line 而不是 word
  • 你在promting,但是你的代码不是这样读的。使用cin &gt;&gt; name; 将忽略空格,输入字符串,然后在任何空格后stop,剩下的直到另一个调用。
  • 如何使用您的示例将名字与姓氏分开?
  • 我添加了拆分方法。使用此方法,您可以将姓名和姓氏分开。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-10-11
  • 1970-01-01
  • 2020-06-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多