重要なお知らせ

「教えて! goo」は2025年9月17日(水)をもちまして、サービスを終了いたします。詳細はこちら>

【GOLF me!】初月無料お試し

前回の質問に回答して頂いた皆さん、ありがとうございました!
読み込んだデータを格納するための構造体配列の個数が足りなかったという、ごく初歩的なミスが原因でした…///
それが解決したばかりで恐縮ですが、新たな問題が発生しました。

風力発電の発電データを1秒ごとに1日分を記録したCSVファイルを読み込み、集計して、集計用の新しいCSVファイルに書き込むプログラムを組もうとしています。以下にソースコードを記載します。

#include<stdio.h>
#include<stdlib.h>

static char filename[100];
static char wfname[100];
char fname2[256];

void str_copy(char[],char[]);//文字列のコピー
void str_cat(char[],char[]);//文字列の連結

struct kaze {
_char jikoku[16];
_double fuusoku;
_double fuuko;
_double denatu;
_double denryoku1;
_double denryoku2;
_double co2;
};

struct kaze data[86450];

int main()
{
_char date2[50];
_char date3[50];
_char month2[10];
_char year2[10];
_char path1[50]="F:\\風力発電\\風車";
_char path2[10]="年";
_char path3[10]="月\\WP";
_char buff[256];
_int month1,month,year,date;
_int kensuu,i,j,uruu;
_FILE *fpin,*fpout;

_printf("集計する年を入力してください。\n");
_scanf("%d",&year);

_printf("集計する月を入力してください。\n");
_scanf("%d",&month);
_if(month==2){
__printf("閏年ですか?(はい -> 1 いいえ -> 2)");
__scanf("%d",&uruu);
_}

_if(month==2){
__if(uruu==1){
___month1=29;
__}
__else{
___month1=28;
__}
_}
_else if(month==4 || month==6 || month==9 || month==11){
__month1=30;
_}
_else{
__month1=31;
_}

_date=year*100+month;
_sprintf(date3,"%d",date);
_str_copy(wfname,date3);
_str_cat(wfname,".csv");
_sprintf(year2,"%d",year);
_sprintf(month2,"%d",month);
_sprintf(fname2,"%s%s%s%s%s%s",path1,year2,path2,month2,path3,wfname);

_if((fpout=fopen(fname2,"w"))==NULL){
__printf("ファイルが作成できません。 --- %s\n",fname2);
__exit(EXIT_FAILURE);
_}
_fprintf(fpout,"日付,平均風速,平均風向,平均電圧,平均発電電力、発電電力量,CO2削減量\n");
_fprintf(fpout,"年/月/日,m/s,°,V,KW,KWh,kg-c\n");
_printf("集計用ファイルを作成しました。 --- %s\n",fname2);
_fclose(fpout);

_date=year*10000+month*100;

_for(j=1;j<=month1;j++){ //このループ
__double fuusoku=0,fuuko=0,denatu=0,denryoku1=0,denryoku2=0,co2=0;
__date++;
__sprintf(date2,"%d",date);
__str_copy(filename,date2);
__str_cat(filename,".csv");

__sprintf(buff,"%s%s%s%s%s%s",path1,year2,path2,month2,path3,filename);
__if((fpin=fopen(buff,"r"))==NULL){
___printf("ファイルが見つかりません。--- %s\n",buff);
___exit(EXIT_FAILURE);
__}

__for(kensuu = 0; fscanf(fpin, "%[^,],%lf,%lf,%lf,%lf,%lf,%lf\n", data[kensuu].jikoku, &data[kensuu].fuusoku,
&data[kensuu].fuuko, &data[kensuu].denatu, &data[kensuu].denryoku1,
&data[kensuu].denryoku2, &data[kensuu].co2) != EOF; kensuu++); //ここで止まる?

__for(i = 12; i < kensuu; i++){
___fuusoku+=data[i].fuusoku;
___fuuko+=data[i].fuuko;
___denatu+=data[i].denatu;
___denryoku1+=data[i].denryoku1;
}
__fuusoku/=86400;
__fuuko/=86400;
__denatu/=86400;
__denryoku1/=86400;
__denryoku2=data[kensuu-1].denryoku2;
__co2=data[kensuu-1].co2;

__fclose(fpin);

__printf("\n%d年%d月%d日の集計結果\n平均風速:%lf(m/s)\n平均風向:%lf(°)\n
__________平均電圧:%lf(V)\n",year,month,j,fuusoku,fuuko,denatu);
__printf("平均発電電力:%lf(kW)\n発電電力量:%lf(kWh)\nCO2削減量:%lf(kg-c)\n"
,denryoku1,denryoku2,co2);

__if((fpout=fopen(fname2,"a"))==NULL){
___printf("ファイルに追記できません。--- %s\n",fname2);
___exit(EXIT_FAILURE);
__}
__fprintf(fpout,"%d/%d/%d,%lf,%lf,%lf,%lf,%lf,%lf\n",year,month,j,fuusoku,fuuko,denatu,denryoku1
,denryoku2,co2);

__printf("以上の結果を記録しました。 --- %s",fname2);
__fclose(fpout);
}
_return EXIT_SUCCESS;
}

void str_copy(char dst[],char src[])
{
_int i;

_for(i=0;src[i]!='\0';i++){
__dst[i]=src[i];
_}
_dst[i]='\0';
}
void str_cat(char dst[],char src[])
{
_int i,j;

_for(i=0;dst[i]!='\0';i++)
;
_for(j=0;src[j]!='\0';j++,i++){
_dst[i]=src[j];
_}
_dst[i]='\0';
}

>>for(j=1;j<=month1;j++){…}

のループについて、1週目は問題なく動くのですが、2週目の

>>for(kensuu = 0; fscanf(fpin, "%[^,],%lf,%lf,%lf,%lf,%lf,%lf\n", data[kensuu].jikoku, &data
[kensuu].fuusoku,&data[kensuu].fuuko, &data[kensuu].denatu, &data[kensuu].denryoku1,
&data[kensuu].denryoku2, &data[kensuu].co2) != EOF; kensuu++);

で止まる(というより無限ループになる?)ようです。このfor文の中でprintfを使い調べたところ、どうやらfscanfに問題があるということは分かりました。しかし、なにぶん最近勉強しはじめたばかりで、どこがどう悪いのか、見当もつきません(泣)

次から次へと大変恐縮ですが、心当たり程度でも結構ですので、ご意見をお願いします!

A 回答 (5件)

\n がないと次の %[^,] で「その改行」も読み込んじゃうから都合悪いと思うよ>#4.

    • good
    • 0

きちんと確認できていませんが、怪しいところといえばfscanf()の


"%[^,],%lf,%lf,%lf,%lf,%lf,%lf\n",
の最後の\nは不要かと思います。
scanf系は空白文字をデフォルトの区切り文字にしてるはずなので。
    • good
    • 0

http://ja.wikipedia.org/wiki/Scanf#.E7.95.B0.E5. …

fscanfが怪しいって思っているなら、まずはそれを確認しましょう。



あとは、趣味の問題ではあるけど
なんで、str_catとstr_copyを作ったんです?標準ライブラリのstrcat,strcpy使えばいいんじゃないですか?
標準ライブラリ使いたくないなら、なんでfscanfやprintf等を使うんですか?

前回指摘がありましたが、sprintfの使い方がもったいないです。
> sprintf(fname2,"%s%s%s%s%s%s",path1,year2,path2,month2,path3,wfname);
こんなのこそstrcatの出番だと思うんですが。
sprintfだと%sと引数の組合せを間違えてもコンパイルエラーにはならないので、思わぬ失敗になることがありますが、strcatなら確実に必要な分だけ連結できるのですから。strncatでオーバーラン防止もできるし。
    • good
    • 0

Cコンパイラは何を使っているのかな?


変数kensuuがint型で定義されてますが、dataの配列が86450となっています。
もし使用しているコンパイラのint型が-32768~32767の場合、dataの件数が86450個なら、メモリを壊していることになります。
この場合kensuuをlong型で定義しないと動かないと思います。
    • good
    • 0

「fscanfに問題があるということは分かりました」というなら, 例えば fscanf が実際にどのような値を返しているのかくらい調べて当然ではないですかね. もちろん, fscanf がどのような状況のときにどんな値を返すのかも (知らないのであれば) 調べるのが当たり前.



そういうところから「どこがどう悪いのか」の検討をつけていくんだよ.

以下前の質問のやり取りに関して苦言を 1つ.

「CSVファイルのデータは86400秒分でも、その上にも行があるのだから、data[86400]では足りないのは当然ですね(笑)」
とか書いてますが, 「その上にも行がある」のは「当然」でもなんでもありません. 質問に書かれていない以上, むしろそれは「あなた以外のだれにとっても当然ではない」のです.

しかし, この str_copy だの str_cat だのの羅列は何とかならんものかねぇ....
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!