C код, удаляющий неправильный символ из строки - PullRequest
0 голосов
/ 07 января 2020

Предполагается, что этот код удалит все начальные пробелы из данной строки, и он работал правильно. Затем, по-видимому, без всякой причины, он начал удалять символы в середине слова. В этом примере дается слово «CHEDDAR», которое не имеет начальных пробелов, поэтому его следует передавать так же, как оно было введено, однако возвращается «CHEDDR», и я понятия не имею, почему. Кто-нибудь знает, как это вообще возможно? Я предполагаю, что это связано с указателями и памятью, но я не владею C и мне нужна помощь. Бег на RHEL. Спасибо.

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

#define REMOVE_LEADING_SPACES(input)                       \
           {                                            \
           stripFrontChar( input, ' ' );                         \
           }


char *stripFrontChar(char *startingString, char removeChar) {
    while (*startingString == removeChar)
        strcpy(startingString, startingString + 1);
    return (startingString);
}

void main(argc, argv)
    char **argv;int argc; {
    char *result = "CHEDDAR";
    REMOVE_LEADING_SPACES(result);
    printf("%s\n", result);
}

РЕДАКТИРОВАТЬ: Сейчас немного поздно, но на основании комментариев я должен был показать, что слово (CHEDDAR я использовал в качестве примера) читается из файла, а не из литерала, как показано в мой код Я пытался упростить этот вопрос, и теперь я понимаю, что это совершенно другой сценарий, поэтому не должен был этого делать. Спасибо, похоже, мне нужно использовать memmov.

EDIT2: На самом деле есть пробел, похожий на "CHEDDAR", поэтому мне просто нужно изменить его на memmov, еще раз спасибо всем.

Ответы [ 4 ]

4 голосов
/ 07 января 2020

Вы копируете строку, используя перекрывающуюся область памяти:

strcpy(startingString, startingString + 1);

Из стандарта C:

7.24.2.3 Функция strcpy

Если копирование происходит между объектами, которые перекрываются, поведение не определено.

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

Другая проблема, на которую указал J oop Eggen в комментарии:

char *result = "CHEDDAR";

Вы не можете изменять строковые литералы. Если вы пытаетесь удалить начальные символы, вы вызываете неопределенное поведение.

Вы должны изменить это значение на

char result[] = "CHEDDAR";

Поскольку ваша строка образца не содержит начальный пробел, это пока не вызывает проблем , Но все равно надо это исправить

3 голосов
/ 07 января 2020

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

Вместо :

char *result = "CHEDDAR";

Использование:

char result[] = "CHEDDAR";

(Примечание: посмотрите, как будет реализовано большинство функций strcpy, а именно al oop, который завершается при отображении нулевого символа исходная строка, а затем используемое вами перекрытие будет по-прежнему видеть нулевой символ источника и помещать его в место назначения (копирование с понижением). он будет перезаписан и может продолжить копирование за пределы строки назначения.)

3 голосов
/ 07 января 2020

Этот код

strcpy(startingString, startingString + 1);

копирует перекрывающиеся строки.

За 7.24.2.3 Функция strcpy , параграф 2 стандарта C :

Функция strcpy копирует строку, указанную s2 (включая завершающий нулевой символ), в массив, на который указывает s1. Если копирование происходит между объектами, которые перекрываются, поведение не определено.

Вы вызываете неопределенное поведение.

2 голосов
/ 07 января 2020

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

char *stripFrontChar(char *startingString, char removeChar) {
    for( ; *startingString == removeChar; startingString++)
        ;
    return (startingString);
}

Но вы должны использовать возврат stripFrontChar ()

printf("%s\n", stripFrontChar(result));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...