Удалить подстроку в скобках в строке - PullRequest
0 голосов
/ 14 мая 2018

Мне нужно удалить каждую подстроку в скобках. Я нашел несколько решений, но ни одно не является хорошим. Вот пример:

Моя строка: текст (lorem (ipsum) abcd) pieceoftext и фактический результат: lorem (ipsum * 1011) *

Однако ожидаемый результат: text (()) pieceoftext или textpieceoftext

Вот код. У меня закончились идеи. Я думал об использовании strtok(), но у меня есть два разных разделителя.

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

int main()
{
    const char *s = "text(lorem(ipsum)abcd)pieceoftext";
    const char *patternA = "(";
    const char *patternB = ")";
    char *target = NULL;
    char *start, *end;

    if (start = strstr( s, patternA ))
    {
        start += strlen( patternA);
        if (end = strstr( start, patternB ) )
        {
            target = (char *)malloc(end - start + 1);
            memcpy(target, start, end - start);
            target[end - start] = '\0';
        }
   }
   if (target)
      printf("Answer: %s\n", target);
   return 0;
}

Будем рады услышать некоторые ваши идеи по решению этой проблемы. Спасибо

Ответы [ 3 ]

0 голосов
/ 14 мая 2018

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

hello(world)world

Простое решение:

Если предвидение является открытием,прекратить экономить.Пока не будет закрытие парен.Когда могут быть смешанные парены, вы просто сохраняете глобальную переменную того, как мы deep (увеличиваем, когда есть открывающая пара, и уменьшаем, когда есть закрывающая пара).Когда эта переменная равна нулю, вы можете сохранить.

Вы можете использовать тот же шаблон заранее, чтобы проверить, достаточно ли закрывающих скобок.

0 голосов
/ 14 мая 2018

Для начала просто выделите достаточно памяти для target, так как вам нужно хранить всю исходную строку s, потому что вы действительно не представляете, сколько места вам понадобится. Не забудьте добавить один для символа конца строки.

Затем измените patternA и patternB с char * на char, чтобы вы могли сравнить их с отдельными символами в s.

Затем вам нужно перебрать исходную строку, отслеживая, находитесь ли вы в скобках или нет. Так как вам нужно поддерживать вложенные скобки, я бы использовал счетчик того, насколько глубоко вы внутри скобок:

int main()
{
    const char *s = "text(lorem(ipsum)abcd)pieceoftext";
    const char patternA = '(';
    const char patternB = ')';
    char *target;
    int targetIndex = 0;
    int parenDepth = 0;

    target = malloc(strlen(s) + 1);
    // check for malloc() error

    for (int sourceIndex = 0; sourceIndex < strlen(s); sourceIndex++) {
        if (s[sourceIndex] == patternA) {
            // we are going deeper into parens, add to level, then ignore the char
            parenDepth++;
            continue;
        }

        if (s[sourceIndex] == patternB) {
            // we are coming out of the parens, lower our level, ignore the parens char
            parenDepth--;
            continue;
        }

        if (parenDepth == 0) {
            // if depth is 0, then we are not inside parens, so copy the char to target
            target[targetIndex++] = s[sourceIndex];
        }
    }

    // add end-of-string
    target[targetIndex] = '\0';

    printf("Answer: %s\n", target);

    return 0;
}
0 голосов
/ 14 мая 2018

Я не понимаю, почему вы не используете только strtok (strtok_r). Я думаю, что это более функционально для этой цели. Просто немного поиграйте с этим.

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

int main(void) {
    char str[] = "text(lorem(ipsum)abcd)pieceoftext";
    char const * delim = ")(";
    char *token;
    char *rest = str;

    while ((token = strtok_r(rest, delim, &rest))) {
         printf("token: %s\n", token);
         printf("rest: %s\n", rest);
    }
}
...