【问题标题】:Variable reset after scanfscanf 后变量复位
【发布时间】:2014-10-04 15:54:32
【问题描述】:

我写了以下函数:

typedef enum {GREEN,BLACK, WHITE} color;

void StartGame(Piece board[8][8])
{
    color currentPlayer=WHITE;
    char location[2];
    int gameover=1;
    while(gameover)
    {
        printf("%d\n",currentPlayer);

        if(currentPlayer==WHITE)
            printf(BOLDWHITE"White: Please select a piece:\n");
        else
            printf(BOLDBLACK"Black: Please select a piece:\n");

        printf("%d\n",currentPlayer);

        scanf("%s",location);

        printf("%d\n",currentPlayer);
        if(currentPlayer==WHITE)
            currentPlayer=BLACK;
        else
            currentPlayer=WHITE;

    }
} 

我在任何级别打印currentPlayer 以查看发生了什么 -> 在这里我得到了什么:

2
White: Please select a piece:
2
a1
0
2
White: Please select a piece:
2

为什么scanf后面的当前玩家为0?我没碰过。

【问题讨论】:

  • 您将一个 3 字节的位置("a1",其中包括一个空字节)读入一个 2 字节的内存块。这是堆栈溢出。
  • 另外,一定要检查scanf的返回值,否则你一定会遇到难以复制的神秘错误。

标签: c linux string gcc scanf


【解决方案1】:

缓冲区location 只能容纳 2 个字符,scanf 在末尾放置一个额外的 NUL 字符。因此,您有堆栈损坏问题。只需给location 更多空间,例如:

char location[8];

编辑

由于您只想读取字符串,我建议您使用fgets,它允许您限制从输入字符串中读取的字符数。因此,我的代码如下所示:

char location[8];
...
fgets(location, sizeof(location), stdin); //instead of scanf, fgets reads at most one less than buffer's size characters.

您只需要担心fgets 会在末尾添加一个最后的结束行字符 (\n),但如果您只处理字符串的前 2 个字符,这不应该是一个交易。

【讨论】:

  • 我为什么要写 STDIN? :D 谢谢!
【解决方案2】:

当您在字符数组位置输入字符串时,您似乎覆盖了 currentPlayer 占用的内存。从控制台输出中可以看出,您输入了字符串a1。要将其存储在数组位置,应至少定义为

char location[3];

因为 scanf 将输入的字符串附加到终止零。

如果你改用函数fgets会更好。

【讨论】:

    【解决方案3】:

    你应该使用这样的东西:

    sprintf(format, "%%%dX", sizeof(buffer));
    fscanf(file, format, &buffer);
    

    【讨论】:

      猜你喜欢
      • 2013-12-08
      • 2011-11-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多