城市很可能是一个合理的定义(更好地命名为城市,没有理由让它复数)是
typedef struct cities {
char name[64];
struct cities * e;
struct cities * n;
struct cities * s;
struct cities * w;
} cities;
而你的问题是在不进入无限循环的情况下编写所有链接
首先要做的是立即修改你的程序,因为你指出了一个城市的西部等,但你没有指出哪个城市,例如:
if(cityHead->w != NULL && w != 1){
printf("--");
printf("%s West: %s\n", cityHead->name, cityHead->w->name);
printcity(cityHead->w,1,0,0,0);
}else{
printf("--");
printf("%s West: None\n", cityHead->name);
}
其他情况依此类推
让我们看看 2 个城市的变化:
int main()
{
cities * c1 = newcity("c1");
cities * c2 = newcity("c2");
c1->e = c2;
c2->w = c1;
printcity(c1, 0, 0, 0, 0);
}
执行:
pi@raspberrypi:/tmp $ ./a.out
--c1 West: None
--c1 East: c2
--c2 West: None
--c2 East: None
--c2 South: None
--c2 North: None
--c1 South: None
--c1 North: None
而我们看到的程序并没有指出c2的东边是c1
原因很简单,比如在
if(cityHead->w != NULL && w != 1){
printf("--");
printf("%s West: %s\n", cityHead->name, cityHead->w->name);
printcity(cityHead->w,1,0,0,0);
}else{
printf("--");
printf("%s West: None\n", cityHead->name);
}
w 明明是用来不进入无穷大的,但是也挡住了printf
所以让我们修改它:
if(cityHead->w != NULL){
printf("--");
printf("%s West: %s\n", cityHead->name, cityHead->w->name);
if (w != 1)
printcity(cityHead->w,1,0,0,0);
}else{
printf("--");
printf("%s West: None\n", cityHead->name);
}
想管理北的时候也报错,递归调用是:
printcity(cityHead->s,0,0,1,0);
但它必须是
printcity(cityHead->n,0,0,1,0);
最后:
void printcity(cities *cityHead,int e,int w,int s,int n){
if(cityHead){
if(cityHead->w != NULL){
printf("--");
printf("%s West: %s\n", cityHead->name, cityHead->w->name);
if (w != 1)
printcity(cityHead->w,1,0,0,0);
}else{
printf("--");
printf("%s West: None\n", cityHead->name);
}
if(cityHead->e != NULL){
printf("--");
printf("%s East: %s\n", cityHead->name,cityHead->e->name);
if (e != 1)
printcity(cityHead->e,0,1,0,0);
}else{
printf("--");
printf("%s East: None\n", cityHead->name);
}
if(cityHead->s != NULL){
printf("--");
printf("%s South: %s\n", cityHead->name,cityHead->s->name);
if (s != 1)
printcity(cityHead->s,0,0,0,1);
}else{
printf("--");
printf("%s South: None\n", cityHead->name);
}
if(cityHead->n != NULL){
printf("--");
printf("%s North: %s\n", cityHead->name,cityHead->n->name);
if (n != 1)
printcity(cityHead->n,0,0,1,0);
}else{
printf("--");
printf("%s North: None\n", cityHead->name);
}
}
}
除此之外,请注意初始测试
if(cityHead){
仅在 printcity 最初使用 NULL 调用时才有用,函数本身永远不会使用 NULL 重复出现
现在执行是:
pi@raspberrypi:/tmp $ ./a.out
--c1 West: None
--c1 East: c2
--c2 West: c1
--c2 East: None
--c2 South: None
--c2 North: None
--c1 South: None
--c1 North: None
如果我们有 4 个城市组成一个正方形:
int main()
{
cities * c1 = newcity("c1");
cities * c2 = newcity("c2");
cities * c3 = newcity("c3");
cities * c4 = newcity("c4");
c1->e = c2;
c2->w = c1;
c1->s = c3;
c3->n = c1;
c2->s = c4;
c4->n = c2;
c4->w = c3;
c3->e = c4;
printcity(c1, 0, 0, 0, 0);
}
执行写了很长时间的verrrrrrrry,在递归过多和堆栈过大后停止。
原因是参数中的int在图中没有足够的扩展。
一种解决方法是在struct中添加一个字段来标记该城市是否已经被管理。但是在修改最后请求的 struct 之后再次通过图表清除标记。
另一种方法是将已经管理的城市保存在一个列表中,在参数中给出该列表:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct cities {
char name[64];
struct cities * e;
struct cities * n;
struct cities * s;
struct cities * w;
} cities;
typedef struct CityList {
cities * city;
struct CityList * next;
} CityList;
int isPresent(cities * c, CityList * l)
{
while (l) {
if (l->city == c)
return 1;
l = l->next;
}
return 0;
}
void add(cities * city, CityList ** l)
{
CityList * cell = malloc(sizeof(CityList));
cell->city = city;
cell->next = *l;
*l = cell;
}
void clear(CityList ** l)
{
while (*l) {
CityList * c = *l;
*l = (*l)->next;
free(c);
}
}
void printcity(cities *cityHead, CityList ** l){
if(cityHead && !isPresent(cityHead, *l)) {
add(cityHead, l);
if(cityHead->w != NULL){
printf("--");
printf("%s West: %s\n", cityHead->name, cityHead->w->name);
printcity(cityHead->w, l);
}else{
printf("--");
printf("%s West: None\n", cityHead->name);
}
if(cityHead->e != NULL){
printf("--");
printf("%s East: %s\n", cityHead->name,cityHead->e->name);
printcity(cityHead->e, l);
}else{
printf("--");
printf("%s East: None\n", cityHead->name);
}
if(cityHead->s != NULL){
printf("--");
printf("%s South: %s\n", cityHead->name,cityHead->s->name);
printcity(cityHead->s, l);
}else{
printf("--");
printf("%s South: None\n", cityHead->name);
}
if(cityHead->n != NULL){
printf("--");
printf("%s North: %s\n", cityHead->name,cityHead->n->name);
printcity(cityHead->n, l);
}else{
printf("--");
printf("%s North: None\n", cityHead->name);
}
}
}
cities * newcity(char name[])
{
cities *temp = (cities*)malloc(sizeof(cities));
strcpy(temp->name,name);
temp->e = temp->n = temp->s = temp->w = NULL;
return temp;
}
int main()
{
cities * c1 = newcity("c1");
cities * c2 = newcity("c2");
cities * c3 = newcity("c3");
cities * c4 = newcity("c4");
CityList * l = NULL;
c1->e = c2;
c2->w = c1;
c1->s = c3;
c3->n = c1;
c2->s = c4;
c4->n = c2;
c4->w = c3;
c3->e = c4;
puts("[]");
printcity(c1, &l);
clear(&l);
/* to make a 8 */
cities * c5 = newcity("c5");
cities * c6 = newcity("c6");
c3->s = c5;
c5->n = c3;
c4->s = c6;
c6->n = c4;
c5->e = c6;
c6->w = c5;
puts("8");
printcity(c1, &l);
clear(&l);
free(c1);
free(c2);
free(c3);
free(c4);
free(c5);
free(c6);
return 0;
}
执行:
pi@raspberrypi:/tmp $ ./a.out
[]
--c1 West: None
--c1 East: c2
--c2 West: c1
--c2 East: None
--c2 South: c4
--c4 West: c3
--c3 West: None
--c3 East: c4
--c3 South: None
--c3 North: c1
--c4 East: None
--c4 South: None
--c4 North: c2
--c2 North: None
--c1 South: c3
--c1 North: None
8
--c1 West: None
--c1 East: c2
--c2 West: c1
--c2 East: None
--c2 South: c4
--c4 West: c3
--c3 West: None
--c3 East: c4
--c3 South: c5
--c5 West: None
--c5 East: c6
--c6 West: c5
--c6 East: None
--c6 South: None
--c6 North: c4
--c5 South: None
--c5 North: c3
--c3 North: c1
--c4 East: None
--c4 South: c6
--c4 North: c2
--c2 North: None
--c1 South: c3
--c1 North: None
pi@raspberrypi:/tmp $
注意你对 newcity 的定义是危险的,因为这条线
strcpy(temp->name,name);
如果名称太长,您可以在 cities 中的字段 name 中写出,从而产生未定义的行为