Как считать одномерный массив из файла?

249
19 февраля 2022, 13:10

Программа должна считывать массив из файла и отсортировать значения по возрастанию. Какие функции/классы можно использовать для считывания массива из файла и дальнейшней его сортировки?

Answer 1

Все довольно просто. Для начала разбейте задание на небольшие подзадачи:

  1. Открыть сам файл с массивом.
  2. Считать оттуда числа.
  3. Отсортировать массив.
  4. Вывести на экран.

Работу с файлами можно реализовать с помощью std::ifstream. Считывание производится оператором >>. Отсортировать массив можно с помощью std::sort. На экран выводим обычным std::cout.

Если собрать все вместе, то получим что-то такое:

#include <algorithm>
#include <iostream>
#include <fstream>
#include <vector>
auto read_numbers_from_file(std::ifstream& f)
{
    std::vector<int> v;
    for (int n; f >> n; )
        v.push_back(n);
    return v;
}
void print_vector(const std::vector<int>& v)
{
    for (auto n : v)
        std::cout << n << '\n';
}
int main()
{
    std::ifstream input_file("numbers.txt");
    if (input_file.is_open()) {
        /* Считываем числа из файла. */
        std::vector<int> numbers = read_numbers_from_file(input_file);
        /* Сортируем полученный вектор. */
        std::sort(numbers.begin(), numbers.end());
        /* Печатаем его содержимое. */
        print_vector(numbers);
    }
}
Answer 2

Для работы с путями и вообще с файловыми системами есть std::filesystem работу с путями желательно строить через него.

std::filesystem::current_path() / "data" — укажет путь до файла который лежит рядом с бинарником Вашей программы.

std::filesystem::exists(path) — проверит существование файла. см CheckAndGetFStream ниже.

Далее открываете и проверяете файл на открытие.

std::ifstream::is_open — вернет true если файл успешно открылся.

Если вы уверенны в корректности данных (формат и содержание) Вы можете просто отдать конструктору вектору 2 итератора (итератор на начало файла и конец) (https://en.cppreference.com/w/cpp/container/vector/vector)

std::istream_iterator<int64_t> begin_file{in_stream}, end_file;

std::vector<int64_t> data(begin_file, end_file);

Если нет, то лучше читать по лексеме с обработкой ошибок а-ля (в таком случае если где-то появилось что-то отличное от is_space(...)==true оно будет игнорироваться и чтение пойдет дальше, а в первом случае закирпичится и данные за этим символом не будут прочтены)

std::vector<int64_t> data{};
int64_t val{0};
while (true) {
    if (in_stream.eof()) {
        break;
    }
    in_stream>> val;
    if (in_stream.fail()) {
        in_stream.clear();
        in_stream.ignore(1);
    } else {
        data.push_back(val);
    }
}

После чтения файла нужно проверить, прочиталось ли вообще хоть что-то)

Для сортировки есть std::sort куда Вы можете указать std::less и std::greater в зависимости от того, как Вам надо отсортировать данные

#include <iostream>
#include <iterator>
#include <fstream>
#include <vector>
#include <algorithm>
#include <functional>
#include <filesystem>

std::ifstream CheckAndGetFStream(std::string file_name) {
    auto path{std::filesystem::current_path() / file_name};
    if (!std::filesystem::exists(path)) {
        throw std::runtime_error{"Error : file not found"};
    }
    std::ifstream in_stream(path);
    if (!in_stream.is_open()) {
        throw std::runtime_error{"Error : file not open"};
    }
    return in_stream;
}

void CopyDataToStdout(std::vector<int64_t>& data) {
    std::copy(std::begin(data), std::end(data), std::ostream_iterator<int64_t>{std::cout, " "});
    std::cout << std::endl;
}

 std::vector<int64_t> ReadIntDataFromFileIt(std::string file_name) {
    auto in_stream{CheckAndGetFStream(file_name)};
    std::istream_iterator<int64_t> begin_file{in_stream}, end_file;
    std::vector<int64_t> data(begin_file, end_file);
    if (!data.size()) {
        throw std::runtime_error{"Error : file not read"};
    }
    std::cout << "Data : " << std::endl;
    std::copy(std::begin(data), std::end(data), std::ostream_iterator<int64_t>{std::cout, " "});
    std::cout << std::endl;
    return data;
 }

 std::vector<int64_t> ReadIntDataFromFileCheck(std::string file_name) {
    auto in_stream{CheckAndGetFStream(file_name)};
    std::vector<int64_t> data{};
    int64_t val{0};
    while (true) {
        if (in_stream.eof()) {
            break;
        }
        in_stream>> val;
        if (in_stream.fail()) {
            in_stream.clear();
            in_stream.ignore(1);
        } else {
            data.push_back(val);
        }
    }
    std::cout << "Data : " << std::endl;
    CopyDataToStdout(data);
    return data;
 }

 void SortAndPrint(std::vector<int64_t>& data) {
    std::sort(std::begin(data), std::end(data), std::less<int64_t>());
    std::cout << "Data after less sort : " << std::endl;
    CopyDataToStdout(data);
    std::sort(std::begin(data), std::end(data), std::greater<int64_t>());
    std::cout << "Data after greater sort : " << std::endl;
    CopyDataToStdout(data);
 }

int main() {
    std::string file_name{"data"};
    try {
        auto data{ReadIntDataFromFileIt(file_name)};
        SortAndPrint(data);
        auto data2{ReadIntDataFromFileCheck(file_name)};
        SortAndPrint(data2);
    } catch (std::runtime_error& rt_excpt) {
        std::cerr << rt_excpt.what() << std::endl;
        return 1;
    } catch (...) {
        std::cerr << "Unkn err" << std::endl;
        return 2;
    }
    return 0;
} 
READ ALSO
Может ли объект пересечь границу адресного пространства?

Может ли объект пересечь границу адресного пространства?

В C и C++ память адресуется побайтовоЕсли верить Стандарту, начало многобайтового объекта - это адрес его самого младшего байта

80
Помогите составить запрос на выборку объявлений в mysql

Помогите составить запрос на выборку объявлений в mysql

для более наглядного представления проблемы опубликовал в sqlfiddle

108
Не прогружается приложение

Не прогружается приложение

Приложение работало (и на телефоне, и на эмуляторе), но после действий с регистрацией в приложении что-то пошло не такСамо приложение устанавливается...

86