【发布时间】:2020-02-27 01:29:59
【问题描述】:
我的代码中有一个非常奇怪的错误,有点难以解释。让我从程序的作用开始:基本上,C++ 程序获取输入文本(来自同一目录中名为“input.txt”的文件)并使用马尔可夫链生成一些类似于输入文本样式的人工输出文本并将其打印到终端。
当我将“爱丽丝梦游仙境”(http://paulo-jorente.de/text/alice_oz.txt) 的文本直接复制并粘贴到“input.txt”中时,它可以工作,但是如果我在文本内容的开头或结尾添加任何单词或字符文件,然后代码停止运行(或无限运行)。但是,如果我在文本文件内容中间的任何位置添加文本,则不会发生这种情况。
如果您想自己测试它,请尝试运行将爱丽丝梦游仙境复制到“input.txt”中的代码。然后在它运行成功后,转到 input.txt 并在 'Alice' 的最后一个文本之后键入一些随机字符或单词(“......再次回家!”)并尝试再次运行它;它会失败。
代码如下:
#include <ctime>
#include <iostream>
#include <algorithm>
#include <fstream>
#include <string>
#include <vector>
#include <map>
using namespace std;
class markovTweet{
string fileText;
map<string, vector<string> > dictionary;
public:
void create(unsigned int keyLength, unsigned int words) {
ifstream f("input.txt");
if(f.good()){
fileText.assign((istreambuf_iterator<char>(f)), istreambuf_iterator<char>());
}else{
cout << "File cannot be read. Ensure there is a file called input.txt in this directory." << "\n" << endl;
return;
}
if(fileText.length() < 1){
return;
}
cout << "\n" << "file imported" << "\n";
createDictionary(keyLength);
cout << "\n" << "createDictionary" << "\n" << "\n";
createText(words - keyLength);
cout << "\n" << "text created, done" << endl;
}
private:
void createText(int w) {
string key, first, second;
size_t next;
map<string, vector<string> >::iterator it = dictionary.begin();
advance( it, rand() % dictionary.size() );
key = (*it).first;
cout << key;
while(true) {
vector<string> d = dictionary[key];
if(d.size() < 1) break;
second = d[rand() % d.size()];
if(second.length() < 1) break;
cout << " " << second;
if(--w < 0) break;
next = key.find_first_of( 32, 0 );
first = key.substr( next + 1 );
key = first + " " + second;
}
cout << "\n";
}
void createDictionary(unsigned int kl) {
string w1, key;
size_t wc = 0, pos, next;
next = fileText.find_first_not_of( 32, 0 );
if(next == string::npos) return;
while(wc < kl) {
pos = fileText.find_first_of(' ', next);
w1 = fileText.substr(next, pos - next);
key += w1 + " ";
next = fileText.find_first_not_of(32, pos + 1);
if(next == string::npos) return;
wc++;
}
key = key.substr(0, key.size() - 1);
while(true) {
next = fileText.find_first_not_of(32, pos + 1);
if(next == string::npos) return;
pos = fileText.find_first_of(32, next);
w1 = fileText.substr(next, pos - next);
if(w1.size() < 1) break;
if(find( dictionary[key].begin(), dictionary[key].end(), w1) == dictionary[key].end() )
dictionary[key].push_back(w1);
key = key.substr(key.find_first_of(32) + 1) + " " + w1;
}
}
};
int main() {
markovTweet t;
cout << "\n" << "Artificially generated tweet using Markov Chains based off of input.txt: " << "\n" << "\n";
//lower first number is more random sounding text, second number is how long output is.
t.create(4, 30);
return 0;
}
这是一个非常奇怪的错误,非常感谢您提供的任何帮助!谢谢!
【问题讨论】:
-
有很多代码需要查看。我会在调试器中戳它,看看它卡在哪里。
-
当您使用调试器运行程序时,您看到了什么?这就是调试器的用途。如果您不知道如何使用调试器,这是一个学习如何使用调试器一次运行一行的好机会,监控所有变量及其值的变化,并分析程序的逻辑执行流程。了解如何使用调试器是每个 C++ 开发人员必备的技能,没有例外。在调试器的帮助下,您应该能够快速找到此程序以及您编写的所有未来程序中的所有错误,而无需向任何人寻求帮助。
-
这是一个学习构建minimal complete example 的好机会,这是一项至关重要的编程技能。您可以用爱丽丝梦游仙境的整个文本重现该错误吗?尝试删除一些文本;错误还在吗?你能把它简化成一行吗?删除一些代码怎么样——别管马尔可夫模型或输出,只需尝试用更简单的程序重现错误。您可能会在此过程中自己发现错误,但无论如何您都会有一个更简单的案例要发布。
-
感谢 tadman 和 Sam 的 cmets。我在 Repl.it 中运行代码,但我转向 Visual Studio 尝试调试它。当我运行本地 Windows 调试器时,代码只是无限运行。我是 C++ 编码的新手 - 有没有更好的调试方法?
-
在我看来,正在使用的编辑器正在向字符集添加字节顺序标记或其他一些更改,从而导致文本添加出现问题。我不知道为什么在中间插入不会触发重新格式化,同时添加到开头或结尾完成 - 这可能取决于相关编辑器跟踪更改的方式。我会在更改前后对文件进行十六进制转储,以查看是否仅存在您所做的更改,或者是否还没有发生其他格式或字符集更改。
标签: c++ text markov-chains markov