2014 dxdy logo

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

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




На страницу Пред.  1, 2, 3, 4
 
 Re: Помогите разобраться, как работать с файлами на C++
Сообщение27.08.2012, 09:59 
Аватара пользователя
Вставлю свои 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 
Аватара пользователя
Вот сейчас вроде правильно, с 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


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group