CSVファイルを読み込みソートして出力するサンプルです。
ポイント
- CSVファイルを読み込んで、一行ずつ構造体にセットします。
- ","の位置を探して、項目の頭から","の間の文字を取り出します。
- 最後の項目は"\nを探して項目の頭から、"\nの間の文字を取り出します。
- sscanfで上手いことする方法が分からなかったので、ごりごり検索してます。
- 構造体の配列をソートします。
- 項目ごとに分割しているので、好きな項目でソートできます。
- 構造体をCSV形式で出力します。
- fprintf(fp, "%d","%s","%s", ...)でごりごりっと出力します。
// 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;
}
"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"
実行結果
ideone 遷移先からソースコードをコピペできたりします
アフィリエイト ここまで
最終更新:2012年09月23日 15:02