►Подклассы strstream...285

Потоковые классы позволяют программисту разбивать входные данные на числа и массивы символов. Так называемые "строковые потоки" позволяют использовать операции, определённые для файлов в классах fstream, для строк в памяти. Соответствующие классы istringstream и ostringstream определены в заголовочном файле sstream.

«В старых версиях С++ эти классы назывались istrstream и ostrstream и были определены в заголовочном файле strstream.»

[Советы]

Строковые потоки используют ту же семантику, что и соответствующие базовые классы для файлов, как видно из приведённой далее демонстрационной программы.

    /* StringStream — чтение и разбор содержимого файла */

    #include <fstream>

    #include <sstream>

    #include <iostream>

    using namespace std ;

    /* parseAccountInfo — чтение переданного */

    /*                    буфера как если бы */

    /*                       это был файл. */

    /*              Формат: имя, счёт, баланс. */

    /*                   При корректной работе */

    /*                      возвращает true. */

    bool parseString( char* pString ,

                        char* pName ,

                       int arraySize ,

                     long& accountNum ,

                       double& balance )

    {

        /* Связывает объект istringstream с входной строкой */

        istringstream inp( pString ) ;

        /* Чтение до разделяющей запятой */

        inp.getline( pName , arraySize , ',' ) ;

        // Номер счёта

        inp >> accountNum ;

        // и его баланс

        inp >> balance ;

        /* Возврат состояния ошибки */

        return !inp.fail( ) ;

    }

    int main( int nNumberofArgs , char* pszArgs[ ] )

    {

      setlocale ( LC_ALL ,".1251" ) ; /* печать русских текстов */

        /* Файловый поток */

        ifstream* pFileStream = new ifstream( "Accounts.txt" ) ;

        if ( !pFileStream -> good( ) )

        {

                cout << "Невозможно открыть Accounts.txt" << endl ;

                return 0 ;

        }

        /* Считываем строку файла, разбираем и выводим результат */ 

_________________ 

285 стр. Глава 24. Использование потоков ввода-вывода

        for ( ; ; )

        {

            /* Добавляем разделитель */

            cout << "=================" << endl ;

            /* Читаем в буфер */

            char buffer[ 256 ] ;

            pFileStream -> getline( buffer , 256 ) ;

            if ( pFileStream -> fail( ) )

            {

                break ;

            }

            /* Разбираем ввод на поля */

            char name[ 80 ] ;

            long accountNum ;

            double balance ;

            bool result = parseString( buffer , name , 80 ,

                                      accountNum , balance ) ;

            /* Вывод результата */

            cout << buffer << " " ;

            if ( result == false )

            {

                cout << "Ошибка разбора строки " ;

                continue ;

            }

            cout << "Имя = " << name << ","

                 << "Счёт = " << accountNum << ", "

                 << "Баланс = " << balance << endl ;

            /* Выводим поля в другом порядке ( вставка ends гарантирует нуль-завершённость буфера ) */

            ostringstream out ;

            out << name << ", "

                << balance << " "

                << accountNum << ends ;

            /* Вывод результата. Класс istringstream работает и с классом string, но пока что мы не будем использовать эту возможность */

            string oString = out.str( ) ;

            cout << oString << " " << endl ;

        }

        /* Пауза для того, чтобы посмотреть на результат работы программы */

        system( "PAUSE" ) ; return 0 ;

    }

Программа начинает работу с открытия файла Accounts.txt, содержащего информацию в формате

Имя, номер счёта, баланс,

В предположении, что файл открыт успешно, программа входит в цикл, считывающий файл построчно до его полного прочтения. Строки считываются при помощи функции-члена getline( ), который читает их до символа новой строки. Затем считанная строка передаётся функции parseString( )

_________________

286 стр. Часть 5. Полезные особенности

Функция parseString( ) связывает с символьной строкой объект istringstream. Программа считывает символы из строки до достижения символа '.' ( или конца строки ) при помощи функции-члена getline( ), после чего используются обычные операторы извлечения из потока для чтения номера счёта и баланса. Чтение выполнено успешно, если inp.fail( ) возвращает false.

После вызова функции parseString( ) выполняется вывод в буфер обработанной информации. Результат работы программы выглядит следующим образом.

    ================

    Chester, 12345 56.60

    Имя = Chester,Счёт = 12345, Баланс = 56.6

    Chester, 56.6 12345

    ================

    Arthur, 34567 67.50

    Имя = Arthur,Счёт = 34567, Баланс = 67.5

    Arthur, 67.5 34567

    ================

    Trudie, 56x78 78.90

    Ошибка разбора строки

    ================

    Valerie, 78901 89.10

    Имя = Valerie,Счёт = 78901, Баланс = 89.1

    Valerie, 89.1 78901

    ===============

    Press any key to continue...

Обратите внимание, как программа способна восстановиться после ошибок во входном файле. Оцените также простоту функции parseString( ), использующей возможности класса istringstream.