2

私はとても初心者なので、これは私の新しい質問です!!! :)

次のようなテキストファイルがあります。

3
55.33  44.27 STN1
77.26  33.44 STN2
22.11 23.12 STN5

cで読みたいです。

そのため、次のようなファイルの read_stn.h というタイトルのファイル ヘッダーに構造体を定義しました。

#include <stdio.h>
#include <sys/file.h>

typedef struct station
 {
     double lat, lon;
     char name[5];
 } station;

次のコードを使用してファイルを読み込もうとします

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "read_stn.h"
void read_stn(char filename[], station **sta,int *station_no)
{
    FILE *fp;
    int i;
    char sta_str[5];
    float longitude, latitude;


    fp = fopen(filename,"r");
    fscanf(fp,"%d",station_no);
    printf("%d\n", *station_no);

    *sta = (station*)malloc(*station_no*sizeof(station *));

    for(i=0;i<*station_no;i++)
    {
        fscanf(fp,"%f %f %s", &longitude, &latitude, sta_str);
        printf("%f %f %s\n", longitude, latitude, sta_str);

        sta[i]->lon=(double)longitude;
        sta[i]->lat=(double)latitude;
        strcpy(sta[i]->name,sta_str);
    }

    fclose(fp);
}

そしてメインルーチン:

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

int main()
{
station *sta;
int i,stn_no;

read_stn("station.dat",&sta,&stn_no);

for(i=0;i<stn_no;i++)
{
    printf("%d %s %f %f\n",i+1, sta[i].name, sta[i].lon, sta[i].lat);
}

free(sta);
return 1;
}

しかし、ファイルを読み取ろうとすると、セグメンテーション コア ダンプが発生しました。私のファイルにエラーはありますか?ポインタ メンバへのポインタの定義に何かエラーがあると思います。手伝ってくれませんか?

4

1 に答える 1

4

あなたはそう遠くありませんでした、いくつかのエラー。

これ:

*sta = (station*)malloc(*station_no*sizeof(station *));

これである必要があります:

*sta = malloc(*station_no * sizeof(station));

複数の構造体ポインタではなく、複数の構造体にメモリを割り当てたいためです。

次に、これ:

sta[i]->lon=(double)longitude;
sta[i]->lat=(double)latitude;
strcpy(sta[i]->name,sta_str);

次のようにする必要があります。

(*sta)[i].lon = (double) longitude;
(*sta)[i].lat = (double) latitude;
strcpy((*sta)[i].name, sta_str);

動的配列は*staではなく に格納されているためstaです。

完全な作業バージョン:

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

typedef struct station {
    double lat, lon;
    char name[5];
} station;

void read_stn(char filename[], station ** sta, int *station_no) {
    FILE *fp;
    int i;
    char sta_str[5];
    float longitude, latitude;

    fp = fopen(filename, "r");
    fscanf(fp, "%d", station_no);
    printf("%d\n", *station_no);

    *sta = malloc(*station_no * sizeof(station));

    for (i = 0; i < *station_no; i++) {
        fscanf(fp, "%f %f %s", &longitude, &latitude, sta_str);
        printf("%f %f %s\n", longitude, latitude, sta_str);

        (*sta)[i].lon = (double) longitude;
        (*sta)[i].lat = (double) latitude;
        strcpy((*sta)[i].name, sta_str);
    }

    fclose(fp);
}

int main() {
    station *sta;
    int i, stn_no;

    read_stn("station.dat", &sta, &stn_no);

    for (i = 0; i < stn_no; i++) {
        printf("%d %s %f %f\n", i + 1, sta[i].name, sta[i].lon, sta[i].lat);
    }

    free(sta);
    return 0;
}

出力:

paul@local:~/src/c/scratch/station$ ./station
3
55.330002 44.270000 STN1
77.260002 33.439999 STN2
22.110001 23.120001 STN5
1 STN1 55.330002 44.270000
2 STN2 77.260002 33.439999
3 STN5 22.110001 23.120001
paul@local:~/src/c/scratch/station$

他にも改善できる点がいくつかあります。たとえば、 を経由するのではなく、fscanf()に直接アクセスしたり、 およびからの戻り値を確認したりする必要がありますが、それらは演習として残しておきます。doublefloatfopen()malloc()

また、今後の参考のために、read_stn()関数内でローカル ポインターを作成し、その中ですべての作業を行い、最後に出力パラメーターに値を割り当てる方が簡単な場合がよくあります。たとえば、関数内でこのすべての間接的な処理を回避するのに役立ちます。

void read_stn(char filename[], station ** sta, int *station_no) {
    FILE *fp;
    station * psta;
    int st_num;

    if ( (fp = fopen(filename, "r")) == NULL ) {
        fprintf(stderr, "Couldn't open file %s\n", filename);
        exit(EXIT_FAILURE);
    }

    fscanf(fp, "%d", &st_num);
    printf("%d\n", st_num);

    if ( (psta = malloc(st_num * sizeof(*psta))) == NULL ) {
        fprintf(stderr, "Couldn't allocate memory\n");
        exit(EXIT_FAILURE);
    }

    for ( int i = 0; i < st_num; ++i ) {
        fscanf(fp, "%lf %lf %s", &psta[i].lon, &psta[i].lat, psta[i].name);
        printf("%f %f %s\n", psta[i].lon, psta[i].lat, psta[i].name);
    }

    *sta = psta;
    *station_no = st_num;

    fclose(fp);
}
于 2013-10-05T14:33:45.993 に答える