Как записать указатель в постоянную память в C - PullRequest
0 голосов
/ 29 августа 2018

Я пытаюсь записать определенный символ в середину строки, на которую указывает другой указатель, чтобы я мог обрезать строку. Моя программа пытается исключить начальные / конечные пробелы из ввода. Поскольку указатель хранится в постоянной памяти, как я могу обойти его и добавить символ «/ 0» между ними. Ниже приведен мой код, и я получаю ошибку сегментации в строке 22 из-за вышеупомянутой проблемы.

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

char *trim(char *s)
{
    while(isspace(*s))
        s++;
    char *end = s + strlen(s) - 1;
    while(end>=s && isspace(*end))
    {
        end--;
    }
    *(end + 1) = '\0'; //Line causing segmentation fault
    return s;

}

int main()
{
    char *e = NULL;
    e = trim("hello  ");
    printf("%s", e);
    printf("hi");
    return 0;
}

Ответы [ 4 ]

0 голосов
/ 29 августа 2018

в общем случае строковые литералы хранятся в разделе только для чтения (это зависит от платформы). Стандарт C гласит, что строковые литералы имеют статическую длительность хранения , любая попытка их изменения дает неопределенное поведение , поэтому НИКОГДА попытка изменить строковые литералы!

но вы можете сделать следующее:

1 - инициализировать массив символов из строкового литерала:

char ch_array[256] = "hello ";

2 - динамически выделять память для строки:

    char* str = malloc(sizeof(char) * 256);
    strcpy(str, "hello ");

    .
    .
    .
    free(str);

3 - или использовать функцию strdup () (имея в виду, что на самом деле это не часть самого стандарта ISO C, это POSIX)

0 голосов
/ 29 августа 2018

Поскольку память только для чтения доступна только для чтения, вы можете использовать массив char вместо строковой константы в качестве аргумента trim.

char f[] = "Hello  ";
e = trim(f);
0 голосов
/ 29 августа 2018

Указатель не сохраняется в памяти кода, это зависит от того, какой type_qualifiers, которые вы используете для объявления указателя.

1 . char *ptr = "Stack overflow" ;

Теперь ptr сохраняется в памяти стека и указывает на память кодов, указывая на то, что она хранит адрес памяти кодов.

2 . char *ptr = malloc(15);
    strcpy(ptr,"stack overflow");

Теперь также ваш указатель хранится в памяти стека и указывает на раздел кучи (который представляет собой не что иное, как расширенную память данных).

3 . char arr[15] , *ptr;
    strcpy(arr,"Stack overflow");
    ptr = arr ;

Теперь ваш указатель хранится в стеке и также указывает на массив, который также хранится в секции стека.

в случае 1, пользователю не разрешено изменять строку, потому что указатель указывает на память кода, но тогда как в случае 2 и случае 3, указатель может изменить строку.

0 голосов
/ 29 августа 2018

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

e = trim (strdup ("hello"));

Будет скопирована строка только для чтения в доступную для записи память


РЕДАКТИРОВАТЬ: @Ankush указал на тот факт, что строка выделена, поэтому она должна быть освобождена

...