目次
課題1のプログラムを修正し、キーボードから入力した交差点データを次の形式でファイル"map.dat"に
保存するプログラムを作って下さい。交差点情報は1つにつき1行に書かれます。また、隣接交差点は
交差道路数(points)分だけ並びます。
交差点データ保存形式
‾‾‾‾‾‾‾‾‾‾
crossing_point(交差点数)
id, x, y, wait, name, points, next[0], … next[points-1] ← cross[0]のデータ
id, x, y, wait, name, points, next[0], … next[points-1] ← cross[1]のデータ
・
・
id, x, y, wait, name, points, next[0], … next[points-1] ← cross[crossing_point-1]のデータ
|
3 1, 12.000000, 23.000000, 11.000000, 長町, 1, 2 2, 34.000000, 56.000000, 90.000000, 西公園, 1, 1 3, 56.000000, 45.000000, 45.000000, 一番町, 2, 1, 2 |
/* writefile.c --- 交差点データのファイル出力 */
#include <stdio.h>
#include <string.h>
#define CrossingNumber 5 /* 交差点数=5 */
#define MaxName 50 /* 最大文字数50文字(半角) */
typedef struct {
double x, y; /* 位置 x, y */
} Position; /* 位置を表す構造体 */
typedef struct {
int id; /* 交差点番号 */
Position pos; /* 位置を表す構造体 */
double wait; /* 平均待ち時間 */
char name[MaxName]; /* 交差点名 */
int points; /* 交差道路数 */
int next[5]; /* 隣接する交差点番号 */
} Crossing;
Crossing cross[CrossingNumber];
void map_write(char *filename, int crossing_number)
{
FILE *fp;
int i, j;
fp = fopen(filename, "w");
if (fp == NULL) {
printf("File %s is not created\n", filename);
return;
}
/* 交差点数の書き込み */
fprintf(fp, "%d\n", crossing_number);
for (i = 0; i < crossing_number; i++) {
/* 関数fprintfを使って、構造体のデータをファイルへ書き出すプログラムを記入しなさい */
fprintf(fp, "%d, %lf, %lf, %lf, %s, %d",
cross[i].id, cross[i].pos.x, cross[i].pos.y,
cross[i].wait, cross[i].name, cross[i].points);
for(j=0; j<cross[i].points; j++) {
fprintf(fp, ", %d", cross[i].next[j]);
}
fprintf(fp, "\n"); /* 改行 */
}
fclose(fp);
}
int main(void)
{
int i,j;
int crossing_number=0; /* 入力した交差点情報の数 */
char YesNo[16]; /* 入力継続の問い合わせに使用 */
for (i = 0; i < CrossingNumber; i++) { /* データの入力 */
crossing_number++; /* 交差点数を1増やす */
/* 構造体crossへデータを代入するプログラムを記入しなさい */
printf("交差点番号=");
scanf("%d", &(cross[i].id)); /* 交差点番号の入力 */
printf("名前=");
scanf("%s", cross[i].name); /* 交差点名の入力 */
printf("x座標=");
scanf("%lf", &(cross[i].pos.x)); /* x座標の入力 */
printf("y座標=");
scanf("%lf", &(cross[i].pos.y)); /* y座標の入力 */
printf("待ち時間=");
scanf("%lf", &(cross[i].wait)); /* 待ち時間の入力 */
printf("交差道路数=");
scanf("%d", &(cross[i].points)); /* 交差道路数の入力 */
for (j = 0; j < cross[i].points; j++) { /* 交差道路数だけ繰り返し */
printf("隣接交差点番号(No.%d)=", j);
scanf("%d", &(cross[i].next[j])); /* 隣接交差点番号の入力 */
}
printf("次のデータを入力しますか?(Yes:\"y\")>");
scanf("%s", YesNo);
if (strcmp(YesNo, "y") != 0) break; /* 入力文字が"y"ならforループを抜ける(break) */
}
for (i = 0; i < crossing_number; i++) { /* データの表示 */
printf("交差点番号:%d, 座標(%lf, %lf), 名前:%s,",
cross[i].id, cross[i].pos.x, cross[i].pos.y,
cross[i].name);
printf(" 待ち時間:%lf, points:%d, adjacent crossing(", cross[i].wait, cross[i].points);
for(j=0; j<cross[i].points; j++) { /* 交差道路数だけ繰り返し */
printf("%d ", cross[i].next[j]);
}
printf(")\n");
}
/* ファイルへの書き込み */
map_write("map.dat", crossing_number);
return 0;
}
|
課題1、2のプログラムを参考に、課題2で保存したファイル"map.dat"を構造体に読み込み、
交差点情報を画面に表示するプログラムを作って下さい。ファイル読み込み部分は既に下のプログラム中に
関数map_read()として書かれています。fscanf()の部分に注意して下さい。解答例は時間が来たら表示します。
プログラムが完成したら、課題2で保存したファイル"map.dat"を実際に読み込み、交差点の各種情報が
正確に読み込まれているかどうか確認して下さい。このプログラムは今後のカーナビプログラムの基礎となり
ますので、確実に動くものを必ず作成して下さい。
/* readfile.c --- 交差点データのファイル入力 */
#include <stdio.h>
#define CrossingNumber 100 /* 交差点数=5 */
#define MaxName 50 /* 最大文字数50文字(半角) */
typedef struct {
double x, y; /* 位置 x, y */
} Position; /* 位置を表す構造体 */
typedef struct {
int id; /* 交差点番号 */
Position pos; /* 位置を表す構造体 */
double wait; /* 平均待ち時間 */
char name[MaxName]; /* 交差点名 */
int points; /* 交差道路数 */
int next[5]; /* 隣接する交差点番号 */
} Crossing;
Crossing cross[CrossingNumber];
int map_read(char *filename)
{
FILE *fp;
int i, j;
int crossing_number; /* 交差点数 */
fp = fopen(filename, "r");
if (fp == NULL) {
printf("File %s is not created\n", filename);
return -1;
}
/* はじめに交差点数を読み込む */
fscanf(fp, "%d", &crossing_number);
for (i = 0; i < crossing_number; i++) {
/* 関数fscanfを使って、構造体のデータをファイルから読み込むプログラムを記入しなさい */
fscanf(fp, "%d,%lf,%lf,%lf, %[^,],%d",
&(cross[i].id), &(cross[i].pos.x), &(cross[i].pos.y),
&(cross[i].wait), cross[i].name, &(cross[i].points));
for(j=0; j<cross[i].points; j++) {
fscanf(fp, ",%d", &(cross[i].next[j]));
}
}
fclose(fp);
/* ファイルから読み込んだ交差点数を返す */
return crossing_number;
}
int main(void)
{
int i,j;
int crossing_number; /* 交差点数 */
/* ファイルの読み込み */
crossing_number = map_read("map.dat");
for (i = 0; i < crossing_number; i++) { /* データの表示 */
printf("交差点番号:%d, 座標(%lf, %lf), 名前:%s,",
cross[i].id, cross[i].pos.x, cross[i].pos.y,
cross[i].name);
printf(" 待ち時間:%lf, points:%d, adjacent crossing(", cross[i].wait, cross[i].points);
for(j=0; j<cross[i].points; j++) { /* 交差道路数だけ繰り返し */
printf("%d ", cross[i].next[j]);
}
printf(")\n");
}
return 0;
}
|
さらに仙台市内の交差点データを
map1.dat
map2.dat
として用意しました。
これをコピーペーストでテキストファイル化し、保存してください。(または、wgetを使って、上記の地図データのURLを貼り付ければ簡単に取得できます。)
その後、まずmap1.datのデータが完成したプログラムで読み込めるかどうか試してみて下さい。
ただし、このファイルには90個の交差点データが入っていますので、プログラム中の CrossingNumber の定義を変更すること。加えて、ファイル名もちゃんと変えること。
map1.datが読み込めたひとは、map2.datが読み込めるようにしてみてください。
map2.datは、map.datにローマ字表記の交差点名を付け加えたものです。
構造体を一箇所修正し、対応するfscanfとprintfの箇所を直すだけです。
次回以降はmap2.datを使いますので、必ず動くようにしておいてください。
コンパイル時に、
"warning: ignoring return value of..."
のような警告が出る場合がある。
エラーでなく、警告なので無視しても特に問題はないが、気になるようだったら、
コンパイル時のオプションで "-Wno-unused-result" を付けると出力が抑制できます。