「C言語/サンプル/CSVファイルの読込ソート出力」の編集履歴(バックアップ)一覧はこちら

C言語/サンプル/CSVファイルの読込ソート出力」(2012/09/23 (日) 15:02:24) の最新版変更点

追加された行は緑色になります。

削除された行は赤色になります。

CSVファイルを読み込みソートして出力するサンプルです。 *** ポイント + CSVファイルを読み込んで、一行ずつ構造体にセットします。 ++ ","の位置を探して、項目の頭から","の間の文字を取り出します。 ++ 最後の項目は"\nを探して項目の頭から、"\nの間の文字を取り出します。 ++ sscanfで上手いことする方法が分からなかったので、ごりごり検索してます。 + 構造体の配列をソートします。 ++ 項目ごとに分割しているので、好きな項目でソートできます。 + 構造体をCSV形式で出力します。 ++ fprintf(fp, "%d","%s","%s", ...)でごりごりっと出力します。 全部書いてから、C言語にはqsort(ソート関数)と、strtok(トークン関数)があるのを知りました。 そんなわけで、qsort strtok関数を使ったバージョンを作ってみました。 [[CSVファイルの読込ソート出力2(qsort strtok使用版)>C言語/基本/CSVファイルの読込ソート出力2]] *** ソース &ref(sortCsv.c) #highlight(c){{ // 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++) { // 文字列比較 // ポイント2.2 構造体に入れたので好きな項目でソートできます 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++) { // ポイント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* 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); // ポイント1 読み込んだテキストを、分解して構造体の配列に設定します。 // Record構造体にデータを設定 setRecord(&record[i], str); i++; } // 入力ファイルをクローズ fclose(fp); // サイズを保存 size = i; // ポイント2 構造体の配列をソートします 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; } }} *** sort.csv &ref(sort.csv) #highlight(){{ "1","CSV読込ソート出力の","2011/01/01" "2","テスト中","2012/10/01" "3","読み込めてますかー","2010/09/10" "4","もっと行を","2011/01/01" "5","増やしてみましょう","2012/10/01" "6","これぐらいかな?","2010/09/10" }} *** 実行結果 &ref(CSVファイルの読込ソート出力.png) &ref(sortOut.csv) ※ファイル名があんまりなのが変更してありますがスクリーンショットはそのままです *** ideone 遷移先からソースコードをコピペできたりします http://ideone.com/iB3oD *** アフィリエイト &amazon2() ここまで
CSVファイルを読み込みソートして出力するサンプルです。 *** ポイント + CSVファイルを読み込んで、一行ずつ構造体にセットします。 ++ ","の位置を探して、項目の頭から","の間の文字を取り出します。 ++ 最後の項目は"\nを探して項目の頭から、"\nの間の文字を取り出します。 ++ sscanfで上手いことする方法が分からなかったので、ごりごり検索してます。 + 構造体の配列をソートします。 ++ 項目ごとに分割しているので、好きな項目でソートできます。 + 構造体をCSV形式で出力します。 ++ fprintf(fp, "%d","%s","%s", ...)でごりごりっと出力します。 全部書いてから、C言語にはqsort(ソート関数)と、strtok(トークン関数)があるのを知りました。 そんなわけで、qsort strtok関数を使ったバージョンを作ってみました。 [[CSVファイルの読込ソート出力2(qsort strtok使用版)>C言語/サンプル/CSVファイルの読込ソート出力2]] *** ソース &ref(sortCsv.c) #highlight(c){{ // 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++) { // 文字列比較 // ポイント2.2 構造体に入れたので好きな項目でソートできます 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++) { // ポイント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* 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); // ポイント1 読み込んだテキストを、分解して構造体の配列に設定します。 // Record構造体にデータを設定 setRecord(&record[i], str); i++; } // 入力ファイルをクローズ fclose(fp); // サイズを保存 size = i; // ポイント2 構造体の配列をソートします 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; } }} *** sort.csv &ref(sort.csv) #highlight(){{ "1","CSV読込ソート出力の","2011/01/01" "2","テスト中","2012/10/01" "3","読み込めてますかー","2010/09/10" "4","もっと行を","2011/01/01" "5","増やしてみましょう","2012/10/01" "6","これぐらいかな?","2010/09/10" }} *** 実行結果 &ref(CSVファイルの読込ソート出力.png) &ref(sortOut.csv) ※ファイル名があんまりなのが変更してありますがスクリーンショットはそのままです *** ideone 遷移先からソースコードをコピペできたりします http://ideone.com/iB3oD *** アフィリエイト &amazon2() ここまで

表示オプション

横に並べて表示:
変化行の前後のみ表示: