[英]C++ string length different than java string length. JNI Android
[英]How to read a CSV dataset in which each row has a distinct length. C++
我是 C++ 的新手,正在研究如何從 csv 文件中讀取數據。 我想將以下 csv 數據讀入向量。 每行是一個向量。 文件名為path.csv:
0
0 1
0 2 4
0 3 6 7
我使用以下 function:
vector<vector<int>> read_multi_int(string path) {
vector<vector<int>> user_vec;
ifstream fp(path);
string line;
getline(fp, line);
while (getline(fp, line)) {
vector<int> data_line;
string number;
istringstream readstr(line);
while (getline(readstr, number, ',')) {
//getline(readstr, number, ',');
data_line.push_back(atoi(number.c_str()));
}
user_vec.push_back(data_line);
}
return user_vec;
}
vector<vector<int>> path = read_multi_int("C:/Users/data/paths.csv");
打印功能:
template <typename T>
void print_multi(T u)
{
for (int i = 0; i < u.size(); ++i) {
if (u[i].size() > 1) {
for (int j = 0; j < u[i].size(); ++j) {
//printf("%d ", u[i][j]);
cout << u[i][j] << " ";
}
printf("\n");
}
}
printf("\n");
}
然后我得到
0 0 0
0 1 0
0 2 4
0 3 6 7
在行的末尾添加零。 是否可以只從 csv 文件中讀取數據而不添加那些額外的零? 謝謝!
根據您看到的 output 和帶有“,”逗號的代碼,我相信您的實際輸入數據確實如下所示:
A,B,C,D
0,,,
0,1,,
0,2,4,
0,3,6,7
所以主要的變化是用strtol
替換atoi
,因為atoi
在解析數字失敗時總是返回0
,但是使用strtol
我們可以檢查解析是否成功。
這意味着解決方案如下:
vector<vector<int>> read_multi_int(string path) {
vector<vector<int>> user_vec;
ifstream fp(path);
string line;
getline(fp, line);
while (getline(fp, line)) {
vector<int> data_line;
string number;
istringstream readstr(line);
while (getline(readstr, number, ',')) {
char* temp;
char numberA[30];
int numberI = strtol(number.c_str(), &temp, 10);
if (temp == number || *temp != '\0' ||
((numberI == LONG_MIN || numberI == LONG_MAX) && errno == ERANGE))
{
// Could not convert
}else{
data_line.emplace_back(numberI);
}
}
user_vec.emplace_back(data_line);
}
return user_vec;
}
然后顯示您的結果:
vector<vector<int>> path = read_multi_int("C:/Users/data/paths.csv");
for (const auto& row : path)
{
for (const auto& s : row) std::cout << s << ' ';
std::cout << std::endl;
}
給出預期的 output:
0
0 1
0 2 4
0 3 6 7
已經很好了,但是有一個明顯的錯誤和另一個錯誤在你的打印 function 中。請看,我是如何使用基於 for 循環的簡單范圍的 output 值的。
如果您的源文件不包含逗號( ','
),但包含不同的分隔符,那么您需要使用此不同的分隔符調用std::getline
,在您的情況下為空白( ' '
)。 請 在此處閱讀有關std::getline
的信息。
如果我們然后使用以下輸入
Header
0
0 1
0 2 4
0 3 6 7
使用更正后的程序。
#include <vector>
#include <fstream>
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
vector<vector<int>> read_multi_int(string path) {
vector<vector<int>> user_vec;
ifstream fp(path);
string line;
getline(fp, line);
while (getline(fp, line)) {
vector<int> data_line;
string number;
istringstream readstr(line);
while (getline(readstr, number, ' ')) {
//getline(readstr, number, ',');
data_line.push_back(atoi(number.c_str()));
}
user_vec.push_back(data_line);
}
return user_vec;
}
int main() {
vector<vector<int>> path = read_multi_int("C:/Users/data/paths.csv");
for (vector<int>& v : path) {
for (int i : v) std::cout << i << ' ';
std::cout << '\n';
}
}
然后我們收到這個 output:
0
0 1
0 2 4
0 3 6 7
這是正確的,但不幸的是與您顯示的 output 不同。
因此,您的 output 例程或其他一些代碼也可能有問題。
除了。 如果沒有逗號,那么您可以使用提取運算符>>
來利用格式化輸入函數。 這將讀取您的輸入直到下一個空格並將其自動轉換為數字。
此外,強烈建議在定義期間初始化所有變量。 你應該總是這樣做。
修改您的代碼以使用格式化輸入、初始化,也許還有更好的變量名,那么它可能如下所示。
#include <vector>
#include <fstream>
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
vector<vector<int>> multipleLinesWithIntegers(const string& path) {
// Here we will store the resulting 2d vector
vector<vector<int>> result{};
// Open the file
ifstream fp{ path };
// Read header line
string line{};
getline(fp, line);
// Now read all lines with numbers in the file
while (getline(fp, line)) {
// Here we will store all numbers of one line
vector<int> numbers{};
// Put the line into an istringstream for easier extraction
istringstream sline{ line };
int number{};
while (sline >> number) {
numbers.push_back(number);
}
result.push_back(numbers);
}
return result;
}
int main() {
vector<vector<int>> values = multipleLinesWithIntegers("C:/Users/data/paths.csv");
for (const vector<int>& v : values) {
for (const int i : v) std::cout << i << ' ';
std::cout << '\n';
}
}
而且,下一步將是使用一些更高級的樣式:
#include <vector>
#include <fstream>
#include <iostream>
#include <string>
#include <sstream>
#include <iterator>
auto multipleLinesWithIntegers(const std::string& path) {
// Here we will store the resulting 2d vector
std::vector<std::vector<int>> result{};
// Open the file and check, if it could be opened
if (std::ifstream fp{ path }; fp) {
// Read header line
if (std::string line{}; getline(fp, line)) {
// Now read all lines with numbers in the file
while (getline(fp, line)) {
// Put the line into an istringstream for easier extraction
std::istringstream sline{ line };
// Get the numbers and add them to the result
result.emplace_back(std::vector(std::istream_iterator<int>(sline), {}));
}
}
else std::cerr << "\n\nError: Could not read header line '" << line << "'\n\n";
}
else std::cerr << "\n\nError: Could not open file '" << path << "'\n\n'";
return result;
}
int main() {
const std::vector<std::vector<int>> values{ multipleLinesWithIntegers("C:/Users/data/paths.csv") };
for (const std::vector<int>& v : values) {
for (const int i : v) std::cout << i << ' ';
std::cout << '\n';
}
}
編輯
您已經展示了您的 output 例程。 那應該改為:
void printMulti(const std::vector<std::vector<int>>& u)
{
for (int i = 0; i < u.size(); ++i) {
if (u[i].size() > 0) {
for (int j = 0; j < u[i].size(); ++j) {
std::cout << u[i][j] << ' ';
}
std::cout << '\n';
}
}
std::cout << '\n';
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.