我有一个程序,它接受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_next
,m_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.h
和cstring
包含了什么?和:
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
指向一个初始化了title
的Video
对象,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
仔细看看,如果你还有问题,请告诉我。