Удалить специальный символ из строки в C под Linux

Используя C в Linux, как я могу удалить символ (или любой другой «конкретный» не ASCII-символ, переданный в качестве параметра функции -) из строки?

Я пробовал с:

void remove_all_chars(char* str, char c) {
    char *pr = str, *pw = str;
    while (*pr) {
        *pw = *pr++;
        pw += (*pw != c);
    }
    *pw = '\0';
}

но я получаю:

:warning: многосимвольная символьная константа.

Должен ли я конвертировать перед строкой в ​​широкий символ что-то вроде

wchar_t wsAux[100];
remove_all_chars(wsAux, "A€bcd", 100);

но это не работает.


person famedoro    schedule 25.03.2014    source источник
comment
Какая кодировка на входе? Кроме того, удалить смысл сделать строку короче?   -  person hyde    schedule 25.03.2014
comment
Я понимаю, что вы делаете с указателями (это довольно умно), но я не могу понять, полностью ли это безопасно. Я бы предпочел выделить новую строку и скопировать только допустимые символы...   -  person n0p    schedule 25.03.2014
comment
@Coconop Это безопасно, так как указатель записи всегда будет меньше или равен указателю чтения. Попробуйте на бумаге.   -  person Some programmer dude    schedule 25.03.2014
comment
Я должен перестать ломать себе голову на экране, бумага сказала мне, что это действительно хорошо ^^   -  person n0p    schedule 25.03.2014
comment
Этот вопрос вращается вокруг того, как именно кодируется текст. Это будет \x80 в Windows-1252, \xe2\x82\xac в UTF-8, \x20\xac в UCS2/UTF-16 или \x00\x00\x20\xac в UCS4/UTF-32.   -  person Phylogenesis    schedule 25.03.2014
comment
@ Филогенез, не могли бы вы привести пример?   -  person famedoro    schedule 25.03.2014
comment
Если вы строго хотите удалить символы, отличные от ASCII, просто удалите любой байт с установленным верхним битом... Конечно, это может оставить дополнительный непреднамеренный мусор из второго и более поздних байтов многобайтовых символов, в зависимости от исходной кодировки , но не вдаваясь в подробности о том, что именно вам нужно, это начало...   -  person twalberg    schedule 25.03.2014
comment
@famedoro Да: здесь.   -  person Phylogenesis    schedule 25.03.2014
comment
Если кодировка UTF8 void remove_all_nonASCII(char* str) { char *pr = str, *pw = str; while (*pr) { *pw = *pr++; pw += ((*pw & ~7F) == 0); } *pw = '\0'; }   -  person chux - Reinstate Monica    schedule 25.03.2014
comment
По сути, вы не можете ожидать, что поместится в char.   -  person David Leonard    schedule 25.03.2014
comment
@DavidLeonard Но иногда вы можете ... например. Кодировка ISO-8859 с беззнаковыми символами...   -  person twalberg    schedule 25.03.2014
comment
@chux Спасибо за ваш пример, но я хочу удалить только € или другой указанный символ.   -  person famedoro    schedule 26.03.2014
comment
@ Филогенез пример в C? Я не нашел его на joelonsoftware.com/articles/Unicode.html   -  person famedoro    schedule 26.03.2014
comment
@famedoro Я хочу сказать, что, не зная кодировки текста, ни вы, ни я, ни кто-либо другой не может точно сказать вам, как его удалить. Любой символ может быть закодирован как несколько разных строк байтов.   -  person Phylogenesis    schedule 26.03.2014
comment
@famedoro Вы не показали, как позвонили remove_all_chars(). Сообщение показало сообщение компилятора, хотя и не указало, какая именно строка его вызвала. Пожалуйста, опубликуйте точный код. Было ли это так: char s[] = "A€bcd"; remove_all_chars(s, '€');?   -  person chux - Reinstate Monica    schedule 26.03.2014
comment
@chux Использование char s[] = A€bcd; remove_all_chars(s, '€'); У меня есть предупреждение: многосимвольное символьное постоянное предупреждение: переполнение в неявном преобразовании константы   -  person famedoro    schedule 27.03.2014
comment
@Phylogenesis Я использую Linux с gcc без каких-либо настроек локали, тогда я думаю, что использую UTF-8   -  person famedoro    schedule 27.03.2014


Ответы (3)


Попробуй это

#include<stdio.h>
void remove_all_chars(char* str) {
    char *pr = str, *pw = str;
    while (*pr) {
    if(isascii(*pr))
    {
        //printf("%c: is ascii char \n", *pr);
        *pw = *pr;
        pw++;
    }
    pr++;
    }
    *pw = '\0';
}

main()
{

    char str[100] = "asÄ—df";
    remove_all_chars(str);
    printf("%s\n",str);

}
person user207064    schedule 25.03.2014
comment
isprint удаляет непечатаемые вещи. Если вы заинтересованы в сохранении всех кодов ASCII, рассмотрите возможность вызова функции isascii. - person EvilTeach; 25.03.2014
comment
@user207064 user207064 спасибо за ваш пример, но я хочу указать символ, который нужно удалить. - person famedoro; 26.03.2014
comment
вы можете заменить if(isascii(*pr)) на - person user207064; 26.03.2014

Я полагаю, вы делаете что-то вроде

remove_all_chars(some_string, 'A€bcd');

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

Вместо этого передайте символы, которые вы хотите удалить, в виде строки:

remove_all_chars(some_string, "A€bcd");

Конечно, при правильной модификации функции remove_all_chars.

person Some programmer dude    schedule 25.03.2014
comment
Нет, если я использовал remove_all_chars(field, A€bcd); Я предупреждаю: передача аргумента 2 для remove_all_chars делает целое число из указателя без приведения. Я также хочу удалить только 1 символ, а не строку. - person famedoro; 25.03.2014
comment
@famedoro Вот почему я добавил последнее предложение о том, что вам нужно соответствующим образом изменить функцию. - person Some programmer dude; 25.03.2014
comment
Я также хочу удалить только 1 символ, а не строку. - person famedoro; 25.03.2014
comment
Модификация, о которой говорит @JoachimPileborg, заключается в сравнении каждого элемента строки запрещенных символов: для каждого char c в строке "A€bcd" убедитесь, что (*pw != c) - person n0p; 25.03.2014
comment
@famedoro Вы должны проверить каждый символ в строке. - person Some programmer dude; 25.03.2014

Я пробовал:

void removeSubstring(char *s,const char *toremove)
{
  while( s=strstr(s,toremove) )
   memmove(s,s+strlen(toremove),1+strlen(s+strlen(toremove)));
}

from Удалить подстроку из строки? и это работает.

Таким образом, символ € рассматривается как строка, на самом деле он занимает 3 байта (попробуйте strlen("€"))!

person famedoro    schedule 27.03.2014