
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を探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・一番好きなみそ汁の具材は?
- ・泣きながら食べたご飯の思い出
- ・「これはヤバかったな」という遅刻エピソード
- ・初めて自分の家と他人の家が違う、と意識した時
- ・いちばん失敗した人決定戦
- ・思い出すきっかけは 音楽?におい?景色?
- ・あなたなりのストレス発散方法を教えてください!
- ・もし10億円当たったら何に使いますか?
- ・何回やってもうまくいかないことは?
- ・今年はじめたいことは?
- ・あなたの人生で一番ピンチに陥った瞬間は?
- ・初めて見た映画を教えてください!
- ・今の日本に期待することはなんですか?
- ・集中するためにやっていること
- ・テレビやラジオに出たことがある人、いますか?
- ・【お題】斜め上を行くスキー場にありがちなこと
- ・人生でいちばんスベッた瞬間
- ・コーピングについて教えてください
- ・あなたの「プチ贅沢」はなんですか?
- ・コンビニでおにぎりを買うときのスタメンはどの具?
- ・おすすめの美術館・博物館、教えてください!
- ・【お題】大変な警告
- ・洋服何着持ってますか?
- ・みんなの【マイ・ベスト積読2024】を教えてください。
- ・「これいらなくない?」という慣習、教えてください
- ・今から楽しみな予定はありますか?
- ・AIツールの活用方法を教えて
- ・最強の防寒、あったか術を教えてください!
- ・歳とったな〜〜と思ったことは?
- ・モテ期を経験した方いらっしゃいますか?
- ・好きな人を振り向かせるためにしたこと
- ・スマホに会話を聞かれているな!?と思ったことありますか?
- ・それもChatGPT!?と驚いた使用方法を教えてください
- ・見学に行くとしたら【天国】と【地獄】どっち?
- ・これまでで一番「情けなかったとき」はいつですか?
- ・この人頭いいなと思ったエピソード
- ・あなたの「必」の書き順を教えてください
- ・14歳の自分に衝撃の事実を告げてください
- ・人生最悪の忘れ物
- ・あなたの習慣について教えてください!!
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
CStringからchar*への型変換に...
-
C言語にて構造体のメンバがNULL...
-
char*を初期化したいのですが
-
C言語のintとcharの違いってな...
-
C言語の文字リテラル中の16進文...
-
C++17で、unsigned char * 配列...
-
2次元配列の文字"列"の初期化方法
-
char 文字列型 の表現範囲が-12...
-
小数点入りの文字列をfloat型に...
-
C言語:小文字を大文字に変換す...
-
文字の代入とコピーについて
-
C言語を用いた環境変数の作成/...
-
szとlpszの違い
-
文字列の演算
-
ostringstreamではまりました
-
動的メモリの初期化方法について。
-
char型にint型の数値を代入する。
-
new charとnew char[N]の違いは?
-
'\\0'とはなんですか?
-
const char* s1とただのchar s1...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
CStringからchar*への型変換に...
-
char*を初期化したいのですが
-
C言語のintとcharの違いってな...
-
小数点入りの文字列をfloat型に...
-
C言語にて構造体のメンバがNULL...
-
char型にint型の数値を代入する。
-
csvファイルをfscanfで読み込む...
-
new charとnew char[N]の違いは?
-
文字型配列に格納した空白の切捨て
-
C++17で、unsigned char * 配列...
-
2次元配列の文字"列"の初期化方法
-
入力された文字列の中の数字を...
-
DWORDとcharの変換
-
char 文字列型 の表現範囲が-12...
-
fgetc( )の戻り値はなぜ整数??
-
fstream型オブジェクトを関数の...
-
C言語の文字リテラル中の16進文...
-
const char* s1とただのchar s1...
-
動的メモリの初期化方法について。
-
strcat関数を自作したいです
おすすめ情報