2016-11-11 67 views
1

我正嘗試在C中編寫一個簡單的文本冒險程序。我嘗試設置每個房間的名稱/描述時遇到了strcpy()問題遊戲(請參閱room_setup())。它爲每個房間設置除前兩個(NO_ROOM和KITCHEN)以外的名稱/描述。strcpy()不能用於某些字符串,但不能用於其他字符

#include <stdio.h> 
#include <stdbool.h> 
#include <string.h> 
#include <ctype.h> 

#define DIRS 4 
#define DEBUG 0 
#define MAX_INPUT_LENGTH 100 

// defines numeric values for each direction 
typedef enum {NORTH, EAST, SOUTH, WEST} en_dirs; 

// defines numeric values for each room 
typedef enum { 
    KITCHEN, 
    PANTRY, 
    HALLWAY_1, 
    HALLWAY_2, 
    TROLLS_DOMAIN, 
    EMPTY_ROOM_1, 
    EMPTY_ROOM_2, 
    EXIT, 
    NO_ROOM 
} en_rooms; 

// defines numeric values for each item 
typedef enum{ 
    APPLE, 
    KEY, 
    NO_ITEM 
} en_items; 

// defines a struct type to store room data 
typedef struct room{ 
    char name[100]; 
    char desc[100]; 
    en_dirs around[DIRS]; 
} Room; 

// defines a struct type to store item data 
typedef struct items{ 
    char name[100]; 
    char desc[100]; 
} Item; 

void str_read(char *s);  // read string from console, point s to it 
void str_upper(char *s); // convert string to upper case 
void room_setup(Room *r); // fill info about rooms into r array 
void item_setup(Item *i); // fill info about items into i array 

int main(void){ 
    char input[MAX_INPUT_LENGTH]; 
    char *verb, *noun; 

    // arrays to store room and item info. NO_**** is always the final element 
    // in their respective enums, so the size of the array will never be larger 
    // than necessary. 
    Room rooms[NO_ROOM]; 
    Item items[NO_ITEM]; 

    room_setup(rooms); // fill rooms array with info 
    item_setup(items); // fill items array with info 

    en_rooms currentRoom = KITCHEN; // set the starting room to the kitchen 

    // main game loop 
    while(1){ 

     // print current room name + description 
     printf("-- %s --\n", rooms[currentRoom].name); 
     printf("%s\n", rooms[currentRoom].desc); 

     printf("\n> "); 

     // read input and convert it to upper case 
     str_read(input); 
     str_upper(input); 

     if(DEBUG){ 
      printf("Input: %s\n", input); 
      printf("Length: %d\n", strlen(input)); 
     } 

     // split input into two pieces (expects max of two words, for now) 
     verb = strtok(input, " "); 
     noun = strtok(NULL, " "); 

     if(DEBUG){ 
      printf("Verb: %s\n", verb); 
      printf("Noun: %s\n", noun); 
     } 

     /* 
     if(strcmp(input, "NORTH") == 0 && rooms[currentRoom].around[NORTH] != NO_ROOM){ 
      currentRoom = rooms[currentRoom].around[NORTH]; 
     } 

     */ 

    } 

    return 0; 
} 

// points s to new string. clears stdin if user has input more than 
// MAX_USER_INPUT characters. 
void str_read(char *s){ 
    fgets(s, MAX_INPUT_LENGTH, stdin); // point s to user input from stdin 

    // clear extra characters from stdin, if the user has input more than 
    // MAX_INPUT_LENGTH characters. 
    if(!strchr(s, '\n')){ // newline does not exist 
     while(fgetc(stdin) != '\n'); // discard until newline 
    } 
} 

// converts string s to upper case 
void str_upper(char *s){ 
    int i; 
    char c; 

    for(i = 0; i < strlen(s); i++){ 
     s[i] = toupper(s[i]); 
    } 
} 

// fills the array r with info on each room. 
void room_setup(Room *r){ 

    strcpy(r[NO_ROOM].name, "Nothing there."); 
    strcpy(r[NO_ROOM].name, "Description"); 
    r[NO_ROOM].around[NORTH] = NO_ROOM; 
    r[NO_ROOM].around[EAST] = NO_ROOM; 
    r[NO_ROOM].around[SOUTH] = NO_ROOM; 
    r[NO_ROOM].around[WEST] = NO_ROOM; 

    strcpy(r[KITCHEN].name, "Kitchen"); 
    strcpy(r[KITCHEN].desc, "This is the kitchen."); 
    r[KITCHEN].around[NORTH] = NO_ROOM; 
    r[KITCHEN].around[EAST] = PANTRY; 
    r[KITCHEN].around[SOUTH] = NO_ROOM; 
    r[KITCHEN].around[WEST] = NO_ROOM; 

    strcpy(r[HALLWAY_1].name, "Hallway"); 
    strcpy(r[HALLWAY_1].desc, "A long hallway."); 
    r[HALLWAY_1].around[NORTH] = HALLWAY_2; 
    r[HALLWAY_1].around[EAST] = NO_ROOM; 
    r[HALLWAY_1].around[SOUTH] = KITCHEN; 
    r[HALLWAY_1].around[WEST] = TROLLS_DOMAIN; 

    strcpy(r[TROLLS_DOMAIN].name, "Troll's Domain"); 
    strcpy(r[TROLLS_DOMAIN].desc, "You see a Troll."); 
    r[TROLLS_DOMAIN].around[NORTH] = NO_ROOM; 
    r[TROLLS_DOMAIN].around[EAST] = HALLWAY_1; 
    r[TROLLS_DOMAIN].around[SOUTH] = EMPTY_ROOM_1; 
    r[TROLLS_DOMAIN].around[WEST] = NO_ROOM; 

    strcpy(r[EMPTY_ROOM_1].name, "Empty Room"); 
    strcpy(r[EMPTY_ROOM_1].desc , "An empty room. There was no reason to come here."); 
    r[EMPTY_ROOM_1].around[NORTH] = TROLLS_DOMAIN; 
    r[EMPTY_ROOM_1].around[EAST] = NO_ROOM; 
    r[EMPTY_ROOM_1].around[SOUTH] = NO_ROOM; 
    r[EMPTY_ROOM_1].around[WEST] = NO_ROOM; 

    strcpy(r[HALLWAY_2].name, "Hallway"); //hallway 2 
    strcpy(r[HALLWAY_2].desc, "A long hallway."); 
    r[HALLWAY_2].around[NORTH] = EXIT; 
    r[HALLWAY_2].around[EAST] = EMPTY_ROOM_2; 
    r[HALLWAY_2].around[SOUTH] = NO_ROOM; 
    r[HALLWAY_2].around[WEST] = NO_ROOM; 

    strcpy(r[EMPTY_ROOM_2].name, "Empty Room"); 
    strcpy(r[EMPTY_ROOM_2].desc , "An empty room."); 
    r[EMPTY_ROOM_2].around[NORTH] = NO_ROOM; 
    r[EMPTY_ROOM_2].around[EAST] = NO_ROOM; 
    r[EMPTY_ROOM_2].around[SOUTH] = NO_ROOM; 
    r[EMPTY_ROOM_2].around[WEST] = HALLWAY_2; 

    strcpy(r[EXIT].name, "Exit"); 
    strcpy(r[EXIT].desc, "You win lol"); 
    r[EXIT].around[NORTH] = NO_ROOM; 
    r[EXIT].around[EAST] = NO_ROOM; 
    r[EXIT].around[SOUTH] = HALLWAY_2; 
    r[EXIT].around[WEST] = NO_ROOM; 

} 

// fills the array i with info on each item. 
void item_setup(Item *i){ 
    strcpy(i[APPLE].name, "Apple"); 
    strcpy(i[APPLE].desc, "A bright red apple."); 

    strcpy(i[KEY].name, "Key"); 
    strcpy(i[NO_ITEM].name, "A silver key."); 

    strcpy(i[NO_ITEM].name, ""); 
    strcpy(i[NO_ITEM].desc, ""); 
} 

一個簡單的測試,我while循環期間的currentRoom增量,有這樣的輸出:

-- -- 


> 
-- -- 


> 
-- Hallway -- 
A long hallway. 

> 
-- Hallway -- 
A long hallway. 

> 
-- Troll's Domain -- 
You see a Troll. 

> 
-- Empty Room -- 
An empty room. There was no reason to come here. 

> 
-- Empty Room -- 
An empty room. 

> 
-- Exit -- 
You win lol 

NO_ROOM和廚房都沒有自己的信息複製到似乎結構。任何人都可以幫我弄清楚我要出錯的地方嗎?

+3

「strcpy()不能在某些字符串上工作,但不能在其他字符串上工作」 - 所以它不適用於任何字符串?或者一旦你弄清楚它是如何工作的,它可能會在字符串上工作嗎?我只是看到了一層代碼,沒有[問]所要求的[mcve]以及其他信息。 – Olaf

+1

你的代碼不應該編譯。 'around'成員的類型是'en_dirs',但它擁有'en_rooms'。 –

+0

@DavidSchwartz謝謝你指出。但是,當改爲「en_rooms」時仍然存在相同的問題。 – Sato

回答

2

足夠的緩衝區大小 - 關閉的1

// Room rooms[NO_ROOM]; 
Room rooms[NO_ROOM + 1]; 

或更好

typedef enum { 
    KITCHEN, 
    PANTRY, 
    ... 
    NO_ROOM, 

    // Insure ROOM_N is 1 greater than all the others. 
    // Putting it last usually does this. 
    ROOM_N 
} en_rooms; 

Room rooms[ROOM_N]; 

同樣的,Item items[NO_ITEM];

其他可能的問題。

+0

它排序它,謝謝!還有很多其他問題是:/ – Sato

2

我們有這樣的:

typedef enum{ 
    APPLE,  // 0 
    KEY,  // 1 
    NO_ITEM // 2 
} en_items; 

好了,NO_ITEM爲2。然後,我們有這樣的:

Item items[NO_ITEM]; 

好了,items是兩個項目的數組。然後我們有:

strcpy(i[APPLE].name, "Apple"); 
strcpy(i[APPLE].desc, "A bright red apple."); 

strcpy(i[KEY].name, "Key"); 
strcpy(i[NO_ITEM].name, "A silver key."); 

strcpy(i[NO_ITEM].name, ""); 
strcpy(i[NO_ITEM].desc, ""); 

所以我們有兩個項目的數組,我們試圖初始化他們三個。哎呀。

相關問題