C++将字符放入C样式字符串中
C++; Putting characters into a C-Style string
我一直在读一本自学书(http://www.amazon.com/gp/product/0321992784)我在第17章做练习。其中一个我解决了,但我不满意,希望得到一些帮助。提前谢谢。
练习:编写一个程序,将cin中的字符读取到您在免费存储中分配的数组中。阅读单个字符,直到输入感叹号(!)。不要使用std::string。不要担心记忆力耗尽。
我做了什么:
char* append(const char* str, char ch); // Add a character to the string and return a duplicate
char* loadCstr(); // Read characters from cin into an array of characters
int main()
{
char* str{ loadCstr() };
std::cout << str << 'n';
return 0;
}
我做了两个函数,一个是创建一个比旧字符串大1的新字符串,并在末尾添加一个字符。
char* append(const char* str, char ch)
/*
Create a new string with a size 1 greater than the old
insert old string into new
add character into new string
*/
{
char* newstr{ nullptr };
int i{ 0 };
if (str)
newstr = new char [ sizeof(str) + 2 ];
else
newstr = new char [ 2 ];
if(str)
while (str [ i ] != ' ')
newstr [ i ] = str [ i++ ]; // Put character into new string, then increment the index
newstr [ i++ ] = ch; // Add character and increment the index
newstr [ i ] = ' '; // Trailing 0
return newstr;
}
这是使用我创建的append函数进行练习的函数,它很有效,但据我所知,每次调用append时,都会出现内存泄漏,因为我创建了一个新的字符数组,但没有删除旧的。
char* loadCstr()
/*
get a character from cin, append it to str until !
*/
{
char* str{ nullptr };
for (char ch; std::cin >> ch && ch != '!';)
str = append(str, ch);
return str;
}
我尝试添加另一个指针来保存旧数组,并在创建新数组后将其删除,但在这个循环中调用了大约6次之后,我得到了一个运行时错误,我认为这告诉我正在删除一些不应该删除的内容?这就是我感到困惑的地方。
这是一个不能超过6个字符的旧版本:
char* loadCstr()
/*
get a character from cin, append it to str until !
*/
{
char* str{ nullptr };
for (char ch; std::cin >> ch && ch != '!';) {
char* temp{ append(str, ch) };
if (str)
delete str;
str = temp;
}
return str;
}
所以我想知道如何修复这个函数,这样就不会出现内存泄漏。再次感谢。(另外请注意,我知道这些函数已经存在,并且使用std::string为我处理所有免费存储的东西,我只想了解它,这是一个学习练习。)
您必须使用标准的C函数std::strlen
而不是sizeof
运算符,因为在您的函数中,sizeof
运算符返回指针的大小而不是字符串的长度。
此外,您还需要删除已分配的数组。
的功能如下
char* append(const char* str, char ch)
/*
Create a new string with a size 1 greater than the old
insert old string into new
add character into new string
*/
{
size_t n = 0;
if ( str ) n = std::strlen( str );
char *newstr = new char[ n + 2 ];
for ( size_t i = 0; i < n; i++ ) newstr[i] = str[i];
delete [] str;
newstr[n] = ch;
newstr[n+1] = ' ';
return newstr;
}
在函数loadCstr
中,它可以像一样调用
str = append( str, ch );
此外,您可以使用标准算法std::copy
来代替复制字符串的循环
学习内存管理或字符串操作如何在内部工作是重点吗?
对于第二个(学习字符串操作),您应该使用std::unique_ptr<char[]>
,它将在指针失效时自动释放附加的数组。您仍然需要计算字符串长度、在字符串之间复制、追加——所有您现在正在做的事情。但是std::unique_ptr<char[]>
将处理解除分配。
对于第一种情况,您最好编写一个RAII类(std::unique_ptr<T>
的自定义版本)并学习如何在析构函数中释放内存,而不是在代码中散布delete []
语句。到处写delete []
实际上是一个坏习惯,学习它会让你的C++编程能力倒退。
- 二进制数之和(使用C样式字符串)
- 从 C 样式字符串中删除子字符串 "in place" 在C++代码中
- 比较 std::string 和 C 样式字符串文字
- 为什么打印 c 样式字符串的'address of index n'会导致子字符串的输出
- 为什么 C 样式字符串的工作空指针检查不?
- C++ - 创建具有相同字符的特定大小的以 null 结尾的 c 样式字符串的更好方法
- C++ 一个自定义类字符串,将其分配给 C 样式字符串
- C++ C 样式字符串/字符数组的大小 - 优化
- 此代码如何启动索引为 1 的 C 样式字符串
- 在C++中标记化"Braced Initializer List"样式字符串(使用 Boost?
- 将 C 样式字符串复制到免费存储上分配的内存中
- std::对 C 样式字符串进行排序,而不复制字符串
- 异常和 C 样式字符串
- 重载分辨率 C 样式字符串
- 如何在C++中有条件地设置 C 样式字符串?
- 转换为C样式字符串
- 是否可以同时使用 C++11 ABI _and_ cxx11 样式和旧样式字符串
- 从scanf读取C样式字符串时出现分段错误
- 如何比较 C 样式字符串
- 我的 C 样式字符串中的最后字符是 I 时的奇数值