C++ 如何使用stringstream将数据正确存储到数组结构中?

C++ 如何使用stringstream将数据正确存储到数组结构中?,c++,csv,c++11,io,stringstream,C++,Csv,C++11,Io,Stringstream,我想知道如何将CSV文件中的数据存储到结构化数组中。我意识到我需要使用getline等等,到目前为止,我已经想出了以下代码: 这是我的结构: struct csvData //creating a structure { string username; //creating a vector of strings called username float gpa; //creating a vector of floats called gpa int age;

我想知道如何将CSV文件中的数据存储到结构化数组中。我意识到我需要使用getline等等,到目前为止,我已经想出了以下代码:

这是我的结构:

struct csvData //creating a structure
{
     string username; //creating a vector of strings called username
     float gpa; //creating a vector of floats called gpa
     int age; //creating a vector of ints called age
};
这是我的数据读取器和存储数据的部件:

csvData arrayData[10];
string data;
ifstream infile; //creating object with ifstream
infile.open("datafile.csv"); //opening file
if (infile.is_open()) //error check

int i=0;
while(getline(infile, data));
{
    stringstream ss(data);
    ss >> arrayData[i].username;
    ss >> arrayData[i].gpa;
    ss >> arrayData[i].age;
    i++;
}
此外,这就是我试图打印信息的方式:

for (int z = 0; z<10; z++)
    {
        cout<<arrayData[z].username<<arrayData[z].gpa<<arrayData[z].age<<endl;
    }

解析代码中没有任何内容实际尝试将单行解析为各个字段:

while(getline(infile, data));
{
这将正确地将输入文件中的一行读入
数据
字符串

 stringstream ss(data);

 ss >> arrayData[i].username;
 ss >> arrayData[i].gpa;
 ss >> arrayData[i].age;
您需要尝试如何使用一行逗号分隔的值,如您在问题中所示:

 Steven,3.2,20
并用逗号将该字符串分隔为各个值。关于
>
操作符,没有什么可以做到这一点<代码>运算符>>使用空格而不是逗号分隔输入。您的怀疑是正确的,您没有正确解析输入

这是一项你必须自己完成的任务。我想,作为一种学习经验,或者作为一项家庭作业,您可能希望自己手动完成这项工作。好吧,那你自己做吧。在
数据中只有一行。使用C++提供的任意数量的工具:<代码> STD::String <代码>查找()(<代码>方法),或者<代码>::从<代码> <代码>查找“< <代码> >”,在<>代码>数据< /COD>字符串中找到每个逗号,然后提取每个逗号之间的字符串的各个部分。然后,您仍然需要将这两个数字字段转换为适当的数据类型。这就是当您将它们中的每一个放入
std::istringstream
,并使用
operator>
将它们转换为数字类型的时候

但是,说了这么多之后,还有另一种肮脏的伎俩,可以快速解决这个问题。回想一下,
数据
中的原始行包含

 Steven,3.2,20
您只需将逗号替换为空格,将其转换为:

 Steven 3.2 20
用空格替换逗号对于
std::replace()
,或者一个小循环来说都很简单。然后,您可以将结果填充到
std::istringstream
,并使用您已经编写的代码,使用
操作符>>
将各个空格分隔的值提取到离散变量中

只是一个小小的警告:如果这确实是你的家庭作业,写代码来手动解析和提取逗号分隔的值,这并不能保证你的老师会给你满分,因为你采取了肮脏的伎俩方法…

正在建设中

Ton,很好的尝试,很好的完整问题。答案如下:

1) 循环后面有一个分号:

while(getline(infile, data));
删除它

我是怎么容易弄明白的?我编译时启用了所有警告,如下所示:

C02QT2UBFVH6-lm:~ gsamaras$ g++ -Wall main.cpp
main.cpp:24:33: warning: while loop has empty body [-Wempty-body]
    while(getline(infile, data));
                                ^
main.cpp:24:33: note: put the semicolon on a separate line to silence this warning
1 warning generated.
if (!infile.is_open())
  cerr << "Error Message by Mr. Tom\n";
事实上,你也应该在没有
-Wall
的情况下得到警告,但是使用它,它也会对你有好处

2) 然后,你读了一些元素,但不是10,那么你为什么要打印10呢?打印您实际阅读的内容,即
i

当您尝试打印数组的所有10个元素时,您打印的是未初始化的元素,因为您没有初始化结构数组

此外,
datafile.csv
中的行数少于10行。因此,您开始填充数组,但当文件没有更多行时,您停止了填充。因此,数组中的某些元素(最后6个元素)保持未初始化状态

打印未初始化的数据会导致未定义的行为,这就是您看到垃圾值的原因

3) 还包括:

if (infile.is_open()) //error check
可以这样写:

C02QT2UBFVH6-lm:~ gsamaras$ g++ -Wall main.cpp
main.cpp:24:33: warning: while loop has empty body [-Wempty-body]
    while(getline(infile, data));
                                ^
main.cpp:24:33: note: put the semicolon on a separate line to silence this warning
1 warning generated.
if (!infile.is_open())
  cerr << "Error Message by Mr. Tom\n";
输出:

C02QT2UBFVH6-lm:~ gsamaras$ g++ -Wall main.cpp
C02QT2UBFVH6-lm:~ gsamaras$ ./a.out 
username,gpa,age00
Steven,3.2,2000
Will,3.4,1900
Ryan,3.6,1900
Tom,3,1900

但是等一下,现在它可以工作了,但为什么会这样:

while(getline(infile, data));
{
   ...
}
不是吗

因为,在循环后加上分号相当于:

while()
{ 
  ;
}
因为正如您可能已经知道的,只有一条线作为主体的循环不需要花括号

我认为它是循环的主体(即您使用的部分
std::stringstream
)发生了什么

它被处决了但只有一次

你看,一对花括号就意味着什么,它是一个匿名作用域/块

因此:

{
    stringstream ss(data);
    ss >> arrayData[i].username;
    ss >> arrayData[i].gpa;
    ss >> arrayData[i].age;
    i++;
}
在它的一个上运行,而不是while循环的一部分,正如您所希望的那样


有什么原因吗?!因为您在循环之前声明了
i

这并没有解决核心问题,即
ss>>arrayData[i].username吃掉了整个输入行,接下来的两次提取都失败了。@PeteBecker该死,远远没有成功!谢谢,印刷没用。有什么想法吗?我一直在尝试,但是我一直在尝试解析第一个字符串。为什么不起作用:while(getline(infle,data,“,”),因为不是文件中的每个值后面都跟有逗号字符。每三个值后跟一个换行符。这就是为什么文件中有多行。你看,一个程序做的正是你告诉它做的,而不是你想要它做的。你让它一直读到下一个逗号字符。这就是它要做的。如果它看到一个换行符,你的程序就不会太在意了,它会一直读到看到逗号为止,所以它会一直读到下一行看到逗号为止,将所有内容和前一行的最后一个值压缩成一个字符串。嘿,伙计,我在解析数据文件时遇到了很多麻烦。你有没有办法给我一些示例代码的提示?我已经被困了5天了…我的答案已经给出了两种不同的解析文件的方法。其中一个问题只需要在您已经编写并包含在问题中的代码中再添加一行代码。你需要重读我的答案。