Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Не открывается файл, Дескриптор все время равен 0 
:(
    Опции темы
BlHol
Дата 6.4.2007, 14:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 126
Регистрация: 26.11.2005

Репутация: нет
Всего: нет



День добрый!
Коротенькая программка:

Код

#include <iostream>
#include <fstream>
using namespace std;

int get_int(int default_value);
char name[20];

int main() {
    char filename[81];
    int n;
    int age;
    int recsize = sizeof(name) + sizeof(int);
    

    cout << "Enter file name: ";
    cin.getline(filename, 80);

    // Open file for binary read and write.    

    fstream  fbin(filename, ios::binary | ios::in);
    if (!fbin) {
        cout << "Could not open file " << filename;
        return -1;
    }

//  Get record number to write to.

    cout << "Enter file record number: ";
    n = get_int(0);

    // Get data from end user.

    cout << "Enter name: ";
    cin.getline(name, 19);
    cout << "Enter age: ";
    age = get_int(0);

    // Write data to the file.
 
    fbin.seekp(n * recsize);
    fbin.write(name, 20);
    fbin.write(reinterpret_cast<char*>(&age), sizeof(int));
    fbin.close();
    return 0;
}

// Get integer function
// Get an integer from keyboard; return default
//  value if user enters 0-length string.
//
int get_int(int default_value) {
    char s[81];

    cin.getline(s, 80);
    if (strlen(s) == 0)
         return default_value;
    return atoi(s);
}



Так вот, binary файл не открывается, если его заранее не создать. Почему? 
Вопрос возник потому, что в случае с открытием текстового файла:

Код

#include <iostream>
#include <fstream>
using namespace std;

int main() {
    char filename[81];

    cout << "Enter a file name and press ENTER: ";
    cin.getline(filename, 80);
    ofstream file_out(filename);
    if (! file_out) {
        cout << "File " << filename << " could not be opened.";
        return -1;
    }
    cout << "File " << filename << " was opened.";
    file_out << "I am Blaxxon," << endl;
    file_out << "the cosmic computer." << endl;
    file_out << "Fear me.";
    file_out.close();
    return 0;
}


проблем не возникает, даже если такого файла не существует.

Помогите, пожалуйста.
Заранее спасибо.
С уважением.
PM MAIL   Вверх
Xenon
Дата 6.4.2007, 14:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1529
Регистрация: 12.4.2006

Репутация: 11
Всего: 50



BlHol, Ну так у тебя он открывается на чтение, а не на запись в первом случае.
Так должно быть
Код

fstream  fbin(filename, ios::binary | ios::out);



--------------------
user posted image  
PM MAIL   Вверх
vinter
Дата 6.4.2007, 14:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Explorer
****


Профиль
Группа: Завсегдатай
Сообщений: 2735
Регистрация: 1.4.2006
Где: Н.Новгород

Репутация: 13
Всего: 56



Цитата(BlHol @  6.4.2007,  14:17 Найти цитируемый пост)
проблем не возникает, даже если такого файла не существует.

потомучто он открывается на вывод, вот он тебе и создается! а в первом случае ты открываешь на ввод, а зачем создавать файл когда ты хочешь что-то читать? что ты будешь читать из вновь созданного файла??


--------------------
Мой блог
PM MAIL WWW   Вверх
Earnest
Дата 6.4.2007, 14:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 53
Всего: 183



Цитата(BlHol @  6.4.2007,  15:17 Найти цитируемый пост)
 fstream  fbin(filename, ios::binary | ios::in);

Ты пытаешься открыть файл на чтение (in), с чего бы ему создаваться?
А текстовый файл ты создаешь как выходной: ofstream.
Если тебе нужно только выводить информацию, оставь ofstream:
Код

ofstream  fbin(filename, ios::binary);



--------------------
...
PM   Вверх
BlHol
Дата 6.4.2007, 15:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 126
Регистрация: 26.11.2005

Репутация: нет
Всего: нет



Граждане, дико извиняюсь. При копировании кода потерял один кусочек. Строка выглядела так:

Код

fstream  fbin(filename, ios::binary | ios::in | ios::out);


Т.е. файл создается и на вход и на выход. (В книжке написано "с произвольной выборкой") А fbin, все равно, 0.




Еще раз прошу прощения.
Но что делать-то?
Заранее спасибо.
PM MAIL   Вверх
Xenon
Дата 6.4.2007, 15:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1529
Регистрация: 12.4.2006

Репутация: 11
Всего: 50



По-моему обойти ограничение можно будет либо очистив флаги  сразу же после создания файла - fbin.clear(), либо открыв файл так:
Код

fstream  fbin(filename, ios::binary | ios::out | ios::app | ios::in);

Но тогда любая белеберда будет открываться ...

Это сообщение отредактировал(а) Xenon - 6.4.2007, 15:49


--------------------
user posted image  
PM MAIL   Вверх
BlHol
Дата 6.4.2007, 15:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 126
Регистрация: 26.11.2005

Репутация: нет
Всего: нет



И еще, что интересно, когда закомментарил /*ios::in*/, все заработало нормально. Почему?
PM MAIL   Вверх
Xenon
Дата 6.4.2007, 15:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1529
Регистрация: 12.4.2006

Репутация: 11
Всего: 50



BlHol, Похоже что такая конструкция рассчитана на уже созданый файл (я имею ввиду ввод/вывод). При открытии файла на вывод он всегда создается, исключая ситуации когда это совершенно невозможно, либо установлены nocreate, или noreplace

Это сообщение отредактировал(а) Xenon - 6.4.2007, 15:58


--------------------
user posted image  
PM MAIL   Вверх
BlHol
Дата 6.4.2007, 16:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 126
Регистрация: 26.11.2005

Репутация: нет
Всего: нет



Спасибо.
Жду еще советов. 

Заранее спасибо.
PM MAIL   Вверх
apook
Дата 6.4.2007, 16:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 794
Регистрация: 12.7.2006

Репутация: 9
Всего: 23



если Buildere то есть
Код

ios::trunc // усечь до нулевой длинны
ios::app   //добавить в конец файла

а если Turbo C++
Код

ios::nocreate // не создавать файл



--------------------
Мои руки из дуба, голова из свинца ну и пусть ...
PM MAIL   Вверх
Xenon
Дата 6.4.2007, 16:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1529
Регистрация: 12.4.2006

Репутация: 11
Всего: 50



apook
А как nocreate поможет избавиться от проблемы?


--------------------
user posted image  
PM MAIL   Вверх
apook
Дата 6.4.2007, 16:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 794
Регистрация: 12.7.2006

Репутация: 9
Всего: 23



Цитата

Спасибо.
Жду еще советов. 

Я подумал что проблема решена и товарищ BlHol хочет
еще любой инфформации по этой теме  smile 


--------------------
Мои руки из дуба, голова из свинца ну и пусть ...
PM MAIL   Вверх
BlHol
Дата 6.4.2007, 17:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 126
Регистрация: 26.11.2005

Репутация: нет
Всего: нет



Естественно, хочет smile 
Проблема почти решена. Просто, пример из книжки не работает как нужно. Пришлось выкинуть ios::in, тогда файл создается. Если не выкидывать, то тогда нужно, чтобы файл уже был.
Просто, в книжке пишут, что конструкция fstream  fbin(filename, ios::binary | ios::in | ios::out);
пригодна и для записи и для чтения в (из) двоичный файл. Вот я и хочу понять, то ли в книге опечатка, то ли я где-то ошибаюсь.
PM MAIL   Вверх
Xenon
Дата 6.4.2007, 17:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1529
Регистрация: 12.4.2006

Репутация: 11
Всего: 50



BlHol, Все правильно, просто файл уже должен быть создан. При чем следует не забывать, что после записи перед чтением (и наоборот) необходимо сбрасывать биты состояния - fbin.clear();
PS. Книжка не Лафоре случайно?

Это сообщение отредактировал(а) Xenon - 6.4.2007, 17:34


--------------------
user posted image  
PM MAIL   Вверх
BlHol
Дата 7.4.2007, 10:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 126
Регистрация: 26.11.2005

Репутация: нет
Всего: нет



Цитата(Xenon @ 6.4.2007,  17:33)
Все правильно, просто файл уже должен быть создан. При чем следует не забывать, что после записи перед чтением (и наоборот) необходимо сбрасывать биты состояния - fbin.clear();
PS. Книжка не Лафоре случайно?

1. Вот меня и интересует. Почему, в случае с тектовым файлом он создается, а, в случае с binary нет. В том ли причина, что при записи в текстовый файл, я прямо указываю ofstream?
И что, значит в книге опечатка и нужно в 
Код

fstream fbin() 
указывать не все флаги, а только те, которые   нужны в данный момент, т.е. при записи в файл 
Код

ios::out
, а при чтении
Код

 ios::in
?
2. Книжка Оверленда, называется "С++ без страха".

С уважением.
PM MAIL   Вверх
Xenon
Дата 7.4.2007, 12:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1529
Регистрация: 12.4.2006

Репутация: 11
Всего: 50



BlHol, Да, если прямо пишешь ofstream файл создается, так как это аналогично fstream("...",ios::out) (как я уже говорил файл будет создан почти в любом случае, кроме недоступности исходного места, либо явного предписания nocreate или noreplace).
Указывать флаги можешь все, но тогда файл уже должен быть создан. Я так понимаю выходом в твоем случае будет хрень, типа:
Код

int main() {
    char filename[81];
    int n;
    int age;
    int recsize = sizeof(name) + sizeof(int);
    

    cout << "Enter file name: ";
    cin.getline(filename, 80);

    // Open file for binary read and write.    

    fstream  fbin;
    fbin.open(filename, ios::binary | ios::out);
    if (!fbin) {
        cout << "Could not open file " << filename;
        return -1;
    }
    fbin.close();
    fbin.clear();
    fbin.open(filename, ios::binary | ios::out | ios::in);
    /* И дальше по плану*/



--------------------
user posted image  
PM MAIL   Вверх
BlHol
Дата 7.4.2007, 15:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 126
Регистрация: 26.11.2005

Репутация: нет
Всего: нет



ВО!!!! Вот теперь все точки над Ё расставлены...
Спасибище огромадное...
С уважением.
PM MAIL   Вверх
BlHol
Дата 10.4.2007, 10:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 126
Регистрация: 26.11.2005

Репутация: нет
Всего: нет



Однако, здравствуйте!
Нарисовался следующий трабл...
Если файлика нет и мы открываем его на запись (только флаг ios::out), то при следующем открытии файла все существующие записи затираются.
Посему вопрос:
Каким образом проверяется существование файла?
Т.е. в итоге задачка такова: если файла нет, то он создается и в него что-то пишется, если он есть, то открывается таким образом, чтоыб его содержимое не уничтожалось.
Заранее спасибо.
С уважением...
PM MAIL   Вверх
dizzy1984
Дата 10.4.2007, 13:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 675
Регистрация: 15.2.2007

Репутация: 3
Всего: 25



Код

ofstream out(sFileName, ios_base::out|ios_base::app);

PM MAIL   Вверх
BlHol
Дата 10.4.2007, 14:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 126
Регистрация: 26.11.2005

Репутация: нет
Всего: нет



С чем сравнивается out  в данном случае?
PM MAIL   Вверх
JackYF
Дата 10.4.2007, 14:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


полуавантюрист
****


Профиль
Группа: Участник
Сообщений: 5814
Регистрация: 28.8.2004
Где: страна тысячи озё р

Репутация: 18
Всего: 162



Цитата(BlHol @  10.4.2007,  14:48 Найти цитируемый пост)
С чем сравнивается out


не понял вопроса...



--------------------
Пожаловаться на меня как модератора можно здесь.
PM MAIL Jabber   Вверх
zkv
Дата 10.4.2007, 15:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата



****


Профиль
Группа: Участник Клуба
Сообщений: 2133
Регистрация: 23.7.2006
Где: Санкт-Петербург

Репутация: 26
Всего: 92



Цитата(BlHol @  10.4.2007,  14:48 Найти цитируемый пост)
С чем сравнивается out  в данном случае? 

тут чтоли?
Цитата(dizzy1984 @  10.4.2007,  13:59 Найти цитируемый пост)
ofstream out(sFileName, ios_base::out|ios_base::app);


здесь ничего не сравнивается, только кроме устанавливаемого бита, определяемого ios::out также устанавливается бит ios::app (append,  "добавлять"), вместе они говорят о том, что файл будет открыт для дозаписи.
PM MAIL   Вверх
BlHol
Дата 10.4.2007, 16:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 126
Регистрация: 26.11.2005

Репутация: нет
Всего: нет



Дописываться будет в конец?
Дело в том, что в данный файл пишется с произвольной выборкой. Т.е. сейчас у меня запись №3, а при следующем открытии файла №1. 
PM MAIL   Вверх
Xenon
Дата 10.4.2007, 16:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1529
Регистрация: 12.4.2006

Репутация: 11
Всего: 50



BlHol, Да, указатель будет вставать в конец и дописываться по-любому будет в конец.
Мне кажется тут лучше сгружать все данные файла в память, манипулировать данными там, затем открывать файл и писать туда из памяти.


--------------------
user posted image  
PM MAIL   Вверх
BlHol
Дата 11.4.2007, 13:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 126
Регистрация: 26.11.2005

Репутация: нет
Всего: нет



Там задачка такая. Открывается файл, вводится номер записи и по этому номеру пишутся данные. Считывание происходит также по номеру записи (они идут по порядку от начала к концу файла). Фишка в том, что я могу сначала записать больший номер (скажем, 10), а затем меньший (например, 2) и одно не затрет другое. Поэтому, если открывать файл только с ios::binary | ios::out, то при следующем открытии новая инфа затирает старую. А если с ios::binary | ios::out | ios::in, то файл должен уже существовать. Вот и требуется, чтобы если файла нет, то он должен создаваться и открываться с   ios::binary | ios::out, а если он уже есть, то с ios::binary | ios::out | ios::in, чтобы не затирать то, что было записано при предыдущем открытии.
PM MAIL   Вверх
Xenon
Дата 11.4.2007, 18:05 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1529
Регистрация: 12.4.2006

Репутация: 11
Всего: 50



Так вот так можно. Можно штатными функциями WinApi проверять есть ли файл. Но можно, по-моему, вполне так - в итоге один фиг.
Код

std::fstream file("d:\\superfile.dat", std::ios::out | std::ios::in | std::ios::binary);
if (!file)
{
    file.clear();
    file.open("d:\\superfile.dat", std::ios::out | std::ios::binary);
    if (!file)
    {
        std::cout << "File could not be created";
        return 0;
    }
}
file.seekp(0, std::ios::beg);
/*Делай что хочешь*/



--------------------
user posted image  
PM MAIL   Вверх
BlHol
Дата 12.4.2007, 10:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 126
Регистрация: 26.11.2005

Репутация: нет
Всего: нет



Спасибо, но почему-то при использовании fbin.clear() не работает. Срабатывает только при закомментареном fbin.clear(). С чего бы это?
PM MAIL   Вверх
Xenon
Дата 12.4.2007, 16:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1529
Регистрация: 12.4.2006

Репутация: 11
Всего: 50



BlHol, у меня данный код работал должным образом. Флаги состояния, по идее, надо сбрасывать, так как если файла не будет существовать, нам будет всегда выбрасывать сообщение, мол, не могу создать файл.


--------------------
user posted image  
PM MAIL   Вверх
BlHol
Дата 17.4.2007, 11:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 126
Регистрация: 26.11.2005

Репутация: нет
Всего: нет



С вашего позволения, немного продолжу.
Попытался решить задачу через switch - case, т.е. предлагаю варианты (записи, чтения, выхода). В каждом из case реализую открытие файла сообразно выбранному варианту.
Почему-то выдает ошибку case bypasses initialization of local variable. Это к чему?
Заранее спасибо.
PM MAIL   Вверх
betal
Дата 17.4.2007, 11:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 208
Регистрация: 26.12.2006

Репутация: нет
Всего: 1



Цитата(Xenon @  6.4.2007,  14:39 Найти цитируемый пост)
BlHol, Ну так у тебя он открывается на чтение, а не на запись в первом случае.
Так должно быть

 smile  
Цитата(vinter @  6.4.2007,  14:39 Найти цитируемый пост)
потомучто он открывается на вывод, вот он тебе и создается! а в первом случае ты открываешь на ввод, а зачем создавать файл когда ты хочешь что-то читать? что ты будешь читать из вновь созданного файла?? 

smile 
Цитата(Earnest @  6.4.2007,  14:52 Найти цитируемый пост)
Ты пытаешься открыть файл на чтение (in), с чего бы ему создаваться?
А текстовый файл ты создаешь как выходной: ofstream.
Если тебе нужно только выводить информацию, оставь ofstream:
 smile 

блин по этому поводу и добавить т нечго. Приходится молча кивать головой smile 
--------------------
101100010100001101100001110100101111011легкие деньги
PM WWW ICQ   Вверх
BlHol
Дата 17.4.2007, 12:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 126
Регистрация: 26.11.2005

Репутация: нет
Всего: нет



Спасибо.
Теперь обнаружил следующий парадокс:
Из той программулины со switch-case привожу 2 case:

Код

switch(c)
        {
         case 1:
           
          cout<<"Warning! Used file will be rewriteble!"<<endl;
           fstream fbin(path, ios::binary | ios::out);

              while(1)
           {
            far = 0;
            int k=0;
           cout<<"Enter number of record (or -1 for exit): ";
           k = get_int(-1);

           if(k==-1)
           {
                cout<<"You entered -1. File will closed"<<endl;
                 break;
            }

          cout<<"Enter model of car: ";
          cin.getline(model_car,19);
          cout<<"Enter mark of car: ";
          cin.getline(mark_car,19);
          cout<<"Enter year of car: ";
          cin.getline(year_car,5);
          cout<<"Enter far of car: ";
           far = get_int(0);

          fbin.seekp(k*recsize);
          fbin.write(model_car,sizeof(model_car));
          fbin.write(mark_car,sizeof(mark_car));
          fbin.write(year_car,sizeof(year_car));
          fbin.write(reinterpret_cast<char*>(&far),sizeof(int));
           }

             fbin.close();
            break;
                
          case 2:
         
        fstream fbin_2(path, ios::binary | ios::out |ios::in);

            if(!fbin_2)
               {
                 cout<<"File "<<path<<" was not opened"<<endl;
                   break;
                }
               else
                cout<<"File "<<path<<" was opened for writing"<<endl;

                 while(1)
           {
            far = 0;
            int k=0;
           cout<<"Enter number of record (or -1 for exit): ";
       k = get_int(-1);

          if(k==-1)
           {
                cout<<"You entered -1. File will closed"<<endl;

                 break;
            }

         cout<<"Enter model of car: ";
          cin.getline(model_car,19);
          cout<<"Enter mark of car: ";
          cin.getline(mark_car,19);
          cout<<"Enter year of car: ";
          cin.getline(year_car,5);
          cout<<"Enter far of car: ";
          far = get_int(0);





          fbin_2.seekp(k*recsize);
          fbin_2.write(model_car,sizeof(model_car));
          fbin_2.write(mark_car,sizeof(mark_car));
          fbin_2.write(year_car,sizeof(year_car));
          fbin_2.write(reinterpret_cast<char*>(&far),sizeof(int));
           }
        fbin_2.close();
            break;
                 


Вот, когда в таком виде компиляю, выдается ошибка case bypasses initialization of local variable.
А когда я каждый блок в case замыкаю в {...} 
Код

case 1:
{

break;
}



ошибка пропадает.
Почкму так происходит?
Заранее спасибо.
С уважением.
PM MAIL   Вверх
zkv
Дата 17.4.2007, 15:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата



****


Профиль
Группа: Участник Клуба
Сообщений: 2133
Регистрация: 23.7.2006
Где: Санкт-Петербург

Репутация: 26
Всего: 92



Цитата(BlHol @  17.4.2007,  12:44 Найти цитируемый пост)
case bypasses initialization of local variable

что написано, то и значит. Нельзя перескакивать через объявление переменной, а когда ставите скобки, то делаете переменные локальные в новом "маленьком" блоке, таким образом не может возникнут "непонятных" для компилятора ситуаций. 
PM MAIL   Вверх
BlHol
Дата 17.4.2007, 19:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 126
Регистрация: 26.11.2005

Репутация: нет
Всего: нет



Я дико извиняюсь. Суть ошибки мне понятна. Мне непонятно, где я перескочил через инициализацию локальной переменной... Я имею в виду в том куске, который я привел выше.
Заранее спасибо.
С уважением.
PM MAIL   Вверх
zkv
Дата 17.4.2007, 21:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата



****


Профиль
Группа: Участник Клуба
Сообщений: 2133
Регистрация: 23.7.2006
Где: Санкт-Петербург

Репутация: 26
Всего: 92



BlHol, в вашем куске, простите, и черт ногу сломит.  Следует как то поудобнее все это дело организовать, километровые кэйсы - не лучший стиль smile 
Цитата(BlHol @  17.4.2007,  19:56 Найти цитируемый пост)
Мне непонятно, где я перескочил через инициализацию локальной переменной... Я имею в виду в том куске, который я привел выше.

обратите внимание на строку 6 вашего листинга.
Код

     fstream fbin(path, ios::binary | ios::out);

Вопросы есть?  smile 
PM MAIL   Вверх
BlHol
Дата 18.4.2007, 09:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 126
Регистрация: 26.11.2005

Репутация: нет
Всего: нет



Задачка так стоит. Организовать выбор варианта (открыть на запись, открыть на чтение, выход). И в зависимости от этого, соответственно открывать файл. Каким образом это можно еще реализовать. Не через if-else же?
Я правильно понимаю, что в case не должно быть объявления переменной и ее инициализации?
Кстати, ошибка выкидывается на второй case. Первый, несмотря на то, что там тоже присутствует fstream fbin(......), благополучно проглатывается.

Заранее спасибо.

Это сообщение отредактировал(а) BlHol - 18.4.2007, 09:29
PM MAIL   Вверх
zkv
Дата 18.4.2007, 10:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата



****


Профиль
Группа: Участник Клуба
Сообщений: 2133
Регистрация: 23.7.2006
Где: Санкт-Петербург

Репутация: 26
Всего: 92



Цитата(BlHol @  18.4.2007,  09:27 Найти цитируемый пост)
Организовать выбор варианта (открыть на запись, открыть на чтение, выход). 

первое, самое простое, что приходит в голову:
Код

switch(c)
{
    case 1:
        ReadData( /*Что то можно передать*/);       
     break;
                
    case 2:
        WriteData( /*Что то можно передать*/);       
    break;
//...
    default:
        printf("\nLets try again..."); 


Заметь, в таком случае подобным ошибкам просто нет места, да и читается проще. 
Цитата(BlHol @  18.4.2007,  09:27 Найти цитируемый пост)
Я правильно понимаю, что в case не должно быть объявления переменной и ее инициализации?
Кстати, ошибка выкидывается на второй case. Первый, несмотря на то, что там тоже присутствует fstream fbin(......), благополучно проглатывается.

попробуй убрать второй кейс - компилятор скажет, что все ок, проблема возникает, если существует возможность "перепрыгнуть" через инициализацию переменной (с goto такая же фигня вроде), сейчас я не возьмусь объяснять почему тут такое строгое ограничение (боюсь соврать). 
Думаю если чел сталкивается с подобной ошибкой, то у него явно проблемы с проектированием  smile  smile 
PM MAIL   Вверх
dizzy1984
Дата 18.4.2007, 10:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 675
Регистрация: 15.2.2007

Репутация: 3
Всего: 25



В конктетном случае организовать работу можно, например, так.
Определите fstream fbin до switch©, затем использйте fbin.Open
Либо определите fstream fbin(path, ios::binary | ios::out |ios::in) до свича, это определение позволит впоследствии как писать так и читать из  файла.
Цитата(BlHol @  18.4.2007,  09:27 Найти цитируемый пост)
Я правильно понимаю, что в case не должно быть объявления переменной и ее инициализации?

Правильно. 
Хотя нет, пардон, в первой ветке case можно определять переменные. Спасобо zkv за разъяснение.
Цитата(BlHol @  18.4.2007,  09:27 Найти цитируемый пост)
Кстати, ошибка выкидывается на второй case

Видимо компилятор приостанавливает проверку подобных ситуаций после появления первой.
Попробуйте исправить второй case и посмотреть проглотит ли компилятор после этого первый.

А на счет причины такого ограничения, может мне кто-нибудь напомнит почему нельзя перескакивать через определения локальных переменных. Я смутно что-то помню про проблемы с деструкторами, но не могу сообразить.

Это сообщение отредактировал(а) dizzy1984 - 18.4.2007, 10:29
PM MAIL   Вверх
BlHol
Дата 18.4.2007, 10:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 126
Регистрация: 26.11.2005

Репутация: нет
Всего: нет



Т.е. банально реализовать чтение, запись в разных функциях?
PM MAIL   Вверх
dizzy1984
Дата 18.4.2007, 11:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 675
Регистрация: 15.2.2007

Репутация: 3
Всего: 25



Разобрался.
Проблема заключается в том, что мы теоретически можем использовать fbin
в ветке case 2:, т.к все ветки switch относятся к одной области видимости.
Если fbin будет исользоваться  в case 2: и управление попадет туда минуя case 1, то переменная fbin будет использоваться будучи не проинициализированной. Это не запрещено в с, но запрещено в с++.
В этом свете сказанное ранее немного меняется. Объявлять переменные можно только в последней ветке switch (default), т.к перепрыгнуть через ние уже никак не получится. Остается неясным момент почему компилятор не может осущестить проверку на факт использования fbin в case2 и при отсутствии такового не выдавать ошибку.

Добавлено через 5 минут и 34 секунды
Цитата(BlHol @  18.4.2007,  10:49 Найти цитируемый пост)
Т.е. банально реализовать чтение, запись в разных функциях?

Если у тебя разница между этими ветками заключается только в том будут ли писаться или читаться данные, то однозначно тебе нужно писать фунцию с флагом определяющим действие в качестве аргумента.
PM MAIL   Вверх
BlHol
Дата 18.4.2007, 12:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 126
Регистрация: 26.11.2005

Репутация: нет
Всего: нет



Ну, не совсем так. У меня же в 1-м и во 2-м case разные переменные. В1-м fbin, во 2-м f_bin_2. Т.о. если мы даже и проскакиваем 1-й case, то f_bin и не инициализируется и не используется. Почему тогда нельзя?

По поводу функции. Я не совсем понял, флаг передавать в виде аргумента?

Заранее спасибо.
PM MAIL   Вверх
dizzy1984
Дата 18.4.2007, 13:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 675
Регистрация: 15.2.2007

Репутация: 3
Всего: 25



Цитата(BlHol @  18.4.2007,  12:17 Найти цитируемый пост)
 Почему тогда нельзя?

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

Цитата(BlHol @  18.4.2007,  12:17 Найти цитируемый пост)
По поводу функции


Пример

Функция осществляющая запись либо перезапись (???)
Код


void DoSomethingWithData(fstream & fbin, bool bFlag)
{
if (bFlag)
{
cout<<"Warning! Used file will be rewriteble!"<<endl;
}
else
{
if(!fbin)
{
cout<<"File "<<path<<" was not opened"<<endl;
break;
}
else
cout<<"File "<<path<<" was opened for writing"<<endl;
}
}

while(1)
{
far = 0;
int k=0;
cout<<"Enter number of record (or -1 for exit): ";
k = get_int(-1);

if(k==-1)
{
cout<<"You entered -1. File will closed"<<endl;
break;
}

cout<<"Enter model of car: ";
cin.getline(model_car,19);
cout<<"Enter mark of car: ";
cin.getline(mark_car,19);
cout<<"Enter year of car: ";
cin.getline(year_car,5);
cout<<"Enter far of car: ";
far = get_int(0);

fbin.seekp(k*recsize);
fbin.write(model_car,sizeof(model_car));
fbin.write(mark_car,sizeof(mark_car));
fbin.write(year_car,sizeof(year_car));
fbin.write(reinterpret_cast<char*>(&far),sizeof(int));
}

fbin.close();
}


Программа и свич, который ее использует
Код

fstream fbin(path, ios::binary | ios::out |ios::in);
//...
switch(c)
{
case 1:
DoSomethingWithData(fbin, true);
break;
case 2:
DoSomethingWithData(fbin, false);
break;
default:
printf("\nLets try again..."); 




Цитата

Warning! Used file will be rewriteble!

Ты хотел написать что файл будет перезаписан? Тогда это  будет "Warning! Used file will be rewritten"

Хорошая практика программирования говорит, что любую повторяющуюся последовательность действий, которая встречается более 2-х раз нужно оформлять в виде отдельной функции. Сам я правда ленюсь это делать и жду 3-х повторений.


PM MAIL   Вверх
BlHol
Дата 18.4.2007, 13:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 126
Регистрация: 26.11.2005

Репутация: нет
Всего: нет



В принципе, понятно, только тут во всех  case разные варианты открытия файла. В данном случае, не все ли равно, реализую ли я это в 3-х функциях или распихаю по case?

Заранее спасибо.
PM MAIL   Вверх
dizzy1984
Дата 18.4.2007, 15:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 675
Регистрация: 15.2.2007

Репутация: 3
Всего: 25



Очень может быть что вы сможете обойтись одной функцией для всех case.
Если хотите услышать мое мнение объясните программу целиком.
Конечно, нет смысла писать 3 функции для 3-х case. Нужно делать подобное если хотя бы 2-а из них логически можно объединить в 1-н.
Тогда вместо 3-х функции для 3-х case будут 2 функции.
Разница вот в чем : 
1. дальнейшие модификации повторяющихся фрагментов вам придется делать либо для каждого case, либо для одной функции с параметрами.
2. если ваш код предстоит разбирать другому программисту он должен потратить
время чтобы понять логику работы программы. Он сделает это быстрее если в
программе будет мало повторяющегося кода, а все похожее по смыслу будет
сведено в несколько функций.

PM MAIL   Вверх
nickless
Дата 18.4.2007, 15:38 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Гентозавр
****


Профиль
Группа: Участник Клуба
Сообщений: 2976
Регистрация: 29.8.2005
Где: Germany

Репутация: 19
Всего: 181



Цитата(dizzy1984 @  18.4.2007,  10:01 Найти цитируемый пост)
Объявлять переменные можно только в последней ветке switch (default)

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

Цитата(BlHol @  18.4.2007,  12:21 Найти цитируемый пост)
В данном случае, не все ли равно, реализую ли я это в 3-х функциях или распихаю по case?

Я бы сделал функции хотя бы для улучшения читабельности. Вообще рекомендуется не писать функции длинее одного экрана, а в твоём коде один только switch на 86 строк! У меня например столько в экран не помещается, в результате нужно протоянно скроллить вверх-вниз, чтобы посмотреть чем же заканчивается этот switch, сколько там веток итд. Да и вообще форматировать код очень важно.


--------------------
user posted image

Real men don't use backups, they post their stuff on a public ftp server and let the rest of the world make copies
- Linus Torvalds
PM MAIL   Вверх
dizzy1984
Дата 18.4.2007, 16:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 675
Регистрация: 15.2.2007

Репутация: 3
Всего: 25



Цитата(nickless @  18.4.2007,  15:38 Найти цитируемый пост)
Переменные можно объявлят где угодно, но желательно обрамить каждый case в блок, чтобы исключить перепрыгивание инициализации и соответствующие варнинги

Я неверно выразился. Подразумевал инициализировать только в последнем блоке. Ворнингов не будет, будут ошибки.
PM MAIL   Вверх
dizzy1984
Дата 19.4.2007, 05:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 675
Регистрация: 15.2.2007

Репутация: 3
Всего: 25



Цитата(BlHol @  18.4.2007,  12:17 Найти цитируемый пост)
Ну, не совсем так. У меня же в 1-м и во 2-м case разные переменные. В1-м fbin, во 2-м f_bin_2. Т.о. если мы даже и проскакиваем 1-й case, то f_bin и не инициализируется и не используется. Почему тогда нельзя?

Сегодня пока умывался еще раз подумал над этим.
Можно сказать что ты использешь ее, т.к вызываешь ее метод. 
В конце case перед закрывающейся фигурной скобкой ты неявно вызываешь деструктор.
Если предположить что в конструкторе ты делаешь что-то типа
Код

sName = new char [32];

а в деструкторе
Код

delete [] sName;

То при проскакивании первого case получится применение оператора delete [] к памяти, не выделенной оператором new. Это UB.
Запусти свою программу и у тебя может отформатироваться жесткий диск  smile 
В с нет конструкторов поэтому нельзя выполнить какие-либо существенные действия при инициализации.
Специально это сейчас проверил. Если конструктор локальных объектов пустой, он разрешает создавать их в ветках case.
Если он заполняется содержимым, появляются ошибки. На наличие деструктора компилятор внимания не обращает, оно и понятно он-то вызовется полюбому.
Вывод такой - если с помощью goto или switch() { case 1: case 2: ... case n} ты можешь перепрыгнуть через определение объекта с непустым конструктором, компилятор выведет ошибку. только в этом случае. переменные не объекты классов и объекты с пустым конструкотром его не волнуют.

PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.1787 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.