Форум программистов, компьютерный форум CyberForum.ru

Удаление фрагмента из строки - C++

Восстановить пароль Регистрация
 
Рейтинг: Рейтинг темы: голосов - 12, средняя оценка - 4.83
Simkara
16 / 3 / 3
Регистрация: 26.11.2011
Сообщений: 92
21.12.2012, 01:07     Удаление фрагмента из строки #1
Дана идеальная строка, которая содержит равное кол-во открытых и закрытых скобок.
Требуется удалить содержимое скобок (скобки тоже удаляются).
Строку задать через Char s[100].

пример:
на входе 12(34)56(78)9
на выходе 12569

набросал код:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <iostream>
#include <string>
using namespace std;
 
int main()
{
    char *r,*l,s[100];
    int i,z=0,left,right;
    cin.getline (s,100);
    
    l=strchr(s,'('); 
    left=l-s;
    while (l=strchr(s,'('))
    {
         while (l=strchr(s,'('))
         {  
           r=strchr(s,')');
           right=r-s;
           if (right==left+1) 
           {
              strcpy(l,l+1);
              r--;
              strcpy(r,r+1);
              break;
           } 
           *l++;
           strcpy(l,l+1);
         }
    }              
    
    cout<<s; 
    
    cin.get();
    cin.get();
    return 0;
}
удаление производится по каждому символу в скобках, как только скобки сливаются "()" они идут на удаление и поиск начинается по новой

но есть проблема, программа хорошо работает если введена одна пара скобок, а при большем количестве программа почему то зацикливается, в чем может быть причина?
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
OstapBender
 Аватар для OstapBender
581 / 519 / 35
Регистрация: 22.03.2011
Сообщений: 1,585
21.12.2012, 01:26     Удаление фрагмента из строки #2
я бы сделал так:
вводим 2 счетчика c1, c2
считаем количество '(' делаем с1++, пока не встретили ')', начинаем считать ')' -> с2++, пока с2!=с1.
када стали ==, удаляем часть, и дальше так же
Croessmah
Модератор
Эксперт С++
 Аватар для Croessmah
11845 / 6824 / 771
Регистрация: 27.09.2012
Сообщений: 16,919
Записей в блоге: 2
Завершенные тесты: 1
21.12.2012, 01:37     Удаление фрагмента из строки #3
C++
1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>
 
int main(){
    char str[]="My (string)name is (Durak)Croessmah";//мания величия )))
    for(char *p1=str,*p2=str;*p2=*p1; ++p1,++p2){
        if (*p1=='(')
            for(--p2;*p1 && (*p1!=')');++p1);
    }
    std::cout<<str;
    std::cin.get();
    return 0;
}
OstapBender
 Аватар для OstapBender
581 / 519 / 35
Регистрация: 22.03.2011
Сообщений: 1,585
21.12.2012, 01:59     Удаление фрагмента из строки #4
Croessmah, валится на строчке "My (st(ri)ng)name is (Durak)Croessmah"
Croessmah
21.12.2012, 02:07
  #5

Не по теме:

Цитата Сообщение от OstapBender Посмотреть сообщение
Croessmah, валится на строчке "My (st(ri)ng)name is (Durak)Croessmah"
Переделать для вложенных скобок труда не составит. Направление дал, обработка конкретных ситуаций - дело ТС

TrueBit
 Аватар для TrueBit
95 / 95 / 12
Регистрация: 19.11.2012
Сообщений: 195
21.12.2012, 02:30     Удаление фрагмента из строки #6
Вот с использованием дополнительной памяти(считается, что скобочное выражение задано правильно):
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <iostream>
using namespace std;
 
int main(){
    char str[]="My (st(ri)ng)name is (Durak)Croessmah";//мания величия )))
    char str2[100]; // максимальная длина 100 символов
    int i=0,j=0,count=0;
    while(str[i]) {
        if(str[i]=='(') {
            count++; i++;
            while(count) { // пропускаем все, что в скобках, включая вложеные
                if(str[i]=='(') {
                    count++; i++;
                } else if(str[i]==')') {
                    count --; i++;
                } else {
                    i++;
                }
            }
        }
        str2[j]=str[i]; i++; j++;
    }
    str2[j]='\0';
    cout << "str2 = " << str2;
    getchar();
}
Croessmah
Модератор
Эксперт С++
 Аватар для Croessmah
11845 / 6824 / 771
Регистрация: 27.09.2012
Сообщений: 16,919
Записей в блоге: 2
Завершенные тесты: 1
21.12.2012, 02:39     Удаление фрагмента из строки #7
Цитата Сообщение от TrueBit Посмотреть сообщение
Вот с использованием дополнительной памяти(считается, что скобочное выражение задано правильно):
Неправильно при "My (st(ri)ng)name is (Durak)(C((roe(s)sm)a)h)"
TrueBit
 Аватар для TrueBit
95 / 95 / 12
Регистрация: 19.11.2012
Сообщений: 195
21.12.2012, 02:57     Удаление фрагмента из строки #8
А если так?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <iostream>
using namespace std;
 
int main(){
    //char str[]="My (st(ri)ng)name is (Durak)Croessmah";//мания величия )))
    char str[]="My (st(ri)ng)name is (Durak)(C((roe(s)sm)a)h)";
    char str2[100]; // максимальная длина 100 символов
    int i=0,j=0,count=0;
    while(str[i]) {
        if(str[i]=='(') {
            count++; i++;
            while(count || str[i]=='(') { // пропускаем все, что в скобках, включая вложеные
                if(str[i]=='(') {
                    count++; i++;
                } else if(str[i]==')') {
                    count --; i++;
                } else {
                    i++;
                }
            }
        }
        str2[j]=str[i]; i++; j++;
    }
    str2[j]='\0';
    cout << "str2 = " << str2;
    getchar();
}
Simkara
16 / 3 / 3
Регистрация: 26.11.2011
Сообщений: 92
21.12.2012, 04:11  [ТС]     Удаление фрагмента из строки #9
Цитата Сообщение от TrueBit Посмотреть сообщение
А если так?
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <iostream>
using namespace std;
 
int main(){
    //char str[]="My (st(ri)ng)name is (Durak)Croessmah";//мания величия )))
    char str[]="My (st(ri)ng)name is (Durak)(C((roe(s)sm)a)h)";
    char str2[100]; // максимальная длина 100 символов
    int i=0,j=0,count=0;
    while(str[i]) {
        if(str[i]=='(') {
            count++; i++;
            while(count || str[i]=='(') { // пропускаем все, что в скобках, включая вложеные
                if(str[i]=='(') {
                    count++; i++;
                } else if(str[i]==')') {
                    count --; i++;
                } else {
                    i++;
                }
            }
        }
        str2[j]=str[i]; i++; j++;
    }
    str2[j]='\0';
    cout << "str2 = " << str2;
    getchar();
}
Можете вкратце объяснить, как работает алгоритм, какую роль играют счетчики i, count?
C++
1
str2[j]='\0';
и что обозначает вот это?
TrueBit
 Аватар для TrueBit
95 / 95 / 12
Регистрация: 19.11.2012
Сообщений: 195
21.12.2012, 04:24     Удаление фрагмента из строки #10
i - для получения i-го символа в исходной строке, count для определения скобок str2[j]='\0' - завершения второй строки смволом конца строки.

Вот код с коментариями, может так понятнее будет:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <iostream>
using namespace std;
 
int main(){
    //char str[]="My (st(ri)ng)name is (Durak)Croessmah";//мания величия )))
    char str[]="My (st(ri)ng)name is (Durak)(C((roe(s)sm)a)h)";
    char str2[100]; // максимальная длина 100 символов
    int i=0; // счетчик для исходной строки
    int j=0; // счетчик для строки в которую будет запись
    count=0; // счетчик для скобок
 
    while(str[i]) { // пока str[i], т.е, пока str[i]!='\0', '\0' - означет конец строки
        if(str[i]=='(') { // если всретили открывающую скобку
            count++; i++; // говорим, что count++ и переходим к просмотру следующего символа
            while(count || str[i]=='(') { // цикл, пока все скобки не закрылись(когда count станет равен нулю, либо пока идут открывающие скобки)
                if(str[i]=='(') { // если очередной символ открывающая
                    count++; i++; // увеличиваем счетчик скобок на 1 (из цикла не выйдем пока все скобки не закроются)
                } else if(str[i]==')') { // если закрывающая
                    count --; i++;       // отпускаем из count одну скобку и переходим к следующему символу
                } else {
                    i++;                 // если очередной символ не открывающая и не закрывающая скобка
                }                        // то переходим к слудующему сиволу
            }
        }
        // вышли с цикла по count => прошли очередные вложеные скобки
        str2[j]=str[i]; i++; j++; // тогда пишем символ после скобок в новую строку str2[i]
    }
    // когда просмотрим все символы первой строки(выйдем из основного цикла)
    str2[j]='\0'; // пишем в конец второй строки завершающий символ(j будет на нужном месте после выхода из цикла)
    cout << "str2 = " << str2; // печать новой строки, полученной из первой
    getchar(); //задержка
}
Simkara
16 / 3 / 3
Регистрация: 26.11.2011
Сообщений: 92
21.12.2012, 04:27  [ТС]     Удаление фрагмента из строки #11
спасибо
TrueBit
 Аватар для TrueBit
95 / 95 / 12
Регистрация: 19.11.2012
Сообщений: 195
21.12.2012, 04:27     Удаление фрагмента из строки #12
Еще можете для тренировки сделать проверку на правильность скобок. Вот алгоритм:
Заведем count=0 для скобок. Делаем цикл по строке
1) Если очередной символ - открывающая скобка, то count++ (тоже, что count=count+1)
2) Если закрывающая, то count-- (тоже, что count=count-1)

Если в конце просмотра строки, счетчик никогда не был меньше нуля, и в конце цикла равен нулю, то скобочное выражение правильное.
Simkara
16 / 3 / 3
Регистрация: 26.11.2011
Сообщений: 92
21.12.2012, 05:37  [ТС]     Удаление фрагмента из строки #13
тогда ))(( он посчитает правильным, нужно еще учитывать порядок

написал функцию chek для проверки скобок
хочу использовать её в main, но выводит ошибку при передаче строки в функцию "invalid conversion from char" (35 строка)

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <iostream>
using namespace std;
 
inline bool chek (char s[100])
{
    bool z=false;
    int i, c=0,l=1,r=0;
    while (s[i])
    {
        if (s[i]=='(') {l=i; c++;}
        if (s[i]==')') 
        {
            r=i;
            c--;
            if (r<l) 
            {
                z=false;
                c=10; 
                break;
            }        
        }
        i++;
    }
    if (c==0){z=true;}
    else if (c!=0 && c!=10){z=false;}
    return z;
}
 
 
int main()
{
    char s[100];
    bool c;
    cin.getline (s,100);
    c=chek(s[100]);
    cout<<c;
    
    cin.get();
    cin.get();
    return 0;
}
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
24.12.2012, 04:00     Удаление фрагмента из строки
Еще ссылки по теме:

Здесь есть удаление столбца, как добавить удаление строки C++
Строки (Удаление слова из строки) C++
Вывести на экран те строки файла, которые содержат в качестве фрагмента заданный текст C++

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
TrueBit
 Аватар для TrueBit
95 / 95 / 12
Регистрация: 19.11.2012
Сообщений: 195
24.12.2012, 04:00     Удаление фрагмента из строки #14
Еще можете для тренировки сделать проверку на правильность скобок. Вот алгоритм:
Заведем count=0 для скобок. Делаем цикл по строке
1) Если очередной символ - открывающая скобка, то count++ (тоже, что count=count+1)
2) Если закрывающая, то count-- (тоже, что count=count-1)
Если в конце просмотра строки, счетчик никогда не был меньше нуля, и в конце цикла равен нулю, то скобочное выражение правильное.
Цитата Сообщение от Simkara Посмотреть сообщение
тогда ))(( он посчитает правильным, нужно еще учитывать порядок

написал функцию chek для проверки скобок
хочу использовать её в main, но выводит ошибку при передаче строки в функцию "invalid conversion from char" (35 строка)

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

Добавлено через 11 минут
Вот немного модифицировал ваш код:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <iostream>
using namespace std;
 
inline bool chek (char * s)
{
    bool z=false;
    int i=0,c=0;
    while (s[i])
    {
        if (s[i]=='(') { c++; } // 1
        if (s[i]==')') {        // 2
            if(c==0)        // если очередной count - отрицательный(ошибка)
                return false;
            else
                c--;
        }
        i++;
    }
    if (c==0) // проверка в конец алгоритма
        return true;
    else
        return false;
}
 
 
int main()
{
    char s[100];
    bool c;
    cin.getline (s,100);
    c=chek(s);
    cout << c;
    
    cin.get();
    cin.get();
    return 0;
}
Помимо аргумента, вы не установили i в 0.
Yandex
Объявления
24.12.2012, 04:00     Удаление фрагмента из строки
Ответ Создать тему
Опции темы

Текущее время: 15:04. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru