Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Обнаружить пустую строку (или продолжение к закрытой теме :))

1.8K
06 сентября 2006 года
Andreww
81 / / 02.01.2004
Ну вот, наговорили кучу разговоров в моей теме http://forum.codenet.ru/showthread.php?t=29001 и закрыли ее :((((( а у меня тут сложность возникла....

Green, долго думал почему что-то не то получается, в итоге случайно обнаружил что вот эта конструкция:

 
Код:
bool isWhitespace(const string& str)
{
    return (str.find_first_not_of(" \t\v\r\n") == string::npos);
}


"не чувствует" пустую строку. То есть обработка данных начинается не после прохода каждой группы, а только по достижении конца файла, что не правильно... Подскажите пожалуйста, как правильно записать пустую строку чтобы ее можно было обнаружить?

Я уже пробовал и так " \n" и так "\n" и сяк " \0".... В общем как только не пробовал, а не "ловится" эта пустая строка....

PS. И так тоже пробовал:

out << endl;

... не проходит....
3
06 сентября 2006 года
Green
4.8K / / 20.01.2000
Я проверил код примера.
Данная функция у меня отлично отлавливает и пустую строку и строку с пробельными символами.
Что значит "записать пустую стоку"?
У тебя есть код, который формирует файл?
Ты проверял зрительно, действительно ли файл вормируется правильно?
Какая строка попадает в приведенную функцию, вместо пустой? Какие в ней символы?
1.8K
06 сентября 2006 года
Andreww
81 / / 02.01.2004
Хм... файл я проверял, там действительно визуально все как надо. В пустой строке записывается пробел, потом ничего. Завтра буду за «нужным» компьютером, найду кусочек кода который формирует файл. Странно все это...
3
06 сентября 2006 года
Green
4.8K / / 20.01.2000
Выложи файл
1.8K
07 сентября 2006 года
Andreww
81 / / 02.01.2004
Вот посмотрите пожалуйста, код с помощью которого я формирую файл с группами чисел:
Код:
ofstream out("contours.txt");

do {

      //---
       какие-то действия
      //---

      for (int i = 0; i < VecSize; i++)
      {
        out << ((A).x) << '\t' << ((A).y) << endl;
      }
       
       out << endl;

     }while (какое-то условие)


Я думаю, не нужно тут углубляться в то что такое (A).x и (A).y, скажем так -- это целые числа, координаты пикселей. (если чуть подробнее то А - это вектор, компонентами которого являются структуры -- но это сейчас не важно.)

Таким образом, с помощью цикла for записывается группа чисел, после нее при помощи out << endl; вставляется пустая строка. Затем опять проделываются какие-то вычисления (обозначены как "какие-то действия"), и снова записываем полученную группу и пустую строчку вслед за ней.

В итоге получаем вот такой текстовый файл (скопировал реальный):

Код:
20  21
21  20
22  20
23  20
24  20
25  20
26  21
26  22
26  23
26  24
26  25
25  26
24  26
23  26
22  26
21  26
20  25
20  24
20  23
20  22
21  22
21  21

20  63
21  62
22  62
23  62
24  62
25  62
26  63
26  64
26  65
26  66
26  67
25  68
24  68
23  68
22  68
21  68
20  67
20  66
20  65
20  64
21  64
21  63

20  106
21  105
22  105
23  105
24  105
25  105
26  106
26  107
26  108
26  109
26  110
25  111
24  111
23  111
22  111
21  111
20  110
20  109
20  108
20  107
21  107
21  106

20  149
21  148
22  148
23  148
24  148
25  148
26  149
26  150
26  151
26  152
26  153
25  154
24  154
23  154
22  154
21  154
20  153
20  152
20  151
20  150
21  150
21  149


И вот эти пустые строки между группами ну никак не могу отловить. Я даже и пробел пробовал записть out << ' ' << endl; и еще как-то .... ну не знаю прям....
3
07 сентября 2006 года
Green
4.8K / / 20.01.2000
У меня отлично работает.
А покажи код парсера.
1.8K
07 сентября 2006 года
Andreww
81 / / 02.01.2004
Код парсера ваш. Сначала вот определяем функцию:
 
Код:
bool isWhitespace(const string& str)
 {
       return (str.find_first_not_of(" \t\v\r\n") == string::npos);
 };

А потом обрабатываем файл:
Код:
ifstream in("contours.txt");

while( !in.eof() ) {
        string str;
        getline(in, str);
        if( isWhitespace(str) ) {
       
         // process data

        } else {

                istringstream is(str);
                int x, y;
                is >> x >> y;
                // store x, y
                    }
       }

Путем установки счетчика в if( isWhitespace(str) ) { // process data} было обнаружено что это условие выполняется только один раз.... я специально убрал свой код дабы не запутывать вас...
3
07 сентября 2006 года
Green
4.8K / / 20.01.2000
Я бы поставил точку останова на строку if( isWhitespace(str) )
и посмотрел бы как реагирует код на различные варианты str, т.е. смотрел бы содержимое str и как выполнится переход по условию.

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

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

P.S. Ну и на всякий случай список необходимых заголовочных файлов:
 
Код:
#include <string>
#include <fstream>
#include <sstream>
using namespace std;
1.8K
07 сентября 2006 года
Andreww
81 / / 02.01.2004
1. Код я действительно использую ваш, без добавлений. Просто я поудалял код внутри условий дабы не загромождать.
2. Поставил точку останова напротив if( isWhitespace(str) ) { и отследил какие значения принимает str. Оказалось, что если натыкаемся на пару чисел, то str принимает значение

{ 4294967295, { }, { "20\t21" } }

а если натыкаемся на пустую строку то

{ 4294967295, { }, { "" } }

Это нормально? Откуда тут куча скобочек и постоянно повторяющееся число 4294967295? Значение str я проверял через Run->Evaluate/Modify (это среда Builder 5).

3. В конце файла пустая строка как раз есть! Просто когда я постил сообщение в форум то потерял ее. И алгоритм действительно доходит сразу до самого конца...
1.8K
07 сентября 2006 года
Andreww
81 / / 02.01.2004
На крайний случай я вот придумал вместо пустой строки записывать пару чисел которых там в принципе быть не может, например 9999999999 9999999999 и потом ориентироваться на них. Вот такой псевдокод:
Код:
while( !in.eof() ) {
fscanf (считать пару чисел)        

        if( пара чисел == 99999999999 99999999999 ) {
       
         обрабатываем группу

        } else {

                сохранить эту пару чисел в базу
               
                    }
       }


Это конечно не так изящно, да и ламерством попахивает :-) но зато думаю будет работать. Если не будет, заканчиваю карьеру програмера :-)))))))
3
07 сентября 2006 года
Green
4.8K / / 20.01.2000
Мистика какая-то. У меня все отлично работает.
Может наведенная ошибка?
Попробуй упрстить программу по-максимому.
Например до такой:
Код:
#include <string>
#include <fstream>
#include <sstream>
using namespace std;

bool isWhitespace(const string& str)
{
    return (str.find_first_not_of(" \t\v\r\n") == string::npos);
}


int main()
{
    ofstream out("2.txt");
    for (int j = 0; j < 3; j++)
    {
        for (int i = 0; i < 3; i++)
        {
            out << 5 << '\t' << 6 << endl;
        }
        out << endl;
    }
    out.close();

    ifstream in("2.txt");
    while( !in.eof() ) {
        string str;
        getline(in, str);
        if( isWhitespace(str) ) {
            int y = 9;
            //
            // process data
            //
        } else {
            istringstream is(str);
            int x, y;
            is >> x >> y;
            // store x, y
        }
    }
}

и проверить, как будет работать в таком случае.
1.8K
08 сентября 2006 года
Andreww
81 / / 02.01.2004
Ой не говорите, цирк какой-то! Я вот только добавил cout << y << endl; чтобы в консоль вывело цифру 9 столько раз сколько есть пустых строк:
 
Код:
if( isWhitespace(str) ) {
            int y = 9;
            cout << y << endl;
            //
            // process data
            //
        }


и что? хе, хе... и ничего цифра 9 выводится 1 раз, хотя пустых строк три. Пора завязывать с этим ;-)
1.8K
08 сентября 2006 года
Andreww
81 / / 02.01.2004
В итоге остановился на ламерском способе -- записать в качестве разделителей отфонарные числа, которых в принципе в программе быть не может и ориентироваться по ним. Вроде работает. Но как говорится "неприятный осадок остался" ;-)
3
08 сентября 2006 года
Green
4.8K / / 20.01.2000
Как вариант, может быть проблема в используемой реализации STL.
3.0K
08 сентября 2006 года
Мerlin
267 / / 25.07.2006
[QUOTE=Green]Как вариант, может быть проблема в используемой реализации STL.[/QUOTE]Это легко может быть. На одном форуме, тоже кто-то жаловался, что не может удалить символ в string переменной. Работал на MS2003 и он тоже пришел к выводу, что STL виновата, так как код в MS2005 работал нормально.

Но а если вместо

if( isWhitespace(str) ) {

написать

if(str.length() < 3) {
?

Ведь сбоит эта ф-ия. Вообще-то из нее в данном случае польза нулевая.
3
08 сентября 2006 года
Green
4.8K / / 20.01.2000
Ну а если при создании или ручном редактировании файла пользователь вобьет троечку пробелов? Пробельные знаки - вещь особая... невидимая... ошибиться, как раз плюнуть.

Я бы для интереса убедился, что find_first_not_of работает неверно. Тогда можно было бы открыто говорить о баге в данной реализации STL.

А далее можно двинуться двумя путями:
1) сложный - воспользоваться другой реализацией STL;
2) простой - реализовать isWhitespace иначе, например, явным перебором всех знаков в строке и сравнении их с пробельными. Если доходим до конца строки не встретив ни одного непробельного символа, возвращаем true, иначе - false.
3
08 сентября 2006 года
Green
4.8K / / 20.01.2000
Кстати, попробуй так:
 
Код:
bool isWhitespace(const string& str)
{
    if (str.size() == 0) return true;
    return (str.find_first_not_of(" \t\v\r\n") == string::npos);
}

если не поможет, то можно полностью переписать так:
Код:
bool isWhitespace(const string& str)
{
    for(int i = 0; i<str.size(); ++i) {
        switch(str)
        {
        case ' ':
        case '\t':
        case '\v':
        case '\r':
        case '\n':
            break;

        default:
            return false;
        }
    }

    return true;
}
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог