線形リストの課題がわかりません
Posted: 2012年7月11日(水) 15:08
大学で次のような課題がでました
市のデータ(cities.txt)を対象として、以下の各機能を持ったプログラムを作成し、提出してください。
1. 情報の登録と一覧表示
2. 情報の削除
3. cities.txt からの情報の読み込み
4. citiesDB.txtへのリスト内容の書き出し
5. 人口でソート
関数の穴埋め形式の課題です。コメントがある部分の関数を完成させるのですが、自分でよくわからないまま入力してみました。
間違っている部分を教えていただきたいです。
コンパイル結果はコメントで書いてあります。
あと、insertCityByPopl()の部分は全くわかりませんでした。こちらもできればお願いします。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define STRLEN 32
#define BUF_LEN 128
#define CITYDB_R_FILE "cities.txt" // 読み込み用ファイル
#define CITYDB_W_FILE "citiesDB.txt" // 書き出し用ファイル
struct cities{
char pref[STRLEN];
char city[STRLEN];
int popl;
float area;
float dens;
char founded[STRLEN];
struct cities *next;
};
struct cities *root=NULL; // rootへのポインタは大域変数として定義
void *mymalloc(size_t sz){
void *p = (void *)malloc(sz);
if(p == NULL){
fprintf(stderr,"ERR: Can't malloc memory %d bytes.",(int)sz);
exit(1);
}
memset(p,0,sz);
return p;
}
void showCity(struct cities *c, FILE *fp){
fprintf(fp,"%s\t%s\t%d\t%.2f\t%.2f\t%s\n",
c->pref, c->city, c->popl, c->area, c->dens, c->founded);
}
struct cities *genNewCityCell(char *pref, char *city, int popl, float area, float dens, char *founded ){
struct cities *c;
c = mymalloc(sizeof(struct cities));
//メモリを確保したcに対して値を代入する
c->pref = pref; //代入に互換性のない?
c->city = city;//代入に互換性のない?
c->popl = popl;
c->area = area;
c->dens = dens;
c->founded = founded;//代入に互換性のない?
return c;
}
void showList(FILE *fp){
struct cities *cur= root;
while(cur != NULL){
showCity(cur,fp);
cur = cur->next;
}
}
void saveList(){
//書き込み用ファイルを開きそのファイルポインタfpに対して
//showList(fp)を呼べばよい。void showList()は12行上で定義している
FILE *fp;
if((fp=fopen(CITYDB_W_FILE,"w"))==NULL){
printf("cannot open!\n");
exit(1);
}
showList(fp);
fclose(fp);
printf("File saved to %s\n",CITYDB_W_FILE);
}
struct cities *line2City(char *buf){
struct cities *c=NULL;
int popl;
char pref[STRLEN], city[STRLEN], founded[STRLEN];
float area, dens;
sscanf(buf, "%s %s %d %f %f %s", pref, city, &popl, &area, &dens, founded);
c = genNewCityCell(pref,city,popl,area,dens,founded);
return c;
}
void addCity(struct cities *c){
struct cities **cur= &root;
//rootから順にたどって末尾に挿入する
while(*cur!=NULL){
cur = &((*cur)->next);
}
*cur = c;
}
void inputStr(char *buf,int len){
fgets(buf,len,stdin);
buf[strlen(buf)-1]='\0';
}
void addNewCity(){
char buf[BUF_LEN] = "";
struct cities *c;
while(strlen(buf)<=0){
printf("Input one line:\n");
inputStr(buf, BUF_LEN);
}
if(strncmp(buf, "Prefecture", 10) == 0) return;
c = line2City(buf);
addCity(c);
}
void deleteCityFromList(char *delcity){
/*
要加筆
順にたどり,当該項目を削除する.
*/
struct cities **cur = &root;
while(*cur!=NULL){
if(delcity==(*cur)->city){
free(*cur);
}
else{
cur = &((*cur)->next);
}
}
}
void deleteCity(){
char buf[STRLEN];
showList(stdout);
printf("Select Delete City Name:");
inputStr(buf, STRLEN);
deleteCityFromList(buf);
}
void readListFILE(FILE *fp){
char buf[BUF_LEN];
struct cities *c;
while( fgets(buf,BUF_LEN,fp) != NULL){
if(strncmp(buf, "Prefecture", 10) == 0) continue;
c = line2City(buf);
if(c != NULL) addCity(c);
}
}
void readList(){
/*
要加筆
ファイルCITYDB_R_FILEを読み取り用で開く
ファイルが開けない場合のエラー処理
readListFILE(fp);
ファイルをクローズ
*/
FILE *fp;
if((fp=fopen(CITYDB_R_FILE,"r"))==NULL){
printf("cannot open!\n");
exit(1);
}
readListFILE(fp);
fclose(fp);
printf("File loaded\n");
}
void insertCityByPopl(struct cities *sc){
struct cities **cur= &root;
/*
要加筆
順にたどり、挿入すべき箇所に sc を挿入
*/
}
void sortList(){
struct cities *cur,*fr;
cur = root;
root = NULL;
while(cur != NULL){
insertCityByPopl(genNewCityCell(cur->pref, cur->city, cur->popl, cur->area, cur->dens, cur->founded));
fr = cur;
cur = cur->next;
free(fr);
}
showList(stdout);
}
int main(int argc, char *argv[]){
char buf[BUF_LEN];
while(1){
printf("Menu(a:add, d:delete, l:list, s:sort, w:write file, r:read file q:quit):\n");
fgets(buf,BUF_LEN,stdin);
switch(buf[0]){
case 'a':
addNewCity();
break;
case 'd':
deleteCity();
break;
case 'l':
showList(stdout);
break;
case 's':
sortList();
break;
case 'w':
saveList();
break;
case 'r':
readList();
break;
case 'q':
exit(0);
break;
}
}
}
cities.txt
Prefecture City Population Area Density Founded
Aichi Nagoya 2239464 326.45 6860 1889-10-01
Aichi Toyohashi 377045 261.35 1443 1906-08-01
Aichi Okazaki 371380 387.24 959 1916-07-01
Aichi Ichinomiya 375939 113.91 3300 1921-09-01
Aichi Seto 132311 111.61 1185 1929-10-01
Aichi Handa 117927 47.24 2496 1937-10-01
Aichi Kasugai 300713 92.71 3244 1943-06-01
Aichi Toyokawa 161595 150.71 1072 1943-06-01
Aichi Tsushima,Aichi 65646 25.08 2617 1947-03-01
Aichi Hekinan 73024 35.86 2036 1948-04-05
Aichi Kariya 145117 50.45 2876 1950-04-01
Aichi Toyota 420286 918.47 458 1951-03-01
Aichi Anjo 176046 86.01 2047 1952-05-05
Aichi Nishio 106643 75.78 1407 1953-12-15
・
・
・
・
・
市のデータ(cities.txt)を対象として、以下の各機能を持ったプログラムを作成し、提出してください。
1. 情報の登録と一覧表示
2. 情報の削除
3. cities.txt からの情報の読み込み
4. citiesDB.txtへのリスト内容の書き出し
5. 人口でソート
関数の穴埋め形式の課題です。コメントがある部分の関数を完成させるのですが、自分でよくわからないまま入力してみました。
間違っている部分を教えていただきたいです。
コンパイル結果はコメントで書いてあります。
あと、insertCityByPopl()の部分は全くわかりませんでした。こちらもできればお願いします。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define STRLEN 32
#define BUF_LEN 128
#define CITYDB_R_FILE "cities.txt" // 読み込み用ファイル
#define CITYDB_W_FILE "citiesDB.txt" // 書き出し用ファイル
struct cities{
char pref[STRLEN];
char city[STRLEN];
int popl;
float area;
float dens;
char founded[STRLEN];
struct cities *next;
};
struct cities *root=NULL; // rootへのポインタは大域変数として定義
void *mymalloc(size_t sz){
void *p = (void *)malloc(sz);
if(p == NULL){
fprintf(stderr,"ERR: Can't malloc memory %d bytes.",(int)sz);
exit(1);
}
memset(p,0,sz);
return p;
}
void showCity(struct cities *c, FILE *fp){
fprintf(fp,"%s\t%s\t%d\t%.2f\t%.2f\t%s\n",
c->pref, c->city, c->popl, c->area, c->dens, c->founded);
}
struct cities *genNewCityCell(char *pref, char *city, int popl, float area, float dens, char *founded ){
struct cities *c;
c = mymalloc(sizeof(struct cities));
//メモリを確保したcに対して値を代入する
c->pref = pref; //代入に互換性のない?
c->city = city;//代入に互換性のない?
c->popl = popl;
c->area = area;
c->dens = dens;
c->founded = founded;//代入に互換性のない?
return c;
}
void showList(FILE *fp){
struct cities *cur= root;
while(cur != NULL){
showCity(cur,fp);
cur = cur->next;
}
}
void saveList(){
//書き込み用ファイルを開きそのファイルポインタfpに対して
//showList(fp)を呼べばよい。void showList()は12行上で定義している
FILE *fp;
if((fp=fopen(CITYDB_W_FILE,"w"))==NULL){
printf("cannot open!\n");
exit(1);
}
showList(fp);
fclose(fp);
printf("File saved to %s\n",CITYDB_W_FILE);
}
struct cities *line2City(char *buf){
struct cities *c=NULL;
int popl;
char pref[STRLEN], city[STRLEN], founded[STRLEN];
float area, dens;
sscanf(buf, "%s %s %d %f %f %s", pref, city, &popl, &area, &dens, founded);
c = genNewCityCell(pref,city,popl,area,dens,founded);
return c;
}
void addCity(struct cities *c){
struct cities **cur= &root;
//rootから順にたどって末尾に挿入する
while(*cur!=NULL){
cur = &((*cur)->next);
}
*cur = c;
}
void inputStr(char *buf,int len){
fgets(buf,len,stdin);
buf[strlen(buf)-1]='\0';
}
void addNewCity(){
char buf[BUF_LEN] = "";
struct cities *c;
while(strlen(buf)<=0){
printf("Input one line:\n");
inputStr(buf, BUF_LEN);
}
if(strncmp(buf, "Prefecture", 10) == 0) return;
c = line2City(buf);
addCity(c);
}
void deleteCityFromList(char *delcity){
/*
要加筆
順にたどり,当該項目を削除する.
*/
struct cities **cur = &root;
while(*cur!=NULL){
if(delcity==(*cur)->city){
free(*cur);
}
else{
cur = &((*cur)->next);
}
}
}
void deleteCity(){
char buf[STRLEN];
showList(stdout);
printf("Select Delete City Name:");
inputStr(buf, STRLEN);
deleteCityFromList(buf);
}
void readListFILE(FILE *fp){
char buf[BUF_LEN];
struct cities *c;
while( fgets(buf,BUF_LEN,fp) != NULL){
if(strncmp(buf, "Prefecture", 10) == 0) continue;
c = line2City(buf);
if(c != NULL) addCity(c);
}
}
void readList(){
/*
要加筆
ファイルCITYDB_R_FILEを読み取り用で開く
ファイルが開けない場合のエラー処理
readListFILE(fp);
ファイルをクローズ
*/
FILE *fp;
if((fp=fopen(CITYDB_R_FILE,"r"))==NULL){
printf("cannot open!\n");
exit(1);
}
readListFILE(fp);
fclose(fp);
printf("File loaded\n");
}
void insertCityByPopl(struct cities *sc){
struct cities **cur= &root;
/*
要加筆
順にたどり、挿入すべき箇所に sc を挿入
*/
}
void sortList(){
struct cities *cur,*fr;
cur = root;
root = NULL;
while(cur != NULL){
insertCityByPopl(genNewCityCell(cur->pref, cur->city, cur->popl, cur->area, cur->dens, cur->founded));
fr = cur;
cur = cur->next;
free(fr);
}
showList(stdout);
}
int main(int argc, char *argv[]){
char buf[BUF_LEN];
while(1){
printf("Menu(a:add, d:delete, l:list, s:sort, w:write file, r:read file q:quit):\n");
fgets(buf,BUF_LEN,stdin);
switch(buf[0]){
case 'a':
addNewCity();
break;
case 'd':
deleteCity();
break;
case 'l':
showList(stdout);
break;
case 's':
sortList();
break;
case 'w':
saveList();
break;
case 'r':
readList();
break;
case 'q':
exit(0);
break;
}
}
}
cities.txt
Prefecture City Population Area Density Founded
Aichi Nagoya 2239464 326.45 6860 1889-10-01
Aichi Toyohashi 377045 261.35 1443 1906-08-01
Aichi Okazaki 371380 387.24 959 1916-07-01
Aichi Ichinomiya 375939 113.91 3300 1921-09-01
Aichi Seto 132311 111.61 1185 1929-10-01
Aichi Handa 117927 47.24 2496 1937-10-01
Aichi Kasugai 300713 92.71 3244 1943-06-01
Aichi Toyokawa 161595 150.71 1072 1943-06-01
Aichi Tsushima,Aichi 65646 25.08 2617 1947-03-01
Aichi Hekinan 73024 35.86 2036 1948-04-05
Aichi Kariya 145117 50.45 2876 1950-04-01
Aichi Toyota 420286 918.47 458 1951-03-01
Aichi Anjo 176046 86.01 2047 1952-05-05
Aichi Nishio 106643 75.78 1407 1953-12-15
・
・
・
・
・