函数未返回所需的字符串
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"
的n
th 字符。由于字符串文字"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 << 'B' << 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();
【讨论】:
以上是关于函数未返回所需的字符串的主要内容,如果未能解决你的问题,请参考以下文章