Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > C++ Builder
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 05.07.2011, 14:40   #1
tiger()
Пользователь
 
Регистрация: 09.04.2011
Сообщений: 49
По умолчанию файловые потоки in

в упор не понимаю где собака порылась...

есть два файла, в которых нужно подсчитывать количество строк, делаю в потоке:
Код:
ifstream new_in, vocabulary_in;
по Check Box-ам определяется, какие файлы должны быть открыты. Если стоит одна галочка, вывести кол-во строк в первом файле, если другая - во втором, если обе - их сумма.

Положение галочек харится в массиве config, а открытые потоки - в массиве streams:

Код:
bool config[2];
bool streams[2];

config[0] = config[1] = 0;
streams[0] = streams[1] = 0;

if (Check_Box1->Checked) config[0] = 1;
if (Check_Box2->Checked) config[1] = 1;
Есть две функции - OpenFiles(); и CloseFiles();, которые открывают и закрывают нужные потоки.

Код:
void OpenFiles(void)
{
if (config[0]) 
   {
    streams[0] = 1;
    new_in.open("file1.txt");
   }
if (config[1])
   {
    streams[1] = 1;
    vocabulary_in.open("file2.txt");
}


void CloseFiles(void)
{
if (streams[0])
   {
    streams[0] = 0;
    new_in.close();
   }
if (streams[1])
   {
    streams[1] = 1;
    vocabulary_in.close();
   }
}

Проблема: если открывать и закрывать подряд один и тот же поток, он работает нормально. Когда включаю в работу функции CloseFiles и OpenFiles, после изменения галочек когда-то открытые потоки уже не считываются.

С чем это может быть связано? Если ли у потоков какие-нибудь особенные хитрости?
tiger() вне форума Ответить с цитированием
Старый 05.07.2011, 15:17   #2
Dogmat
Пользователь
 
Регистрация: 12.06.2008
Сообщений: 76
По умолчанию

Цитата:
Сообщение от tiger() Посмотреть сообщение
после изменения галочек когда-то открытые потоки уже не считываются.
Вы на все 100% уверены, что "когда-то открытые" потоки не закрывались? По описанию ничего не вижу. Может собака все-таки зарыта неподалеку от управляющих контролов? Попробуйте в определенных местах кода понатыкать ifstream::good() (прошу прощения - is_open() вернее), повторите действия, при которых возникает вопрос и посмотрите, соответствуют ли ваши ожидания действительности. Не знаю, в каких ситуациях потоки могут закрываться, но если существует такая завидная тенденция, то, может быть, это все-таки их закрывает один из обработчиков ваших контролов?

Последний раз редактировалось Dogmat; 05.07.2011 в 16:01.
Dogmat вне форума Ответить с цитированием
Старый 06.07.2011, 09:26   #3
tiger()
Пользователь
 
Регистрация: 09.04.2011
Сообщений: 49
По умолчанию

Цитата:
Сообщение от Dogmat Посмотреть сообщение
Вы на все 100% уверены, что "когда-то открытые" потоки не закрывались? По описанию ничего не вижу. Может собака все-таки зарыта неподалеку от управляющих контролов? Попробуйте в определенных местах кода понатыкать ifstream::good() (прошу прощения - is_open() вернее), повторите действия, при которых возникает вопрос и посмотрите, соответствуют ли ваши ожидания действительности. Не знаю, в каких ситуациях потоки могут закрываться, но если существует такая завидная тенденция, то, может быть, это все-таки их закрывает один из обработчиков ваших контролов?
понатыкал, проверил в какие моменты открыты и закрыты потоки, все по тексту. то есть после изменения состояния Box-ов старые потоки закрываются и новые открываются. но работает только новый. те которые когда-то были открыты перестают работать.

вот текст самого подсчета строк:

Код:
void TMain_Form::Count(void)
{
        whole_length = 0;

        if (config[0])
                while (getline(new_in, S))
                {
                        whole_length++;
                }
        if (config[1])
                while (getline(vocabulary_in, S))
                {
                        whole_length++;
                }
ps что такое контрол?

---------------

как в реальности получается:
например, поставить галочку на new, подсчитать, убрать галочку, подсчитать (должен быть 0 и поток закрыт), потом снова открыть и посчитать.

config[0] == 1
streams[0] == 1
new_in.is_open() == 1
строки подсчитаны правильно

config[0] == 0
streams[0] == 0
new_in.is_open() == 0
строки == 0

config[0] == 1
streams[0] == 1
new_in.is_open() == 1
но строки == 0

Последний раз редактировалось tiger(); 06.07.2011 в 09:42.
tiger() вне форума Ответить с цитированием
Старый 06.07.2011, 10:23   #4
evg_m
Старожил
 
Регистрация: 20.04.2008
Сообщений: 5,527
По умолчанию

-------------------------------------------
программа — запись алгоритма на языке понятном транслятору

Последний раз редактировалось evg_m; 06.07.2011 в 10:34.
evg_m на форуме Ответить с цитированием
Старый 06.07.2011, 11:41   #5
tiger()
Пользователь
 
Регистрация: 09.04.2011
Сообщений: 49
По умолчанию

В общем, максимально упростил все и задача сузилась до такого:

Код:
if (new_in.is_open()) new_in.close();
if ((new_Check_Box->Checked) && (new_in.is_open() == 0)) new_in.open(file1);
 
whole_length = 0;
 
while (getline(new_in, S))
                   whole_length++;
 
//вывод значения
Ставлю галочку - считает правильно. Убираю - пишет 0, все правильно. Ставлю снова - 0.
tiger() вне форума Ответить с цитированием
Старый 06.07.2011, 23:24   #6
Dogmat
Пользователь
 
Регистрация: 12.06.2008
Сообщений: 76
По умолчанию

Посмотрел я в чем дело. Но не понял по какой причине происходит. Не закрываются потоки почему-то. По скольку полный исходный код вы нам не продемонстрировали, составил сбственный с фрагментами вашего, но с некоторыми отличиями.
Шестой Builder:

header
Код:
#ifndef Unit1H
#define Unit1H

#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <fstream>
#include <string>

using namespace std;

class TMainForm: public TForm
{
__published:
    void __fastcall CalcBtnClick(TObject *Sender);
    void __fastcall CheckBoxClick(TObject *Sender);
public:
    __fastcall TMainForm(TComponent *Owner);
    __fastcall ~TMainForm();
protected:
private:
    void UpdateCheckState();
    void OpenFiles();
    void CloseFiles();
    int CalculateLines();

    TGroupBox *GroupBox;
    TButton *CalcBtn;
    TCheckBox *F1CheckBox;
    TCheckBox *F2CheckBox;

    bool config[2];
    bool streams[2];

    ifstream new_in;
    ifstream vocabulary_in;
};

extern PACKAGE TMainForm *MainForm;

#endif
source
Код:
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"

#pragma package(smart_init)
#pragma resource "*.dfm"
TMainForm *MainForm;

__fastcall TMainForm::TMainForm(TComponent* Owner): TForm(Owner)
{
    AnsiString checkBox1Caption = "Calc for file1";
    AnsiString checkBox2Caption = "Calc for file2";
    int space(5);
    int checkBoxWidth = 20 + Canvas->TextWidth(checkBox1Caption);
    int checkBoxHeight = Canvas->TextHeight(checkBox1Caption);
    int groupBoxWidth = space + checkBoxWidth + space;
    int groupBoxHeight = 2 * space + checkBoxHeight + space + checkBoxHeight + space;
    int buttonWidth = groupBoxHeight - space;
    int buttonHeight = buttonWidth;

    GroupBox = new TGroupBox(this);
    GroupBox->Parent = this;
    GroupBox->Name = "GroupBox";
    GroupBox->Caption = "";
    GroupBox->Width = groupBoxWidth;
    GroupBox->Height = groupBoxHeight;
    GroupBox->Top = space;
    GroupBox->Left = space;
    GroupBox->Tag = 0;

    F1CheckBox = new TCheckBox(GroupBox);
    F1CheckBox->Parent = GroupBox;
    F1CheckBox->Name = "File1CheckBox";
    F1CheckBox->Caption = checkBox1Caption;
    F1CheckBox->Width = checkBoxWidth;
    F1CheckBox->Height = checkBoxHeight;
    F1CheckBox->Top = 2 *space;
    F1CheckBox->Left = space;
    F1CheckBox->Tag = 0;
    F1CheckBox->OnClick = CheckBoxClick;

    F2CheckBox = new TCheckBox(GroupBox);
    F2CheckBox->Parent = GroupBox;
    F2CheckBox->Name = "File2CheckBox";
    F2CheckBox->Caption = checkBox2Caption;
    F2CheckBox->Width = checkBoxWidth;
    F2CheckBox->Height = checkBoxHeight;
    F2CheckBox->Top = F1CheckBox->Top + F1CheckBox->Height + space;
    F2CheckBox->Left = space;
    F2CheckBox->Tag = 1;
    F2CheckBox->OnClick = CheckBoxClick;

    CalcBtn = new TButton(this);
    CalcBtn->Parent = this;
    CalcBtn->Name = "CalculateButton";
    CalcBtn->Caption = "Start";
    CalcBtn->Width = buttonWidth;
    CalcBtn->Height = buttonHeight;
    CalcBtn->Top = space + GroupBox->Top;
    CalcBtn->Left = GroupBox->Left + GroupBox->Width + space;
    CalcBtn->Tag = 1;
    CalcBtn->OnClick = CalcBtnClick;

    this->ClientWidth = space + groupBoxWidth + space + buttonWidth + space;
    this->ClientHeight = space + groupBoxHeight + space;

    config[2] = config[1] = false;
    streams[2] = streams[1] = false;
}

__fastcall TMainForm::~TMainForm()
{
}

void __fastcall TMainForm::CalcBtnClick(TObject *Sender)
{
    OpenFiles();
    Caption = AnsiString("Result == ") + CalculateLines();
    CloseFiles();
}

int TMainForm::CalculateLines()
{
    string S;
    int whole_length(0);

    if (config[0])
    {
        while (getline(new_in, S))
                whole_length++;
    }

    if (config[1])
    {
        while (getline(vocabulary_in, S))
                whole_length++;
    }

    return whole_length;
}

void __fastcall TMainForm::CheckBoxClick(TObject *Sender)
{
    UpdateCheckState();
}

void TMainForm::UpdateCheckState()
{
    config[0] = F1CheckBox->Checked;
    config[1] = F2CheckBox->Checked;
}

void TMainForm::OpenFiles()
{
    if (config[0])
    {
        new_in.open("D:\\file1.txt", ios_base::in);
        streams[0] = new_in.is_open();
    }

    if (config[1])
    {
        vocabulary_in.open("D:\\file2.txt", ios_base::in);
        streams[1] = vocabulary_in.is_open();
    }
}

void TMainForm::CloseFiles()
{
    if (streams[0])
    {
        new_in.close(); // (!!!)
        streams[0] = !new_in.is_open();
    }

    if (streams[1])
    {
        vocabulary_in.close(); //(!!!)
        streams[1] = !vocabulary_in.is_open();
    }
}
Dogmat вне форума Ответить с цитированием
Старый 06.07.2011, 23:24   #7
Dogmat
Пользователь
 
Регистрация: 12.06.2008
Сообщений: 76
По умолчанию

tiger(), обратите внимание, как я инициализирую массив streams
Код:
    if (streams[0])
    {
        new_in.close();
        streams[0] = !new_in.is_open();
    }
А не как у вас streams[0] = false (а вернее 0); Такой код как раз показал, что рано еще присваивать false). Поток по какой-то причине не закрывается. Поскольку поток не закрыт, его открытие не произойдет (даже если stream[0] = streams[1] = true), а указатель так и останется в позиции eof. По этой причине все последующие попытки подсчитать число строк выдают количество равное 0 (whole_length == 0). При этом потоки постоянно висят открытыми.

Для себя поэкспериментировал с совсем уж простыми примерами, потоки нормально открываются и закрываются в VisualStudio, затем в Builder - тоже. В чем здесь проблема сам понять не могу. Ребята, подскажите, по какой причине потоки могут не закрываться. Самому теперь интересно. Код рабочий, можете прям так копировать.

Последний раз редактировалось Dogmat; 06.07.2011 в 23:33.
Dogmat вне форума Ответить с цитированием
Старый 06.07.2011, 23:28   #8
Dogmat
Пользователь
 
Регистрация: 12.06.2008
Сообщений: 76
По умолчанию

если вместо:
Код:
    if (streams[0])
    {
        new_in.close();
        streams[0] = !new_in.is_open();
    }

    if (streams[1])
    {
        vocabulary_in.close();
        streams[1] = !vocabulary_in.is_open();
    }
использовать:

Код:
    if (streams[0])
    {
        new_in.clear();
        new_in.close();
        streams[0] = !new_in.is_open();
    }

    if (streams[1])
    {
        vocabulary_in.clear();
        vocabulary_in.close();
        streams[1] = !vocabulary_in.is_open();
    }
тогда работать будет.

Последний раз редактировалось Dogmat; 06.07.2011 в 23:33.
Dogmat вне форума Ответить с цитированием
Старый 07.07.2011, 09:21   #9
tiger()
Пользователь
 
Регистрация: 09.04.2011
Сообщений: 49
По умолчанию

Dogmat, с clear() действительно все заработало.
Похоже в процессе вызова разных функций ставятся какие-то флаги.
Потоки на самом деле закрываются, я проверял is_open(). И открываются. Наврное, как Вы сказали, стоят на конце файла.
Большое спасибо!!
tiger() вне форума Ответить с цитированием
Старый 07.07.2011, 11:18   #10
Dogmat
Пользователь
 
Регистрация: 12.06.2008
Сообщений: 76
По умолчанию

Нашел у себя ошибку:

Вместо
Код:
streams[0] = !new_in.is_open();
и
Код:
streams[1] = !vocabulary_in.is_open();
нужно
Код:
streams[0] = new_in.is_open();
и
Код:
streams[1] = vocabulary_in.is_open();
У меня работает без всяких clear(), причем в любом случае, хоть с ошибкой, хоть без ошибки, потому как поток открывается в соответствии с состоянием config[i], а закрывается поскольку streams[i] у меня (если с ошибкой) всегда оставался равен true. Что вчера не так было теперь вообще не ясно ))).

А у вас в первом сообщении:
Код:
if (streams[0])
   {
    streams[0] = 0;
    new_in.close();
   }
if (streams[1])
   {
    streams[1] = 1;
    vocabulary_in.close();
   }
Может в этом у вас ошибка?

Последний раз редактировалось Dogmat; 07.07.2011 в 12:10.
Dogmat вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Файловые системы с++ и с _Art_ Общие вопросы C/C++ 4 28.02.2011 18:09
Файловые потоки &&blad&& Общие вопросы Delphi 4 05.02.2011 18:22
Файловые потоки. dixonich Операционные системы общие вопросы 6 06.01.2011 19:35
файловые потоки Crab2 Общие вопросы C/C++ 6 22.06.2010 09:39
задача на файловые потоки в C++ Klyan Помощь студентам 1 06.01.2008 01:49