如何在链接列表中搜索特定字符串并返回该值



我有一个程序,它接受5个参数的输入。输入是视频标题、url、评论、长度和评级。然后根据标题对它们进行排序。用户将需要指定insert(输入视频信息)、lookup

例如

输入:

insert
Arthur Benjamin: Lightning calculation and other "Mathemagic"
http://www.youtube.com/watch?v=M4vqr3_ROIk
Hard to believe.
15.25  
4  
lookup  
Arthur Benjamin: Lightning calculation and other "Mathemagic"

输出:

Arthur Benjamin: Lightning calculation and other "Mathemagic" , http://www.youtube.com/watch?v=M4vqr3_ROIk, Hard to believe., 15.25, 4

我的问题是处理主中的查找

if(user == "lookup")
{
getline(cin, title);
if(vlistObj -> lookup(videoObj))
{
vlistObj->print();
}
}

以及在我的链接列表中查找

bool Vlist::lookup(Video *other)
{
Node *node = m_head;
return node->m_next -> m_video->GetTitle() == other-> GetTitle();
}

老实说,我非常不知道如何让查找搜索特定的标题(假设已经给出了很多视频标题/信息),只打印我问的内容(假设它在列表中)。

这是完整的代码:

#include <iostream>
#include <stdlib.h>
#include <cstring>
using namespace std;
class Video {
public:
Video(string video_title, string video_link, string video_comment, double video_length, int video_number);
void print();
const string& GetTitle() const { return title; }
private:
std::string title;
string link;
string comment;
double length;
int rating;
};

Video::Video(string video_title, string video_link, string video_comment, double video_length, int video_number)
: title(video_title), link(video_link), comment(video_comment), length(video_length), rating(video_number)
{
}
void Video::print(){
cout << title << ", " << link << ", " << comment << ", " << length << ", " << rating << endl;
}

class Vlist {
public:
Vlist() {m_head = nullptr; }
bool lookup(Video *other);
void Insert(Video *video);
void print();
private:
class Node {
public:
Node(Video *video, Node *next) {m_video = video; m_next = next; }
Video *m_video;
Node *m_next;
};
Node *m_head;
};

void Vlist::Insert(Video* video)
{
if (m_head == NULL || m_head->m_video -> GetTitle() > video->GetTitle())
{
m_head = new Node(video, m_head);
}
else
{
Node *node = m_head;
while (node->m_next != NULL && node->m_next -> m_video->GetTitle() < video->GetTitle())
{
node = node->m_next;
}
node->m_next = new Node(video, node->m_next);
}
}
bool Vlist::lookup(Video *other)
{
Node *node = m_head;
return node->m_next -> m_video->GetTitle() == other-> GetTitle();
}
void Vlist::print()
{
Video *video;
Node *node = m_head;
while(node != NULL)
{
node -> m_video-> Video::print();
node = node->m_next;
}
}

int main()
{
string sort_type, url, comment, title, user;
int rating;
double length;
int initial = 0, last = 0, number;
Vlist *vlistObj= new Vlist();
Video *videoObj;
while (getline(cin,user)) {
if(user == "insert")
{
getline(cin,title);
getline(cin, url);
getline(cin, comment);
cin >> length;
cin >> rating;
cin.ignore();
videoObj = new Video(title,url, comment, length, rating);
vlistObj->Insert(videoObj);
}
if(user == "lookup")
{
getline(cin, title);
if(vlistObj -> lookup(videoObj))
{
vlistObj->print();
}
}
if(user == "print")
{
vlistObj->print();
}
}
}

此外,我确实需要注意的是,我收到了一个分段错误。但我知道这是因为我在查找中的代码。如果我没有键入查找,程序将正确运行和输出

错误出现在Vlist::lookup函数中,其中当前节点指针指向m_next,然后指向m_video:不需要m_nextm_head应直接指向m_video

在完整的工作代码下面,我还修改了一些内容,以消除编译器中的所有警告

#include <iostream>
#include <stdlib.h>
#include <cstring>
using namespace std;
class Video {
public:
Video(string video_title, string video_link, string video_comment, double video_length, int video_number);
void print();
const string& GetTitle() const { return title; }
private:
string title;
string link;
string comment;
double length;
int rating;
};

Video::Video(string video_title, string video_link, string video_comment, double video_length, int video_number)
: title(video_title), link(video_link), comment(video_comment), length(video_length), rating(video_number)
{
}
void Video::print(){
cout << title << ", " << link << ", " << comment << ", " << length << ", " << rating << endl;
}

class Vlist {
public:
Vlist():m_head(nullptr) {}     // init_list
bool lookup(const string& title);  // gets user input directly
void Insert(Video *video);
void print();
Video* get(const string& title);   // new:returns pointer in list with given title
private:
class Node {
public:
Node(Video *video, Node *next):m_video(video), m_next(next) {}   // init_list
Video *m_video;
Node *m_next;
} *m_head;    // declared directly together with class definition
};

void Vlist::Insert(Video* video)
{
if (m_head == NULL || m_head->m_video -> GetTitle() > video->GetTitle())
{
m_head = new Node(video, m_head);
}
else
{
Node *node = m_head;
while (node->m_next != NULL && node->m_next -> m_video->GetTitle() < video->GetTitle())
{
node = node->m_next;
}
node->m_next = new Node(video, node->m_next);
}
}
bool Vlist::lookup(const string& title)
{
Node *node = m_head;
while (node->m_next != NULL && node-> m_video->GetTitle() != title)
{
node = node->m_next;
}
return node-> m_video->GetTitle() == title; // there was one pointer too many here
}
void Vlist::print()
{
Node *node = m_head;
while(node != NULL)
{
node -> m_video-> Video::print();
node = node->m_next;
}
}
Video* Vlist::get(const string& title) // returns required item from list
{
Node *node = m_head;
while (node != NULL) {
if (node->m_video->GetTitle() == title)
return node->m_video;
node = node->m_next;
}
return nullptr;
}

int main()
{
string sort_type, url, comment, title, user;
int rating;
double length;
Vlist *vlistObj= new Vlist;
Video *videoObj;
while (getline(cin,user)) {
if(user == "insert")
{
getline(cin,title);
getline(cin, url);
getline(cin, comment);
cin >> length;
cin >> rating;
cin.ignore();
videoObj = new Video(title, url, comment, length, rating);
vlistObj->Insert(videoObj);
}
if(user == "lookup")   // more than a few changes here
{
getline(cin, title);
if (vlistObj -> lookup(title))
{
videoObj = vlistObj->get(title);
videoObj->print();
} else {
cout << "not found!n";
}
}
if(user == "print")
{
vlistObj->print();
}
}
}

大编辑

以前的版本没有正确遍历Vlist

现在lookup命令正确地搜索了Vlist,从而最终打印出正确的Video

概述

在研究具体问题之前,您的代码显示您正在努力将所有部分组合在一起,并且在某种意义上是猜测,而不是特别关注代码中的每一行。你不能仅仅通过"尝试一下,看看它是否有效,那只会让你变老、变灰、沮丧。花点时间确切地知道下一行代码需要做什么,制定一行代码,然后制定一个测试以确保它成功(或者与gdb交朋友并在那里检查——你表示你正在使用g++)

示例:

#include <iostream>
#include <limits>
// #include <stdlib.h>
// #include <cstring>

stdlib.hcstring包含了什么?和:

void Vlist::print()
{
// Video *video;        /* unused */

// int initial = 0, last = 0, number = 0;   /* unused */

other是如何初始化的?如果将指针传递给Video对象,则该对象至少必须初始化title,因此GetTitle()返回一个有意义的值。。。

bool Vlist::lookup(Video *other)
{
Node *node = m_head;
return node->m_next -> m_video->GetTitle() == other-> GetTitle();
}

这真的没有多大意义?

慢慢来,放慢速度,了解你需要做什么,然后拿起键盘(而不是相反)

要与你的语法使用保持一致。您在某些位置包含std::string,然后在其他位置仅包含string,这依赖于using namespace std;。请参阅为什么"使用命名空间std;"被认为是不好的做法?

此外,在C++中的任何条件下,->周围都不存在空间。这是一个连接对象及其成员的运算符,其间没有任何内容。

具体问题

很明显,当您尝试打印Vlist时,您所拥有的不会输出与查找匹配的Video对象。(为了找到一个感兴趣的标题而打印整个列表没有多大意义)。lookup()函数不能返回bool,相反,它必须返回一个指向包含标题的节点的指针(如果找到)或指向未找到的nullptr的指针。这意味着您必须保存并验证返回,才能知道哪个Node包含要打印的记录。在main()中,看起来像:

else if (user == "lookup") {
if (getline(std::cin, title)) {
videoObj = new Video (title);   /* you must construct a new videoObj */
Video *video = nullptr;         /* you want a Video* pointer returned */
if ((video = vlistObj->lookup(videoObj))) { /* lookup & assign return */
video->print();             /* output the video, not list */
}
else {
std::cout << "title not found: '" << title << "'.n";
}
}
}

既然videoObj指向一个初始化了titleVideo对象,lookup()函数就可以完成它的工作了——返回一个指向列表中包含该标题(以及所有其他信息)的节点的指针,或者如果找不到标题,则返回nullptr。(注意else向用户指示该条件)

lookup()的重写就是:

Video *Vlist::lookup (Video *other)
{
Node *node = m_head;

while (node) {  /* iterate over nodes in list looking for title */
if (node->m_video->GetTitle() == other->GetTitle())
return node->m_video;           /* return pointer to node if found */
node = node->m_next;
}
return nullptr;                         /* nullptr if not */
}

(注意:简单地将other作为std::string传递更有意义,但如果您需要Video对象,这是一种最简单的方法)

还有一系列其他需要清理的内容,对初始化的调整,语法修复——删除->周围的空格等等……不胜枚举。更不用说需要确保您没有泄漏内存——这是留给您(以及您正确编写的析构函数)的。在程序退出之前,使用valgrind验证您是否释放了所有内存。

把语法清理和初始化放在一起,你可以做一些类似的事情:

#include <iostream>
#include <limits>
class Video {
public:
Video ( std::string video_title, std::string video_link, std::string video_comment, 
double video_length, int video_number );
void print();
const std::string& GetTitle() const { return title; }
private:
std::string title {}, link {}, comment {};
double length;
int rating;
};

Video::Video ( std::string video_title = "", 
std::string video_link = "", 
std::string video_comment = "", 
double video_length = 0, int video_number = 0)
: title(video_title), link(video_link), comment(video_comment), 
length(video_length), rating(video_number)
{
}
void Video::print()
{
std::cout << title << ", " << link << ", " << comment << ", " << 
length << ", " << rating << 'n';
}

class Vlist {

public:
Vlist() { m_head = nullptr; }
Video *lookup (Video *other);
void Insert (Video *video);
void print();

private:
class Node {
public:
Node (Video *video = nullptr, Node *next = nullptr) {
m_video = video; m_next = next;
}
Video *m_video;
Node *m_next;
};
Node *m_head;
};
void Vlist::Insert (Video* video)
{
if (m_head == nullptr || m_head->m_video->GetTitle() > video->GetTitle()) {
m_head = new Node (video, m_head);
}
else {
Node *node = m_head;
while (node->m_next != nullptr &&
node->m_next->m_video->GetTitle() < video->GetTitle()) {
node = node->m_next;
}
node->m_next = new Node(video, node->m_next);
}
}
Video *Vlist::lookup (Video *other)
{
Node *node = m_head;

while (node) {  /* iterate over nodes in list looking for title */
if (node->m_video->GetTitle() == other->GetTitle())
return node->m_video;           /* return pointer to node if found */
node = node->m_next;
}
return nullptr;                         /* nullptr if not */
}
void Vlist::print()
{
Node *node = m_head;
while (node != nullptr) {
node->m_video->Video::print();
node = node->m_next;
}
}

int main (void) {

std::string sort_type {}, url {}, comment {}, title {}, user {};
int rating = 0;
double length = 0;
Vlist *vlistObj = new Vlist();
Video *videoObj = nullptr;
while (getline(std::cin, user)) {
if (user == "insert") {
if (getline (std::cin, title) &&
getline (std::cin, url) &&
getline (std::cin, comment) &&
std::cin >> length &&
std::cin >> rating) {
std::cin.ignore (std::numeric_limits<std::streamsize>::max(), 'n');
videoObj = new Video (title, url, comment, length, rating);
vlistObj->Insert(videoObj);
}
}
else if (user == "lookup") {
if (getline(std::cin, title)) {
videoObj = new Video (title);   /* you must construct a new videoObj */
Video *video = nullptr;         /* you want a Video* pointer returned */
if ((video = vlistObj->lookup(videoObj))) { /* lookup & assign return */
video->print();             /* output the video, not list */
}
else {
std::cout << "title not found: '" << title << "'.n";
}
}
}
else if (user == "print") {
std::cout << "nlist content:n";
vlistObj->print();
}
}
}

示例输入文件

为了尽量减少代码的使用,您需要在链表中有多个节点。尝试查找一个不存在的节点——验证该代码路径如何?

$ cat dat/ll_video2.txt
insert
Arthur Benjamin: Lightning calculation and other "Mathemagic"
http://www.youtube.com/watch?v=M4vqr3_ROIk
Hard to believe.
15.25
4
insert
Arthur Benjamin: Some Other "Mathemagic"
http://www.youtube.com/watch?v=SomeOther
Hard to swallow.
25.25
7
lookup
Arthur Benjamin: Lightning calculation and other "Mathemagic"
lookup
Arthur Benjamin: Some Other "Mathemagic"
lookup
Mickey & Minnie do Disney
print

示例使用/输出

三次查找的结果都得到了正确处理,并且列表内容按照它们应该的方式打印,结果是print命令输入作为上面最后一行输入:

$ ./bin/ll_video <dat/ll_video2.txt
Arthur Benjamin: Lightning calculation and other "Mathemagic", http://www.youtube.com/watch?v=M4vqr3_ROIk, Hard to believe., 15.25, 4
Arthur Benjamin: Some Other "Mathemagic", http://www.youtube.com/watch?v=SomeOther, Hard to swallow., 25.25, 7
title not found: 'Mickey & Minnie do Disney'.
list content:
Arthur Benjamin: Lightning calculation and other "Mathemagic", http://www.youtube.com/watch?v=M4vqr3_ROIk, Hard to believe., 15.25, 4
Arthur Benjamin: Some Other "Mathemagic", http://www.youtube.com/watch?v=SomeOther, Hard to swallow., 25.25, 7

仔细看看,如果你还有问题,请告诉我。

相关内容

  • 没有找到相关文章

最新更新