【问题标题】:Why is this c++ program to reverse a word not working为什么这个 c++ 程序反转一个单词不起作用
【发布时间】:2021-01-14 22:42:58
【问题描述】:

我对 c++ 非常陌生,并编写了这个程序来反转一个单词。我尝试的是基本上循环遍历一个数组并将第一个字母与最后一个、第二个与倒数第二个等交换。但是结果是一些有线字符╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠Ω ⌠7p≈╗。我不想变通,因为网上有很多例子。我只是想知道为什么我正在做的事情不起作用。

#include <iostream>
using namespace std;

int main()
{
    char word[10];
    for (int i = 0; i < 10; i++)
    {
        word[i] = word[sizeof(word - i)];
    }

    cout << word << endl;

    return 0;
}

它也给了我这个警告warning C6001: using uninitialized memory 'word'。但我虽然通过char word[10]初始化了内存。

【问题讨论】:

  • 你的数组不包含任何内容。它是未初始化的。你要逆转什么?!
  • word[i] = word[sizeof(word)-i];
  • 哦抱歉,我怎么没注意到
  • 你已经标记了这个 C++,使用 std::string 来反转一个字符串,你只需使用另一个的反向迭代器来构造它,即 auto reversed_string = std::string(mystr.rbegin(), mystr.rend())
  • 您将问题中的代码从char word[10]; 更改为char word[5] = {'a', 'p', 'p', 'l', 'e'};。您不能进行此类根本性更改,因为现在不仅错误消息不再匹配代码,而且已经给出的答案也不再匹配问题(并且必须更新)。

标签: c++ reverse c-strings function-definition


【解决方案1】:

问题是sizeof(word - i) 实际做了什么。

简短回答:它返回指针大小(4 或 8)。

更详细的答案:

  • word 具有类型 char[10] 和大小 10
  • 当您执行word + 1 时,编译器会将数组衰减为指向char 的指针,以便能够执行此操作。所以结果类型是char *
  • 现在 sizeof(char *) 是 4 或 8,具体取决于您构建它的平台(32 位或 64 位)
  • 所以word[sizeof(word - i)] 总是指同一个单元格

还有第二个问题。在C 中,文本字符串必须以空字符结尾以指示其大小。你的word 包含apple 末尾没有零字符,所以在apple 之后打印垃圾(它甚至可能导致程序崩溃)。

此外,您的代码更像 C,在 C++ 中可以这样完成:

int main()
{
    std::string word{"apple"};
    std::string reversed{word.rbegin(), word.rend()};
    std::cout << word << '\n';
    std::cout << reversed<< '\n';

    return 0;
}

【讨论】:

    【解决方案2】:

    至少存在三个问题。

    第一个是数组没有初始化,有一个不确定的值。

    char word[10];
    

    第二个就是这个循环

    for (int i = 0; i < 10; i++)
    

    在任何情况下都不会反转数组。

    即使你像这样更新了数组

    char word[5] = {'a', 'p', 'p', 'l', 'e'};
    

    尽管如此循环没有意义。

    for (int i = 0; i < 10; i++) 
    

    还有这个表达

    sizeof(word - i)
    

    不正确。由于指针算法,这个表达式word - i 具有char * 类型。至少你是说

    sizeof(word ) - i
    

    相反,您可以编写如下内容

    #include <iostream>
    #include <utility>
    #include <cstring>
    
    //...
    
    char word[] = "Hello World!";
    
    for ( size_t i = 0, n = std::strlen( word ); i < n / 2; i++ )
    {
        std::swap( word[i], word[n - i - 1] );
    }
    
    std::cout << word << std::endl;
    

    或者您可以编写一个单独的函数。给你。

    #include <iostream>
    #include <utility>
    #include <cstring>
    
    char * reverse( char *s )
    {
        for ( size_t i = 0, n = std::strlen( s ); i < n / 2; i++ )
        {
            std::swap( s[i], s[n - i - 1] );
        }
    
        return s;
    }
    
    int main() 
    {
        char word[] = "Hello World!";
        
        std::cout << word << '\n';
        std::cout << reverse( word ) << '\n';
    }   
    

    程序输出是

    Hello World!
    !dlroW olleH
    

    【讨论】:

    • 第三个问题:sizeof(word - i)
    【解决方案3】:

    sizeof(word - 1) 将是 4 或 8。因为它是一个指针。 你需要的是strlen(word)

    另外,word 未初始化,请执行char word[10] = "blabla" 之类的操作。

    请注意,对于您所做的编辑,其中:

        char word[5] = {'a', 'p', 'p', 'l', 'e'};
    

    strlen 不起作用,因为您需要一个字符为 null 或 0,才能知道字符串在哪里结束。

    另外,您似乎是在用 C++ 编写的,对于您拥有 std::string 的这些东西,您不需要 char 数组。并且您可以调用word.length() 获取长度,它可以动态设置字符串所需的大小并增长。

    【讨论】:

      【解决方案4】:

      在您的情况下,word声明,但未初始化。该警告意味着 word 数组可以包含未初始化的值。

         char word[10];
      

      要查看合理字符而不是垃圾(未初始化)值,请将值输入word 或在代码中对其进行初始化。

      为什么会有这种行为?堆栈包含垃圾,直到程序将特定值放入堆栈上定义的变量中。

      【讨论】:

      • 数组不能为空。关于“垃圾”的事情也有点令人困惑。尝试使用未初始化的值是未定义的行为。就这样。如果你让它编译无效代码,“垃圾”或“随机”值只是编译器所做工作的一个症状
      • 谢谢。更新了答案并删除了空洞和垃圾的措辞。
      【解决方案5】:

      C/C++ 没有声明变量的自动初始化。由于 C/C++ 使用的是指针,因此必须在引用之前为每个数组填充一个值。

      【讨论】:

        猜你喜欢
        • 2013-01-26
        • 2016-04-20
        • 1970-01-01
        • 2015-05-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-01-17
        • 1970-01-01
        相关资源
        最近更新 更多