C++中的字符串串联有什么问题?
What's wrong with my String concatenation in C++?
我正在通过为嵌入式项目创建一个字符串类来学习C++,但我的字符串类的连接有问题。
这是我的主要方法和输出
#include <iostream>
#include "string.hpp"
using namespace std;
int main() {
String s1("hello "), s2("world");
String s3 = s1 + s2;
cout << "s1=" << s1 << endl;
cout << "s2=" << s2 << endl;
cout << "s3=" << s3 << endl;
return 0;
}
s1=hello
s2=world
s3=hello
它不是打印出"hello world",而是打印"hello ">
这是我的string.hpp类:
#pragma once
#include <cstring>
#include <iostream>
class String {
public:
String() : c_str(NULL), len(0)
{
}
String(const String& str) : c_str(new char[str.len]), len(str.len)
{
strncpy(c_str, str.c_str, len);
c_str[len] = ' ';
}
String(const char* str) : String(str, strlen(str))
{
strncpy(c_str, str, len);
c_str[len] = ' ';
}
String(const char* str, const int n) : len(n), c_str(new char[n+1])
{
strncpy(c_str, str, len);
}
~String()
{
delete[] c_str;
}
const char* get_c_str()
{
return c_str;
}
bool contains(const String &cmd, const size_t pos)
{
return strncmp(c_str+pos, cmd.c_str, cmd.len) == 0;
}
size_t length()
{
return len;
}
friend std::ostream& operator<<(std::ostream& os, const String obj)
{
os << obj.c_str;
return os;
}
friend void swap(String& s1, String& s2)
{
using std::swap;
swap(s1.c_str, s2.c_str);
swap(s1.len, s2.len);
}
bool operator==(const String& str)
{
return strncmp(c_str, str.c_str, len) == 0;
}
char operator[](const size_t i)
{
return c_str[i];
}
String& operator=(const String& src)
{
String tmp(src);
swap(*this, tmp);
return *this;
}
String operator+(const String& rhs)
{
const size_t new_len = len + rhs.len;
char* new_c_arr = new char[new_len+1];
strcpy(new_c_arr, c_str);
strcat(new_c_arr, rhs.c_str);
printf("new_c_arr=%sn", new_c_arr);
return String(new_c_arr, len);
}
String operator+(const char* rhs)
{
const size_t new_len = len + strlen(rhs) + 1;
char* new_c_arr = new char[new_len];
strcpy(new_c_arr, c_str);
strcat(new_c_arr, rhs);
return String(new_c_arr, new_len);
}
private:
char* c_str;
int len;
};
我在寻找类似问题时在 SO 上阅读了"三巨头",但不确定是否正因为如此。
此代码以多种方式中断。
#pragma once
实际包括防护装置比#pragma once
更便携。
String() : c_str(NULL), len(0)
{
}
默认构造函数使c_str
为 null;其他函数从不检查这种情况。请记住,即使是空的 C 字符串也只有一个字符。
String(const String& str) : c_str(new char[str.len]), len(str.len)
{
strncpy(c_str, str.c_str, len);
c_str[len] = ' ';
}
您只为c_str
分配了str.len
个字符,但您正在访问c_str[len]
。
String(const char* str) : String(str, strlen(str))
{
strncpy(c_str, str, len);
c_str[len] = ' ';
}
委派给的构造函数已执行复制。你怎么又把strncpy
叫到这里来了?
String(const char* str, const int n) : len(n), c_str(new char[n+1])
{
strncpy(c_str, str, len);
}
在这里,您没有确保字符串以 null 结尾。
const char* get_c_str()
{
return c_str;
}
应标记为const
。
bool contains(const String &cmd, const size_t pos)
{
return strncmp(c_str+pos, cmd.c_str, cmd.len) == 0;
}
同上。而且您没有检查pos
是否在范围内。
size_t length()
{
return len;
}
const
.
friend std::ostream& operator<<(std::ostream& os, const String obj)
{
os << obj.c_str;
return os;
}
obj
应通过 const 引用传递,而不是通过值传递。
bool operator==(const String& str)
{
return strncmp(c_str, str.c_str, len) == 0;
}
再const
,逻辑甚至不正确。按照这个逻辑,"something" == "something else"
因为你只是比较前len
个字符。
char operator[](const size_t i)
{
return c_str[i];
}
如果您要返回副本,则应将其const
。如果要允许用户修改字符串中存储的字符,则应返回char &
。(更好的是,有两个单独的重载,一个const
和一个非const
。
String operator+(const String& rhs)
{
const size_t new_len = len + rhs.len;
char* new_c_arr = new char[new_len+1];
strcpy(new_c_arr, c_str);
strcat(new_c_arr, rhs.c_str);
printf("new_c_arr=%sn", new_c_arr);
return String(new_c_arr, len);
}
您正在构造长度错误的新字符串,并且还泄漏了new_c_arr
.并且这个函数应该是const
的(并且真的应该在operator+=
方面实现,而你没有(。
String operator+(const char* rhs)
{
const size_t new_len = len + strlen(rhs) + 1;
char* new_c_arr = new char[new_len];
strcpy(new_c_arr, c_str);
strcat(new_c_arr, rhs);
return String(new_c_arr, new_len);
}
再次泄漏new_c_arr
;此外,此处new_len
包括空终止符,而其他operator+
中的版本不包含。采用长度的构造函数似乎不包括 null 终止符作为长度的一部分。
方法String operator+(const String& rhs)
中的问题行:
return String(new_c_arr, len);
您需要更改为以下内容:
return String(new_c_arr, new_len+1);
您正在初始化返回的字符串,其长度仅等于第一部分。不是整个串联的字符串。
看到另一个运算符是否正常。
顺便说一下,你在operator+
和constructor
中创造了很多新的char[]
。
对于operator+
,您在每次调用中创建一个新char[]
并传递给字符串的构造函数(之后不删除(,并且在构造函数中创建一个新char[]
来存储destructor
中删除的字符串,在operators
中创建的新char[]
被泄漏。
- 警告处理为错误这里有什么问题
- C++我的数学有什么问题,为什么我的代码不能正确循环
- 当我尝试添加 2 个大字符串时,我无法弄清楚出了什么问题
- 违反const正确性:我应该现实地期待什么问题
- 这个带有模板<类 Vector 的C++代码片段有什么问题>
- 我的逻辑反转字符串中的元音有什么问题?
- 需要以下代码的帮助,下面的代码有什么问题
- 常量公共成员有什么问题?
- 以下代码中的函数模板有什么问题?
- 这个返回元素位置的基于循环的函数有什么问题?
- creat_list2功能有什么问题?
- 格式说明符C++有什么问题
- 任何人都可以告诉我我的 C++ 代码出了什么问题?
- 从 argv[1] 转换为字符 * 字符串后有什么问题?
- 我的堆栈和库存清单程序的结构有什么问题?
- 此工厂功能有什么问题?
- 以下 C++ 代码有什么问题?
- 数组为此合并排序函数提供了正确的输出,但向量给出了不正确的输出.出了什么问题?
- reinterpret_cast,只读访问,简单的可复制类型,会出什么问题?
- 它解决了什么问题,对于非真空初始化,生命周期在初始化之前就开始了