C++ Read file line by line then split each line using the delimiter
我想逐行读取一个txt文件,并且在读取了每一行之后,我想根据选项卡" \ t"拆分行,并将每个部分添加到结构中的元素中。
我的结构是1 * char和2 * int
1 2 3 4 5 6 | struct myStruct { char chr; int v1; int v2; } |
其中chr可以包含多个字符。
一行应该是这样的:
1 | randomstring TAB number TAB number NL |
尝试:
注意:如果chr可以包含多个字符,则使用字符串表示。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | std::ifstream file("plop"); std::string line; while(std::getline(file, line)) { std::stringstream linestream(line); std::string data; int val1; int val2; // If you have truly tab delimited data use getline() with third parameter. // If your data is just white space separated data // then the operator >> will do (it reads a space separated word into a string). std::getline(linestream, data, '\\t'); // read up-to the first tab (discard tab). // Read the integers using the operator >> linestream >> val1 >> val2; } |
除非您也打算将此结构用于C,否则我将用std :: string替换预期的char *。
接下来,由于我打算能够从流中读取它,因此我将编写以下函数:
1 2 3 4 5 | std::istream & operator>>( std::istream & is, myStruct & my ) { if( std::getline(is, my.str, '\\t') ) return is >> my.v1 >> my.v2; } |
以str作为std :: string成员。这将使用tab作为第一个定界符写入您的结构,然后任何空格定界符将在接下来的两个整数之前执行。 (您可以强制它使用选项卡)。
要逐行阅读,您可以继续阅读这些内容,或者先将一行阅读为一个字符串,然后将该字符串放入istringstream中并调用上面的内容。
您将需要决定如何处理失败的读取。上面任何失败的读取都将使流处于失败状态。
1 2 3 4 5 6 7 8 9 10 11 | std::ifstream in("fname"); while(in){ std::string line; std::getline(in,line); size_t lasttab=line.find_last_of('\\t'); size_t firsttab=line.find_last_of('\\t',lasttab-1); mystruct data; data.chr=line.substr(0,firsttab).c_str(); data.v1=atoi(line.substr(firsttab,lasttab).c_str()); data.v2=atoi(line.substr(lasttab).c_str()); } |
我在遵循这里的一些建议时遇到了一些困难,因此我发布了一个完整的示例,该示例在制表符分隔的文件上重载结构的输入和输出运算符。另外,它还从
我相信,这与遵循操作符语义的过程一样简单。
成对
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | #ifndef PAIRWISE_VALUE #define PAIRWISE_VALUE #include <string> #include <iostream> struct PairwiseValue { std::string labelA; std::string labelB; float value; }; std::ostream& operator<<(std::ostream& os, const PairwiseValue& p); std::istream& operator>>(std::istream& is, PairwiseValue& p); #endif |
成对的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | #include"pairwise.h" std::ostream& operator<<(std::ostream& os, const PairwiseValue& p) { os << p.labelA << '\\t' << p.labelB << '\\t' << p.value << std::endl; return os; } std::istream& operator>>(std::istream& is, PairwiseValue& p) { PairwiseValue pv; if ((is >> pv.labelA >> pv.labelB >> pv.value)) { p = pv; } return is; } |
测试文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | #include <fstream> #include"pairwise.h" int main(const int argc, const char* argv[]) { std::ios_base::sync_with_stdio(false); // disable synch with stdio (enables input buffering) std::string ifilename; if (argc == 2) { ifilename = argv[1]; } const bool use_stdin = ifilename.empty(); std::ifstream ifs; if (!use_stdin) { ifs.open(ifilename); if (!ifs) { std::cerr <<"Error opening input file:" << ifilename << std::endl; return 1; } } std::istream& is = ifs.is_open() ? static_cast<std::istream&>(ifs) : std::cin; PairwiseValue pv; while (is >> pv) { std::cout << pv; } return 0; } |
编译中
1 2 | g++ -c pairwise.cc test.cc g++ -o test pairwise.o test.o |
用法
1 2 | ./test myvector.tsv cat myvector.tsv | ./test |