C++ 从文本文件中逐字读取单词或逐字符读取单词
Posted
技术标签:
【中文标题】C++ 从文本文件中逐字读取单词或逐字符读取单词【英文标题】:C++ Reading in words from a text file, word by word or char by char 【发布时间】:2011-04-12 11:51:58 【问题描述】:我一直在谷歌上搜索并阅读我的书,并尝试编写代码来阅读文本文件并处理其中的单词,一个接一个,所以我可以按字母顺序排列它们并保持计数用了多少个词,一个词用了多少。我似乎无法让我的 GetNextWord() 函数正常工作,这让我发疯了。
我需要一个接一个地读取单词,如果是大写,则将每个字母转换为小写。我知道如何做到这一点,并且已经成功地做到了。它只是逐个字符地获取单词并将其放入阻止我的字符串中。
这是我最近的一次尝试:任何帮助都会非常棒,或者提供有关如何逐字读取输入文件的教程的链接。 (单词是字母字符 a-z 和 '(不要)以空格、逗号、句点、; 、 : 等结尾......
void GetNextWord()
string word = "";
char c;
while(inFile.get(c))
while( c > 64 && c < 123 || c == 39)
if((isupper(c)))
c = (tolower(c));
word = word + c;
outFile << word;
【问题讨论】:
另外,在你的 while 条件中加上括号以清楚地定义它们。 不要使用不可移植的幻数。使用 'A' 或 'Z' 或任何 39 应该是的。 学习使用调试器,或将std::cout << "c " << (int)c << '\n';
、std::cout << "word is now '" << word << "'\n";
等放入您的函数中,这样您就可以看到它正在执行的每个步骤。故障排除技巧比回答这个问题更重要。
文件是否包含连字符(意思是跨越换行符的单词)?
【参考方案1】:
您可以使用>>
运算符逐字读取文件。例如,请参阅此链接:http://www.daniweb.com/forums/thread30942.html。
我在这里摘录了他们的例子:
ifstream in ( "somefile" );
vector<string> words;
string word
if ( !in )
return;
while ( in>> word )
words.push_back ( word );
【讨论】:
但该运算符使用与所询问的单词不同的定义。【参考方案2】:你的逻辑是错误的。只要c
没有改变,内部循环就会运行,并且其中没有任何东西会改变c
。
你为什么有两个循环呢?我想你可能会对这个函数是应该读取下一个单词还是所有单词感到困惑。尝试将这些问题分开,将它们放入不同的函数中(其中一个正在调用另一个)。我发现以自上而下的顺序处理此类问题最容易:
while(inFile.good())
std::string word = GetNextWord(inFile);
if(!word.empty())
std::cout << word << std::endl;
现在通过定义GetNextWord()
来填补空白,以读取直到下一个单词边界的所有内容。
【讨论】:
我会试一试并报告我的结果,谢谢【参考方案3】:我个人喜欢使用std::getline(std::istream&, std::string&)
读取输入(在<string>
标头中,但您当然还需要#include
流标头)。
此函数在换行符处中断,根据您的问题定义,换行符是空格。但这不是您问题的全部答案。读入文本行后,您将需要使用string operations 或标准算法将字符串分解为单词。或者你可以手动循环字符串。
胆量大概是这样的:
std::string buffer;
while (std::getline(std::cin, buffer)
// break each line into words, according to problem spec
【讨论】:
如果文本中有连字符,这可能会出现问题。 像“back-scatter”这样的连字符并不重要,因为问题规范定义了它是算作一个词还是两个词。但是,如果我正确理解 Space_C0wb0y ,那么在下一行连字符的单词将需要比我所展示的更多的逻辑。由于这个程序听起来很像家庭作业,我怀疑这将是有效的输入,但如果是,那么就需要处理这样的输入。【参考方案4】:我用
// str is a string that holds the line of data from ifs- the text file.
// str holds the words to be split, res the vector to store them in.
while( getline( ifs, str ) )
split(str, res);
void split(const string& str, vector<string>& vec)
typedef unsigned int uint;
const string::size_type size(str.size());
uint start(0);
uint range(0);
/* Explanation:
* Range - Length of the word to be extracted without spaces.
* start - Start of next word. During initialization, starts at space 0.
*
* Runs until it encounters a ' ', then splits the string with a substr() function,
* as well as making sure that all characters are lower-case (without wasting time
* to check if they already are, as I feel a char-by-char check for upper-case takes
* just as much time as lowering them all anyway.
*/
for( uint i(0); i < size; ++i )
if( isspace(str[i]) )
vec.push_back( toLower(str.substr(start, range + 1)) );
start = i + 1;
range = 0;
else
++range;
vec.push_back( toLower(str.substr(start, range)) );
我不确定这对您是否特别有帮助,但我会尝试。 toLower 函数是一个快速函数,它只使用 ::toLower() 函数。这会读取每个字符直到一个空格,然后将其填充到一个向量中。我不完全确定你对 char by char 的意思。
你想一次提取一个单词字符吗?或者您想在进行过程中检查每个字符?或者你的意思是你想提取一个词,完成,然后回来?如果是这样,我会 1) 无论如何推荐一个向量,并且 2) 让我知道,以便我可以重构代码。
【讨论】:
我最初的计划是一次一个字符一个字符地读入一个单词,当它遇到空格或任何标点符号时,它将停止获取该单词,将所有这些字符变成一个字符串并发送字符串到我的其他函数以进行进一步处理。将所有大写字母变为小写字母。 IE“不要”会变成“不要”。【参考方案5】:如果 c == 'a',什么会终止你的内部循环? 'a' 的 ASCII 值是 97。
【讨论】:
如果 c == a 那么它不会终止内部循环。如果字符不是 A-Z、a-z 和 ',则内部循环终止以上是关于C++ 从文本文件中逐字读取单词或逐字符读取单词的主要内容,如果未能解决你的问题,请参考以下文章