// C言語/基本/CSVファイル読込sort出力
// CSVファイルを読み込んで、構造体に設定しソートしてから再度CSVファイルに出力するサンプルです。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// Record構造体
struct Record {
	// インデックス
	int idx;
	// タイトル
	char title[100];
	// 日付
	char date[11];
};

// CSVファイルから読み込んだ文字列をRecord構造体に設定します
void setRecord(struct Record* pR, const char* str) {
	int i = 0, start = 1, size;
	char* pStr;
	char buff[100];
	for (i = 0; i < 3; i++) {
		// ","を探す
		pStr = strstr(&str[start], "\",\"");
		if (pStr == NULL ) {
			// ","がない場合、最後の"を探す
			pStr = strstr(&str[start], "\"\n");
		}
		size = pStr - &str[start];
		switch (i) {
		case 0:
			// インデックス
			strncpy(buff, &str[start], size);
			pR->idx = atoi(buff);
			break;
		case 1:
			// タイトル
			strncpy(pR->title, &str[start], size);
			break;
		case 2:
			// 日付
			strncpy(pR->date, &str[start], size);
			break;
		default:
			break;
		}
		start = start + size + 3;
	}
}

// Recordのソートを行います
// 今回は3番目の項目と1番目の項目の昇順にしました。
struct Record** sort(struct Record* pRecord, struct Record** out, int size) {
	int i, j;
	struct Record* ptmp;
	int cmp;

	// 出力用ポインタ配列にRecordのポインタをすべて設定する
	for (i = 0; i < size; i++) {
		out[i] = &pRecord[i];
	}

	for (i = 0; i < size - 1; i++) {

		for (j = i + 1; j < size; j++) {
			// 文字列比較
			// ポイント２．２ 構造体に入れたので好きな項目でソートできます
			cmp = strcmp(out[i]->date, out[j]->date);
			if (cmp > 0 || (cmp == 0 && out[i]->idx > out[j]->idx)) {
				// 日付が、out[i] > out[j]の場合、もしくは
				// 日付が同じで、インデックスがout[i] > out[j]の場合ポインタ入れ替え
				ptmp = out[i];
				out[i] = out[j];
				out[j] = ptmp;
			}
		}
	}
	return out;
}

// CSVファイル出力
void output(FILE* fp, struct Record** out, int size) {
	int i;

	printf("sort後\n");
	for (i = 0; i < size; i++) {
		// ポイント３ カンマ区切りの文字列を作成して出力します
		fprintf(fp, "\"%d\",\"%s\",\"%s\"\n", out[i]->idx, out[i]->title,
				out[i]->date);
		printf("\"%d\",\"%s\",\"%s\"\n", out[i]->idx, out[i]->title,
				out[i]->date);
	}
}

int main(int argc, char *argv[]) {
	char str[255];
	// 構造体の配列
	struct Record record[100];
	// 構造体のポインタの配列（ソート用）
	struct Record *sorted[100];
	int i = 0, size;
	// fopen(ファイル名, オプション)でファイルを開きます
	FILE* fp = fopen(argv[1], "r");
	// ファイルを開けない場合、FILEのポインタがNULLになります
	if (fp == NULL ) {
		puts("ファイルが開けないよ！");
		return EXIT_FAILURE;
	}
	printf("sort前\n");
	// fgets(読み込むバッファ, バッファのサイズ, FILEのポインタ)で一行ずつ読み込みます
	while (fgets(str, 255, fp)) {
		// 読み込んだ内容をそのまま出力
		printf(str);
		// ポイント１ 読み込んだテキストを、分解して構造体の配列に設定します。
		// Record構造体にデータを設定
		setRecord(&record[i], str);
		i++;
	}
	// 入力ファイルをクローズ
	fclose(fp);
	// サイズを保存
	size = i;

	// ポイント２ 構造体の配列をソートします
	sort(record, sorted, size);

	// 出力ファイルを開きます
	fp = fopen(argv[2], "w");
	// ファイルを開けない場合、FILEのポインタがNULLになります
	if (fp == NULL ) {
		puts("ファイルが開けないよ！");
		return EXIT_FAILURE;
	}
	// 出力ファイルに書き込みます
	output(fp, sorted, size);
	// 出力ファイルをクローズ
	fclose(fp);

	return EXIT_SUCCESS;
}
