在 C++ 程序中作为输入的文本文件将不起作用,除非文本被复制和粘贴
Text file as input in C++ program will not work unless the text is copy and pasted
我的代码中有一个非常奇怪的错误,有点难以解释。让我从程序的作用开始:基本上,C++ 程序获取输入文本(来自同一目录中名为 "input.txt" 的文件)并使用马尔可夫链生成一些类似于输入文本样式的人工输出文本并将其打印到终端。
当我将 'Alice in Wonderland' (http://paulo-jorente.de/text/alice_oz.txt) 的文本直接复制并粘贴到 "input.txt" 时,它会起作用,但是如果我在 'Alice in Wonderland' (http://paulo-jorente.de/text/alice_oz.txt) 的开头或结尾添加任何单词或字符文本文件的内容,然后代码停止 运行ning(或 运行s 无限)。但是,如果我在文本文件内容中间的任何位置添加文本,则不会发生这种情况。
如果您想自己测试,请尝试 运行将爱丽丝梦游仙境的代码复制到 "input.txt"。然后在 运行s 成功后,转到 input.txt 并在 'Alice' 的最后一个文本(“...home again!”)后键入一些随机字符或单词并尝试运行 再说一遍;它会失败。
代码如下:
#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;
}
这是一个非常奇怪的错误,非常感谢您提供的任何帮助!谢谢!
关于 std::map
的 operator[]()
的时间复杂度,这可能是需要考虑的事情。
Using operator[] : “[]” can also be used to insert elements in map. Similar to above functions and returns the pointer to the newly constructed element. Difference is that this operator always constructs a new element i.e even if a value is not mapped to key, default constructor is called and assigns a “null” or “empty” value to the key. Size of map is always increased by 1.
Time complexity : log(n) where n is size of map
courtesy from: geeksforgeeks
在您的 class 的 createDictionary()
函数中尝试在 2nd while 循环中添加这行代码:
{
//...code
if (find(dictionary[key].begin(), dictionary[key].end(), w1) == dictionary[key].end()) {
dictionary[key].push_back(w1);
std::cout << dictionary.size() << std::endl;
//code...
}
当我从文件中复制文本时,它生成了 62037 个条目到您的字典或哈希图中。 运行 大约需要 20 - 30 秒并完成。
当我将文本“再见!”添加到文件末尾并保存它时,运行 program/debugger 它生成了 62039 个条目。 运行.
又花了大约 20-30 秒
然后我将文本 "Hello World " 添加到文件的开头,将其保存并 运行 program/debugger 并生成了 62041 个条目。 运行.
又花了大约 20-30 秒
但是,在此过程中有几次,它在您的地图中生成了那么多条目,但代码仍在循环中……有一次大约在 620xx - 640xx 之间。我不知道是什么导致它生成那么多键……但就像我说的,有几次它停止打印值,但仍在重复相同的 while 循环,但是地图没有增加...
这是我第一次在文件开头输入文本,然后在末尾添加附加文本。这是当我决定打印出你的地图的大小并注意到我得到了这个无限循环......然后我停止了调试器回到文本文件并将插入的文本保留在开头,但删除了附加的文本最后确保在文本末尾留下一个 space。
这次当我 运行 program/debugger 时,它工作正常并生成了 62039 个条目。 运行 又花了大约 20-30 秒。之后,第一个成功的 运行 开头插入的文本是我在末尾添加文本的时候,它 运行 很好。然后我什至尝试让 "Hello World!" 后跟一个换行符,方法是在文本文件中使用 enter 并在 "Good Bye!" 前面加上一个,它仍然工作正常。
是的,有什么东西导致了错误,但我不知道到底是什么导致了它。但是,我相信我已经追踪到它在这个 while
循环和退出的条件 b运行ching 中......它应该已经跳出这个循环并进入 createText
功能却一直没有爆发,你的条件是:
if (next == std::string::npos) return
和
if (w1.size() < 1) break;
不知何故没有被满足。
时间复杂度还可以,但是,它不是最好的,但也不是最差的,因为在 O(log n)
时间内有大约 62-63k 个条目 运行ning。这也不包括计算确实需要考虑的 space 复杂性。
可能是在一个 运行 期间,您可能会遇到堆栈溢出,这会导致无限循环,而下一次 运行 它可能不会。我认为这与直接将文本添加到文本文件没有任何关系,只是它会增加 O(log N) time
中地图的大小并增加 space 的复杂性。
无论您向该文本文件中添加什么以及保存后,您的程序或算法的编写方式如何,它都会通过迭代器按 char 类型将该文件的所有内容作为指针索引拉取 classes 并将其存储到单个字符串中,fileText
。构造此字符串后,您的 class 成员字符串中大约有 336940 个字符。
希望这些信息可以指导您缩小程序中错误的位置并确定真正导致错误的原因。确实很难缩小这个罪魁祸首。
我的代码中有一个非常奇怪的错误,有点难以解释。让我从程序的作用开始:基本上,C++ 程序获取输入文本(来自同一目录中名为 "input.txt" 的文件)并使用马尔可夫链生成一些类似于输入文本样式的人工输出文本并将其打印到终端。
当我将 'Alice in Wonderland' (http://paulo-jorente.de/text/alice_oz.txt) 的文本直接复制并粘贴到 "input.txt" 时,它会起作用,但是如果我在 'Alice in Wonderland' (http://paulo-jorente.de/text/alice_oz.txt) 的开头或结尾添加任何单词或字符文本文件的内容,然后代码停止 运行ning(或 运行s 无限)。但是,如果我在文本文件内容中间的任何位置添加文本,则不会发生这种情况。
如果您想自己测试,请尝试 运行将爱丽丝梦游仙境的代码复制到 "input.txt"。然后在 运行s 成功后,转到 input.txt 并在 'Alice' 的最后一个文本(“...home again!”)后键入一些随机字符或单词并尝试运行 再说一遍;它会失败。
代码如下:
#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;
}
这是一个非常奇怪的错误,非常感谢您提供的任何帮助!谢谢!
关于 std::map
的 operator[]()
的时间复杂度,这可能是需要考虑的事情。
Using operator[] : “[]” can also be used to insert elements in map. Similar to above functions and returns the pointer to the newly constructed element. Difference is that this operator always constructs a new element i.e even if a value is not mapped to key, default constructor is called and assigns a “null” or “empty” value to the key. Size of map is always increased by 1. Time complexity : log(n) where n is size of map
courtesy from: geeksforgeeks
在您的 class 的 createDictionary()
函数中尝试在 2nd while 循环中添加这行代码:
{
//...code
if (find(dictionary[key].begin(), dictionary[key].end(), w1) == dictionary[key].end()) {
dictionary[key].push_back(w1);
std::cout << dictionary.size() << std::endl;
//code...
}
当我从文件中复制文本时,它生成了 62037 个条目到您的字典或哈希图中。 运行 大约需要 20 - 30 秒并完成。
当我将文本“再见!”添加到文件末尾并保存它时,运行 program/debugger 它生成了 62039 个条目。 运行.
又花了大约 20-30 秒然后我将文本 "Hello World " 添加到文件的开头,将其保存并 运行 program/debugger 并生成了 62041 个条目。 运行.
又花了大约 20-30 秒但是,在此过程中有几次,它在您的地图中生成了那么多条目,但代码仍在循环中……有一次大约在 620xx - 640xx 之间。我不知道是什么导致它生成那么多键……但就像我说的,有几次它停止打印值,但仍在重复相同的 while 循环,但是地图没有增加...
这是我第一次在文件开头输入文本,然后在末尾添加附加文本。这是当我决定打印出你的地图的大小并注意到我得到了这个无限循环......然后我停止了调试器回到文本文件并将插入的文本保留在开头,但删除了附加的文本最后确保在文本末尾留下一个 space。
这次当我 运行 program/debugger 时,它工作正常并生成了 62039 个条目。 运行 又花了大约 20-30 秒。之后,第一个成功的 运行 开头插入的文本是我在末尾添加文本的时候,它 运行 很好。然后我什至尝试让 "Hello World!" 后跟一个换行符,方法是在文本文件中使用 enter 并在 "Good Bye!" 前面加上一个,它仍然工作正常。
是的,有什么东西导致了错误,但我不知道到底是什么导致了它。但是,我相信我已经追踪到它在这个 while
循环和退出的条件 b运行ching 中......它应该已经跳出这个循环并进入 createText
功能却一直没有爆发,你的条件是:
if (next == std::string::npos) return
和
if (w1.size() < 1) break;
不知何故没有被满足。
时间复杂度还可以,但是,它不是最好的,但也不是最差的,因为在 O(log n)
时间内有大约 62-63k 个条目 运行ning。这也不包括计算确实需要考虑的 space 复杂性。
可能是在一个 运行 期间,您可能会遇到堆栈溢出,这会导致无限循环,而下一次 运行 它可能不会。我认为这与直接将文本添加到文本文件没有任何关系,只是它会增加 O(log N) time
中地图的大小并增加 space 的复杂性。
无论您向该文本文件中添加什么以及保存后,您的程序或算法的编写方式如何,它都会通过迭代器按 char 类型将该文件的所有内容作为指针索引拉取 classes 并将其存储到单个字符串中,fileText
。构造此字符串后,您的 class 成员字符串中大约有 336940 个字符。
希望这些信息可以指导您缩小程序中错误的位置并确定真正导致错误的原因。确实很难缩小这个罪魁祸首。