【问题标题】:C++ | Why am I getting weird characters after executing this program?C++ |为什么执行此程序后出现奇怪的字符?
【发布时间】:2019-02-01 08:31:56
【问题描述】:

在向myString 输入一些字母后,我得到一个输出,其中包含与myString 完全相同的字母以及一些奇怪的乱码字符。 例如,我输入 "letters",我得到的输出如下:

字母 ÷ìu ╝■( Bñìu¿☻÷u³■( ʶì Ä◄ÿub◄ÿu←öïÜ ÉpB º■( ( ─ ( î¯u Å{N´■   b◄ÿu─[uÉpB ö ( ¯pB ÉpB P4å Ç

此外,这些奇怪的字符在不同的输入下看起来会有所不同,但在使用相同的输入重建后它们不会改变。

这是我写的代码:

#include <iostream>
using namespace std;
int main()
{
    constexpr int BUFFER_SIZE = 128;

    char myString[BUFFER_SIZE + 1] = {}; // + 1 for null. Initialize all with null.

    cout << "Enter a string: ";
    fgets(myString, BUFFER_SIZE, stdin);

    int myString_size = sizeof(myString);
    for (int i = 0; i < myString_size; i++) {
        cout << myString[i];
    }
    system("PAUSE");
    return 0;
}

现在,我知道 fgets() 函数会在 letters 末尾放置一个换行符 但是为什么这些字符仍然出现?

【问题讨论】:

  • 一个简单的提示:sizeof 不是返回字符串的长度
  • ...反正你也不能走过去。
  • 所以@gogaz sizeof 实际返回的值是 128,对吗?
  • @FeritYiğitBALABAN no sizeof 返回数据类型的字节数。
  • @gogaz 它返回数组的大小,而不是 c 样式字符串的长度。 OP 应使用strlen() 而不是sizeof() 来确定输入的所有字符的大小。

标签: c++ arrays


【解决方案1】:

C 字符串与字符串开头和终止空字符之间的字符数一样长(不包括终止空字符本身)。要获取 C 字符串的长度,请使用:

size_t myString_size = strlen(myString);

然后,循环应该类似于:

for (size_t i = 0; i < myString_size; i++) {
    cout << myString[i];
}

【讨论】:

    【解决方案2】:

    您保留了128 字节的缓冲区myString,在其声明过程中未初始化(即,它可能包含 128 个字节中的每一个的任意值)。当输出到控制台时,这些任意值中的每一个都可能产生“奇怪的东西”。

    当你输入一个字符串时,例如"Hello!",当只有myString 的第一部分将被赋值时,即He、...、!\n\0。所有其他内容都将保持与fgets 之前的状态相同,即它们仍可能包含“奇怪的东西”。

    在您的循环中,您打印所有 128 字符,即奇怪的字符。顺便说一句:使用&lt;=sizeof(myString),您可以在缓冲区末尾后移一位并访问非保留内存。

    要克服这个问题,请尝试以下方法:

    int main()
    {
        char myString[128];
        cout << "Enter a string: ";
        fgets(myString, 128, stdin);
        size_t myString_size = strlen(myString);
        for (size_t i= 0; i < myString_size; i++) {
            cout << myString[i];
        }
    }
    

    或者:

    #include <string.h>
    int main()
    {
        char myString[128];
        cout << "Enter a string: ";
        fgets(myString, 128, stdin);
        cout << myString;
    }
    

    或者:

    int main()
    {
        char myString[128];
        cout << "Enter a string: ";
        fgets(myString, 128, stdin);
        size_t myString_size = strlen(myString);
        for (size_t i= 0; i < myString_size && myString[i] != '\0'; i++) {  // stop when reaching the end of the string
            cout << myString[i];
        }
    }
    

    【讨论】:

    • 我做了 size_t myString_size = (unsigned)strlen(myString);但现在我收到一条错误消息:strlen 未在此范围内声明。我添加了字符串标题,但为什么会出现这个错误?
    • 你是#include &lt;string.h&gt;(注意.h)吗?
    【解决方案3】:

    sizeof(myString) 返回缓冲区char[128] 的大小(以字节为单位),而不是字符串的大小。要遍历字符串的字符,您可以使用如下循环:

    for (char *c = &myString[0]; *c != '\0' ; ++c)
         std::cout << c;
    

    或转换为std::string:

    for (char c : std::string(myString))
         std::cout << c;
    

    或更简单地说:

    std::cout << std::string(myString);
    

    【讨论】:

      猜你喜欢
      • 2021-07-13
      • 2011-04-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-27
      • 2021-03-12
      相关资源
      最近更新 更多