Присвоение NULL середине c-строки

Я пишу функцию eliminate(char *str, int character), которая принимает на вход c-строку и удаляемый символ, сканирует str на наличие экземпляров character и заменяет значение по текущему индексу на... что? Я думал NULL, но это кажется рискованным и может привести к путанице с другими функциями, которые полагаются на нуль-терминатор в c-строке. Например:

char *eliminate(char *str, int character) {
    if (!str) return str;

    int index = 0;
    while (str[index])
       if (str[index] == character)
          str[index++] = '\0'; //THIS LINE IS IN QUESTION
    return str;
}

Мой вопрос в том, как мне правильно реализовать эту функцию, чтобы я эффективно удалял все экземпляры указанного символа в строке? И если правильное исключение присваивает заменяемому символу '\0', как это не влияет на всю строку (т. е. она фактически заканчивается на первом встреченном '\0'). Например, если бы я дважды запускал вышеуказанную функцию для одной и той же строки, второй вызов просматривал бы строку только до того места, где был заменен последний символ.


person Mike B    schedule 26.09.2015    source источник
comment
Возможно, вы захотите переосмыслить этот цикл... кажется, что он будет работать вечно...   -  person Barry    schedule 26.09.2015
comment
NULL не является символом и никогда не должен использоваться как целочисленное значение. Большинство компиляторов определяют его как (void *)0. Включите предупреждения компилятора и обратите на них внимание!   -  person too honest for this site    schedule 26.09.2015
comment
И выберите один язык.   -  person too honest for this site    schedule 26.09.2015
comment
@user2864740: user2864740: константы NUL нет, и OP четко пишет NULL.   -  person too honest for this site    schedule 26.09.2015
comment
@ChrisBeck: Вот почему я попросил удалить один язык. В любом случае, даже если NULL определено как 0 в C++, его не следует использовать как целое число (и больше не как константу нулевого указателя. C++11 представил nullptr по уважительным причинам)   -  person too honest for this site    schedule 26.09.2015
comment
Вы забыли указать свою настоящую цель.   -  person Lightness Races in Orbit    schedule 26.09.2015
comment
Не изменяйте свой вопрос, как только вы получили ответ, который делает ответ неверным. Это не форум. Вместо этого вы можете добавить примечание об исправлении.   -  person too honest for this site    schedule 26.09.2015
comment
Эй, это может быть дубликат stackoverflow.com/questions/5457608/   -  person Mike B    schedule 26.09.2015
comment
@MikeB: Нет. OP хочет заменить, а не удалить. Но неясно, какова его точка зрения, так что она может быть просто искажена.   -  person too honest for this site    schedule 26.09.2015
comment
Вы все равно не правильно определяете. Как вы определяете окончательный конец строки после замены?   -  person too honest for this site    schedule 26.09.2015
comment
@Olaf, MikeB является оператором. Читая вопрос, я понимаю, что он хочет удалить персонажа. Замена на 0 — это просто плохая формулировка (или, если это было преднамеренно, плохая идея). Вопрос, который он нашел, действительно делает то, что он задает.   -  person Jongware    schedule 26.09.2015
comment
@Jongware: Ну да, я не заметил, что он на самом деле ОП, когда писал комментарий. Однако это полностью отличается от того, что он пишет в вопросе (и что подразумевает его код). Не может быть настолько сложно увидеть разницу между заменой и удалением. Дело в том, что он спрашивает, верен ли его подход, но не дает четкого определения правильности, то есть чего он на самом деле хочет достичь.   -  person too honest for this site    schedule 26.09.2015
comment
@Olaf: Я предлагаю идею о том, что ОП, возможно, рассудил, что замена символа на 0, который не является допустимым символом в строке C, таким образом равна его удалению.   -  person Jongware    schedule 26.09.2015
comment
@Jongware: не обязательно. Он может иметь в виду что-то вроде strtok. Простая замена не позволит вызывающей стороне определить фактический конец строки, если только она не хранит информацию об исходной длине. Нет проблем, если его нужно укоротить, но показания противоположны.   -  person too honest for this site    schedule 26.09.2015
comment
После последнего редактирования он действительно выглядит как дубликат stackoverflow.com/questions/5457608/ и ответ stackoverflow. com/a/28609778/4023446 с RemoveChars.   -  person Orest Hera    schedule 26.09.2015


Ответы (2)


Можно использовать такую ​​замену, если вы знаете, что делаете.

Это может работать, только если буфер символов char *str доступен для записи (динамически выделенный, например, malloc, или просто массив символов в стеке char str[SIZE]). Он не может работать для строковых литералов.

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


Целочисленный тип аргумента символьной функции не имеет смысла: int character -> char character

person Orest Hera    schedule 26.09.2015
comment
Это не всегда работает надежно, так как OP не сохраняет дальнейший контекст, где он фактически поставил терминатор. Это зависит от не показанного контекста. - person too honest for this site; 26.09.2015
comment
@Olaf Что ненадежно? OP хочет заменить какой-либо символ на «\ 0». Вопрос задается в контексте строки C с нулевым завершением. Итак, я предполагаю, что автор хочет, чтобы подстрока с нулевым завершением была отмечена каким-то разделителем. Конечно, это изменяет исходный буфер, поэтому буфер нельзя использовать как раньше для исходной строки, как с strtok. - person Orest Hera; 26.09.2015
comment
Взгляните на strtok и почему он не является потокобезопасным. Тогда вы, возможно, увидите разницу. - person too honest for this site; 26.09.2015
comment
@Olaf Я знаю, как работает strtok, и я знаю о strtok_r. Именно поэтому я написал в первой строке, что это можно сделать, только если вы знаете, что делаете. Создание такой подстроки вполне безопасно, если вызывающая сторона может правильно освободить исходную строку. - person Orest Hera; 26.09.2015
comment
если вы знаете, что то, что вы делаете, здесь слишком амбивалентно. Тем более, что ОП, видимо, новичок. - person too honest for this site; 26.09.2015
comment
@Olaf Да, теперь я вижу это после нескольких выпусков вопросов и всех этих комментариев. - person Orest Hera; 26.09.2015

Замена символа на '\0' может привести к путанице. Я бы устранил нежелательного персонажа, переместив на его место следующего подходящего персонажа.

char *eliminate(char *str, int character) {
    if (!str) return str;

    int index = 0, shiftIndex = 0;
    while (str[index]) {
       if (str[index] == character) 
          index++;
       else {
          str[shiftIndex] = str[index];
          shiftIndex++, index++;
       }
    }
    str[shiftIndex] = '\0';
    return str;
}
person Dko    schedule 26.09.2015