I just wanted to insert a character into the string.

void insert( char* str, const char ch, unsigned int pos ){ unsigned int sz = strlen( str ) + 1; //беру длину +1 для 0 char* buf = new char[ sz + 1 ]; //создаю новый буфер memcpy( buf, str, sz * sizeof( char ) ); //копирую содержимое в него delete []str; //удаляю старую строку str = buf; //даю адрес на новую строку (! мб из за этого ошибка?) for( unsigned int i = sz; i >= pos; --i ){//сдвиг символов str[i+1] = str[i]; if( i==0 ) break; } str[ pos ] = ch; //вставка символов str[ sz ]=0; //0 в конец printf("str: [%s]\n", str); //вывод как надо "abcdefg" } int main(){ char* str = new char[7]; memcpy( str, "abcefg", 7 * sizeof( char )); printf( "str: [%s]\n", str ); //вывод нормальный insert( str, 'd', 3 ); printf( "str: [%s]\n", str ); //вывод ▌▌▌▌▌▌▌▌▌▌▌▌, в дебагере str = "ЭЭЭЭЭЭЭЭ" -35 return 0; } 

    4 answers 4

    You have some kind of a mixture of C and C ++ programming styles. Therefore, if it were not for the presence of the operator new , then it would be possible to conclude that the program is written in C.

    As for the function. Function parameters are local variables of the function. The function deals with a copy of the value of the original str argument declared in main . Therefore, this sentence in the function

     str = buf; 

    does not change the value of the original pointer declared in main . It changes the value of the local variable of the function str same name.

    At the same time, the function inside the function deletes the memory pointed to by the source pointer. Therefore, after exiting the function, the initial str pointer will contain an incorrect value, and the program will have undefined behavior, trying to access the memory addressed by this pointer.

    It is necessary to pass the first argument to the function either by reference or through a pointer to the argument.

    When dealing with strings, there is generally no need to use the memcpy function. This function is for copying raw bytes. You'd better use the standard strcpy function.

    All standard functions that deal with strings usually return a pointer to the result string. Therefore, you should follow this rule.

    Below is a sample program that shows how a function can be implemented when the first parameter is declared as a pointer to the original argument. An alternative would be to declare the first parameter as a link.

     char * insert( char * &s, char c, size_t pos ); ^^^^^^^^^ 

    Keep in mind that the standard strlen function has the size_t return type as well as the sizeof operator. Therefore, you should declare variables with this type that will store the corresponding values ​​returned by this function. Otherwise, for very large lines, there may also be a problem with the program’s undefined behavior.

    And besides, you should check in the function the correctness of the given position to insert a new element. If the position is out of the allowed range, the function can simply return the original string without changing it.

    Here is the demo itself

     #include <cstdio> #include <cstring> char * insert( char **s, char c, size_t pos ) { size_t n = std::strlen( *s ); if ( !( n < pos ) ) { n += 2; char *tmp = new char[ n ]; size_t i = 0; for ( ; i < pos; i++ ) tmp[i] = s[0][i]; tmp[i++] = c; for ( ; i < n; i++ ) tmp[i] = s[0][i-1]; delete [] *s; *s = tmp; } return *s; } int main() { char* str = new char[7]; std::strcpy( str, "abcefg" ); std::printf( "str: [%s]\n", str ); std::printf( "str: [%s]\n", insert( &str, 'd', 3 ) ); delete [] str; return 0; } 

    Its output to the console

     str: [abcefg] str: [abcdefg] 

    It is advisable to free the allocated memory at the end of the program.

      To change the pointer, pass the pointer to the pointer in the function. Otherwise, it turns out that you are changing the local copy of the pointer, and you release the memory at the old address (but the current address is outside the function). Because of this, you get garbage, trying to print a string according to the old (still unchanged) pointer.

      • Only it was necessary to add that when working it is necessary to dereference this pointer, i.e. write delete []*str; *str = buf; delete []*str; *str = buf; . By the way, if there is a delete, it means that the author has C ++, so it’s better to pass the link to the pointer, and not the pointer to the pointer! - Mikhailo
      • @Mikhailo The fact that pointers need to be dereferenced to access the value seems obvious to me. In contrast to the transfer of non-constant link, which, by the way, should be avoided for no particular reason. - free_ze
       delete []str; 

      You deleted the memory pointed to by the str variable, and now there is garbage.

       str = buf; 

      And here you wrote the new address in a variable, which is an argument to the insert() function, but this does not affect the value of the variable str in the calling code.

      To change the pointer outside the function, you can go two ways:

      1. To transfer not the pointer, but its address
      2. Return new value from function

        Replace insert with:

         void insert( char*& str, const char ch, unsigned int pos ) 

        (Ie use the transfer by reference.)

        And also correct the for loop:

          for( unsigned int i = sz-1; i >= pos; --i ){//сдвиг символов 

        If, like you, unsigned int i = sz; - you go beyond the boundary of the allocated memory , which does not add health to the program.