【问题标题】:Problems of cin and scanf() on MinGW-w64MinGW-w64 上 cin 和 scanf() 的问题
【发布时间】:2020-08-09 06:19:36
【问题描述】:

我的MinGW-w64的版本是:x86_64-8.1.0-release-posix-seh-rt_v6-rev0.7z

我的系统版本是:Windows 10 2004

当我尝试使用 MinGW-w64 的 g++ 编译和运行这个源文件时,我遇到了麻烦。 这个文件的名字是“temp.cpp”

#include <iostream>
using namespace std;
int main()
{
    char player1[8] = {0}, player2[8] = {0};
    cin >> player1 >> player2;
    cout << player1 << ' ' << player2;
    return 0;
}

我通过输入这行代码在 PowerShell 中构建并运行了这个文件。

g++ -g .\temp.cpp -o .\temp.exe; .\temp.exe

然后我输入了输入。

Rock Scissors

按下回车键后。我明白了。

 Scissors

第一个单词没有打印出来。

然后我使用 VS Code 来调试源文件。我输入输入后发现,player1[0] 中的数据没有被“R”替换。相反,它仍然是0

然后我将整个mingw64文件夹复制到另一台电脑上再试一次,同样的事情又发生了。

然后我用scanf()替换了cin。

#include <iostream>
using namespace std;
int main()
{
    char player1[8] = {0}, player2[8] = {0};
    scanf("%s %s", player1, player2);
    printf("%s %s", player1, player2);
    return 0;
}

同样的事情又发生了。

然后我下载旧版MinGW-w64:x86_64-5.4.0-release-posix-seh-rt_v5-rev0.7z

使用旧版本,现在可以正常打印了。

为什么?

【问题讨论】:

  • 您的数组长度应为 9 个字符,以便允许 8 个字符用于剪刀加空终止符,或者只使用 std::string 代替

标签: c++ mingw-w64


【解决方案1】:

哦...您的数组对于Scissors 来说太短了一个字符。 nul-terminating 字符需要 9 个字符 8 + 1。所以在你的堆栈上发生的事情是你有 Player1 后跟 Player2 (但由于堆栈增长,Player1 位于Player2) 上方的内存中,例如

    |        Player2                |        Player1                |
    +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
    | S | c | i | s | s | o | r | s | \0| o | c | k | \0|   |   |   |
    +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+

因此,当您输入 "Scissors" 并且为字符串结尾写入 nul 终止字符时,您会用 '\0' 覆盖 Player1 的第一个字符,导致它看起来是一个空 -字符串。

经验教训——不要吝啬缓冲区大小!(或者更好的是,使用std::string

声明:

char player1[32] = {0}, player2[32] = {0};

#include <string>
...
std::string player1 {}, player2 {};

然后再试一次。

【讨论】:

  • 或者更好的是,使用std::strings。
  • 阿门 -- 解决了很多零散的问题:)
  • 非常感谢!这正是问题所在。但是我还是想知道为什么低版本的mingw会容忍我的错过。 (也许它使用不同的方法来存储输入?)
  • 没有。超出数组末尾的写入会调用 Undefined Behavior,因此几乎任何事情都可能发生。如果可能看起来有效,或者它可能会出现 segFault。在这种情况下,不难推断发生了什么。这是在 C++ 中使用普通旧数组的陷阱之一。它们的好处是速度快得令人眼花缭乱,但编译器对此无能为力。 std::stringstd::vector 等 STL 容器提供自动内存管理,因此它们可以根据需要增长。每个都有自己的位置,但使用 C++ 提供的细节会带来好处。祝你编码好运!
猜你喜欢
  • 2010-12-26
  • 2012-01-18
  • 2018-01-03
  • 1970-01-01
  • 1970-01-01
  • 2017-01-03
  • 1970-01-01
  • 2014-10-24
相关资源
最近更新 更多