Выделение памяти для строковых указателей?

Я как бы борюсь с некоторыми основами для C. Я пытался скомпилировать эту программу, и она выдала ошибку Signal 11. Я знаю, что это связано с выделением памяти, но я не уверен, как правильно использовать malloc(), чтобы это работало. Кто-нибудь может помочь?

{
    
    char *string = "Lol";
    convert_lower(string);
    printf("%s\n", string); 

    return 0; 
}

char *convert_lower(char *word) {

    for ( ; *word; ++word) *word = tolower((char)*word); // J.F. Sebastian 
    return word;  
 
}

person stringy_mozzar3lla    schedule 06.10.2020    source источник


Ответы (2)


Вы даете convert_lower() указатель на строковый литерал, поэтому он попытается модифицировать постоянную память. Вот почему вы получаете ошибку времени выполнения.

Вам необходимо сделать доступную для записи копию данных строкового литерала, прежде чем вы сможете изменить ее, например:

char *literal = "Lol";
char *string = malloc(strlen(literal)+1);
strcpy(string, literal);
convert_lower(string);
printf("%s\n", string); 
free(string);

Это можно упростить, используя вместо этого strdup(), который будет обрабатывать выделение и копирование для вас:

char *string = strdup("Lol");
convert_lower(string);
printf("%s\n", string); 
free(string);

И затем вы можете упростить это, просто не выделяя динамическую память вообще:

char string[] = "Lol";
convert_lower(string);
printf("%s\n", string); 
person Remy Lebeau    schedule 06.10.2020

Есть как минимум две серьезные ошибки.

Во-первых, вы не можете изменить строковый литерал. Любая попытка изменить строковый литерал приводит к неопределенному поведению.

char *string = "Lol";
convert_lower(string);

Второй заключается в том, что внутри функции изменяется переданный указатель. поэтому функция возвращает указатель, указывающий на завершающий ноль, а не на начало строки.

И вместо приведения к char

tolower((char)*word)

вам нужно привести к беззнаковому символу

tolower( (unsigned char)*word)

Функция может быть определена как

char * convert_lower( char *word ) 
{
    for ( char *p = word; *p; ++p ) 
    {
        *p = tolower( ( unsigned char )*p );
    }

    return word;
}

и позвонил как

char string[] = "Lol";
puts( convert_lower(string) );

Если вы хотите сделать копию исходной строки, преобразовав все символы в нижний регистр, функция может выглядеть следующим образом:

#include <string.h>
#include <stdlib.h>
#include <stdio.h>

//...

char * convert_lower( const char *word ) 
{
    char *result = malloc( strlen( word ) + 1 );

    if ( result != NULL )
    {
        char *p = result;
    
        while ( ( *p++ = tolower( ( unsigned char )*word++ ) ) != '\0' );
    }

    return result;
}

И функция может быть вызвана как

char *string = "Lol";
char *lower_case_string = convert_lower( string );

if ( lower_case_string != NULL ) puts( lower_case_string );

free( lower_case_string );
person Vlad from Moscow    schedule 06.10.2020