C++ STRCAT Implementation Partial Question

Asked 1 years ago, Updated 1 years ago, 398 views

using namespace std;

class My_string

{

private:

char* str;

public:

My_string(char *a) { str = a; };

~My_string() { };

int my_strlen() {

int b = 0;

while (1) {

if (str[b] == NULL)

{

break;

        }

        b++;
    }
    return b;
};
void my_strcpy(char* a) {
    str = a;
};
void my_strcat(char* a) {
    char* idx;
    idx = str;
    char* b;
    b=a;

    while (*str !='\0')
    {
        str++;
    }
    while (*b!='\0')
    {
        *(str++) = *(b++);
    }
    *str = '\0';
    str = idx;
};
void print() {
    cout << str;
};

};

int main()

{

char lang[100];

for (int i = 0; i < 100; i++) { lang[i] = NULL; }

string comd;

cout << "First String : ";

cin >> lang;

class My_string My_comd(lang);

while (1) {

cout << "Please Enter Command(strlen,strcpy,strcat,print,quit) : ";

cin >> comd;

if (comd == "strlen") {

cout << "String length : " << My_comd.my_strlen() << endl;

continue; }

else if (comd == "strcpy") {

cin >> lang;

My_comd.my_strcpy(lang);

cout << "Strcpy is done" << endl;

continue;


    }


    else if (comd == "print") {


        cout << "Current String : ";


        My_comd.print();


        cout << endl;


        continue;
    }
    else if (comd == "strcat") {
        cin >> lang;
        My_comd.my_strcat(lang);
        cout << "strcat is done" << endl;
        continue;
    }
    else if (comd == "quit") {
        cout << "I'll end it.";
        break;
    }
}
return 0;

} In this code, an error occurs only when calling the MY_STRCAT member function in CLASS, so how do I fix it? I don't understand the problem even if I'm not sure.

c++

2023-01-20 00:02

1 Answers

The character pointer (char *) looks similar to a string, but if you think of a string in another common language, you can get a lot of errors.

In C/C++, the pointer is int which simply indicates the location on memory. When lang is entered in "shiftpsh", this is the approximate memory space.

... s h i f t p s h NULL NULL NULL ...
    ^
    lang

If you observe the My_string constructor, this is what it looks like.

private:
    char *str;
public:
    My_string(char *a) { str = a; };

Previously, char * was mentioned as int indicating the location on memory. str = a stores str the location information in memory of a.

The important thing is that the copy of location information occurs, but the copy of the string that is actually in that location does not occur. Therefore, lang and str share the same memory space. The memory space looks like this.

... s h i f t p s h NULL NULL NULL ...
    ^
    lang and at the same time, My_comd's str

Now, run strcat and get the second string "asdf". This is where the problem occurs. cin>> lang in memory space, str shares memory spaces such as lang and . When you receive lang again, the memory space becomes like this.

... s h i f t p s h NULL NULL NULL ...
    ↓ Type "asdf" in lang
... ... a s d f NULL NULL NULL ...
    ^
    lang[0] and at the same time, My_comd's str[0]

Oh, I didn't touch str but str also changed.

Let's check the my_strcpy function, too.

    void my_strcat(char *a) {
        char *idx;
        idx = str;
        char *b;
        b = a;
        while (*str != '\0') {
            str++;
        }
        while (*b != '\0') {
            *(str++) = *(b++);
        }
        *str = '\0';
        str = idx;
    };
// ...
    My_comd.my_strcat(lang);

First, a provides lang. As mentioned earlier, a is the location in memory of lang. lang already said it shares memory locations such as str. So this is what happens.

... a s d f NULL NULL NULL ...
    ^
    lang = str = idx = a = b

Now, let's just increase str until the first \0 appears.

... a s d f NULL NULL NULL ...
    ^       ^
    |       |       str
    |
    lang = idx = a = b

Now let's observe the process of increasing b until the first \0 appears.

... a s d f NULL NULL NULL ...
    ^       ^
    b       str

    ↓ ↓ *(str++) = *(b++);

... ... a s d f a NULL NULL NULL ...
      ^       ^
      b       str

    ↓ ↓ *(str++) = *(b++);

... ... a s d f a s NULL NULL NULL ...
        ^       ^
        b       str

    ↓ ↓ *(str++) = *(b++);

... ... a s d f a s d NULL NULL NULL ...
          ^       ^
          b       str

    ↓ ↓ *(str++) = *(b++);

... ... a s d f a s d f NULL NULL NULL ...
            ^       ^
            b       str

    ↓ ↓ *(str++) = *(b++);

You can see that an unintended infinite loop is executed. This is because b and str initially refer to the same memory space, so they were eventually operating on the same string. This function will continue to run like this, and if it exceeds the size of lang that you initially set (100), it will refer to the unallocated memory space and result in a segmentation fault.

It is necessary to provide an independent space different from lang in the memory space by malloc, new char[N]. Search for keywords such as "C/C++ Memory Allocation". Here's a quick way to use malloc and new.

char* str = (char*) malloc(N * sizeof(char));
// // or
char* str = new char[N];

Both allocate new memory space to store strings of length N including \0.

And don't forget that assigning char * when writing code only copies locations in memory space. Therefore, if you want to copy a string, you have to copy each character in the string. for- You can turn the statement around and do so if the task requires it, but because this memory copy is very common and there is room for optimization, you can also use predefined functions such as memcpy of C and std::copy of C++.

This is what happens when you use the new and for-loop to fix the constructor.

private:
    char *str;
public:
    My_string(char *a) {
        str = new char[100];
        for (int i = 0; i < 100; i++) {
            str[i] = a[i];
        }
    };

    ~My_string() {
        delete str;
    };

You can fix functions such as my_strcat in the same way.


2023-01-20 09:09

If you have any answers or tips


© 2024 OneMinuteCode. All rights reserved.