C ++;将字符放入C样式字符串

时间:2016-03-27 20:18:28

标签: c++ arrays string pointers

我一直在读一本自学书(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;
}

我创建了2个函数,1创建一个大于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 ] != '\0')
            newstr [ i ] = str [ i++ ]; // Put character into new string, then increment the index

    newstr [ i++ ] = ch; // Add character and increment the index
    newstr [ i ] = '\0'; // Trailing 0

    return newstr;
}

这是使用我创建的附加功能进行练习的功能,它可以工作,但是根据我的理解每次调用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次调用后,我得到一个运行时错误,我想我会删除我不应该删除的内容&# 39;吨?这是我困惑的地方。

这是一个不超过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为我处理所有免费商店的东西,我只想了解它,这是一个学习练习。)

2 个答案:

答案 0 :(得分:0)

要了解内存管理,还是了解字符串操作如何在内部工作?

对于第二个(学习字符串操作),你应该使用std::unique_ptr<char[]>,它会在指针死亡时自动释放附加的数组。你仍然需要计算字符串长度,在字符串之间复制,追加 - 你现在正在做的所有事情。但std::unique_ptr<char[]>将处理释放。

对于第一种情况,你最好编写一个RAII类(std::unique_ptr<T>的自定义版本)并学习如何在析构函数中释放内存,而不是在代码中散布delete []语句。在任何地方写delete []实际上都是一个坏习惯,学习它会使你的C ++编程能力向后移动。

答案 1 :(得分:0)

您必须使用标准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] = '\0';

    return newstr;
}

在函数loadCstr中,可以像

一样调用它
str = append( str, ch );

也可以使用标准算法std::copy

代替复制字符串的循环