C++でCVSファイルを読み込んだりソートしたり出力したりするサンプルです。


C++の練習
  • CSVファイルを読み込み構造体にデータを設定
  • CSVの内容を第一カラムでソート
  • ソートした内容でCSVファイルを出力
  • 入出力ファイル名はコマンドラインからパラメータで渡す
  • CSVの内容
    • データはダブルコートで囲みカンマ区切りとする
    • カラムの数は固定(インデックス、名前、住所)
    • 行数は不定

C++はあまりやった事がないので、セオリーとかまったくわからないですが!

ソース

//============================================================================
// Name        : CsvIO.cpp
// Author      : ちゃぱてぃ
// Version     :
// Copyright   : ちゃぱてぃ商店IT部
// Description : C++練習:CSVを読み込んでソートして出力する
//============================================================================
 
#include <iostream>
#include <iomanip>
#include <string>
#include <fstream>
#include <stdlib.h>
#include <vector>
#include <algorithm>
 
using namespace std;
 
const char *sep = "\",\""; // セパレータ","形式
 
// 住所構造体
struct Address {
public:
	// インデックス
	int idx;
	// 名前
	string name;
	// 住所
	string address;
};
 
// 住所構造体 < 演算子オーバーロード - 昇順ソート用
bool operator<(const Address& left, const Address& right) {
	return left.idx < right.idx;
}
 
// 住所構造体 > 演算子オーバーロード - 降順ソート用
bool operator>(const Address& left, const Address& right) {
	return left.idx > right.idx;
}
 
// メイン関数
int main(int argc, char *argv[]) {
 
	// 引数を標準出力に出力
	for (int i = 0; i < argc; i++) {
		printf("%d番目の引数 = %s\n", i, argv[i]);
	}
 
	if (argc < 4) {
		cout << "使い方\n"
				"    CvsIO 読み込むファイル名"
				" 出力ファイル名(昇順) 出力ファイル名(降順)";
		return 0;
	}
 
	// 読み込みファイルオープン
	ifstream ifs(argv[1]);
 
	if (ifs.fail()) {
		cerr << "ファイルが存在しません。" << argv[1] << endl;
		exit(0);
	}
 
	string line; // ファイルから読み込んだテキストを入れる
	vector<Address> vec; // 構造体を格納するvector
 
	while (getline(ifs, line)) { // 一行ずつ読み込み
		unsigned int sidx = 1; // ダブルコート囲みなので1からスタート
		unsigned int eidx = 0;
		if (line.size() == 0) {
			// 空行の場合処理しない
			continue;
		}
		if (line.data()[0] != '\"') {
			// 先頭がダブルコート以外の場合処理しない
			continue;
		}
 
		Address adr;
		for (int i = 0; i < 3; i++) {
			eidx = line.find(sep, sidx);
			string val;
			if (eidx == string::npos) {
				// 最後の要素の場合
				val = line.substr(sidx, line.size() - sidx - 1);
			} else {
				val = line.substr(sidx, eidx - sidx);
				sidx = eidx + 3;
			}
 
			// 構造体に値設定
			switch (i) {
			case 0:
				// インデックス
				sscanf(val.data(), "%d", &adr.idx);
				break;
			case 1:
				// 名前
				adr.name = val;
				break;
			case 2:
				// 住所
				adr.address = val;
				break;
			default:
				break;
			}
 
		}
		// vectorに住所構造体を設定
		vec.push_back(adr);
	}
 
	// ソート(昇順)
	stable_sort(vec.begin(), vec.end());
 
	// CSV出力(昇順)
	ofstream ofs(argv[2]);
	for (unsigned int i = 0; i < vec.size(); i++) {
		Address adr = vec[i];
		ofs << "\"" << adr.idx << "\",\"" << adr.name << "\",\"" << adr.address
				<< "\"" << endl;
	}
 
	// ソート(降順)
	stable_sort(vec.begin(), vec.end(), greater<Address>());
 
	// CSV出力(降順)
	ofstream ofs2(argv[3]);
	for (unsigned int i = 0; i < vec.size(); i++) {
		Address adr = vec[i];
		ofs << "\"" << adr.idx << "\",\"" << adr.name << "\",\"" << adr.address
				<< "\"" << endl;
	}
}
 

入力CSVファイル(data.txt)

"3","hogehoge","ほげほげ"
"2","mogemoge","もげもげ"
"1","aaaa","bbbb"
 
"4","mogemoge","もげもげ4"
 

実行結果

CsvIO.exe C:\cpp\data.txt C:\cpp\out1.txt C:\cpp\out2.txt
0番目の引数 = CvsIO.exe
1番目の引数 = C:\cpp\data.txt
2番目の引数 = C:\cpp\out1.txt
3番目の引数 = C:\cpp\out2.txt
 

出力CSVファイル(out1.txt)

"1","aaaa","bbbb"
"2","mogemoge","もげもげ"
"3","hogehoge","ほげほげ"
"4","mogemoge","もげもげ4"
 

出力CSVファイル(out2.txt)

"4","mogemoge","もげもげ4"
"3","hogehoge","ほげほげ"
"2","mogemoge","もげもげ"
"1","aaaa","bbbb"