2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




Начать новую тему Ответить на тему На страницу Пред.  1, 2, 3, 4
 
 Re: Помогите разобраться, как работать с файлами на C++
Сообщение27.08.2012, 09:59 
Заслуженный участник
Аватара пользователя


12/10/05
478
Казань
Вставлю свои 5 копеек. :) Лично я всегда использовал связку fread + filelength для получения всего файла, а потом выполнял разбор полученного массива байт:
код: [ скачать ] [ спрятать ]
Используется синтаксис C++

#include <stdio.h>

using namespace std;

list<string> parseFile(const string & filename)
{
    list<string> res;
    FILE *fid;
    fid = fopen(filename.c_str(), "rt");
    if(fid = NULL)
        return res;/*можно наверно, исключение выкинуть, но когда-то я слышал, что в c++ лучше этого не делать. Возможно, с тех пор все изменилось*/
    long size = _filelength(fileno(fid));
    char *buf = new char[size+1];/*+1 в конце нужен что бы туда запихнуть нулевой символ.*/
    if(size !=fread(buf, 1, size, fid))
        return res;/*упс, что-то случилось - количество прочитанных байт меньше размера файла, но такого не должно быть.*/
    buf[size] = '\0';/*делаем из массива байт "null-terminated" - строку*/
    string str;
    str += buf;
    delete [] buf;
//Разбиваем данные по символам переноса строки:
    return splitStr(str, "\n");
}

list<string> splitStr(string str,  const char * delim)
{
    list<string> res;
    char *ptr;
    while( (ptr = strtok((char *)str.c_str()), delim) != NULL)
    {
        int len = strlen(ptr);
        if(len != 0)
        {
            string str(ptr);
            res.push_back();
            ptr+=len;
        }
        ptr++;
    }
    return res;
}

int main(int, char **)
{
      list<string> lines = parseFile("data.txt");
      if(lines.size() <= 0)
             return -1;
      list<list<string>> values;
      for(list::iterator it = lines.begin(), it != lines.end; it++)
      {
           values.push_back(splitStr(*it, " "));
      }
////////////
//Тут можно сделать разбор строк в values, используя функции strtol, strtod, strtof - в зависимости от того, что ожидается на входе
////////////
      return 0;
}
 


Решение длинновато, и я его написал по памяти - возможно, копмилироваться не будет, но думаю, смысл понятен. Я умышленно не использовал fscanf, для ввода и распознавания чисел из файла, поскольку на мой взгляд это самая неудобная функция, которая есть в сишной библиотеке. scanf для ввода с консоли - еще куда ни шло, но для ввода из файла... Имхо, проще запомнить, какая функция преобразует строки в числа, нежели запомнить однобуквенные модификаторы, которые использует scanf/fscanf.

PS:
если для олимпиады длинно, то можно ф-ции parseFile и splitStr таскать с собой на флешке. :) Если конечно, это разрешается...
UPD:
исправил кое-какие ошибки в коде (не знаю, все или нет...)

 Профиль  
                  
 
 Re: Помогите разобраться, как работать с файлами на C++
Сообщение27.08.2012, 11:02 
Заслуженный участник
Аватара пользователя


12/10/05
478
Казань
Вот сейчас вроде правильно, с strtok запутался:
код: [ скачать ] [ спрятать ]
Используется синтаксис C++
#include <stdio.h>
 
using namespace std;
 
list<string> parseFile(const string & filename)
 {
     list<string> res;
     FILE *fid;
     fid = fopen(filename.c_str(), "rt");
     if(fid = NULL)
         return res;/*можно наверно, исключение выкинуть, но когда-то я слышал, что в c++ лучше этого не делать. Возможно, с тех пор все изменилось*/
     long size = _filelength(fileno(fid));
     char *buf = new char[size+1];/*+1 в конце нужен что бы туда запихнуть нулевой символ.*/
     if(size !=fread(buf, 1, size, fid))
         return res;/*упс, что-то случилось - количество прочитанных байт меньше размера файла, но такого не должно быть.*/
     buf[size] = '\0';/*делаем из массива байт "null-terminated" - строку*/
     string str;
     str += buf;
     delete [] buf;
 //Разбиваем данные по символам переноса строки:
     return splitStr(str, "\n");
 }
 
list<string> splitStr(string str,  const char * delim)
 {
     list<string> res;
     char *ptr = strtok((char *)str.c_str(), delim);
     while(ptr != NULL)
     {
             string str(ptr);
             res.push_back();
             ptr = strtok(NULL, delim);
     }
     return res;
 }
 
int main(int, char **)
 {
       list<string> lines = parseFile("data.txt");
       if(lines.size() <= 0)
              return -1;
       list<list<string>> values;
       for(list::iterator it = lines.begin(), it != lines.end; it++)
       {
            values.push_back(splitStr(*it, " "));
       }
 ////////////
 //Тут можно сделать разбор строк в values, используя функции strtol, strtod, strtof - в зависимости от того, что ожидается на входе
 ////////////
       return 0;
 }
 

 Профиль  
                  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 47 ]  На страницу Пред.  1, 2, 3, 4

Модераторы: Karan, Toucan, PAV, maxal, Супермодераторы



Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group