Не инициализированы и ошибки памяти (строки и указатели) - PullRequest
0 голосов
/ 09 февраля 2020

Вот что мне нужно сделать: удалить все вхождения числа, которое чаще всего встречается в данной строке

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

Проблема в том, что работает нормально, когда я его компилирую, но не проходит серию автоматически сгенерированных тестов и отображает «доступ к неинициализированному значению» и «ошибка памяти» в строках, помеченных <------. </p>

Я знаю, что это не совсем «минимально воспроизводимый код», но я надеюсь, что кто-то может указать на проблему, поскольку я сталкиваюсь с множеством подобных ошибок при работе с указателями.

char* find_number(char* string,int search)
{
    int sign=1;
    int number=0,temp=0;
    char* p = string;
while(*string != '\0') {<----------
        p=string;
        if(*string=='-') sign=-1;
        else if(*string==' ') {
            string++;
            continue;
        } else if(*string>='0' && *string<='9') {
            temp=0;

            while(*string != '\0' && *string>='0' && *string<='9') {
                temp=temp*10+*string-'0';
                string++;
            }

            number=temp*sign;
            if(number==search) {
                return p;
            }
        } else {
            sign=1,number=0;
        }
        string++;
    }
    return NULL;
}

char* delete_most_frequent(char* string)
{
    //writing all integers in a string to an array
    char* pointer=string;
    char* s = string;
    int temp=0, sign = 1,i=0,array[1000],number=0,counters[1001]= {0},n=0;
    while (*s != '\0') {<------------
        if (*s == '-') sign = -1;<----------
        else if (*s >= '0' && *s <='9') {<----------
            temp = 0;
            while (*s != '\0' && *s >= '0' && *s <= '9') {
                temp = temp * 10 + *s - '0';
                s++;
            }
            number=sign*temp;
            if(number>=0 && number<=1000) {
                array[i]=number;
                i++;
            }
        }
        number=0;
        sign=1;
        s++;
    }
    n=i;//size of the array
    //finding the number that occurs most frequently
    int max=0;
    for (i=0; i<n; i++) {
        counters[array[i]]++;
        if(counters[array[i]]>counters[max]) {
            max=array[i];
        }
    }

    char* p=find_number(string,max);//pointer to the first digit of wanted number
//deleting the integer
    while (*string != '\0') {
        if (p != NULL) {
            char *beginning = p, *end = p;
            while(*end>='0' && *end<='9')
                end++;
            //while (*beginning++ = *end++);
            while(*end != '\0'){
                *beginning = *end;
                beginning++;
                end++;
            }
            *beginning = '\0';
        } else string++;
        p=find_number(string,max);
    }
    return pointer;//pointer to the first character of a string
}

int main()
{
    char s[] = "abc 14 0, 389aaa 14! 15 1, 153";
    printf("'%s'", delete_most_frequent(s));
    return 0;
}

1 Ответ

0 голосов
/ 18 февраля 2020

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

    while(*string != '\0') {
            :
        while(*string != '\0' ...) {
                :
            string++;
        }
            :
        string++;
    }

, поэтому у вас есть два вложенных цикла while, оба из которых перемещают указатель в поисках NUL терминатор, чтобы закончить l oop. Проблема заключается в том, что если внутренний l oop проходит весь путь до NUL (он может остановиться раньше, но не может), то приращение внешнего l oop будет увеличивать указатель past NUL. Затем он счастливо пройдет через (вероятно, недействительную) память в поисках другого NUL, который может не существовать. Это трудно поймать, так как в большинстве написанных вами тестовых случаев, вероятно, есть несколько NUL (вскоре) после строки, поэтому она будет работать нормально - вам почти нужно специально написать тестовый случай, чтобы вызвать этот режим сбоя чтобы поймать это.

Одним из исправлений было бы проверить, что вы еще не обнулились, прежде чем увеличивать - if (*string) string++; вместо просто string++;

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...