【问题标题】:String printing causes a C program to crash字符串打印导致 C 程序崩溃
【发布时间】:2014-11-05 21:08:38
【问题描述】:

以下代码由于某种原因崩溃,产生以下消息“进程返回 -1073741819 (0xC0000005)”。调试器说这一行存在分段错误:

printf("|%s|", grid[a][b]);

但是,我认为这不是真正的错误,这意味着之前一定会出错。由于我对 C 中的字符串和数组不是很有经验,请你看看我的代码,看看你是否能找到错误。

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

#define VALUES1 3
#define VALUES2 3
#define NAMELEN 10

void printgrid(char grid[VALUES1][VALUES2]);
void play(char grid[VALUES1][VALUES2], char player);
int game(void);


int main() {

    return game();
}


int game() {
    char grid[VALUES1][VALUES2], player, turn, names[2][NAMELEN];
    int a, b;

    for (a = 0; a < 2; ++a){
        printf("Please enter the name of player number %d\n", a + 1);
        scanf("%s", names[a]);
    }

    for (a = 0; a < VALUES1; ++a){
        for (b = 0; b < VALUES2; ++b){
            grid[a][b] = ' ';
        }
    }

    for (turn = 9; turn > 0; --turn){
        if (turn % 2 == 1){
            player = names[0];
        }
        else {
            player = names[1];
        }
        play(grid, player);
        printf("\n");
        printgrid(grid);
        printf("\n");
    }

    return 0;
}


void printgrid(char grid[VALUES1][VALUES2]) {
    int a, b;

    for (a = 0; a < VALUES1; ++a) {
        for (b = 0; b < VALUES2; ++b) {
            printf("|%s|", grid[a][b]);
        }
        printf("\n");
    }
}


void play(char grid[VALUES1][VALUES2], char player) {
    int row, column;

    printf("Enter the row number:\n");
    scanf("%d", &row);
    printf("Enter the column number:\n");
    scanf("%d", &column);

    --row;
    --column;

    grid[row][column] = player;
}

编辑: 使用 %c 输出

|þ||þ||þ|
|±||±||þ|
|±||±||þ|

【问题讨论】:

  • grid[a][b]char,而不是字符串,因此您应该在printf 中使用%c 格式(或使用putchar)。你的编译器可以告诉你,如果你通过启用所有警告来指示它。
  • 正如@MOehm 所说,%s 将需要一个字符数组。你传递给它一个字符文字。因此 printf 正在向前读取内存以寻找空终止符。因此,为什么会出现分段错误。几乎任何时候一个函数向前读入不是它自己的内存,程序就会崩溃。 %c 是您所需要的。
  • edit您的问题标题更具体。 “C 程序崩溃”没有具体说明您遇到的问题,如果它出现在该站点的未来用户的搜索中,它将完全没有意义。对于您的汽车维修人员来说,这并不比“我的车坏了”更有意义。
  • 谢谢!首先,我想打印一个字符串而不仅仅是一个字符。我应该如何改变我的代码来实现这一点?其次, %c 不会使程序崩溃,但播放的角色始终相同。我想要代码在他们玩完广场后将名字打印到广场上!

标签: c arrays string multidimensional-array


【解决方案1】:

问题在于您使用player。您将其指定为char,但尝试为其分配char* 值。在整个函数中混合使用 charchar *。意图很明确。您想在游戏过程中使用name[0]name[1] 中的第一个字符来构建游戏网格。您可以这样做,但在使用时您必须非常小心

此外,在编译代码时,总是打开警告。他们会立即引导您解决代码中的问题:

$ gcc -Wall -Wextra -o bin/play play.c

play.c: In function ‘game’:
play.c:36:20: warning: assignment makes integer from pointer without a cast [enabled by default]
            player = names[0];
                    ^
play.c:39:20: warning: assignment makes integer from pointer without a cast [enabled by default]
            player = names[1];
                    ^
play.c: In function ‘printgrid’:
play.c:56:13: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘int’ [-Wformat=]
            printf("|%s|", grid[a][b]);
            ^

使player 的使用保持一致的一种解决方案是将其声明为char *,然后在需要将player 用作字符时将其声明为dereference(即*player,其完整形式为*(player + 0) 等同于 player[0]) 解决方案如下:

int game() {
    char grid[VALUES1][VALUES2], turn, names[2][NAMELEN];
    char *player;
    int a, b;

    for (a = 0; a < 2; ++a){
        printf("Please enter the name of player number %d\n", a + 1);
        scanf("%s", names[a]);
    }

    for (a = 0; a < VALUES1; ++a){
        for (b = 0; b < VALUES2; ++b){
            grid[a][b] = ' ';
        }
    }

    for (turn = 9; turn > 0; --turn){
        if (turn % 2 == 1){
            player = names[0];
        }
        else {
            player = names[1];
        }
        play(grid, *player);
        printf("\n");
        printgrid(grid);
        printf("\n");
    }

    return 0;
}


void printgrid(char grid[VALUES1][VALUES2]) {
    int a, b;

    for (a = 0; a < VALUES1; ++a) {
        for (b = 0; b < VALUES2; ++b) {
            printf("|%c|", grid[a][b]);
        }
        printf("\n");
    }
}

输出:

$ ./bin/play
Please enter the name of player number 1
Don
Please enter the name of player number 2
Millie
Enter the row number:
1
Enter the column number:
2

| ||D|| |
| || || |
| || || |
...
Enter the row number:
3
Enter the column number:
1

|M||D||D|
|D||M||M|
|D||M||D|

顺便说一句,您可以通过简单的if 语句改进printgrid 的输出以消除内部列中的双||

void printgrid(char grid[VALUES1][VALUES2]) {
    int a, b;

    for (a = 0; a < VALUES1; ++a) {
        for (b = 0; b < VALUES2; ++b) {
            if (b == 0)
                printf("|%c|", grid[a][b]);
            else
                printf("%c|", grid[a][b]);
        }
        printf("\n");
    }
}

输出:

|M|D|D|
|D|M|M|
|D|M|D|

【讨论】:

    猜你喜欢
    • 2015-11-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多