#c #list #csv #file
#c #Список #csv #файл
Вопрос:
В CSV-файле на строку приходится по три ячейки. Я пытаюсь прочитать каждую ячейку в закрытую переменную-член класса, который я создал. Я не могу понять, как прочитать всю ячейку A1 в одну строковую переменную, затем B1 в двойную переменную и C3 в другую отдельную двойную переменную. Я поиграл с getline и перегрузкой ostream operator >> но безрезультатно.
class LinkedTemp
{
private:
// the struct that will temporarily hold all items being read from file
struct Govee
{
string date;
double temperature;
double humidity;
struct Govee *next;
};
Govee *head; // pointer to head of all ListNodes
string time;
double temp;
double humi;
public:
// default constructor
// set private members
LinkedTemp()
{
head = nullptr;
time = "";
temp = 0.0;
humi = 0.0;
}
void append()
{
Govee *nodePtr, *newNode = nullptr;
// create a newNode and fill it with data (node will then be appended)
newNode = new Govee;
newNode->date = this->time;
newNode->temperature = this->temp;
newNode->humidity = this->humi;
newNode->next = nullptr;
// start at beginning of list
nodePtr = head;
// if list does not exist, make node the first node
if (!head)
head = newNode;
else
{
// traverse the list
while (nodePtr != nullptr)
nodePtr = nodePtr->next;
// append newNode onto the end of the list
nodePtr->next = newNode;
}//end else statement
}//end append function
// supports
// cout << object
friend ostream amp;operator << (ostream amp;strm, LinkedTemp amp;r)
{
strm << "Date: " << r.time << endl;
strm << "Temp: " << r.temp << endl;
strm << "Humi: " << r.humi << endl;
return strm;
}
// will fill all public member variables of class
// file >> object
friend istream amp;operator >> (istream amp;strm, LinkedTemp amp;r)
{
getline(strm, r.time);
strm >> r.temp;
strm >> r.humi;
return strm;
}
}; // end class
И в основном у меня есть что-то вроде:
int main()
{
//open file
fstream file;
file.open("Feb.csv");
// create LinkedTemp object
LinkedTemp list;
// read file into LinkedTemp object
// while (file)
//{
file >> list;
//}
// append the information into the list
// list.append();
// display all the contents of the list
cout << list;
return 0;
}
Но я либо читаю всю строку, либо только часть 2020-02-07 файла .csv, а не всю 2020-02-07 00:00:00. Формат файла .csv см. в прикрепленном изображении. Изображение файла .csv
Комментарии:
1. Сначала показанный код вызывает getline . Это считывает всю строку в
time
. Все три значения. Затем показанный код снова использует>>
оператор во входном потоке. Имеет ли это смысл для вас? Итак, первая строка в csv-файле находится в строке. Это становится «временем». Вместо этого код использует>>
для чтения все, что следует за первой строкой, как слова, разделенные пробелами , в файле csv. Общий итог: первая прочитанная строка становится строкой.>>
считывает два слова после первой строки, которые должны быть разделены пробелами. Остальная часть файла игнорируется. Как сказал бы мистер Спок: это крайне нелогично.2. Не могли бы вы сделать отступ в своем коде? Трудно читать все в столбце 1.
3. @John Kugelman — спасибо!
Ответ №1:
Вы можете сделать это , сохранив все токены в vector
of vector
of strings
. Это создаст 2-мерную строковую матрицу, которую вы можете обработать в любом случае, когда захотите позже. Следующий код — это то, что вам нужно:
#include <string>
#include <fstream>
#include <sstream>
#include <iostream>
struct data{
std::string s0;
double d0;
double d1;
};
int main()
{
// create a vector of your class to store all of your data,
// in your case it's a list so you can tweak it according to your needs
std::vector <data> vec_data;
// create a vector of vectors of strings to store all the tokens you read from file
std::vector <std::vector<std::string>> vec_tokens;
std::ifstream is("file.csv");
if(is.is_open()) {
std::string line;
while(getline(is, line)) {
std::stringstream ss_line(line);
std::string token;
std::vector <std::string> vec_temp;
while(getline(ss_line, token, ',')) {
vec_temp.push_back(token);
}
vec_tokens.push_back(vec_temp);
}
}
// convert all tokens into data
for(auto i: vec_tokens) {
vec_data.push_back({i[0], std::stod(i[1]), std::stod(i[2])});
}
// clean up tokens
vec_tokens.clear();
// check if it worked
for(auto i: vec_data) {
std::cout << i.s0 << " , " << i.d0 << " , " << i.d1 << std::endl;
}
return 0;
}
Возможно, вам потребуется обработать исключения (например, для std::stod
) в случае, если программе предоставлен мусорный CSV-файл.