函数未返回所需的字符串

Posted

技术标签:

【中文标题】函数未返回所需的字符串【英文标题】:Function not returning desired string 【发布时间】:2018-09-27 14:20:05 【问题描述】:
#include <iostream>
#include <string>

using namespace std;
string wordB(string input);

int main() 
    //ask for word
    cout << "Enter a word\n";

    //get word
    string input = "";
    cin >> input;

    //return with b in between all letters
    cout << wordB(input);
    cout << endl << input;


string wordB(string str) 
    string rString = "";

    for (unsigned i = 0; i < str.length(); ++i) 
        rString += "B" + str.at(i);
    
    cout << endl << rString;

    return rString;

尝试显示用户输入的单词,每个字符之间都有字母“B”。当我用 "join" 这个词运行它时,我会返回 "trtr"

【问题讨论】:

未定义的行为。 str.at(i) 是一个整数值。 "B" + n 其中n 是一个整数值访问字符串文字"B"nth 字符。由于字符串文字"B" 表示为两个char 的数组,因此n 的任何小于零或大于1 的值都会落在末尾。您的代码将所有结果附加到rString 【参考方案1】:

"B" + str.at(i); 并没有像你认为的那样做;这不是字符串连接。它说:取一个指向字符串文字"B"开头的char*指针,将其推进等于字符str.at(i)的ASCII码的字符数,并将结果指针视为指向一个nul-终止的字符串。除非 str.at(i) 恰好是 '\x0''\x1'(不太可能),否则您的程序会表现出未定义的行为。

有很多不同的方法可以做你想做的事。这是一个:

rString.push_back('B');
rString.push_back(str[i]);

【讨论】:

rString += "B" + str.substr(i, 1);【参考方案2】:

从 C++14 开始提供的一个特别好的修复方法是编写

rString += "B"s + str.at(i);

注意s,这是一个用户定义的文字。然后强制使用std::string 上的重载+ 运算符,而不是内置的+,后者实际上在@987654326 上执行可疑(并且可能未定义)指针运算 @literal "B" 衰减为 const char*

【讨论】:

【参考方案3】:

诚然这是一个陷阱……在这一行中

rString += "B" + str.at(i);

"B" + str.at(i) 部分并没有像人们预期的那样:它将str.at(i) 添加到char 指针(指向“B”的第一个字母)。修复很简单:

rString += std::string("B") + str.at(i);
                        //  ^-------------- now calls the correct operator

出于好奇考虑一下:

(rString += "B") += str.at(i);

我不建议写它(它太混淆了),但它做了正确的事情,因为有一个std::string::operator+(char*) 和一个std::string::operator+(char)

【讨论】:

我推荐使用 stringstream @smac89:为什么,出于兴趣? @Bathsheba 看起来更干净 IMO:ss &lt;&lt; 'B' &lt;&lt; str.at(i) @Bathsheba 好点,但你只能在最后做.str(),而不是在连接之间 @smac89 我和 Bathsheba 在一起,我不喜欢 stringstream 附带的样板。但是还有另一个答案的空间;)继续添加它。不同的答案越多越好【参考方案4】:

您看到的是order of evaluation 的结果。

+= 运算符将强制计算表达式的右侧,并将结果附加到字符串中。

这是导致您面临问题的原因,因为右侧不是 std::string,因此 rhs 中 + 运算符的含义仅转换为指针算术而不是字符串连接,如您所期望的.

一个简单的解决方法是更明确地这样做:

rString = rString + "B" + str.at(i);

这将导致编译器首先将= 运算符的右侧计算为字符串,然后得到连接。它还提供了额外的好处,即允许编译器通知您右侧是否不是字符串。


另一种选择是使用字符串流。我觉得它看起来更干净所以在这里:

#include <sstream>
...

string wordB(string str) 
    std::ostringstream oss;

    for (unsigned i = 0; i < str.length(); ++i) 
        oss << 'B' << str.at(i);
    
    cout << endl << oss.str();

    return oss.str();

【讨论】:

以上是关于函数未返回所需的字符串的主要内容,如果未能解决你的问题,请参考以下文章

更新:正在输出内存位置而不是所需的字符串

在 Windows 批处理脚本的 for 循环中未通过“查找”命令获得所需的输出

webpack 包中所需的模块未定义

函数和变量范围所需的总堆栈大小如何相关?

从 TextBox 获取输入时,Linq 查询未返回值

通过 xsl 将 XML 转换为 HTML 会导致以下问题:xsl 中的关键函数未提供所需的输出