Доступ к месту записи нарушения при работе с указателями на символ - PullRequest
5 голосов
/ 10 декабря 2011

Я пишу очень простую программу, которая удаляет повторяющиеся символы из строки.Я запустил его в Visual Studio и получил ошибку:

Необработанное исключение в 0x00d110d9 в inteviews.exe: 0xC0000005: Место записи нарушения прав доступа 0x00d27830.

Я действительно непосмотри в чем проблема.текущая ячейка получает значение следующей ячейки.

void remove(char *str, char a) {
    while (*str != '\0') {
        if (*(str+1) == a) {
            remove(str + 1, a);
        }

        *str = *(str +1 );//HERE I GET THE ERROR
        ++str;
    }
}


int _tmain(int argc, _TCHAR* argv[])
{
    char *str = "abcad";

    while (*str != '\0') {
        remove(str,*str);
        str++;
    }

    std::cout << str << std::endl;

    return 0;
}

РЕДАКТИРОВАТЬ:

Я уже пытался изменить его на char str[] = "abcad", но я все еще получаюта же ошибка.

Ответы [ 3 ]

9 голосов
/ 10 декабря 2011

Вы пытаетесь изменить строковый литерал. Вы не можете этого сделать.

char *str = "abcad";

Это строковый литерал. Он создан в постоянной памяти, поэтому попытка записи в него является нарушением прав доступа.

6 голосов
/ 10 декабря 2011

Одна проблема в том, что вы создали строковый литерал только для чтения и попытались изменить его:

char *str = "abcad"; // String literals are read-only!

Вместо этого вы можете использовать массив символов:

char str[] = "abcad";
3 голосов
/ 10 декабря 2011

Есть все виды проблем с вашей программой. Я начал с того, что попытался записать их все, но я чувствую, что код не подлежит восстановлению. Имеются ошибки индексации, ошибки передачи параметров, сомнительная рекурсия и т. Д.

Другие ответы, указывающие на ошибку при попытке изменить литерал только для чтения, верны. Это является причиной ошибки в опубликованном вами коде.

Основная причина ваших проблем, на мой взгляд, в том, что код труднее писать, когда у вас есть только один буфер. Вы завязали себе узлы, пытаясь обойти это ограничение в своем дизайне, но со вторым буфером для работы код тривиален.

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

int main(void)
{
    const char *input = "abcad";
    char *output = malloc(strlen(input)+1);

    char *in = input;
    char *out = output;
    while (*in)
    {
        if (*in != input[0])
        {
            *out = *in;
            out++;
        }
        in++;
    }
    *out = '\0';

    printf("%s\n", output);

    free(output);

    return 0;
}

Если вы хотите стать по-настоящему умным, вы на самом деле можете успешно управлять только одним буфером, если у вас есть два разных указателя для итерации.

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

int main(void)
{
    char str[] = "abcad";
    char compare = str[0];

    char *in = str;
    char *out = str;
    while (*in)
    {
        if (*in != compare)
        {
            *out = *in;
            out++;
        }
        in++;
    }
    *out = '\0';

    printf("%s\n", str);

    return 0;
}

Обратите внимание, что мы должны были взять копию первого символа в буфере, удаляемый символ, поскольку он может быть изменен итерацией.

Итак, теперь вы вернулись к тому, с чего начали, с одним буфером. Но теперь код работает и его легко понять.

Обратите внимание, что мой ответ написан на C согласно вашему тегу, но обратите внимание, что ваш код - C ++.

...