質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

解決済

3回答

1468閲覧

コアダンプします助けてください(fscanf()の使い方について)

y_o

総合スコア12

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

0クリップ

投稿2019/06/27 05:54

編集2019/06/27 07:43

C言語で記述しています。
環境 Linux(それ以外わからないです m(_ _)m )

やりたいこと
既に同じファイル内に用意している.datファイルから一行づつ文字型配列に読み込んで、読み込んだ値(行の末尾の値)を行ごとに平均をとりたい。

*用意している.datは%d,%d,%d\nが200行と*****が一行を、50セットあるものになっています。こんな感じです↓

%d,%d,%d\n    ←ここと
:
:
%d,%d,%d\n
*****         
%d,%d,%d\n    ←ここと
:
:
%d,%d,%d\n    ←ここと...で平均とりたいです。
*****
:
:

CMAC_data_Gamma09.dat は既に用意しています。
どうやら、while内if(fscanf(fp,"%s",str) == EOF)でコアダンプしているようです。

C

1 2//trans_data.c 3#include <stdio.h> 4#include <math.h> 5 6char str[20], file[20]; 7int data[50][200], sum_data[200]; 8 9int main(int argc, char **argv){ 10 int i, j, pos1, pos2, try1, try2; 11 double Gamma; 12 FILE *fp; 13 14 Gamma = atof(argv[1]); 15 16 i = 0; j = 0; 17 18 if(Gamma == 0.9) fp = fopen("CMAC_data_Gamma09.dat", "r"); 19 if(Gamma == 0.95) fp = fopen("CMAC_data_Gamma095.dat", "r"); 20 if(Gamma == 0.85) fp = fopen("CMAC_data_Gamma085.dat", "r"); 21 if(Gamma == 0.8) fp = fopen("CMAC_data_Gamma08.dat", "r"); 22 if(Gamma == 0.7) fp = fopen("CMAC_data_Gamma07.dat", "r"); 23 if(Gamma == 0.6) fp = fopen("CMAC_data_Gamma06.dat", "r"); 24 25 if(fp == NULL){ 26 printf("can not open file.\n"); 27 return 1; 28 } 29 else{ 30 printf("opened file.\n"); 31 } 32printf("check0\n"); 33 while(1){ 34 if(fgets(str,16,fp) == NULL) 35 break; 36printf("check1\n"); 37 if(strncmp(str,"*****",5) == 0){ 38printf("check2\n"); 39 pos1 = 0; 40 pos2++; 41 } 42 else{ 43printf("check3\n"); 44 sscanf(str,"%d,%d,%d", &try1, &try2, &data[pos1][pos2]); 45 pos1++; 46 } 47 } 48printf("check4\n"); 49 fclose(fp); 50 51 for(i = 0; i < 50; i++){ 52 for(j = 0; j < 200; j++){ 53 sum_data[j] += data[i][j]; 54 } 55 } 56 57printf("check5\n"); 58 59 if(atof(argv[1]) == 0.1) fp = fopen("learn_rete01.csv", "w"); 60 if(atof(argv[1]) == 0.3) fp = fopen("learn_rete03.csv", "w"); 61 if(atof(argv[1]) == 0.4) fp = fopen("learn_rete04.csv", "w"); 62 if(atof(argv[1]) == 0.5) fp = fopen("learn_rate05.csv", "w"); 63 if(atof(argv[1]) == 0.6) fp = fopen("learn_rate06.csv", "w"); 64 if(atof(argv[1]) == 0.7) fp = fopen("learn_rate07.csv", "w"); 65 66 if(fp == NULL){ 67 printf("can not open file.\n"); 68 return 1; 69 } 70 else{ 71 printf("opened file.\n"); 72 } 73 74 for(i = 0; i < 200; i++){ 75 fprintf(fp, "%d, %lf\n", i*10, sum_data[i]/50.); 76 } 77 78printf("check6\n"); 79 80 fclose(fp); 81 printf("closed file.\n"); 82 83 return 0; 84}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

y_waiwai

2019/06/27 05:58

このままではコードが見づらいので、質門を編集し、<code>ボタンで、出てくる’’’の枠の中にコードを貼り付けてください
maisumakun

2019/06/27 05:59

C言語でなければならないという制約はありますでしょうか。
y_o

2019/06/27 06:03

y_waiwaiさんありがとうございます! すぐに直します!
y_o

2019/06/27 07:12

misumakunさん コメントありがとうございます。 C言語が一番わかる言語なのでCで書きたいです。
maisumakun

2019/06/27 07:15

文字列処理はC言語がいちばん苦手なので、そのためだけでも別言語を覚えたほうが楽かもしれません。 (極論、カンマ区切りのデータなら「Excelに貼り付けてマクロ」というほうが楽かもしれませんし)
y_o

2019/06/27 08:16

maisumakunさん そうなんですけどね...w研究でC言語使ってデータの改変を自動でするようにしたいんですよ..
guest

回答3

0

ベストアンサー

見当違いのあてずっぽでいくらやってもだめです。悪いのがファイルアクセス関数だと決めつけてしまって、ちゃんとしたパラメータが渡されているかどうかを見ていませんね。

コンピュータにおいて、浮動小数点数の扱いには注意が必要です。
内部表現が2進数なので、見た通りの数として扱われるとは限らないからです。
詳しくは'浮動小数点数 誤差'とかでググっていただくとして。

例えばコマンドラインオプションに 0.9を与えたときに Gamma == 0.9が1になるかというと、そうとも言えない、ということです。つまり、fp=open(...)は実行されるかどうか、処理系により...

さらに悪いことに、変数fpを初期化していないのでfpの値は不定で、nullであることは期待出来ません。

結果として、ファイルが開けていないにもかかわらずif(fp == NULL){のチェックもすり抜けて、実際にファイルアクセスをしようとするfscanf()あるいはfgets()のところで無効なfpへのアクセスが行われコアダンプ...とあいなります。

浮動小数点の比較の定石通りに

#define EPS 0.001 if( fabs(Gamma-0.9)<EPS )...

みたいなことにするか、あるいは文字列のまま
if( strcmp(argv[1],"0.9")==0 )
とでもするか、そんなところでしょう。(後半戦も同様)

ついでに言えば、pos2も初期化されていませんが&data[pos1][pos2]として使われています。だめです。

投稿2019/06/27 08:21

thkana

総合スコア7610

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

y_o

2019/06/27 08:25

回答ありがとうございます。 初心者なので理解が追い付いていませんが、Googleingしたりしてやってみます。
y_o

2019/06/27 08:54

ありがとうございます! fgets(str,16,fp) == NULL でのコアダンプは回避できました!!
guest

0

Cent OS7環境のgccを使ってテストしてみました。

(1) atof(argv[1])が0を返しています。
math.hではなく、stdlib.hをincludeしてください。
なお、今回、指定した範囲ではstdlib.hをincludeすると想定どおりの動きをしましたが、
1より小さい数値は浮動小数点では通常、誤差を含みますのでatofを使わず、直接文字列で比較した方が安全です。
(2) (1)の影響でGamma==0.0となり、ファイルをオープンしませんが、fpにゴミが入っており、不当な動作をします。
最初にfp=NULL; を入れておくとopenしなかったことを認識できます。
さらに最初のファイルをcloseした後、次のファイルをopenする前にfp=NULL;しておいた方が安全です。
(2) pos1、pos2が初期化されておらず、ゴミをみて動作しました。
最初に実行した時にはpos1=32767、pos2=-1223608448が入っていました(みていたゴミの内容)
ファイルを読むループに入る前に0に初期化してください。

投稿2019/06/27 08:56

sage

総合スコア1216

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

y_o

2019/06/27 09:01

回答ありがとうございます。 初期化とstdlib.hですね!ありがとうございます!
guest

0

まず、scanf系の関数は危険なので使わないようにしましょう

char str[300], file[300];

ファイルの中で300文字以上の行があれば、このプログラムは暴走してしまいますね

投稿2019/06/27 06:08

y_waiwai

総合スコア87719

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

y_o

2019/06/27 06:12

回答ありがとうございます。 str[300] → str[20] とかにすれば解決しますか? それと、fscanf()を使わないならどうすれば...
y_waiwai

2019/06/27 06:15

解決しません 20文字以上の行で暴走するようになるだけですw fgets 関数を使えばどーでしょう
y_o

2019/06/27 07:08

fgetsもコアダンプしました...コードを編集して更新するのでお願いします m(_ _)m
y_waiwai

2019/06/27 07:34

んじゃつぎは、配列の変数をmain関数の外で定義するようにしてみよう
y_waiwai

2019/06/27 07:40

それだけじゃなく、 > int data[50][200], sum_data[200]; も関数の外へ。
y_o

2019/06/27 07:42

了解しました!! 直しましたがコアダンプはまだ治りませんよねww
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問