我有一个文件,我应该读取每一行并将其存储在数组的结构中,我正在读取文件,但结果是混合的,因为数据是用逗号分隔的,我如何让它读取用逗号分隔的行?
struct Data{
std::string a;
std::string b;
std::string c;
}
int main(){
Data cd[100];
std::ifstream inFile;
std::string data;
inFile.open("data.txt");
if(inFile.good()){
while(getline(inFile, data)){ //when I add, ',' right after data nothing shows up
std::stringstream ss(data);
ss >>cd[0].a >> cd[0].b >> cd[0].c;
std::cout <<cd[0].a<<std::endl;
}
}
else{
std::cout << "can't open" << std::endl;
}
inFile.close();
//close the file
return 0;
}
答案 0 :(得分:0)
你在struct
之后错过了一个分号,并且在每个循环期间总是覆盖100个结构数组中的第一个结构:最简单的解决方案是创建一个索引计数器,你将随之增加每一行。
要拆分用户定义的分隔符,C ++标准库没有预先制作的功能:要么使用boost,要么滚动自己的解决方案。
即。像这样的东西
#include <string>
#include <fstream>
#include <iostream>
struct Data {
std::string a;
std::string b;
std::string c;
};
int main() {
Data cd[100];
size_t index = 0;
std::ifstream inFile;
std::string data;
inFile.open("data.txt");
if (inFile.good()) {
while (getline(inFile, data)) { //when I add, ',' right after data nothing shows up
std::string::size_type startPos = data.find_first_not_of(",", 0); /* skip leading delimiters */
std::string::size_type endPos = data.find_first_of(",", startPos); /* find first real delimiter */
cd[index].a = data.substr(startPos, endPos - startPos); /* save substring */
startPos = data.find_first_not_of(",", endPos); /* find next start position */
endPos = data.find_first_of(",", startPos); /* find next endPosition */
cd[index].b = data.substr(startPos, endPos - startPos); /* save substring */
startPos = data.find_first_not_of(",", endPos); /* find next start position */
endPos = data.find_first_of(",", startPos); /* find next endPosition */
cd[index].c = data.substr(startPos, endPos - startPos); /* save substring */
++index;
}
}
else {
std::cout << "can't open" << std::endl;
}
inFile.close();
//close the file
return 0;
}
限制:根据您的结构,它假定您的文件中每行有3个值 - 并且根据您的结构数组,不应超过100行。我建议使用漂亮的std::vector而不是普通的旧C风格数组。
答案 1 :(得分:0)
这可能会在很多情况下帮助你。打开文件并逐行读取文本到std :: string。然后这个有用的实用功能很好用
<强> Utility.h 强>
#ifndef UTILITY_H
#define UTILITY_H
#include <string>
class Utility {
public:
static std::vector<std::string> splitString( const std::string& strStringToSplit, const std::string& strDelimiter, const bool keepEmpty = true );
private:
Utility(); // Private - Not A Class Object
Utility( const Utility& c ); // Not Implemented
Utility& operator=( const Utility& c); // Not Implemented
};
#endif // UTILITY_H
<强> Utility.cpp 强>
#include "Utility.h"
std::vector<std::string> Utility::splitString( const std::string& strStringToSplit, const std::string& strDelimiter, const bool keepEmpty ) {
std::vector<std::string> vResult;
if ( strDelimeter.empty() ) {
vResult.push_back( strStringToSplit );
return vResult;
}
std::string::const_iterator itSubStrStart = strStringToSplit.begin(), itSubStrEnd;
while ( true ) {
itSubStrEnd = search( itSubStrStart, strStringToSplit.end(), strDelimiter.begin(), strDelimiter.end() );
std::string strTemp( itSubStrStart, itSubStrEnd );
if ( keepEmpty || !strTemp.empty() ) {
vResult.push_back( strTemp );
}
if ( itSubStrEnd == strStringToSplit.end() ) {
break;
}
itSubStrStart = itSubStrEnd + strDelimeter.size();
}
return vResult;
} // stringToSplit
要在任何类或函数中使用它,您只需包含Utility.h
<强>的main.cpp 强>
#include <iostream>
#include "Utility.h"
int main() {
std::string welcome( "Hello,World,How,Are,You,Today,!" );
std::vector<std::string> result;
result = Utility::splitString( welcome, std::string( "," ) );
for ( unsigned u = 0; u < result.size(); u++ ) {
std::cout << result.at( u ) << std::endl;
}
return 0;
}
你的打印出来应该是:
Hello
World
How
Are
You
Today
!
每个单词以逗号分隔,不带空格。您可以使用任何字符作为定义分隔符,它可以是空格,冒号,分号,连字符等。这是一个非常有用且方便的实用程序函数,可以在许多情况下一次又一次地使用;特别是当您尝试解析文件或字符串时。现在你必须要记住这将解析字符串的事实。您仍然必须逐行读取文件并将每一行存储到一个字符串中,然后创建一个字符串向量,用于存储此函数的结果。
首先在类中使用此函数可能看起来不太直观,但我有大约十几个有用的实用程序函数,用于将字符串转换为大写和小写,将字符串转换为不同的基本数据类型,如int,浮动,甚至将用逗号分隔的一串值转换为vec2,vec3&amp; vec4对象,其中所有这些函数在无法实例化的类中声明为静态。它充当容器或包装器,几乎像命名空间。换句话说,我的大多数独立字符串操作函数都会被大量使用,我最终会在这个类中包含它们。
答案 2 :(得分:0)
你回答说你需要用作结构,你仍然可以。有不同的方法。现在根据你的问题和你提供的例子你的struct有3个字符串,你需要它们的数组;让我们假设每行文本都有3个由逗号分隔的字符串值。我创建了一个名为custom.txt的文本文件,这是它的内容:
<强> custom.txt 强>
Hello,world,how
are,you,today
每一行都有三个单词,用逗号分隔,没有空格:现在,我将演示如何使用我在上一个答案中显示的实用函数,在读取一行文本后拆分字符串然后解析它填充你的结构数组。
#include <iostream>
#include <fstream>
#include <tchar.h>
#include <conio.h>
#include "Utility.h"
struct MyStruct {
std::string str1;
std::string str2;
std::string str3;
}; // MyStruct
void parseLine( std::string& strLine, std::vector<std::string>& results, MyStruct& myStruct ) {
results = Utility::splitString( strLine, std::string( "," ) );
myStruct.str1 = results[0];
myStruct.str2 = results[1];
myStruct.str3 = results[2];
} // parseLine
bool readLine( std::fstream& in, std::string& line ) {
if ( in.eof() ) {
return false;
}
std::getline( in, line );
return true;
} // readLine
int main() {
std::string filename( "custom.txt" );
std::string strLine;
sd::fstream fin;
fin.open( filename.c_str(), std::ios_base::in ) {
if ( !fin.is_open() ) {
std::cout << "Error reading in file " << filename << std::endl;
return -1;
}
std::vector<std::string> results;
// Since I only have 2 lines in this file
MyStruct myStruct[2];
int line = 0;
while ( readLine( fin, strLine ) ) {
parseLine( strLine, results, myStruct[line] );
line++;
}
std::cout << "Results: " << std::endl;
for ( unsigned u = 0; u < 2; u++ ) {
std::cout << myStruct[u].str1 << " " << myStruct[u].str2 << " " << myStruct[u].str3 << std::endl;
}
std::cout << std::endl;
std::cout << "Press any key to quit." << std::endl;
_getch();
return 0;
} // main
关于这个特定实现需要注意的一件事是,循环是根据结构中确切存储的值(3个字符串)确定的,并且数组中的数量必须与行数相匹配保存的文件。这必须提前知道。如果你没有提前知道文件中有多少行,那么我认为你不能使用数组,因为它们在编译时必须是一个常量整数类型。如果您在堆上使用带有指针的动态内存,那么您可以自动化此系统,而无需知道单行上有多少元素,或者不知道特定文件中有多少行。