У меня есть строка, и я хочу удалить все - ,( ,) ,& ,$ ,# ,! ,[ ,] ,{ ,} ," ,' от начала или конца слова

Каждое слово представляет собой строку, между ними нет пробелов, так как каждое слово читается с помощью scanf.

Если это между словами, просто игнорируйте их.

Например:

"..!Hello!!!."

будет производить

Hello

и

"??Str'ing!!"

будет производить

   Str'ing

Поскольку я новичок, мне разрешено использовать только циклы и стандартный заголовок <string.h> в C.

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

У меня есть это до сих пор, но оно удаляет знаки препинания из всего кода, а не только из начала и конца слов:

void punc(char *str) {
    char *pr = str;
    char *pw = str;
    while (*pr) {
        *pw = *pr++;
         pw += (is_punc(*pw) == false);
    }
    *pw = '\0';
}

person new_hello_world    schedule 20.03.2020    source источник
comment
Пожалуйста, напишите, что вы пробовали до сих пор.   -  person Stephen Newell    schedule 20.03.2020
comment
Когда вы читаете индекс, просто проверьте, является ли последний или следующий символ после того, который вы хотите удалить, пробелом — если да — - удалить символ по текущему индексу (вы можете использовать memmove для настройки всей строки или пары указателей (указатель чтения и указатель записи) и просто пропустить запись удаляемых символов). Вы можете использовать strspn(), чтобы перейти к следующему символу в вашем списке удаления, или strcspn(), чтобы перепрыгнуть через символы, не входящие в список.   -  person David C. Rankin    schedule 20.03.2020
comment
Вот пример удаления конечных и начальных пробелов из файла, который можно адаптировать для удаления любого символа.   -  person David C. Rankin    schedule 20.03.2020
comment
Что должно произойти со строкой abc'-'def? Пунктуацию убрать или оставить без изменений или как?   -  person Jonathan Leffler    schedule 20.03.2020
comment
@Jonathan Leffler, поскольку он находится между строками, он останется без изменений   -  person new_hello_world    schedule 20.03.2020
comment
Итак, вы хотите удалить только последовательности выбранных знаков препинания, когда символ перед последовательностью является «пробелом» (или началом строки) или символ после последовательности является «пробелом» (или концом строки)? Таким образом, знаки препинания в abc '-' def должны исчезнуть, потому что есть пробел до и после последовательности знаков препинания (и оба пробела должны быть оставлены в строке)? Кроме того, вы пропустили ? в заголовке, но показали удаляемый символ — значит, заголовок вопроса неверен?   -  person Jonathan Leffler    schedule 20.03.2020
comment
да, вы правы, каждая строка похожа на слово, и, поскольку «-» - это все знаки препинания, их следует удалить. Однако, если abc '-' def представляет собой одну большую строку, то нет, '-' не следует удалять, поскольку она находится в середине строки.   -  person new_hello_world    schedule 20.03.2020
comment
. не является частью списка удаления в заголовке вашего вопроса, поэтому этот пример и пример "..!Hello!!!." не подходят друг другу; вы должны исправить это.   -  person Armali    schedule 20.03.2020


Ответы (1)


Хороший способ сделать это — сбрить все знаки пунктуации с передней и задней части массива символов, для этого примера я использую ваши указатели, перемещая их по массиву символов, пока не будет найден первый непунктуационный символ, null завершить его и вернуть указатель на 1-й не пунктуационный символ:

Текущий образец

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

char *punc(char *str)
{
    int iterations = 0;
    char *pr = str;                   
    char *pw = &str[strlen(str) - 1]; //pointer to str end
    while (ispunct(*pr))  // I'm using ctype.h ispunct() standard function here 
    {                     // You can repalce it by your helper function    
        pr++;
        printf("it%d ", iterations++); //count and print iterations
    }
    while (ispunct(*pw))
    {      
        if(pw <= pr){  //using pointer comparison to avoid unnecessary iterations
           break;
        }
        pw--;
        printf("it%d ", iterations++);  //count and print iterations
    }   
    *(pw + 1) = '\0';
    return pr;
}

int main()
{
    char str1[] = ".[],!hello-.,?!-worl.d.?(!.";  //test1
    char str2[] = "!.';?";                        //test2   
    char *result1, *result2; 

    result1 = punc(str1);
    printf("  %s\n", result1);    
    result2 = punc(str2);
    printf("  %s\n", result2);    
    strcpy(str1, result1);  //if you want to really replace str with new string   
    return 0;
}

Выход:

it0 it1 it2 it3 it4 it5 it6 it7 it8 it9   hello-.,?!-worl.d
it0 it1 it2 it3 it4
person anastaciu    schedule 20.03.2020
comment
Примеры в вопросе изменены и упрощены. Первоначально одним из входных данных был "Hello I am a str'ing, and I am called Jack-Tack!. My -mom is Darlean." (где двойные кавычки на обоих концах представляют собой скорее нотацию строки C, чем часть данных). - person Jonathan Leffler; 20.03.2020
comment
Спасибо большое, теперь понятно - person new_hello_world; 20.03.2020
comment
@new_hello_world, рад помочь. - person anastaciu; 20.03.2020
comment
Привет @anastaciu, мне было интересно, как я могу решить проблему, из-за которой он не переходит в режим потери памяти, если строка содержит только пунктуацию, например что-то вроде этого !.';?. В этом я просто хотел бы избавиться от всего, но он уходит в переполнение памяти. - person new_hello_world; 21.03.2020
comment
@new_hello_world Вы можете сравнить указатели, чтобы проверить, когда они проходят мимо друг друга, если это произойдет, это означает, что ни один из них не нашел ничего, кроме знаков препинания, и вы можете затем вернуть результат. Я отредактировал изменения в ответе. - person anastaciu; 21.03.2020