// C言語/サンプル/CSVファイル読込sort出力 // CSVファイルを読み込んで、構造体に設定しソートしてから再度CSVファイルに出力するサンプルです。 // qsort strtok使用版 #include #include #include // Record構造体 struct Record { // インデックス int idx; // タイトル char title[100]; // 日付 char date[11]; }; // CSVファイルから読み込んだ文字列をRecord構造体に設定します void setRecord(struct Record* pR, char* str) { int i = 0; // 最初の","を探す char* pStr = strtok(&str[1], "\",\""); while (pStr) { switch (i) { case 0: // インデックス pR->idx = atoi(pStr); break; case 1: // タイトル strcpy(pR->title, pStr); break; case 2: // 日付 strcpy(pR->date, pStr); break; default: break; } i++; // ","を探す pStr = strtok(NULL, "\",\""); if (pStr == NULL ) { // ","がない場合、最後の"を探す pStr = strtok(NULL, "\"\n"); } } } // ポイント2.3 Record構造体比較関数を作ります。 // Record構造体比較関数 // qsortから呼び出され、比較結果を返す事でソートを実現します。 int compRecord(const void * p1, const void * p2) { struct Record *r1 = *((struct Record **) p1); struct Record *r2 = *((struct Record **) p2); // 文字列比較 // ポイント2.2 構造体に入れたので好きな項目でソートできます int cmp = strcmp(r1->date, r2->date); if (cmp != 0) { // 日付が違う場合、strcmpの結果をそのまま返します return cmp; } // 日付が同じ場合、インデックスを比較します if (r1->idx > r2->idx) { return 1; } else if (r1->idx < r2->idx) { return -1; } // インデックスも同じ場合0を返します return 0; } // CSVファイル出力 void output(FILE* fp, struct Record** out, int size) { int i; printf("sort後\n"); for (i = 0; i < size; i++) { // ポイント3 カンマ区切りの文字列を作成して出力します 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* fpr = fopen(argv[1], "r"); FILE* fpw = fopen(argv[2], "w"); // ファイルを開けない場合、FILEのポインタがNULLになります if (fpr == NULL || fpw == NULL ) { puts("ファイルが開けないよ!"); return EXIT_FAILURE; } printf("sort前\n"); // fgets(読み込むバッファ, バッファのサイズ, FILEのポインタ)で一行ずつ読み込みます while (fgets(str, 255, fpr)) { // 読み込んだ内容をそのまま出力 printf(str); // ポイント1 読み込んだテキストを、分解して構造体の配列に設定します。 // Record構造体にデータを設定 setRecord(&record[i], str); i++; } // サイズを保存 size = i; // 出力用ポインタ配列にRecordのポインタをすべて設定する for (i = 0; i < size; i++) { sorted[i] = &record[i]; } // ポイント2 構造体の配列をソートします // qsortのパラメータは1.ソートするデータの配列 2.ソートするデータの個数 3.データ一個あたりのサイズ 4.比較関数のポインタ qsort(sorted, size, sizeof(sorted[0]), compRecord); // 出力ファイルに書き込みます output(fpw, sorted, size); // ファイルをクローズ fclose(fpr); fclose(fpw); return EXIT_SUCCESS; }