printfの有無によるsegmentation faultの発生について

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
kanikama

printfの有無によるsegmentation faultの発生について

#1

投稿記事 by kanikama » 1年前

現在C言語を学んでおり、ファイル入出力の問題で分からないところがあったので質問させていただきます。
初学者ゆえに、拙いコードや分かりにくい質問などありましたら申し訳ありません。

テキストファイルと駅名を引数として、任意の2つの駅名の距離を求めるプログラムを作成しています。起点となる駅が存在し、その駅からの距離の差の絶対値をここでは「距離」としており、テキストファイルには駅名と基点駅からの距離が ',' 区切りで記述されています。また、存在しない駅名が入力された時には、-1と表示します。

私は以下のようにプログラムを記述しました。

コード:

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

double dist(char *name1, char *name2, char *fo)
{
    int i, num = 0;
    int jud = 0,jud2 = 0;
    char *str;
    double dist1, dist2;
    FILE *fp;

    fp = fopen(fo, "r");
    if (fp == NULL) 
    {
        printf("ファイルが開けません\n");
        return -1;
    }

    while (fscanf(fp, "%s", str) != EOF)
    {
        char *token = strtok(str, ",");
        if (strcmp(token, name1) == 0)
        {
            dist1 = atof(strtok(NULL, ","));
            jud = 1;
        } else if (strcmp(token, name2) == 0)
        {
            dist2 = atof(strtok(NULL, ","));
            jud2 = 1;
        }
    }

    if(jud == 1 && jud2 == 1)
    {
        return fabs(dist1 - dist2);
    }
    else
    {
        return -1;
    }
}

int main(int argc, char **argv)
{   
    double di;

    if (argc != 4)
    {
        printf("Argument error");
		exit(1);
    }

    di = dist(argv[2], argv[3], argv[1]);
    if (dist < 0)
    {
        printf("distance:-1.0\n");
        return 0;
    }

    printf("distance:%.1f\n",di);  

    return 0;
}
テキストファイルは以下を用いました。

コード:

start,0.0
nishi,10.4
higashi,12.5
kita,16.4
minami,17.8
chuo,24.2
このコードで実行したところ、Segmantation faultとなったため、どこまでプログラムが実行されているか確認するため、55行目(main関数内di =……)の直前に

コード:

printf("1\n");
と記載したところ、プログラムが問題なく実行されてしまいました。
自身で調べて、printfの記述によってメモリがたまたまかみ合い、実行されたということは分かったのですが、最初のプログラムのどこにエラーがあるのかが分かりません。お教え頂ければ幸いです。

OS :Windows
コンパイラ名:gcc

長文、失礼いたしました。

box
記事: 2002
登録日時: 14年前

Re: printfの有無によるsegmentation faultの発生について

#2

投稿記事 by box » 1年前

コード:

    di = dist(argv[2], argv[3], argv[1]);
    if (dist < 0)
ここで引用した2行のうち下の方で、
関数名であるdistの値が負かどうかを判断しているのはマズくないですか?
di
が正しいのでは?
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

kanikama

Re: printfの有無によるsegmentation faultの発生について

#3

投稿記事 by kanikama » 1年前

ご回答ありがとうございます。
自分の記述ミスです。ご指摘の通り、

コード:

 di = dist(argv[2], argv[3], argv[1]);
    if (di < 0)
 
の意図であったのを間違えました。

box
記事: 2002
登録日時: 14年前

Re: printfの有無によるsegmentation faultの発生について

#4

投稿記事 by box » 1年前

それで、問題は解決したんですか?
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

kanikama

Re: printfの有無によるsegmentation faultの発生について

#5

投稿記事 by kanikama » 1年前

解決しておりません。お知恵をお貸しいただけますと幸いです。

malch
記事: 4
登録日時: 5年前

Re: printfの有無によるsegmentation faultの発生について

#6

投稿記事 by malch » 1年前

fscanf関数の使い方がおかしいです。
使い方を調べてみてください。

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: printfの有無によるsegmentation faultの発生について

#7

投稿記事 by みけCAT » 1年前

未初期化の変数 str の値を fscanf 関数に渡しているのがダメですね。
事前に文字列を読み込むための領域を確保しておかなければなりません。

c - Crash or "segmentation fault" when data is copied/scanned/read to an uninitialized pointer - Stack Overflow
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

kanikama

Re: printfの有無によるsegmentation faultの発生について

#8

投稿記事 by kanikama » 1年前

お三方、大変ありがとうございました。以下のようにコードを書き直し、正常な動作を確認することができました。

コード:

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

double dist(char *name1, char *name2, char *fo)
{
    int i, num = 0;
    int jud = 0,jud2 = 0;
    char str[256];
    double dist1, dist2;
    FILE *fp;

    fp = fopen(fo, "r");
    if (fp == NULL) 
    {
        printf("ファイルが開けません\n");
        return -1;
    }

    while (fscanf(fp, "%s", str) != EOF)
    {
        char *token = strtok(str, ",");
        if (strcmp(token, name1) == 0)
        {
            dist1 = atof(strtok(NULL, ","));
            jud = 1;
        } else if (strcmp(token, name2) == 0)
        {
            dist2 = atof(strtok(NULL, ","));
            jud2 = 1;
        }
    }

    fclose(fp);

    if(jud == 1 && jud2 == 1)
    {
        return fabs(dist1 - dist2);
    }
    else
    {
        return -1;
    }


}

int main(int argc, char **argv)
{   
    double di;

    if (argc != 4)
    {
        printf("Argument error");
		exit(1);
    }

    di = dist(argv[2], argv[3], argv[1]);
    if (di < 0)
    {
        printf("distance:-1.0\n");
        return 0;
    }

    printf("distance:%.1f\n",di);  

    return 0;
}

コード:

//出力

./a.out station.txt start nishi
distance:10.4
 ./a.out station.txt start higashi
distance:12.5
./a.out station.txt sayda dajc
distance:-1.0
./a.out station.txt nishi higashi
distance:2.1

ポインタの理解を誤っておりました。
重ねて感謝申し上げます。ありがとうございました。

返信

“C言語何でも質問掲示板” へ戻る