在我的C ++代码中,我想从文本文件(* .txt)中读取并对每个条目进行标记。更具体地说,我希望能够从文件中读取单个单词,例如“格式”,“堆栈”,“杰森”,“欧洲”,等。
我选择使用fstream
来执行此任务,而我不知道如何将其设置为我想要使用的分隔符(空格,\n
,以及连字符甚至撇号就像在“麦当劳”中一样。我想空间和\n
是默认分隔符,但连字符不是,但我想把它们当作分隔符,这样在解析文件时,我会把“blah blah xxx animal - cat”中的单词简单地称为“blah”,“blah”,“xxx”,“animal”,“cat”。
也就是说,我希望能够从“堆栈溢出”,“你是”,等,中获取两个字符串,并且仍然能够维护\n
和空间同时作为分隔符。
答案 0 :(得分:19)
istream对待"白色空间"作为分隔符。它使用区域设置来告诉它哪些字符是空白区域。反过来,语言环境包括对字符类型进行分类的ctype facet
。这样的方面看起来像这样:
#include <locale>
#include <iostream>
#include <algorithm>
#include <iterator>
#include <vector>
#include <sstream>
class my_ctype : public
std::ctype<char>
{
mask my_table[table_size];
public:
my_ctype(size_t refs = 0)
: std::ctype<char>(&my_table[0], false, refs)
{
std::copy_n(classic_table(), table_size, my_table);
my_table['-'] = (mask)space;
my_table['\''] = (mask)space;
}
};
一个小测试程序,以显示它的工作原理:
int main() {
std::istringstream input("This is some input from McDonald's and Burger-King.");
std::locale x(std::locale::classic(), new my_ctype);
input.imbue(x);
std::copy(std::istream_iterator<std::string>(input),
std::istream_iterator<std::string>(),
std::ostream_iterator<std::string>(std::cout, "\n"));
return 0;
}
结果:
This
is
some
input
from
McDonald
s
and
Burger
King.
istream_iterator<string>
使用>>
从流中读取单个字符串,因此如果直接使用它们,您应该得到相同的结果。您需要包含的部分是创建语言环境,并使用imbue
使流使用该语言环境。
答案 1 :(得分:1)
您可以使用
istream::getline(char* buffer, steamsize maxchars, char delim)
虽然这只支持单个分隔符。要进一步拆分不同分隔符上的行,可以使用
char* strtok(char* inString, const char* delims)
需要多个分隔符。当你使用strtok时,你只需要第一次传递缓冲区的地址 - 之后只传入一个null,它会给你下一个它给你的令牌,当没有时返回一个空指针更多。
编辑:具体的实现类似于
char buffer[120]; //this size is dependent on what you expect the file to contain
while (!myIstream.eofbit) //I may have forgotten the exact syntax of the end bit
{
myIstream.getline(buffer, 120); //using default delimiter of \n
char* tokBuffer;
tokBuffer = strtok(buffer, "'- ");
while (tokBuffer != null) {
cout << "token is: " << tokBuffer << "\n";
tokBuffer = strtok(null, "'- "); //I don't need to pass in the buffer again because it remembers the first time I called it
}
}