Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Центр помощи > [С++] Баланс скобок с строке


Автор: katz 26.1.2007, 21:20
Привет. Такая вот задача. Проверить наличие баланса скобок в файле.

Автор: Xenon 26.1.2007, 21:25
katz, Баланс скобок?

Автор: Данкинг 26.1.2007, 21:39
Это типа число открывающих равно числу закрывающих? Если так - то и мне покажите, как это сделать в качестве урока работы с файлами и строками на С++ ! smile 

Автор: Sartorius 26.1.2007, 22:28
 Вот тебе баланс скобок в строке (на файл сам перенесешь)
Код

int i = 0;
char str[] = "bla bla bla";
for(int j = 0; j < strlen(str); j++)
{
   if(str[j] == ')') i--;
   if(str[j] == '("') i++;
   if(i < 0)
   {
      cout << "Ахтунг, нарушен порядок скобок";
      return -1;
    }
}

if(i !=0)
{
   cout << "Alarm, баланс скобок нарушен";
}
}

Автор: zkv 26.1.2007, 22:35
я тоже попробую smile
Код

#include <iostream>
#include <fstream>
#include <iterator>

using namespace std;

bool ValidateBrackets( const char *pcFileName );

int main(int argc, char* argv[])
{
        if( ValidateBrackets( "input.txt" ) )
            cout<<"All right";
        else
            cout<<"Very bad";
        cin.get();
}
bool ValidateBrackets( const char *pcFileName )
{
    ifstream fin( pcFileName );
    int iNumOpenBrackets = 0;
    
    for( istream_iterator<char> itFIn(fin); 
         itFIn != istream_iterator<char>(); 
         ++itFIn )
    {
        if( *itFIn == '(' )
            ++iNumOpenBrackets;
        else if( *itFIn == ')' )
            if( !iNumOpenBrackets )
                return false;
            else 
                --iNumOpenBrackets;
    }
    return static_cast<bool>(!iNumOpenBrackets);
}

Автор: Данкинг 26.1.2007, 23:03
Первую понял, во второй операторы незнакомые покамест...

Автор: Oleg_Ci 27.1.2007, 07:22
Всё-таки, под балансом что надо понимать ?
1) (()) - здесь ясно - баланс есть.
2) ))(( - а так? smile  не одной "собранной"
т.е. строка ведь должна открываться '(' а потом закрыватся ')'.
у меня второй пример за баланс несчитается.
Код

#include <iostream>
#include <fstream>
using std::cout;
using std::cin;
using std::ifstream;

bool balans( const char * filename = "text.txt" ); // проверка баланса

////////////// MAIN ////////////////////
int main()
{
    if( balans())
        cout << "Ok !\n";
    else cout << "Error balans !\n";

    cin.get(); // пауза
    return 0;
}
/////////////// End main //////////////////

bool balans( const char * filename ){
    ifstream file( filename ); // открываем файл
    if( !file.is_open()){ // если неоткрывается
        cout << "Error open file " << filename << "\n";
        cin.get(); // пауза
        exit(1);
    }
    int bracket = 0;
    char c;
    while( file.get(c)){
        switch (c){
            case '(': bracket++; break;
            case ')': bracket--; break;
            default: break;
        }
        if( bracket < 0 ) // если закрытых скобок больше то баланс нарушен!
            return false;
    }
    if( bracket )
        return false;
    else return true;
}

Автор: Oleg_Ci 27.1.2007, 07:37
У zkv, принцып такой-же, второй вариант ошибочный.
Я имею ввиду этот - 
Цитата
2) ))(( - а так?   не одной "собранной"

Автор: Kuvaldis 27.1.2007, 14:57
Модератор: Название темы должно отражать ее суть!

Автор: V.A.KeRneL 28.1.2007, 11:37
Цитата(Kuvaldis @  27.1.2007, 14:57 Найти цитируемый пост)

Модератор: Название темы должно отражать ее суть!

ИМХО, содержит. «http://www.google.com/search?hl=en&q=%D0%91%D0%B0%D0%BB%D0%B0%D0%BD%D1%81+%D1%81%D0%BA%D0%BE%D0%B1%D0%BE%D0%BA&btnG=Google+Search» — общепринятый термин. И то что многие здесь его не знают, не отменяет этого. Аффтар katz не виноват! smile

Автор: zkv 28.1.2007, 14:11
оффтоп - восстановление справедливости smile
Цитата(V.A.KeRneL @  28.1.2007,  11:37 Найти цитируемый пост)
ИМХО, содержит. «Баланс скобок» — общепринятый термин. И то что многие здесь его не знают, не отменяет этого. Аффтар katz не виноват! smile

просто на момент написания сего замечания:
Цитата

Модератор: Название темы должно отражать ее суть! 

тема называлась "[c++]"

Автор: V.A.KeRneL 28.1.2007, 19:38
Хотя нет, я погорячился. 
katz виноват... в том, что до сих пор не пометил задачу решённой! 
(Просто даже передать не могу, как меня это раздражает!)

Автор: Akeem 28.1.2007, 20:19
один только момент это задача из теори алгоритмов и тут просится чтобы в сроке находились баланс скобок вида ({[]()})


тогда алгоритм  немного усложнен.

Автор: V.A.KeRneL 28.1.2007, 20:50
Ах, да, Akeem, действительно, возможно это имелось в виду. Но в любом случае katz'у следовало более подробно обрисовать ситуацию.

Вот, как раз, решил в прошедшем семестре эту задачку. 
brackets.c: 
Код

/* brackets
   
   Copyright (C) 2006 Vadim A. Kazantsev aka V.A.KeRneL.
 */

#include <stdio.h>
/*#include <stdio_ext.h>*/
//#include <stdlib.h>
//#include <malloc.h>
//#include <string.h>

/* ************************************************************************ */

#if defined( VERBOSE )
#    define Vprintf( args )    printf args
#    define Vputchar( args )   putchar args
#else
#    define Vprintf( args )    /* empty */
#    define Vputchar( args )   /* empty */
#endif

/* ************************************************************************ */

/**/
#define TRUE   1
#define FALSE  0
typedef int bool;
/**/

/*
enum _bool { 
    FALSE = 0;
#define FALSE FALSE
    TRUE  = 1;
#define TRUE  TRUE
};

typedef   struct _bool   bool;
#define bool bool
*/

/* ************************************************************************ */

#define STACK_SIZE 1000  /* (may be changed) */

typedef struct { 
    int s[ STACK_SIZE + 1 ];  /* body of stack */
    //int t[ STACK_SIZE + 1 ];  /* type of element */
    int top;                  /* position of higher element */
    int count;                /* number of stack element */
} stack;

stack ss;

int last_elem;
//int last_type;

void init_stack( stack * s );
void push( stack * s, int x /*, int type*/ );
int  pop( stack * s );
bool /*int*/ is_empty( stack * s );

void 
init_stack( stack * s ) 
{ 
    s->top = 0;
    s->count = 0;
}

void 
push( stack * s, int x /*, int type*/ ) 
{ 
    if ( s->count >= STACK_SIZE ) { 
        printf( "Warning: stack overflow push x = %d\n", x );
    } else { 
        s->top = ( s->top + 1 ) % STACK_SIZE;
        s->s[ s->top ] = x;
        //s->t[ s->top ] = type;
        s->count = s->count + 1;
    }
}

int 
pop( stack * s ) 
{ 
    int x;
    
    if ( is_empty( s ) ) { printf( "Warning: empty stack pop\n" ); } 
    else { 
        x = s->s[ s->top ];
        last_elem = x;
        //last_type = s->t[ s->top ];
        s->top = ( s->top - 1 ) % STACK_SIZE;
        s->count = s->count - 1;
    }
    
    return ( x );
}

bool /*int*/ 
is_empty( stack * s ) 
{ 
    if ( s->count <= 0 ) { 
        return ( TRUE );
    } else { 
        return ( FALSE );
    }
}

/* ************************************************************************ */
/* *******************************   Main   ******************************* */
/* ************************************************************************ */

#define MAX_LEN   ( STACK_SIZE - 1 )

char brackets[ MAX_LEN + 1 ];

/* 
   Main.
 */
int 
main( void ) 
{ 
    int t;         /* number of test cases */
    //int i, j;      /* counters */
    char * b_ptr;  /* pointer for `brackets' string */
    char _top;
    
    scanf( "%d", &t );
    //printf( "%d\n", t );
loop: 
    while ( t-- ) { 
        scanf( "%s", brackets );
        //printf( "%s\n", brackets );
        b_ptr = ( char * ) brackets;
        while ( *b_ptr ) { 
            //printf( "%c", *b_ptr );
            //push( &ss, ( int ) *b_ptr );
            //printf( "%c", ( char ) pop( &ss ) );
            switch ( *b_ptr ) { 
            case '(': case '[': case '{': case '<': 
                push( &ss, ( int ) *b_ptr );
                break;
            case ')': case ']': case '}': case '>': 
                if ( is_empty( &ss ) ) { 
                    Vprintf(( "%c", *b_ptr ));
                    Vputchar(( '\n' ));
                    puts( "NO" );
                    Vputchar(( '\n' ));
                    goto loop;
                }
                _top = ( char ) pop( &ss );
                //printf( "  _top = %c\n", _top );
                //printf( "*b_ptr = %c\n", *b_ptr );
                if (    !( _top == '(' && *b_ptr == ')' ) 
                     && !( _top == '[' && *b_ptr == ']' ) 
                     && !( _top == '{' && *b_ptr == '}' ) 
                     && !( _top == '<' && *b_ptr == '>' ) ) 
                { 
                    Vprintf(( "%c", _top ));
                    Vprintf(( "%c", *b_ptr ));
                    Vputchar(( '\n' ));
                    puts( "NO" );
                    Vputchar(( '\n' ));
                    goto loop;
                }
                Vprintf(( "%c", _top ));
                Vprintf(( "%c", *b_ptr ));
                break;
            default: 
                ;
            }
            ++b_ptr;
        }
        Vputchar(( '\n' ));
        puts( is_empty( &ss ) ? "YES" : "NO" );
        Vputchar(( '\n' ));
    }
    
    return ( 0 );
}  /* main() */

/* brackets.c ends here.  */


Example

input1.txt: 
Код

8
()
(())
()()
)()(
({[<>]})
()({[<>]})()
([({})<>({})])()
(({)(}))


output1.txt: 
Код

YES
YES
YES
NO
YES
YES
YES
NO


Компиляция: 
Код

gcc brackets.c -o brackets && chmod -x brackets


Запуск: 
Код

./brackets < input1.txt


==========================================================================================
P.S. Всегда следуйте правилам форма! В частности: 
Если вопрос решён, то воспользуйтесь ссылкой "Пометить как решённый", которая находится под кнопками создания темы или флажком при ответе smile
==========================================================================================

Автор: katz 29.1.2007, 20:04
Спасибо парни выручили.!!!!!

Автор: Sartorius 29.1.2007, 21:15
Хотя топик и решен....
У V.A.KeRneL очень грамоздкое решение ИМХО 
Предлагаю такое :
Первый вызов : isBalanced(str, strlen(str));
Код

bool isBalanced(char * str, int len)
{
    int   counter[3] = {0}; //( { [
    static const char  end_bracket[3] = {')', '}', ']'};
    static const char  start_bracket[3] = {'(', '{', '['};

    int old_pos = 0;
    
    if(len <= 0)
        return true;

    for(int pos = 0; pos < len; pos++)
    {
        for(int j = 0; j < 3; j++)
        {
            if(str[pos] == start_bracket[j]) counter[j] ++;
            if(str[pos] == end_bracket[j]) counter[j] --;
        }
        if(counter[0] < 0 || counter[1] < 0 || counter[2] < 0)
            return false;
        old_pos = pos;
        for(int j = 0; j < 3; j++)
        {
            if(counter[j]) // открылась скобка
            {
                for(pos = pos + 1; pos < len; pos++)
                {
                    if(str[pos] == start_bracket[j]) counter[j]++; 
                    if(str[pos] == end_bracket[j]) counter[j]--; 
                    if(!counter[j]) break;
                }
                if(pos == len) return false;
                if(!isBalanced(str + old_pos + 1, pos - 1 - old_pos))
                    return false;
            }
        }
    }
    return true;
}

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)