简体   繁体   中英

C++; Putting characters into a C-Style string

I've been reading a book for self study ( http://www.amazon.com/gp/product/0321992784 ) and I'm on chapter 17 doing the exercises. One of them I solved, but I'm not satisfied and would like some help. Thank you in advanced.

The Exercise: Write a program that reads characters from cin into an array that you allocate on the free store. Read indvidual characters until an exclamation mark(!) is entered. Do not use std::string. Do not worry about memory exhaustion.

What I did:

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;
}

I made 2 functions, 1 to create a new string with a size 1 larger than the old and add a character at the end.

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;
}

This is the function for the exercise using the append function I created, It works, but from what I understand each time I call append, there is a memory leak because I create a new character array and didn't delete the old.

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;
}

I tried adding another pointer to hold the old array and delete it after making a new one, but after about 6 calls in this loop I get a runtime error that I think tells me I'm deleting something I shouldn't? which is where I got confused.

This is the old one that doesn't work beyond 6 characters:

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;
}

So I want to know how I can fix this function so there are no memory leaks. Thank you again. (Also please note, I do know these functions already exist and using std::string handles all the free store stuff for me, I just want to understand it and this is a learning exercise.)

Is the point to learn about memory management, or about how string operations work internally?

For the second (learning about string operations), you should use std::unique_ptr<char[]> which will automatically free the attached array when the pointer dies. You'll still need to calculate string length, copy between strings, append -- all the things you are doing now. But std::unique_ptr<char[]> will handle the deallocation.

For the first case, you're better off writing an RAII class (custom version of std::unique_ptr<T> ) and learning how to free memory in a destructor, than scattering delete [] statements all over your code. Writing delete [] everywhere is actually a bad habit, learning it will move your ability to program C++ backwards.

You have to use standard C function std::strlen instead of the sizeof operator because in case of your function the sizeof operator returns the size of pointer instead of the length of the string.

Also you need to delete already allocated array.

The function can look the following way

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;
}

And in the function loadCstr it can be called like

str = append( str, ch );

Also instead of the loop to copy the string you could use standard algorithm std::copy

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM