【问题标题】:Unexpected output when I try to reverse a char*当我尝试反转 char* 时出现意外输出
【发布时间】:2014-01-10 11:57:19
【问题描述】:
#include<iostream>
#include<string>
using namespace std;

void reverse(char* str)
{
    char *new_str = str;
    while(*new_str != '\n'){
        new_str++;
    }
    while(new_str != str){
        cout << *new_str;
        new_str--;
    }
    cout << *new_str;
}

int main()
{
    char *str = new char[1024];
    str = "hello world";

    reverse(str);
}

当我尝试运行它时,我得到了一些疯狂的输出并且我的计算机开始发出哔哔声。我在这里做错了什么?

【问题讨论】:

    标签: c++ string algorithm coding-style reverse


    【解决方案1】:

    C 字符串的结尾由字符'\0' 标记。您使用了'\n',即newline character。

    【讨论】:

    • 如此简单。谢谢!你知道为什么我会收到一条警告,告诉我“不推荐从字符串常量到 'char*' 的转换”。我知道这是因为 str = "hello world";但这只是我可以忽略的警告吗?
    • 是的,因为你使用的是字符串常量,你应该使用const char *而不是char *。 const 表示指向的数据是常量。
    • 另外,main() 中的前两行应替换为const char *str = "hello world";。不需要为字符串常量分配,编译器会为你做。
    • 啊,好的。再次感谢您!
    • 这也是内存泄漏,因为新的数组指针丢失了(+ 从未使用过)。
    【解决方案2】:

    你的意思是除了使用裸漏new,弃用char*而不是const char*甚至更好的std::string,不使用标准库算法std::reverse,将IO与你的算法混合,包括整个namespace std(这可能会间接将std::reverse() 纳入范围)而不将您自己的reverse() 放在自己的命名空间中?

    #include <algorithm>
    #include <iostream>
    #include <iterator>
    #include <string>
    
    // using namespace std; // for the brave, and drop the std:: in the next 3 lines
    
    int main()
    {
        std::string str = "hello world";    // std::string instead of char*
        std::reverse(begin(str), end(str)); // standard library algorithm
        std::cout << str;                   // IO separate from algorithm
    }
    

    如果您只对如何编写反向算法感兴趣,这里是one way to do it,而不依赖于您有一个空终止符这一事实:

    template<class BidirIt>
    void reverse(BidirIt first, BidirIt last)
    {
        while ((first != last) && (first != --last)) {
            std::swap(*first++, *last);
        }
    }
    

    【讨论】:

    • @DarkWanderer 不要让我开始:定义你自己的 reverse() 函数,如果不小心 &lt;string&gt; 也包含 &lt;algorithm&gt;,那么你就会让自己面临令人讨厌的 ADL 错误。
    • 我知道如何使用 STL。反转的 char* 是一个面试类型的问题,所以你的回答对我没有帮助。所以谢谢,但不,谢谢。
    • @user3150601 你没有给出那个上下文。但即便如此:您仍然可以使用与std::reverse 相同的签名,采用两个迭代器而不是依赖于隐式空终止符。例如。如果您被要求反转std::vector,那么您将不得不更改整个算法。您还可以将 IO 与算法本身分开。模拟 STL 仍然比您发布的内容更好(没有冒犯,但您问了什么明显错误,并且该代码永远不应该通过代码审查)。
    • 那么我发布的内容在技术上不正确吗?这难道不是面试官希望看到的吗?我无法想象他们正在寻找预定义的 reverse()。
    • 看这个答案的第一句话+ cmets。这段代码有几个问题,即可能的段错误、内存泄漏、混合输出与处理等。
    【解决方案3】:

    问题在于,一开始你为 str 分配了已分配内存的地址,然后将其重新分配为指向 C++ 中类型为 const char[] 的字符串字面量。

    char *str = new char[1024];
    str = "hello world";
    

    这个字符串文字有终止零字符'\0'。它没有新行字符'\n'。所以这个函数是无效的,因为它会尝试访问数组之外​​的内存来搜索新行字符。

    有效代码如下所示

    #include <iostream>
    using namespace std;
    
    void reverse( const char* s )
    {
        const char *p = s;
    
        while ( *p ) p++;
    
        while ( p != s ) cout << *--p;
    }
    
    int main()
    {
        const char *s = "hello world";
    
        reverse( s );
    }
    

    或者如果你想自己交互输入一个字符串,那么 main 可以看起来像

    int main()
    {
        const size_t N = 1024;
        char s[N];
    
        cout << "Enter a statement: ";
        cin.getline( s, N );
    
        reverse( s );
    }
    

    【讨论】:

    • 并且reverse 应该重命名(print_reverse ?),因为它不会反转任何内容。
    • @Jarod42 我认为这对于这个简单的练习并不重要。虽然名称反向可能会使用户感到困惑。
    【解决方案4】:

    纠正你的功能:

    void reverse(char* str)
    {
        char *new_str = str;   
        while(*new_str){ // use this instead of *new_ptr != '\n'
            new_str++;
        }
        while(new_str != str){
            cout << *new_str;
            new_str--;
        }
        cout << *new_str;
    }
    

    【讨论】:

      猜你喜欢
      • 2018-09-03
      • 1970-01-01
      • 2017-09-17
      • 1970-01-01
      • 1970-01-01
      • 2022-12-16
      • 1970-01-01
      • 1970-01-01
      • 2019-12-20
      相关资源
      最近更新 更多