LINUX.ORG.RU

[c++] пробежаться по файлу и считать числа из строк

 


0

0

Есть текстовый файл вида

1 121
3 123
5 111

Надо считать все числа из него в массив. 3 раза я это делал и 3 раза по разному. В последний раз примерно так:

bool ReadFile()
{
    int i;
    if(!file.is_open())
    {
        file.open("data.txt",fstream::in);  //то открываем его
        
        if (file.fail())                    //возвращаем ошибку, если не смогли открыть
        {
            //соответствующий throw
        }
    }
    //тут считываем фигню
    if(file.eof())                      //если файл кончился, закрываем его и возвращаем false
    {
        file.close();
        return false;
    }
    //дописываем фигню в соответствующие массивы
    return true;
}

//соответственно, используется оно так:

while(ReadFile())
{
  //...
}

А как надо?

★★★★★

Последнее исправление: Obey-Kun (всего исправлений: 1)

вот уже скоро вам ответят знатоки

gavv
()
Ответ на: комментарий от Reset

симпатично, но если задача сложнее, например каждая строка имеет вид

[одно число] [ещё от одного до десяти чисел],

то уже не катит

Obey-Kun ★★★★★
() автор топика

[code] ifstream fin(«input.txt»); if (!fin) cerr << «can`t open file»; else { int temp; while (fin >> temp) cout << temp; //запихнуть в массив } [/code]

а так?

hired777
()
std::ifstream f("/path/to/file");

std::vector<int> arr;
std::copy(std::istream_iterator<int>(f), std::istream_iterator<int>(),
          std::back_inserter(arr));
archimag ★★★
()
Ответ на: комментарий от Reset

если использовать хороший tokenizer, то будет и короче и эффективнее, и чем просто на си, и чем flex

gavv
()

кстати, посмотрите file.exceptions(...)

gavv
()
Ответ на: комментарий от LamerOk

я понимаю, но в любом случае оно для такого:

[одно число] [ещё от одного до десяти чисел]

нафиг не нужно.

Для такого файла из того, что насоветовали выше, наверное использую c'шные fgets, strktok и atoi. Так быстрее. Не важна была бы скорость, использовал бы STL'ные фичи вместо них.

Obey-Kun ★★★★★
() автор топика
Ответ на: комментарий от Obey-Kun

> наверное использую c'шные fgets, strktok и atoi. Так быстрее

на самом деле тут и strtok не очень нужен, особенно, если надо побыстрее - просто «идешь» по строке попутно заменяя промежуточные ' ' на \0, а если хочется еще быстрее - то вместо fgets стоит загружать сразу большой блок из файла и при проходе по нему смотреть не только пробелы, но и \n

lester ★★★★
()
Ответ на: комментарий от lester

да, кстати, а как тут быть с кроссплатформенностью? у виндовских текстовых файлов строки, кажется, не на \n кончаются?

Obey-Kun ★★★★★
() автор топика
Ответ на: комментарий от Obey-Kun

> да, кстати, а как тут быть с кроссплатформенностью? у виндовских текстовых файлов строки, кажется, не на \n кончаются?

тогда еще на \r проверку надо( в винде \r\n )

lester ★★★★
()
Ответ на: комментарий от lester

> strtok не очень нужен, особенно, если надо побыстрее - просто «идешь» по строке попутно заменяя промежуточные ' ' на \0

strtok именно этим и занимается )))

LamerOk ★★★★★
()
Ответ на: комментарий от lester

ясно, спасибо.

А ведь ещё одна фигня есть. Файлы могут иметь или не иметь пустую строку в конце (как принято в мире posix).

Так что придётся ещё и проверку на пустую строку ввести.

Obey-Kun ★★★★★
() автор топика
Ответ на: комментарий от Obey-Kun

> Так что придётся ещё и проверку на пустую строку ввести.

просто после прохода указатель на начало текущей подстроки с NULL сравнить и если не NULL - добавить ее

lester ★★★★
()
Ответ на: комментарий от lester

> а мужики то не знают!

Для мужиков есть маны. )))

LamerOk ★★★★★
()
Ответ на: комментарий от enep

Сила может быть и грубая, но эффективная, да и программа пишется моментально. Максимум 10-15 минут и парсер готов.

Reset ★★★★★
()
Ответ на: комментарий от Obey-Kun

так ведь он ещё и не построчно читает

хотя можно сделать вот такое

std::istream& operator>>(std::istream& is, my_string& s)
{
  return getline(is, s);
}

:)

Obey-Kun ★★★★★
() автор топика
Ответ на: комментарий от JackyTreehorn

Я же сказал, задача теперь такая:

каждая строка имеет вид

[одно число] [ещё от одного до десяти чисел],

например,

1 234 423 543 545
3 254 435 546 766 454
6 655
4 434 543

считать первый столбец в vector int'ов, остальное в vector<vector<int>> (т.е. получается {1, 3, 6, 4} и {{234, 423, 543, 545}, {254, 435, 546, 766, 454}, {655}, {434, 543}}

Тут, наверное, надо getline, полученный_string >> some_int, полученный_string >> some_ints в цикле.

Obey-Kun ★★★★★
() автор топика
Ответ на: комментарий от Obey-Kun

> Тут, наверное, надо getline, полученный_string >> some_int, полученный_string >> some_ints в цикле.

Точнее, так:

1. getline

2. полученный_string >> some_int_arr

3. остатки строки с помощью copy идут в vector<vector<int>>

Obey-Kun ★★★★★
() автор топика

Хочу: из файла вида

4 45 54 43
456 45 545 45
66 65 76

544 546
45

Получить вывод

4 45 54 43
456 45 545 45
66 65 76
544 546
45

При этом числа надо выводить по одному (т.е. конвертировать в int).

Реализация:

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

int main() {
    static ifstream txtInput;
    int typeCounter = 0;
    txtInput.open("input.txt", fstream::in);
    int lineNum = 0;
    while (!txtInput.eof()) {
        istringstream fullLine;
        string tmpTxtLine;
        getline(txtInput, tmpTxtLine);
        ++lineNum;
        fullLine.str(tmpTxtLine);

        while (fullLine.good()) {
            double x;
            fullLine >> x;
            cout << x << " ";
        }
        cout << endl;
    }
}

Вывод:

4 45 54 43 
456 45 545 45 
66 65 76 
76 
544 546 
45 
45

Почему так? Как правильно?

Obey-Kun ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.