提问人:Hector Ta 提问时间:6/5/2022 最后编辑:Hector Ta 更新时间:6/6/2022 访问量:445
在类 C++ 中使用运算符+= 连接 2 个字符串
Concatenate 2 string using operator+= in class C++
问:
在问之前,我见过一些类似的问题,但我仍然停留在使用 .operator+=
目前,我可以通过构造函数方法正确获取单独的字符串。但是当我编译代码时,方法中的行显示错误:str[length+i] = s[i];
String& String::operator+= (const String& s)
'operator[]' 不匹配(操作数类型为 'const String' 和 'unsigned int')
所以我需要你的帮助来修复这个错误。
这是我的代码:
#include <iostream>
#include <cstring>
class String {
// Initialise char array
char* data;
unsigned length;
public:
// Constructor without arguments
String();
// Constructor with 1 arguments
String(char* s);
// Copy Constructor
String(const String& source);
// Move Constructor
String(String&& source);
// Destructor
~String() { delete[] data; }
/*!
* @brief String length.
* @return Value in String @c length.
*/
unsigned len ( ) const;
/*!
* @brief Append to String.
* @param[in] s A String object.
* @return A String reference to *this.
* @post String will equal the concatenation of itself with @a s.
*/
String& operator+= (const String& s);
};
// Constructor with no arguments
String::String()
: data{ nullptr }
{
data = new char[1];
data[0] = '\0';
}
// Constructor with one arguments
String::String(char* s)
{
if (s == nullptr) {
data = new char[1];
data[0] = '\0';
}
else {
data = new char[strlen(s) + 1];
// Copy character of s[]
// using strcpy
strcpy(data, s);
data[strlen(s)] = '\0';
std::cout << data << "\n";
}
}
// Copy Constructor
String::String(const String& source)
{
data = new char[strlen(source.data) + 1];
strcpy(data, source.data);
data[strlen(source.data)] = '\0';
}
// Move Constructor
String::String(String&& source)
{
data = source.data;
source.data = nullptr;
}
unsigned String::len ( ) const
{
return length;
}
String& String::operator+= (const String& s)
{
unsigned len = length + s.len();
char* str = new char[len];
for (unsigned j=0; j < length; j++)
str[j] = data[j];
for (unsigned i=0; i < s.len(); i++)
str[length+i] = s[i];
delete data;
length = len;
data = str;
return *this;
}
int main()
{
// Constructor with no arguments
String a;
// Convert string literal to
// char array
char temp[] = "Hello world.";
// Constructor with one argument
std::cout << "s1: ";
String s1{ temp };
// Copy constructor
String s11{ a };
char temp1[] = "Goodbye!";
std::cout << "s2: ";
String s2{ temp1 };
String s3 = String s1 + String s2;
return 0;
}
主函数的另一种写法:
int main()
{
String s1("Hello World.");
String s2("Goodbye!");
std::cout << "s1: " << s1 << std::endl;
std::cout << "s2: " << s2 << std::endl;
String s3 = s1 + s2;
std::cout << "s3: " << s3 << std::endl;
std::cout << "The last char of s3: " << s3[s3.size()-1] << std::endl;
return 0;
}
预期结果:
s1: Hello World.
s2: Goodbye!
s3: Hello World.Goodbye!
The last char of s3: !
如何修改我的代码以正确获取和最后一个字符?s3
s3
答:
对于初学者来说,两个构造函数都没有设置数据成员。
所以运营商length
String& String::operator+= (const String& s)
{
unsigned len = length + s.len();
char* str = new char[len];
//...
具有未定义的行为。
另外,如果数据成员长度已初始化,则需要将
char* str = new char[len + 1];
而不是
char* str = new char[len];
为终止零字符“\0”保留内存,因为您在复制构造函数中使用了标准的 C 字符串函数strcpy
strcpy(data, source.data);
并且该类没有用于 loo[ 的下标运算符
for (unsigned i=0; i < s.len(); i++)
str[length+i] = s[i];
而且你忘了附加终止零字符.'\0'
请注意,此表达式中使用的类中没有成员函数size
s3[s3.size()-1]
而这个结构
String s3 = String s1 + String s2;
无效。至少你应该写
字符串 s3 = s1 + s2;
并相应地定义运算符 +。
评论
在许多构造函数中,您没有设置 which 使其具有不确定的值 - 读取此类值会使程序具有未定义的行为。因此,首先要解决以下问题:length
#include <algorithm> // std::copy_n
// Constructor with no arguments
String::String() : data{new char[1]{'\0'}}, length{0} {}
// Constructor with one argument
String::String(const char* s) { // note: const char*
if (s == nullptr) {
data = new char[1]{'\0'};
length = 0;
} else {
length = std::strlen(s);
data = new char[length + 1];
std::copy_n(s, length + 1, data);
}
}
// Copy Constructor
String::String(const String& source) : data{new char[source.length + 1]},
length{source.length}
{
std::copy_n(source.data, length + 1, data);
}
// Move Constructor
String::String(String&& source) : String() {
std::swap(data, source.data);
std::swap(length, source.length);
}
在您尝试使用下标运算符时,,但您没有添加这样的运算符,因此使用 :operator+=
String::operator[]
s[i]
s.data[i]
String& String::operator+=(const String& s) {
unsigned len = length + s.length;
char* str = new char[len + 1];
for (unsigned j = 0; j < length; j++) str[j] = data[j];
for (unsigned i = 0; i < s.length; i++) str[length + i] = s.data[i];
str[len] = '\0';
delete[] data; // note: delete[] - not delete
length = len;
data = str;
return *this;
}
如果您希望能够在对象上使用下标运算符,则需要添加一对成员函数:String
class String {
public:
char& operator[](size_t idx);
char operator[](size_t idx) const;
};
char& String::operator[](size_t idx) { return data[idx]; }
char String::operator[](size_t idx) const { return data[idx]; }
为了工作,你需要一个免费的重载:String s3 = s1 + s2;
operator+
String operator+(const String& lhs, const String& rhs) {
String rv(lhs);
rv += rhs;
return rv;
}
此外,为了支持打印您在替代功能中尝试的类似内容,您需要一个重载。例:String
main
operator<<
class String {
friend std::ostream& operator<<(std::ostream& os, const String& s) {
os.write(s.data, s.length);
return os;
}
};
评论
String::operator[]
operator<<
评论
operator[]
str[length+i] = s.data[i]
length
String s1("Hello World.");
String(const char*)