从文本文件中读取和分析房间

时间:2014-12-03 11:15:55

标签: c file struct

我的程序崩溃,我无法找到位置。我几乎在每一行都尝试使用printf进行调试,但我无法找到错误。 我认为它可能属于readLine功能,但我完全迷失了。

我使用的输入文件是

*HallStudyCellarKitchen*StudyHallGarden*CellarHall*KitchenHallGarden*GardenStudyKitchen

这意味着每一个' *'将一个新房间分开,然后显示该房间的门通向哪里。

我的程序代码

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

#define MAX 10
#define BMAX 100
struct room * rooms[MAX];
int rp; // room count


// struct room - name, array of up to 4 doors, number of doors
struct room {char * name; struct door * doors[4]; int dp;};
// struct door - name for the room it connects to, & a pointer to that room
struct door {char * name; struct room * room;};

struct door * newDoor(char * name){
    struct door * d; // pointer d to the address of door
    d = (struct door *) malloc(sizeof(struct door));
    d->name = name; // name of new door is name
    d->room = NULL; // NULL room pointer
    return d;

};

struct  room * newRoom(char * name){
    struct room * r; // pointer r to the address of room
    printf("New room is %s\n",name);
    r = (struct room *) malloc(sizeof(struct room));
    r->name = name; // name of new room is name
    r->dp = 0; // no doors
    return r;
};

showRoom(struct  room * r){
    int i;
    printf("room name: %s\n", r->name);
        for (i = 0; i < (r->dp); r++){
            printf("%d %s\n", i,r->doors[i]->name);
        }
}

showRooms(){
    int i;
      for (i = 0; i < rp; i++){
    showRoom(rooms[i]);
      }
}


char * readLine(FILE * fin){
  char buffer[BMAX];
  int i,j;
  char ch;
  char * l;
  i = 0;
  ch = getc(fin);
  if (ch == EOF)
    return NULL;
  while (ch!='\n' && i < (BMAX - 1)){
    buffer[i] = ch;
    i++;
    ch = getc(fin);
  }
  if (ch != '\n')
    while (ch != '\n')
      ch = getc(fin);
  buffer[i] = '\0';
  l = malloc((i+1) * sizeof(char));
  for (j = 0; j <= i; j++)
    l[j] = buffer[j];
    l[j] = '\0';

  return l;

}

readRooms(FILE * fin)
{  char * l;
   rp = 0;
    // printf("3"); fflush(stdout);
    while((l = readLine(fin)) != NULL)
    {  
         if(rp > MAX)
      {  
          printf("it's too many rooms\n");
         exit(0);
      }
      //printf("%s",l);
      rooms[rp] = newRoom(l);
      //l = readLine(fin);

      if (strncmp(l,"*")==0){
          //printf("2"); fflush(stdout);
          rp++;  

      }

         while(strncmp(l,"*")!=0) 
      {
          //printf("1"); fflush(stdout);
            if((rooms[rp] -> dp) > 4)
         {  printf("it's too many doors\n");
            exit(0);
         }
         rooms[rp] -> doors[rooms[rp] -> dp] = newDoor(l);
         rooms[rp] -> dp++;
         l = readLine(fin);

      }
      //rooms[rp] -> dp = 0;
      //rp++;
      //l = readLine(fin);
   }
}

connect()
{  int i,j,k;
   for(i = 0; i < rp; i++)
    for(j = 0; j < rooms[i]->dp; j++)
    {  for(k = 0; k < rp; k++)
        if(strcmp(rooms[k]->name,rooms[i]->doors[j]->name) == 0)
        {  rooms[i]->doors[j]->room = rooms[k];
           break;
        }
       if(k == rp)
       {  printf("can't find %s\n",rooms[i]->doors[j]->name);
          exit(0);
       }
    }
}

int main(int argc,char ** argv){
    FILE * fin;
    struct room * r; // current room
   // struct door * d;
   int d;

    if((fin=fopen(argv[1],"r"))==NULL)
   {  printf("cannot open %s\n",argv[1]);
      exit(EXIT_FAILURE);
   }
   printf("11"); fflush(stdout);
     readRooms(fin);
     printf("22");
   fclose(fin);
   showRooms();
   connect();
   r = rooms[0];
   while(1)
   {  showRoom(r);
      printf("enter door number> ");
      scanf("%d",&d);
       if(d >= (r->dp))
       printf("bad door number\n");
      else
       r = r->doors[d]->room;
   }

return EXIT_SUCCESS;
}

可能导致崩溃的原因,我该如何解决?

3 个答案:

答案 0 :(得分:0)

readLine函数确实看起来有点容易出错:

char * readLine(FILE * fin){
    char buffer[BMAX];
    int i,j;
    char ch;
    char * l;
    i = 0;
    ch = getc(fin);
    if (ch == EOF)
        return NULL;
    while (ch!='\n' && i < (BMAX - 1)){
        buffer[i] = ch;
        i++;
        ch = getc(fin);
    }
    // The test on the next line is not necessary: it will be caught
    // by the first run of the following while loop.
    if (ch != '\n')
        while (ch != '\n')
            ch = getc(fin);
    buffer[i] = '\0';
    // Allocate a region of memory of (probably) i+1 bytes
    l = malloc((i+1) * sizeof(char));
    // j will range from zero to i, terminating when j = i+1
    for (j = 0; j <= i; j++)
        l[j] = buffer[j];
    // j now equals i+1 and l[j] is one beyond the size of the memory allocated at l.
    l[j] = '\0';

    return l;

}

通过更改循环上的条件

来解决此问题
    // j will range from zero to i-1, terminating when j = i
    for (j = 0; j < i; j++)
        l[j] = buffer[j];
    // j now equals i and l[j] is the last element of the memory allocated at l.
    l[j] = '\0';

注意:

1)您应该始终检查malloc的返回值。

2)malloc分配的内存的实际大小可能超过请求的大小,具体取决于堆实现,处理器体系结构和使用的实际库函数。

此外,您应该很好,并使用free在您指定的每个指针上调用malloc。当进程终止时(如果它在相当常见的操作系统中运行),内存将被最终清理,但是做家务管理是一种好习惯,特别是在readLine返回的临时缓冲区上。

您可能还想查看if(rp > MAX)中的readRooms行,看看是否会导致第11个房间过度运行。

答案 1 :(得分:0)

2个地方int strncmp(const char *s1, const char *s2, size_t n);的使用不正确。建议替换为strcmp()

// if (strncmp(l,"*")==0)
if (strcmp(l,"*")==0)

如果编译器没有对此发出警告,请启用更多警告或获取新编译器。

怀疑关闭1

// if (rp > MAX)
if (rp >= MAX)

// if((rooms[rp] -> dp) > 4)
if ((rooms[rp] -> dp) >=  4)

readLine()的小修补程序

char * readLine(FILE * fin){
  char buffer[BMAX];
  int i,j;

  // char ch;
  int ch;

  char * l;
  i = 0;
  ch = getc(fin);
  if (ch == EOF)
    return NULL;

  // while (ch!='\n' && i < (BMAX - 1)){
  while (ch!='\n' && ch!= EOF &&  i < (BMAX - 1)){

    buffer[i] = ch;
    i++;
    ch = getc(fin);
  }
  if (ch != '\n')

    // while (ch != '\n')
    while (ch != '\n' && ch!= EOF)

      ch = getc(fin);
  buffer[i] = '\0';

  // l = malloc((i+1) * sizeof(char));
  l = malloc(i+1);  // sizeof(char) is always 1
  if (l == NULL) Handle_OOM();

  for (j = 0; j <= i; j++)
    l[j] = buffer[j];
  l[j] = '\0';

  return l;

}

答案 2 :(得分:0)

  

可能导致崩溃的原因,我该如何解决?

崩溃的一个可能(和可能的)原因是readRooms()

中的这个循环
         while(strncmp(l,"*")!=0) 
      {
          //printf("1"); fflush(stdout);
            if((rooms[rp] -> dp) > 4)
         {  printf("it's too many doors\n");
            exit(0);
         }
         rooms[rp] -> doors[rooms[rp] -> dp] = newDoor(l);
         rooms[rp] -> dp++;
         l = readLine(fin);

      }

当达到EOF时,循环结束时的l = readLine(fin)l设置为NULL,并且此空指针被错误地传递给strncmp()(也就是说,正如chux所说,错过了第三个论点。)

在您解决这个问题之前,您必须决定输入文件的格式,也就是说房间是否在同一条线上,就像您的问题一样 - 那么您就无法阅读目前形式为readLine()的单人间 - 或者房间分开。