Автор Тема: ifstream  (Прочитано 2749 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн ioann.sys

ifstream
« : 04 Июля 2015, 08:58:10 »
Доброе утро!
Требуется прочесть файл настроек, и в дальнейшем его парсить.

И тут я встрял... не вижу таких базовых методов, как ifstream::good() или хотя бы ifstream::eof(). Только is_open(). Как жить?
Debian GNU/Linux jessie/sid on notebook ASUS N750JK
 

Оффлайн vic5710

Re: ifstream
« Ответ #1 : 04 Июля 2015, 09:54:35 »
 
Пользователи, которые поблагодарили этот пост: ioann.sys

Оффлайн ioann.sys

Re: ifstream
« Ответ #2 : 04 Июля 2015, 10:10:34 »
все там есть
http://kvodo.ru/urok-10-1-rabota-s-tekstovyimi-faylami-v-c.html

Спасибо конечно, но это я знаю и пытался применить. Базовый клас std::ios изменен и переименован в std::ios_base.

p.s.: C++11;
Debian GNU/Linux jessie/sid on notebook ASUS N750JK
 

Оффлайн vic5710

Re: ifstream
« Ответ #3 : 04 Июля 2015, 13:42:48 »
тогда я не в курсе. но  как вариант можно применять С-функции - fopen,fread,fwrite,fclose. там все классически

Cообщение объединено 04 Июля 2015, 17:36:32
вот еще что-то
http://habrahabr.ru/post/246257/
« Последнее редактирование: 04 Июля 2015, 17:36:32 от vic5710 »
 

Оффлайн smallNix

Re: ifstream
« Ответ #4 : 06 Июля 2015, 21:30:04 »
ioann.sys, кто так пишет??? Сначала надо поздороваться. Потом  описать проблему и ОБЯЗАТЕЛЬНО указать техническую сторону вопроса!!! Какой язык программирования, какой компилятор, какая ОС. Мы должны догадаться по твоему первому сообщению? Твой сарказм во втором сообщении не имеет под собой оснований, т.к. ты ничего не указал ранее, спасибо, что сподобился написать, что надо под C++ 11.
Теперь перейдём к самой проблеме: проблемы нет вовсе.
 Под Debian 8, g++ 4.9.2  делаем следущее:
1) Создаём файл 1.dat с содержимым:
John Smith 1
John Smith 2
John Smith 3
John Smith 4
John Smith 5
John Smith 6

потом в этом же каталоге создаём файл main.cpp :
#include <iostream>
using std::cout;
using std::cin;
using std::endl;

#include <fstream>
using std::ifstream;
using std::ios;

int main (int argc, char** argv) {
 ifstream inner ("1.dat", ios::in);
 if (!inner) {
  cout << "Не удалось создать файл!\n";
  return -1;
 }
 char name [30];
 char lastName [30];
 int brainPoints = 0;
 while (inner >> name >> lastName >> brainPoints) {
  cout << name << " " << lastName << " " <<  brainPoints << endl;
 }

 return 0;
}

Собираем так:
g++ -c -std=c++11 main.cpp && g++ -o prog main.o && ./prog

Всё работает. Проверено. Тему можно закрыть.  :P
Кто-то же должен что-то делать...
 

Оффлайн ioann.sys

Re: ifstream
« Ответ #5 : 06 Июля 2015, 23:21:49 »
smallNix, по-порядку...
кто так пишет???
Я  ;D


Сначала надо поздороваться.
А что, доброе утро (в первом посте) не считается за приветствие?

Потом  описать проблему и ОБЯЗАТЕЛЬНО указать техническую сторону вопроса!!! Какой язык программирования, какой компилятор, какая ОС.
ifstream. Я искренне надеялся, что "крестоносцы" сразу поймут)). Какая может быть речь об OS, если пост на форуме debianforum.ru


вой сарказм во втором сообщении не имеет под собой оснований, т.к. ты ничего не указал ранее, спасибо, что сподобился написать, что надо под C++ 11.
Это был не сарказм.

На счёт кода:
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
    ifstream f("filename"); // для ifstream не обязательно указывать ios_base::in
    if( !f.is_open() )
    {
      clog << "error" << endl;
    }

    string buffer;
    while( getline(f, buffer) )
    {
      // здесь парсинг буффера
    }

f.close();
return 0;
}


smallNix, и тебе спасибо!


p.s.: я сначала держал настройки приложения в глобальной структуре, а теперь "курю" map.
Debian GNU/Linux jessie/sid on notebook ASUS N750JK
 

Оффлайн smallNix

Re: ifstream
« Ответ #6 : 07 Июля 2015, 01:19:18 »
C++, структура...  ;D Может лучше класс? Хотя можно и структуру если так удобнее. Настройки можно дерхать в любой удобной форме, хоть в хэш таблице.  :) Не знаю какую библиотеку ты используешь (и используешь ли вообще), но в QT, например, есть прекрасный класс (по моему QSettings), это очень удобно, да и про сереализацию посмотри.

Cообщение объединено 07 Июля 2015, 01:30:15
Если напишешь класс, потом сможешь его перенести в другие проекты.

Cообщение объединено 07 Июля 2015, 01:37:35
Цитировать
if( !f.is_open() )
{
 clog << "error" << endl;
}

Зачем так проверять? Моя проверка быстрее. Хотя не настаиваю.
Цитировать
while( getline(f, buffer) )
Мне кажется это имеет смысл только если у тебя сложный парсинг. Если у тебя простые строки, как в моём примере, то данные без усилий попадают в переменные.

Cообщение объединено 07 Июля 2015, 15:06:26
Цитировать
Базовый клас std::ios изменен и переименован в std::ios_base
Глянул ради интереса - это не правда:
http://stackoverflow.com/questions/19128054/ios-and-ios-base-class-for-stream-formatting

Ещё замечание:
Цитировать
if( !f.is_open() )
{
 clog << "error" << endl;
}
если файл не получилось открыть на чтение (нет файла, права не те и т.д.), то ты попытаешься обратиться к методу неинициализированного объекта - всё развалится )))
« Последнее редактирование: 07 Июля 2015, 15:06:26 от smallNix »
Кто-то же должен что-то делать...
 

Оффлайн ioann.sys

Re: ifstream
« Ответ #7 : 09 Июля 2015, 19:19:30 »
smallNix, решил воспользоваться твоим приложением и "оформить" настройки в виде класса.

Код: ("C++/main.cpp") [Выделить]
#include "global"

int main()
{
    app_settings.show();
    return 0;
}


Код: ("global") [Выделить]
#ifndef _APP_GLOBAL_
#define _APP_GLOBAL_

// prototype
class _c_app_settings
{
public:
    _c_app_settings(string);
    void show(void);

private:
    map<string, string> data;
    ifstream f;
};



// А здесь его реализация
_c_app_settings::_c_app_settings(string FILENAME_SETTINGS = "settings.ini")
{
    cout << "Конструктор вызван!" <<  endl;
    f.open(FILENAME_SETTINGS.c_str());
    if (!f.is_open())
    {
        // Кстати, на счёт твоего замечания: этот код для краткости. На самом деле, в проекте используются исключения и различные проверки.
        // в общем, к таким критичным "мелочам", попрошу не придераться))
        clog << "error" << endl;
        return; // чтобы всё не развалилось)))
    }
 
    // начинаем парсить файл и внутренними (приватными) методами загонять настройки в карту data;
    // code here
}


// Показ текущей конфигурации
void _c_app_settings::show_values()
{
    for (map<string, string>::iterator it = data.begin(); it != data.end(); it++)
    {
        cout << it->first << " : " << it->second << endl;
    }

    return;
}

// а теперь  ВНИМАНИЕ!
// создаём глобальный объект
_c_app_settings app_settings1;    // OK
_c_app_settings app_settings2("settings.ini"); // OK
_c_app_settings app_settings3(); NOT OK

С таким раскладом, всё работает. Но есть вызывать пустой конструктор (), то так не работает.
Debian GNU/Linux jessie/sid on notebook ASUS N750JK
 

Оффлайн smallNix

Re: ifstream
« Ответ #8 : 09 Июля 2015, 23:20:45 »
 Заставил меня вспоминать и копаться  ;D
Ответ на твой вопрос:
http://stackoverflow.com/questions/877523/error-request-for-member-in-which-is-of-non-class-type
И тут
http://stackoverflow.com/questions/16364116/request-for-member-which-is-of-non-class-type
Если кратко - ты всех путаешь: система сборки думает, что ты определяешь функцию app_settings3() возвращающую объект типа _c_app_settings. Для вызова по умолчанию следует использовать
_c_app_settings app_settings1;

Если попробуешь собрать такой файлик:
  1 #include <iostream>
  2 using std::cout;
  3 using std::endl;
  4 #include <cstring>
  5 using std::string;
  6
  7
  8 class class1 {
  9 public:
 10  class1 (string fName = "1.dat");
 11  void show ();
 12 private:
 13  string fileName;
 14 };
 15
 16
 17 class1::class1 (string fName) {
 18  fileName = fName;
 19 }
 20
 21 void class1::show () {
 22  cout << "fileName = " << fileName << endl;
 23 }
 24
 25
 26
 27 int main () {
 28  class1 obj1;
 29  class1 obj2 ("2.dat");
 30 
 31  class1 obj3 ();
 32 
 33  obj1.show ();
 34  obj2.show ();
 35  obj3 ();
 36  cout.flush ();
 37  return 0;
 38 }

То всё соберётся, но линковщик не сможет найти реализацию функции obj3. Однако, такой трюк с динамической памятью уже проходит. Следующий вариант работает хорошо:
1 #include <iostream>
  2 using std::cout;
  3 using std::endl;
  4 #include <cstring>
  5 using std::string;
  6
  7
  8 class class1 {
  9 public:
 10  class1 (string fName = "1.dat");
 11  void show ();
 12 private:
 13  string fileName;
 14 };
 15
 16
 17 class1::class1 (string fName) {
 18  fileName = fName;
 19 }
 20
 21 void class1::show () {
 22  cout << "fileName = " << fileName << endl;
 23 }
 24
 25
 26
 27 int main () {
 28  class1 obj1;
 29  class1 obj2 ("2.dat");
 30 
 31  class1* obj3 = new class1 ();
 32 
 33  obj1.show ();
 34  obj2.show ();
 35  obj3->show ();
 36  cout.flush ();
 37  return 0;
 38 }



 Теперь пара мелких замечаний:
1) Лично я всегда разделяю интрефйесную часть и реализацию на два файла (.h и .cpp), используя стражи включения.
2) Параметры по умолчанию всегда только в интерфейсной части.

P.S.: Я не придираюсь, а стараюсь помочь: увидел опасное место - сообщил  ;)
 
Кто-то же должен что-то делать...
 
Пользователи, которые поблагодарили этот пост: ioann.sys

Оффлайн ioann.sys

Re: ifstream
« Ответ #9 : 23 Августа 2015, 01:11:36 »
smallNix, опять нужны твои объяснения на следующий вопрос:
Почему я получаю ошибку сегментирования, если пытаюсь объявить глобальную переменную за пределами фунции main?
То есть, есть три файла c_settings.h, c_settings.cpp и main.cpp.

Код: (C++) [Выделить]
#include <iostream>
#include "c_settings.h"
using namespace std;

c_settings app_settings; // получается ошибка сегментирования

int main()
{
//c_settings app_settings; // а внутри функции - всё отлично.
app_settings.show();
return 0;
}
Debian GNU/Linux jessie/sid on notebook ASUS N750JK
 

Теги: