简体   繁体   English

strcpy()对某些字符串不起作用,但对其他字符串不起作用

[英]strcpy() not working on some strings but not others

I'm trying to write a simple text adventure program in C. I'm having an issue with strcpy() when trying to set the name/description of each room in the game (see room_setup()). 我试图用C语言编写一个简单的文本冒险程序。尝试设置游戏中每个房间的名称/描述时,strcpy()出现问题(请参阅room_setup())。 It sets the name/description for every room except for the first two (NO_ROOM and KITCHEN). 它为每个房间(前两个房间除外)(NO_ROOM和KITCHEN)设置名称/描述。

#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, "");
}

As a simple test, I made currentRoom increment during the while loop, and had this output: 作为一个简单的测试,我在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 and KITCHEN haven't had their info copied to the struct it seems. 看起来NO_ROOM和KITCHEN的信息尚未复制到结构中。 Can anyone help me work out where I'm going wrong? 谁能帮助我找出我要去的地方?

Insufficient buffer size - off by 1. 缓冲区大小不足-减1。

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

or better 或更好

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];

Same with Item items[NO_ITEM]; Item items[NO_ITEM];相同Item items[NO_ITEM];

Likely other issues. 可能还有其他问题。

We have this: 我们有这个:

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

Okay, so NO_ITEM is 2. Then we have this: 好的,所以NO_ITEM为2。那么我们有这个:

Item items[NO_ITEM];

Okay, so items is an array of two items. 好的,所以items是两个项的数组。 Then we have this: 然后我们有这个:

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, "");

So we have an array of two items, and we're trying to initialize all three of them. 因此,我们有一个包含两个项目的数组,我们正在尝试初始化所有三个项目。 Oops. 哎呀。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM