Удаление символов в круглых скобках в C - PullRequest
5 голосов
/ 06 сентября 2011

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

Случай 1:

Ввод: (Hello) WorldВыход: World

Случай 2:

Вход: (Hello WorldВыход: (Hello World

Случай 3:

Вход: Hello)(WorldВыход: Hello)(World

Корпус 4:

Вход: Hello((hi) World)Выход: Hello

Случай 5:

Вход: (Hello) hi (World)Вывод: hi

Вот мой код:

#include <stdio.h>
int main(){
    char string[100] = {0};
    char removedletters[100] = {0};
    fgets(string, 100, stdin);
    char *p;
    int x = 0;
    int b = 0;
    for (p=string; *p!=0; p++) {
        if (*(p-1) == '(' && x) {
            x = 0;
        }
        if (*p == ')') {
            x = 1;
        }
        if (!x){
            removedletters[b] = *p;
            b++;
        }
    }
    puts(removedletters);
}

Варианты 1, 3 и 5 верны, но не в случае 2 и 4. Что не так с моим кодом?

Ответы [ 2 ]

2 голосов
/ 06 сентября 2011

Вы вызываете неопределенное поведение:

for(p=string; *p!=0; p++){
    if(*(p-1) == '(' && x){
        x = 0;
    }

Первый раз, когда p++ оценивается, находится в конце цикла цикла, поэтому, в первый раз, *(p-1) указывает слева от string, т.е. вы делаете *(string-1).

К сожалению, вы потеряете любую гарантию, если у вас будет неопределенное поведение.

1 голос
/ 06 сентября 2011

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

В полупсевдокоде:

// str is the input string, set up to and from pointers.
stacktype stack = empty-stack
char *from = str
char *to = str

// Process every character once and once only.
while *from != '\0':
    switch *from:
        // Open, transfer character and store position on stack.
        case '(':
            *to++ = *from++
            stack.push (to - 1)
            break

        // Close, get most recent '(' and adjust to for overwrite.
        //   If no most recent, just transfer as is.
        case ')':
            if stack is not empty:
                to = stack.pop()
            else:
                *to++ = *from++
            break

        // Anything else, just transfer.
        default:
            *to++ = *from++

// Terminate string at truncated position.
*to = '\0'

Это будет проходить через строку символ за символом, запоминая все позиции ( в стеке, но по-прежнему передавая символы.

Всякий раз, когда вы найдете символ ), вы настраиваете указатель to так, что начинаете перезапись с самого последнего символа (, эффективно удаляя все внутри и включая раздел (...).

...