我正在编程一个双链表,从给定的文件中读取字符串。因此,我写了一个名为Node的类,在其中我存储了一个字符串(读取的单词)和一些用于单词长度和其他参数的整数。
读取文件中的所有字符串后,我打开第二个文件,再次读取每个单词,并将该单词与链表中的字符串进行比较。之后,我将找到的每个单词存储在一个结果文件中。
现在我想向用户显示找到的单词在文本中的哪个位置,例如:
"在文本文件的200处找到单词"
因此,我创建了一个计数器,每次创建新节点时该计数器都会递增。我现在的问题是,我的计数器只是计算总共创建了多少节点。所以我只看到创建了大约56000个节点,但我无法存储节点的数量。
我做错了什么?
编辑:我没有尝试递减计数器,因为我从未删除过节点。这是我的完整代码
#include <iostream>
#include <string>
#include <stdio.h>
#include <fstream>
#include <cstring>
using namespace std;
class Word
{
public:
Word (string inputstring = 0, int b = 0, int c = 0, int l = 0, Word *n = 0, Word *p = 0 ) : word (inputstring), book (b), chapter (c), length (l), next (n), prev (p)
{
++counter;
}
int book;
int chapter;
int length;
string word;
Word *next;
Word *prev;
static size_t howMany()
{
return counter;
}
private:
static size_t counter;
};
size_t Word::counter;
int main ()
{
string inputstring = "empty";
string compare = "empty";
int l1 = 0;
int book = 0;
int chapter = 0;
int count = 0;
Word *p = 0;
Word *x = 0;
Word *start = 0;
ifstream file;
file.open("Beispieltext.txt");
ofstream outfile;
if (!file) cout << ("can't open input file");
else cout << "File: Beispieltext.txt openn";
// create nodes
while (file >> inputstring)
{
l1 = (int)inputstring.length();
if ( (!(inputstring[0] >= 'A' && inputstring[0] <= 'Z')) && (!(inputstring[0] >= 'a' && inputstring[0] <= 'z'))) inputstring = inputstring.substr(1,l1--); // l1-- reduce length
while ( (!(inputstring[l1-1] >= 'A' && inputstring[l1-1] <= 'Z')) && (!(inputstring[l1-1] >= 'a' && inputstring[l1-1] <= 'z'))) inputstring = inputstring.substr(0,--l1); // --l1 go till n-1
// book?
if (std::strncmp(inputstring.data(), "BOOK", 4) == 0) ++book, chapter = 0/*, cout << "nBook Nr.: " << book << "n"*/;
// Chapter?
if (std::strncmp(inputstring.data(), "CHAPTER", 7) == 0) ++chapter/*, cout << "chapter: " << chapter << "n"*/;
if (p == NULL)
{
p = new Word (inputstring);
} else
{
x = new Word (inputstring, book, chapter, l1, 0, p);
p->next = x;
p = x;
}
}
file.close();
cout << "File: Beispieltext.txt closed!n";
// n...0
for (; p; p = p->prev) start = p; // go to start
// Open compare file 1
file.open("Suchbegriffe_1.txt");
if (!file) cout << "Can't open compare file!n";
else cout << "File: Suchbegriffe.txt open!n";
// Open result file 1
outfile.open("Result_1.txt");
if(!outfile) cout << "Can't open Result_1.txt file!n";
else cout << "File: Result_1.txt open!n";
while (file >> compare)
{
l1 = (int)compare.length();
// Search
x = start;
// 0...n go to end
for (; x; x = x->next)
{
if (l1 == x->length)
{
if (compare == x->word)
{
outfile << "Word: " << compare << " found in book Nr.: " << x->book << ", chapter: " << x->chapter << "!n";
outfile << "Word: " << compare << " is the " << x->howMany() << " Word in the book.n";
count++;
}
}
}
outfile << "Word: " << compare << ", " << count << "x found!n";
count = 0;
}
file.close();
cout << "File: Suchbegriffe_1.txt closed!n";
outfile.close();
cout << "File: Result.txt closed!n";
// Open compare file 2
file.open("Suchbegriffe_2.txt");
if (!file) cout << "Can't open compare file!n";
else cout << "File: Suchbegriffe.txt open!n";
// Open result file 2
outfile.open("Result_2.txt");
if (!outfile) cout << "Can't open Result_2 file!n";
else cout << "File: Result_2.txt open!n";
while (file >> compare)
{
l1 = (int)compare.length();
// Search
x = start;
// 0...n go to end
for (; x; x = x->next)
{
if (l1 == x->length)
{
if (compare == x->word)
{
outfile << "Word: " << compare << " found in book Nr.: " << x->book << ", chapter: " << x->chapter << "!n";
count++;
}
}
}
outfile << "Word: " << compare << ", " << count << "x found!n";
count = 0;
}
file.close();
cout << "File: Suchbegriffe_2.txt closed!n";
outfile.close();
cout << "File: Result_2.txt closed!n";
}
我现在的问题是,我的计数器只是计算总共创建了多少节点。
是的,因为您有一个全局计数器来统计创建的节点。
所以我只看到创建了大约56000个节点,但我无法存储节点的数量。
如果您希望每个节点都有一个不同的数字,那么您不能将一个数字存储在一个地方,并期望它有几个不同的值!
你需要
-
或者在每个节点中存储一个数字作为成员变量,不是静态变量(但如果节点是从列表的开头或中间添加或删除的,请确保它们都是正确的,如果程序中同时有两个列表,请确保列表中的第一个节点的数字为0,即它必须是该列表中的数字,而不仅仅是已分配节点的全局计数器。)
-
或更简单,只需在遍历列表时保留一个计数器,并为您看到的每个节点递增。你已经在统计匹配单词的数量了,为什么不能只统计所有检查单词的总数,包括不匹配的单词?
例如:
while (file >> compare)
{
int checked = 0;
int found = 0;
for (Word* x = start; x; x = x->next)
{
if (compare == x->word)
{
outfile << "Word: " << compare << " found in book Nr.: " << x->book << ", chapter: " << x->chapter << " at word " << checked << "!n";
found++;
}
checked++;
}
outfile << "Word: " << compare << ", " << found << "x found!n";
}
请注意,我在循环中声明变量(而不是在函数的顶部),并且不必检查单词长度,因为比较std::string
已经做到了这一点。为什么要将长度存储在Word
类中?x->word.length()
告诉您长度,您不需要显式存储它。
此外,这太疯狂了:
for (; p; p = p->prev) start = p; // go to start
这将通过一个大列表来查找开始。。。只需在分配第一个节点时设置开始并保留它!
x = new Word (inputstring, book, chapter, l1, 0, p);
if (!start)
start = x; // remember the start
p->next = x;
p = x;
变量counter
是静态的,这意味着它是类中唯一的变量。
假设我在读三个单词:"a"、"b"one_answers"c"。当我在"a"上调用howMany
时,它将返回3,"b"one_answers"c"的howMany
也将返回3。
我建议将所有的Word
保存在std::vector
中,只需调用std::vector.size()
即可获得Word
计数。I将从counter
和howMany
中删除static
,并将单词计数作为参数传递给Word
构造函数,这样您就可以将其存储在counter
成员变量中。
我建议您在结果文件中存储一个整数值和您找到的单词。并在打印结果时显示。
或者,您可以在节点类中使用位置变量来确定它的位置。
快速修复:
class Word
{
public:
Word (string inputstring = 0, int b = 0, int c = 0, int l = 0, Word *n = 0, Word *p = 0 )
: word (inputstring), book (b), chapter (c), length (l), next (n), prev (p)
{
currCont = ++counter;
}
int book;
int chapter;
int length;
string word;
Word *next;
Word *prev;
int currCont;
size_t howMany()
{
return currCont;
}
private:
static size_t counter;
};
// ...later...
x = start;
// 0...n go to end
for (; x; x = x->next)
{
if (l1 == x->length)
{
if (compare == x->word)
{
outfile << "Word: " << compare << " is the " << x->howMany() << " Word in the book.n";
count++;
}
}
}
outfile << "Word: " << compare << ", " << count << "x found!n";
count = 0;
}