Удаление массива вхождений из строки в C - PullRequest
0 голосов
/ 17 сентября 2018

У меня проблемы с циклом в моем коде.У меня есть метод, который принимает два массива символов (фраза, символы).Массив символов содержит символы, которые должны читаться по отдельности и сравниваться с фразой.Если это соответствует, каждое вхождение символа будет удалено из фразы.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
//This method has two parameters: (str, c)
//It will remove all occurences of var 'c'
//inside of 'str'
char * rmstr(char * c, char * str) {

    //Declare counters and pointers
    int stemp = 0;
    int ctemp = 0; 
    char *p = str;
    char *d = c;
    //Retrieve str count
    while(str[stemp] != '\0') {
        stemp++;
    }
    //Retrieve c count
    while(c[ctemp] != '\0') {
        ctemp++;
    }
    //Output information
    printf("String Count: %d\n",stemp);
    printf("Character Count: %d\n",ctemp);
    //Iterate through arrays
    for (int i = 0; i != stemp; i++) {
        for (int j = 0; j != ctemp; j++) {
            if (c[j] != str[i]){
                *p++ = str[i];
            } 
                break;
        }
        printf("%s\n",str);
    }
    *p = 0;
    return str;
}

int main()
{
    char c[256] = "ema";
    char input[256] = "Great message!";
    char *result = rmstr(c, input);
    printf("%s", result);
    return 0;
}

В этом случае ввод будет «Великое сообщение!»и символ, который я хотел бы удалить все вхождения символов: e, m, a (как указано в main).

Используя приведенный выше код, получим следующий вывод:

Grat mssag!

Он проходит только одну итерацию и удаляет «e».Я бы хотел, чтобы он проходил через «m» и «a».

1 Ответ

0 голосов
/ 17 сентября 2018

После того, как вы исправите break;, из-за которого выходил внутренний цикл, может иметь смысл переупорядочить ваши циклы и удалить циклы по символам, проверяя символы в str.Это более удобно, позволяя вам перетасовать каждый символ на единицу в str, если он соответствует символу c.Если вы используете функции из string.h, такие как memmove, для перемещения символов вниз, это не имеет значения.

Простая реализация, использующая только указатели для ручной работы через str, удаляющую все символы в c может выглядеть примерно так:

#include <stdio.h>

char *rmstr (char *str, const char *chars)
{
    const char *c = chars;          /* set pointer to beginning of chars */
    while (*c) {                    /* loop over all chars with c */
        char *p = str;              /* set pointer to str */
        while (*p) {                /* loop over each char in str */
            if (*p == *c) {         /* if char in str should be removed */
                char *sp = p,       /* set start pointer at p */
                    *ep = p + 1;    /* set end pointer at p + 1 */
                do
                    *sp++ = *ep;    /* copy end to start to end of str */
                while (*ep++);      /* (nul-char copied on last iteration) */
            }
            p++;                    /* advance to next char in str */
        }
        c++;                        /* advance to next char in chars */
    }
    return str;     /* return modified str */
}

int main (void) {

    char c[] = "ema";
    char input[] = "Great message!";

    printf ("original: %s\n", input);
    printf ("modified: %s\n", rmstr (input, c));

    return 0;
}

(есть много способов сделать это - насколько это зависит от вас. Используете ли вы указатели, как указано выше, или получаете длины и используете строку-индексы также являются предметом выбора)

Пример использования / вывода

$ ./bin/rmcharsinstr
original: Great message!
modified: Grt ssg!

Если вы действительно хотите использовать memmove (для решения проблемы перекрывающейся природыисточник и место назначения), чтобы переместить оставшиеся символы в str на единицу каждый раз, когда символ в str соответствует символу в c, вы можете оставить циклы в исходном порядке, например,

#include <string.h>

char *rmstr (char *str, const char *chars)
{
    char *p = str;                  /* set pointer to str */
    while (*p) {                    /* loop over each char in str */
        const char *c = chars;      /* set pointer to beginning of chars */
        while (*c) {                /* loop over all chars with c */
            while (*c == *p) {      /* while the character matches */
                memmove (p, p + 1, strlen (p)); /* shuffle down by 1 */
                c = chars;          /* reset c = chars to check next */
            }
            c++;                    /* advance to next char in chars */
        }
        p++;                        /* advance to next char in str */
    }
    return str;     /* return modified str */
}

(убедитесь, что вы понимаете, почему вы должны сбросить c = chars; в этом случае)

Наконец, если вы действительно хотите краткий способ сделать это, вы можете использовать strpbrk и memmove и уменьшить своифункция к:

#include <string.h>

char *rmstr (char *str, const char *chars)
{
    /* simply loop using strpbrk removing the character found */
    for (char *p = strpbrk (str, chars); p; p = strpbrk (str, chars))
        memmove (p, p+1, strlen(p));

    return str;     /* return modified str */
}

(всегда существует более одного пути к skin-the-cat в C)

Вывод один и тот же.Посмотрите здесь и дайте мне знать, если у вас есть дополнительные вопросы.

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