c言語でcsvファイルの処理で、処理速度が速いプログラムを書こうと思っています。
以下のようなcsvファイル、件数は約10000000件以上あるものを使います
shop,ymd,gend,age,area,amt
20,2008-05-01,3,5,014,128
22,2008-05-01,2,4,015,350
:
二列目の日別、つまりymd別に最後列のamdの小計を出したいんですが、組んだプログラムを実行してみると、セグメンテーション違反ですと出てしまうんです。以下のようなプログラムを組んだんですが
#include <stdio.h>
#include <string.h>
#include <time.h>
#define MM 256
int main()
{
FILE *fp;
char str[MM],*p1, *p2,*ymd;
int num, sum;
clock_t start,end;
start = clock();
fp = fopen("csv.csv","r");
if(fp == NULL){
printf("ファイルが開けませんでした。\n");
return(0);
}
sum = 0;
fgets(str, sizeof(str), fp);
while(fgets(str, sizeof(str), fp) != NULL){
p1 = strtok(str, ",");
p1 = strtok( NULL,",");
ymd = p1;
p2 = strrchr(str,',');
sum[ymd] = atoi(p2+1);
break;
}
while( fgets(str, sizeof(str), fp) != NULL && p1 != NULL){
p1 = strtok(str, ",");
p1 = strtok( NULL,",");
p2 = strrchr(str,',');
if ( p2 != NULL ) {
if(ymd == p1){
sum[ymd] += atoi(p2+1);
}else{
printf("%s ,%d \n",ymd,sum[ymd]);
strcpy(ymd,p1);
}
}
}
printf("%s ,%d \n",p1,sum);
fclose(fp);
end=clock();
printf("%.2f秒\n",(double)(end-start)/CLOCKS_PER_SEC);
return(0);
}
うまくいきません。大体、処理速度は3秒以内を目指しています。
どなたかご教授御願いいたします。
No.7ベストアンサー
- 回答日時:
No.6です。
>やっぱりポインタはイコールでつなげられないんですか。
ポインタ同士で代入(右辺のアドレスを左辺に入れる等)はできます。
まず、エラーの意味を理解してください。
簡単に書けば「型が違うから代入できない」と言っているのです。
No.6の
--------
>char str[MM],*p1, *p2,ymd1[20], ymd2[20];
と定義しているのに、
>ymd1 = p1;
のような使い方はできませんよ。
--------
について理解されていますでしょうか?
>char str[MM],*p1, *p2,ymd1[20], ymd2[20];
をわかりやすいように分解します。
--------
char str[MM];
char *p1;
char *p2;
char ymd1[20];
char ymd2[20];
--------
p1、p2は「char型のポインタ」
str[]、ymd1[]、ymd2[]は「char型の配列」です。
>ymd1 = p1;
は、ymd[0]に対してp1に格納されているアドレスを代入しようとしているためエラーとなっています。
ひとつアドバイス。
どんなに短いプログラムでも、どこで何の処理を行うのかコメントは降っておいた方が理解しやすいと思う。
No.6
- 回答日時:
No.5
>ポインタの比較はできないってコンパイルできないので、
その際にエラーメッセージで行数は表示されませんでしたか?
>char str[MM],*p1, *p2,ymd1[20], ymd2[20];
と定義しているのに、
>ymd1 = p1;
のような使い方はできませんよ。
この回答への補足
エラーの内容は
test4.c: In function ‘main’:
test4.c:27: error: incompatible types in assignment
test4.c:36: error: incompatible types in assignment
こう出ます。
やっぱりポインタはイコールでつなげられないんですか。
別の手法でいくしかないみたいですね。
No.5
- 回答日時:
「セグメンテーション違反を直す」のは当然として, 「どこに時間がかかっているのか」をきちんと把握できていますか? #2 でも書かれていますが, 「どうしても必要な時間」より速くはできません.
ちなみに sum[ymd] ではコンパイルエラーにはならないです>#1. C では a[x] において「a と x の一方が整数, もう一方がポインタ」なら (その他いくつか条件はあるけど) OK です.
この回答への補足
限界を超えてまで早くしようとは思ってません。
目標は、目標として前回よりも早くなればいいんです。
あの、つまらない質問だと思うんですがポインタとポインタってstrcmpで比較する方法ってないんでしょうか?
ちょっとスクリプトを変えたんですが
#include <stdio.h>
#include <string.h>
#include <time.h>
#define MM 256
int main()
{
FILE *fp;
char str[MM],*p1, *p2,ymd1[20], ymd2[20];
int num, sum=0;
clock_t start,end;
start = clock();
fp = fopen("/data/testdata/journal/j080240.csv","r");
if(fp == NULL){
printf("ファイルが開けませんでした。\n");
return(0);
}
num=1;
fgets(str, sizeof(str), fp);
while(fgets(str, sizeof(str), fp) != NULL && num==1){
p1 = strtok(str, ",");
p1 = strtok( NULL,",");
ymd1 = p1;
p2 = strrchr(str,',');
sum = atoi(p2+1);
num = 2;
}
while( fgets(str, sizeof(str), fp) != NULL && p1 != NULL){
p1 = strtok(str, ",");
p1 = strtok(NULL,",");
p2 = strrchr(str,',');
ymd2 = p1;
if ( p2 != NULL ) {
if(strcmp(ymd1,ymd2) != 0){
printf("%s ,%d \n",ymd1,sum);
strcpy(ymd1,ymd2);
}else{
sum += atoi(p2+1);
}
}
}
printf("%s ,%d \n",ymd2,sum);
fclose(fp);
end=clock();
printf("%.2f秒\n",(double)(end-start)/CLOCKS_PER_SEC);
return(0);
}
という風に変えたんですが、ポインタの比較はできないってコンパイルできないので、ポインタの比較ができないなら、別のアプローチを考えなきゃいけないんですが...
No.4
- 回答日時:
3秒ですか
メモリに余裕があるのならファイルを全部メモリに読み込んでから処理すれば少しは速くなるかも
あと日付が必ず同一日は連続しているとかいう保証があればプログラムも楽になりそうですが
No.3
- 回答日時:
C/C++に連想配列はありません。
自作するなり、C++でstlなどを使います。あと、文字列の扱いがぜんぜんなっていません。
全体的なアルゴリズムも間違っています。
No.1
- 回答日時:
>char str[MM],*p1, *p2,*ymd;
>int num, sum;
>sum[ymd] = atoi(p2+1);
sumの定義と使い方が食い違っています。コンパイルエラーは出なかったのですか?
char *型のymdを、配列の添字として使えるのですか?
この回答への補足
コンパイルでは、エラーが出なかったんです。
ただ、実行するとセグメンテーション違反です、とでるだけで。
sumの定義が違いますか...
C言語に触れるのも、結構久しぶりなので使い方を結構忘れていて、うろ覚えな感じで書き出したので。
最初から調べなおしてみたいと思います。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# プログラミングの授業の課題です 1 2023/01/17 22:15
- C言語・C++・C# c言語 プログラムのエラー 1 2023/02/11 20:31
- C言語・C++・C# c言語の問題の説明、各所ごとに 5 2023/07/26 11:03
- C言語・C++・C# バイナリファイルをコピーするのにかかる時間を測りたいのですが実行するとFatel error:gli 2 2022/11/03 01:10
- C言語・C++・C# 宣言する関数の形が決まっている状態で、 str1とstr2の文字列をこの順に引っ付けてstrに保存し 2 2022/05/30 18:21
- C言語・C++・C# c言語の問題です 3 2023/01/10 16:15
- C言語・C++・C# c言語配列の結合についてです。 なぜうまくいかないのでしょうか。 #include <stdio.h 4 2022/05/30 22:42
- C言語・C++・C# このプログラミング誰か教えてくれませんか 1 2022/06/02 15:27
- C言語・C++・C# str[j++]の意味 2 2022/08/30 16:20
- Visual Basic(VBA) 【前回の続き続きです、ご教示ください】VBAの記述方法がわかりません。 2 2022/08/24 20:49
このQ&Aを見た人はこんなQ&Aも見ています
-
10代と話して驚いたこと
先日10代の知り合いと話した際、フロッピーディスクの実物を見たことがない、と言われて驚きました。今後もこういうことが増えてくるのかと思うと不思議な気持ちです。
-
家・車以外で、人生で一番奮発した買い物
どんなものにお金をかけるかは人それぞれの価値観ですが、 誰もが一度は清水の舞台から飛び降りる覚悟で、ちょっと贅沢な買い物をしたことがあるはず。
-
【お題】引っかけ問題(締め切り10月27日(日)23時)
【大喜利】 「日本で一番高い山は富士山……ですが!」から始まった、それは当てられるわけ無いだろ!と思ったクイズの問題
-
自分のセンスや笑いの好みに影響を受けた作品を教えて
子どもの頃に読んだ漫画などが その後の笑いの好みや自分自身のユーモアのセンスに影響することがあると思いますが、 「この作品に影響受けてるな~!」というものがあれば教えてください。
-
好きな和訳タイトルを教えてください
洋書・洋画の素敵な和訳タイトルをたくさん知りたいです!【例】 『Wuthering Heights』→『嵐が丘』
-
C言語でファイル読み書きを早くしたい。
C言語・C++・C#
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・プリン+醤油=ウニみたいな組み合わせメニューを教えて!
- ・タイムマシーンがあったら、過去と未来どちらに行く?
- ・遅刻の「言い訳」選手権
- ・【大喜利】【投稿~11/12】 急に朝起こしてきた母親に言われた一言とは?
- ・好きな和訳タイトルを教えてください
- ・うちのカレーにはこれが入ってる!って食材ありますか?
- ・好きな「お肉」は?
- ・あなたは何にトキメキますか?
- ・おすすめのモーニング・朝食メニューを教えて!
- ・「覚え間違い」を教えてください!
- ・とっておきの手土産を教えて
- ・「平成」を感じるもの
- ・秘密基地、どこに作った?
- ・【お題】NEW演歌
- ・カンパ〜イ!←最初の1杯目、なに頼む?
- ・一回も披露したことのない豆知識
- ・これ何て呼びますか
- ・初めて自分の家と他人の家が違う、と意識した時
- ・「これはヤバかったな」という遅刻エピソード
- ・これ何て呼びますか Part2
- ・許せない心理テスト
- ・この人頭いいなと思ったエピソード
- ・牛、豚、鶏、どれか一つ食べられなくなるとしたら?
- ・ハマっている「お菓子」を教えて!
- ・【大喜利】【投稿~11/1】 存在しそうで存在しないモノマネ芸人の名前を教えてください
- ・好きなおでんの具材ドラフト会議しましょう
- ・餃子を食べるとき、何をつけますか?
- ・あなたの「必」の書き順を教えてください
- ・ギリギリ行けるお一人様のライン
- ・10代と話して驚いたこと
- ・つい集めてしまうものはなんですか?
- ・自分のセンスや笑いの好みに影響を受けた作品を教えて
- ・【お題】引っかけ問題(締め切り10月27日(日)23時)
- ・大人になっても苦手な食べ物、ありますか?
- ・14歳の自分に衝撃の事実を告げてください
- ・【大喜利】【投稿~10/21(月)】買ったばかりの自転車を分解してひと言
- ・ホテルを選ぶとき、これだけは譲れない条件TOP3は?
- ・家・車以外で、人生で一番奮発した買い物
- ・人生最悪の忘れ物
- ・【コナン30周年】嘘でしょ!?と思った○○周年を教えて【ハルヒ20周年】
- ・あなたの習慣について教えてください!!
- ・都道府県穴埋めゲーム
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
C言語のプログラムについてです
-
const char* s1とただのchar s1...
-
文字列ポインタと配列の違いで...
-
fgetc( )の戻り値はなぜ整数??
-
C言語入門者です。 int str_len...
-
文字列内の数字削除
-
strcat関数を自作したいです
-
文字列str内の全ての数字を...
-
char*を初期化したいのですが
-
C言語にて構造体のメンバがNULL...
-
char型にint型の数値を代入する。
-
C言語 配列の長さの上限
-
C言語のポインタに直接アドレス...
-
関数から配列を返すには?
-
プログラムによく出てくるst...
-
C言語の課題が出たのですが自力...
-
構造体のextern方法
-
本日までの累計を表示させたい!
-
Cのエラー
-
プログラミング MATLAB
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
C言語のintとcharの違いってな...
-
CStringからchar*への型変換に...
-
char*を初期化したいのですが
-
C言語にて構造体のメンバがNULL...
-
fstream型オブジェクトを関数の...
-
小数点入りの文字列をfloat型に...
-
new charとnew char[N]の違いは?
-
char型にint型の数値を代入する。
-
DWORDとcharの変換
-
C言語のプログラムについてです
-
2次元配列の文字"列"の初期化方法
-
文字型配列に格納した空白の切捨て
-
C++17で、unsigned char * 配列...
-
char 文字列型 の表現範囲が-12...
-
文字列の途中から途中までを抽出
-
警告
-
C言語 strstrの実装
-
コマンドライン引数 *argv[]は...
-
csvファイルをfscanfで読み込む...
-
C言語の文字リテラル中の16進文...
おすすめ情報