Skip to content

Instantly share code, notes, and snippets.

@komasaru
Created March 7, 2020 04:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save komasaru/ae27e6ff2b86f9bef6e06b355b5766bc to your computer and use it in GitHub Desktop.
Save komasaru/ae27e6ff2b86f9bef6e06b355b5766bc to your computer and use it in GitHub Desktop.
C++ source code to read csv data(v2).
#include "csv.hpp"
#include <iostream>
#include <string>
#include <vector>
// getline: 1行取得し、必要に応じて伸張
int Csv::getline(std::string& str) {
char c;
for (line = ""; fin.get(c) && !endofline(c); )
line += c;
split();
str = line;
return !fin.eof();
}
// endofline: \r, \n, \r\n, EOF をチェックして捨てる
int Csv::endofline(char c) {
int eol;
eol = (c == '\n' || c == '\n');
if (c == '\r') {
fin.get(c);
if (!fin.eof() && c != '\n')
fin.putback(c); // 読みすぎ
}
return eol;
}
// split: 行をフィールド単位に分割
int Csv::split() {
std::string fld;
unsigned int i, j;
nfield = 0;
if (line.length() == 0)
return 0;
i = 0;
do {
if (i < line.length() && line[i] == '"')
j = advquoted(line, fld, ++i); // クォートをスキップ
else
j = advplain(line, fld, i);
if (nfield >= field.size())
field.push_back(fld);
else
field[nfield] = fld;
nfield++;
i = j + 1;
} while (j < line.length());
return nfield;
}
// advquoted: クォートでくくられたフィールド: 次のセパレータのインデックスを返す
int Csv::advquoted(const std::string& s, std::string& fld, int i) {
unsigned int j;
fld = "";
for (j = i; j < s.length(); j++) {
if (s[j] == '"' && s[++j] != '"') {
unsigned int k = s.find_first_of(fieldsep, j);
if (k > s.length()) // セパレータが見つからなかった
k = s.length();
for (k -= j; k-- > 0; )
fld += s[j++];
break;
}
fld += s[j];
}
return j;
}
// advplain: クォートでくくられていないフィールド: 次のセパレータのインデックスを返す
int Csv::advplain(const std::string& s, std::string& fld, int i) {
unsigned int j;
j = s.find_first_of(fieldsep, i); // セパレータを探す
if (j > s.length()) // 見つからなかった
j = s.length();
fld = std::string(s, i, j - i);
return j;
}
// getfield: n番目のフィールドを返す
std::string Csv::getfield(unsigned int n) {
if (n < 0 || n >= nfield)
return "";
else
return field[n];
}
#ifndef TEST_CSV_CSV_HPP_
#define TEST_CSV_CSV_HPP_
#include <iostream>
#include <string>
#include <vector>
// CSV クラス
class Csv { // カンマで区切られた値を読んで解析する
std::istream& fin; // 入力ファイルポインタ
std::string line; // 入力行
std::vector<std::string> field; // フィールド文字列
unsigned int nfield; // フィールド数
std::string fieldsep; // セパレータ文字
int split();
int endofline(char);
int advplain(const std::string& line, std::string& fld, int);
int advquoted(const std::string& line, std::string& fld, int);
public:
Csv(std::istream& fin = std::cin, std::string sep = ",") :
fin(fin), fieldsep(sep) {}
int getline(std::string&);
std::string getfield(unsigned int n);
int getnfield() const { return nfield; }
};
#endif
/*********************************************
* CSV 読み込みテスト *
*********************************************/
#include "csv.hpp"
#include <iostream>
#include <string>
#include <vector>
// TestCsv main: Csv クラスのテスト
int main(void) {
std::string line;
Csv csv;
while (csv.getline(line) != 0) {
std::cout << "line = '" << line << "'\n";
for (int i = 0; i < csv.getnfield(); i++)
std::cout << "field[" << i << "] = '"
<< csv.getfield(i) << "'\n";
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment