Как прочитать два числа из файла
Я хотел бы прочитать числа из файла в двухмерный массив.
- строка, содержащая w, h
- h строк, содержащих w целых чисел, разделенных пробелом
Предполагая, что у вас нет посторонних пробелов:
Вы можете сжать последний цикл for для понимания вложенного списка:
Чтобы сделать ответ простым, вот программа, которая читает целые числа из файла и сортирует их
После прочтения каждой строки файла конвертируем каждую строку в цифру
Писать их так просто, надеюсь, это поможет
Для меня эта, казалось бы, простая проблема - вот что такое Python. Особенно, если вы работаете с таким языком, как C ++, где простой анализ текста может быть проблемой, вы по-настоящему оцените функционально-модульное решение, которое Python может дать вам. Я бы сделал это по-настоящему простым с помощью пары встроенных функций и некоторых выражений генератора.
Вам понадобятся open(name, mode) , myfile.readlines() , mystring.split() , int(myval) , а затем, возможно, вы захотите использовать пару генераторов, чтобы собрать их все вместе с помощью питона ,
Посмотрите выражения генератора здесь. Они могут действительно упростить ваш код в отдельные функциональные блоки! Представьте, что вы делаете то же самое в 4 строки в C ++ . Это было бы чудовищем. Особенно генераторы списков, когда я был парнем C ++, мне всегда хотелось, чтобы у меня было что-то подобное, и я часто заканчивал тем, что создавал пользовательские функции для создания каждого вида массива, который хотел.
Не уверен, зачем тебе ш, ч. Если эти значения действительно необходимы и означают, что должно быть прочитано только указанное количество строк и столбцов, попробуйте следующее:
Работает как с python2 (например, Python 2.7.10), так и с python3 (например, Python 3.6.4)
Другой путь: работает как с python2 (например, Python 2.7.10), так и с python3 (например, Python 3.6.4), а также для комплексных матриц см. пример ниже (только измените int на complex )
Я обновил код, этот метод работает для любого числа матриц и любых видов матриц ( int , complex , float ) в исходном файле in.txt .
Эта программа дает матричное умножение как приложение. Работает с python2, для работы с python3 внесите следующие изменения
Когда я только начинал изучать Python, главным помощником в работе для меня, как наверное и для большинства программистов, был Stack Overflow. Я почерпнул оттуда много полезной информации, в том числе и о работе с файлами. Однако даже такая тривиальная задача, как оказалось, имеет несколько различных решений, отличающихся друг от друга простотой реализации и скоростью работы.
Большинство предложенных методов предполагают чтение файла построчно с дальнейшим разбиением на блоки и их преобразованием из строкового типа в числовой, поскольку Python в отличии от C/C++ работает с файлами как с массивом строк. Выполнить последовательное чтение данных в массив без преобразования типов, как это можно сделать в C/C++, стандартными средствами языка невозможно (насколько мне известно), и это существенно увеличивает время работы программы при обработке больших объемов данных.
Как уже было сказано выше, файлы в Python представляют собой массив строк, поэтому все найденные методы можно символически поделить на два типа в зависимости от используемого подхода:
- построчное считывание с разбиением и преобразованием типов
- использование библиотек, которые средствами других языков (например, C/C++) считывают файл и передают полученные данные интерпретатору Python
Самый популярный и простой вариант. Заключается в построчном чтении с разбиением полученной строки на блоки, которые затем преобразуются к необходимому типу данных (в данном случае float) и добавляются к заранее созданному списку.
Способ аналогичен предыдущему, за исключением того, что преобразованием данных из строкового формата в числовой занимается функция map.
Данный способ можно назвать стрельбой из пушки по воробьям, однако у него все же есть свои плюсы: если данные в файле расположены хаотично и отсутствует постоянная структура, то функции split невозможно задать конкретный разделитель и для решения задачи можно использовать регулярное выражение, которое найдет в строке все числа, несмотря на их расположение и наличие разделителей.
Если данные записаны в виде матрицы с постоянными разделителями, то выполнить их чтение можно при помощи модуля CSV Reader, указав в качестве параметра значение разделителя.
Библиотека Numpy предоставляет широкий набор модулей и функций для обработки числовых данных, в том числе и для чтения массивов из файлов. Одна из реализаций возможна с помощью функции loadtxt, результат работы которой будет записан в numpy.array.
Данный способ не сильно отличается от предыдущего, за исключением того, что genfromtxt предоставляет более широкий набор входных параметров: указание различных типов данных для каждого из столбцов, передача ключей для создания ассоциативного массива и так далее.
Для тестирования скорости чтения числовых данных были сгенерированы 7 тестовых файлов, содержащих 5 столбцов и 10, 100, 1 000, 10 000, 100 000, 1 000 000 и 10 000 000 строк случайных чисел формата float. Размер самого большого файла составил 742 Мб.
Для измерения времени работы программы использовалась функция time. Существует мнение, что измерять с её помощью время работы некорректно. Однако в данном случае меня интересовало работа с большими объемами данных, когда время работы программы составляло несколько десятков секунд. В таком случае отклонение в полсекунды вносило погрешность менее 1%.
Fortran
Несмотря на то, что Fortran считается устаревшим языком, он все еще очень популярен в научном программировании благодаря простоте написания кода, скорости обмена данных и обширном количестве библиотек, созданных за последние полвека.
Например, считать числовую матрицу из файла можно всего за 3 строчки кода при условии корректности входных данных.
Дискуссии о том, что лучше: Fortran или C++ ведутся уже давно, даже среди авторов EasyCoding этот спор возникал несколько раз, поэтому мне было еще интересней протестировать чтение матриц на данном языке.
В ходе эксперимента были протестированы 7 программ на языке Python и по одной на Fortran и C++, код которых представлен выше. Запуск программ осуществлялся на компьютере с Intel Core i5 2.7 GHz и 8 Гб оперативной памяти.
Для запуска программ использовались следующие интерпретаторы и компиляторы:
GNU Fortran (GCC) 6.1.0
Для каждой программы проводилась серия испытаний и измерялось время работы, после чего записывался результат в виде среднего арифметического полученных данных. В таблице ниже жирным в каждой строке выделено наименьшее время работы в зависимости от способа чтения и размера входного файла.
Число строк | Способ | ||||||||
---|---|---|---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 | Fortran | C++ | |
10 | 0.048 | 0.048 | 0.045 | 0.044 | 0.173 | 0.216 | 0.479 | 0.005 | 0.005 |
100 | 0.053 | 0.052 | 0.05 | 0.048 | 0.185 | 0.223 | 0.511 | 0.007 | 0.006 |
1 000 | 0.056 | 0.053 | 0.053 | 0.052 | 0.187 | 0.233 | 0.6 | 0.01 | 0.01 |
10 000 | 0.085 | 0.076 | 0.096 | 0.083 | 0.305 | 0.292 | 0.636 | 0.032 | 0.041 |
100 000 | 0.414 | 0.403 | 0.561 | 0.482 | 1.537 | 0.874 | 0.796 | 0.244 | 0.363 |
1 000 000 | 3.835 | 4.502 | 6.086 | 5.276 | 13.607 | 6.754 | 1.763 | 2.584 | 3.662 |
10 000 000 | 47.931 | 156.944 | 137.398 | 144.75 | 162.724 | 85.642 | 13.632 | 25.652 | 36.622 |
Однако при увеличении объема входных данных лучше всех себя показал метод 7 с использованием библиотеки Pandas, который даже обогнал по скорости чтения данных языки C++ и Fortran.
Также из результатов теста можно видеть, что программа на Fortran справилась с чтением данных быстрей аналога на C++, что еще раз доказывает его превосходство над самым популярным языком программирования в мире.
10 комментариев к записи
ошибка в таблице ! 0.044 не меньше чем 0.005 а больше почти в 9 раз!
Нет ошибки. Автор сравнивал скорости Python решений.
С++, который обгонит всё перечисленное:
Причем не особо кошерная реализация. Но соответствует предоставленному коду.
Кошерная реализация это:
Спасибо за приведенное полезное сравнение. Не хватает сравнения скорости записи (в рам для точности)
Необходимо установить соответствующую библиотеку numpy либо из репозиториев, либо посредством pip.
2 способ выдает:
[/, /, /]
при числах в файле:
1 2 3
4 5 6
7 8 9
Что не так?
Проверьте версию интерпретатора Python. В 3.7 работает нормально.
На С++ вы читали потоками, это медленно. Надо было попробовать функциями ввода вывода,fopen, fclose, fread должно быть быстрее. В С++ тоже несколько способов. Могло получиться сопоставимо с лучшим результатом.
На олимпиадах по программированию для ввода данных в программу используют, как правило, файл с названием input.txt(содержит входные данные), а для вывода используется output.txt(содержит все выходные данные). В данной статье мы разберем, как нам брать данные из файла input.txt и записывать в output.txt.
Из input.txt в output.txt
Если Вы любите решать олимпиадные задачи, то Вам просто необходимо иметь шаблон такой программы, чтобы каждый раз не реализовывать её. Ежели Вы впервые столкнулись с этим, то мы сейчас разберем, как это всё делается.
Мы уже говорили, как считывать данные из файла и записывать данные в файл посредством функций стандартной библиотеки <iostream> языка программирования C++. Давайте же применим наши знания в решении данной задачи.
Считывание и ввод данных из input.txt
Организуем ввод всех данных из файла input.txt в наши переменные и массивы. Я покажу, как считать разные типы данных: числа, строки, ряды чисел(для массива).
Итак, для начала создадим файл input.txt, откроем с помощью текстового редактора и заполним его различными значениями. Я разместил пару чисел на одной строке, одно число на следующей строке, 10 чисел еще на одной строке и строку текста на последней. Файл input.txt содержит следующее:
Теперь напишем программу, которая будет брать все эти значения и заносить в нужные нам переменные.
Допустим, мне нужно занести первые два числа на первой строке(15 и 20) в переменные a и b соответственно.
Значение числа на второй строке(10) в переменную N, и при этом, договоримся, что на второй строке число указывает на количество чисел, размещенных на третей строке. То есть на третей строке у нас N чисел через пробел, их мы будем заносить в массив.
И, наконец, на четвёртой строке файла у нас расположено слово, его мы тоже занесем в переменную.
Теперь напишем программу, которая считает это всё и поместит в переменные, с которыми мы сможем работать. Я буду размещать код поэтапно, чтобы было понятно, что и где добавилось. Для начала Вы можете узнать как считывать из файла в C++.
Подключим необходимые заголовки
Откроем файл input.txt для чтения
Считаем первые два числа из файла input.txt в переменные a и b
Разделителем чисел в файле служат пробелы. Поэтому просто выводим поток из fin прямо в переменные по порядку.
Считаем число со второй строчки в переменную N
Указатель положения в файле сместился автоматически на следующую строчку и считал число.
То есть числа можно разделять пробелами или переносами строк, и просто выводить информацию по порядку из файла в соответствующие переменные.
Теперь определяем массив с размером N и вносим в него следующие 10 чисел из файла
В результате массив mass[] заполнился следующими 10-ю числами из файла(числами с третьей строки).
И теперь считаем следующую за всем этим слово
Теперь выведем значения всех переменных в консоль
Определяем переменные и заносим в них наши значения, которые мы запишем в файл.
Откроем файл output.txt для записи.
Теперь, аналогично с обычным выводом в консоль, передаем в поток файла наши данные.
Теперь компилируем и запускаем программу, после чего открываем файл output.txt с помощью текстового редактора и видим записанные в него значения наших переменных, размещенных на разных строках.
Содержимое файла output.txt
Весь код программы для записи переменных в файл:
Вот мы и разобрались с выводом данных в файл output.txt.
Шаблон считывания данных из input.txt и записи в файл output.txt
Теперь создадим шаблон программы для использования в будущих решениях олимпиадных задач, чтобы каждый раз не писать один и тот же код для получения данных из input.txt и записи в output.txt.
Синтезируем две наши написанные программы и получим следующий код.
Вот и получился шаблон. Проверим его.
Допустим, нам нужно взять первое число из файла input.txt и записать его в файл output.txt.
Для этого просто определяем числовую переменную, считываем данные из потока fin, и выводим значение переменной в поток fout. Всё просто, вот так:
В файле input.txt у меня записано число 15, после запуска программы в файле output.txt появилось число 15. Всё работает, всё просто.
Итоги
Итак, мы научились получать данные из файла и записывать их в другой файл. Создали шаблон для будущих решений олимпиадных задач. Кстати, если вы решаете задачи по программированию на языке C++, то загляните в раздел с решениями задач. Если у Вас остались вопросы, то задавайте их в комментариях.
Для вас это может быть интересно:
Считать значения из input.txt и записать в output.txt на C++ : 5 комментариев
То чувство, когда с этим возишься дольше, чем с решением самой задачи.:)
Пример шаблона считывания и записи хороший, сохраню себе. Спасибо за идею.
А как таким образом считать строку из файла? У меня считает только одно слово до пробела, а нужно чтобы считывало все предложение до конца строки.
Есть смысл построчно записывать в массив
Есть ли подобное на Basic?
Спасибо большое выручили
Добавить комментарий Отменить ответ
Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.
На серьезных олимпиадах, а также во многих других ситуациях вам надо читать данные не с клавиатуры, а из файла, и выводить данные в файл, а не на "экран". В таком случае вы должны знать имена этих файлов; в задачах они, как правило, указаны, на этом сайте имена файлов почти всегда — input.txt для входных данных и output.txt для выходных.
Во многих языках программирования ввод/вывод данных через файлы очень похож на ввод/вывод с клавиатуры — те же команды, только немного другие параметры. В питоне, к сожалению, это не так.
Ввод данных
Самый простой способ ввести данные из файла в питоне — это сразу считать их в массив строк. Это делается так:
Здесь input.txt — файл, откуда надо считать данные, параметр "r" указывает, что вы собираетесь именно читать (read) данные, а не записывать (write, см. ниже). Команда open , как говорят, «открывает файл на чтение», а команда readlines считывает весь файл в массив строк.
Теперь data — это массив строк, каждый элемент которого — это очередная строка из входного файла. Например, если в файле было написано
то data будет содержать массив ["1 2 3\n", "4 5 6\n", "some text\n"] . (Здесь "\n" — это символ перевода строки, он будет на конце каждой строки массива data , кроме, возможно, последней. Если вы считываете числа, то можете о нем не беспокоиться, а если считываете строки и он вам мешает, то, как правило, от него можно избавиться командой a = a.rstrip("\n") , где a — строка, у которого вы хотите его убрать.)
Каждый элемент массива data — это как результат отдельной команды input() , которой вы пользовались для чтения с клавиатуры. Поэтому дальше вы пишете программу так же, как писали и раньше, но вместо каждого очередного обращения к input() вы обращаетесь к очередному элементу массива data . В простых случаях все просто, в более сложных вам надо аккуратно подсчитывать, к какому именно элементу массива вам надо обратиться.
Пример. Пусть во входном файле два числа по одному на строке. Их считываем так (здесь и далее слева — пример чтения с клавиатуры, справа — из файла):
Если же два числа в одной строке:
Более сложный пример: сначала число N , а потом N строк по одному числу в каждой:
Обратите внимание на то, что здесь написано i + 1 — потому что в первой (нулевой) строке было n .
Вывод
Проще всего выводить данные — записав их в одну большую строку и выведя эту строку. Вывод строки в файл делается так:
здесь s — строка, которую нужно вывести. Это должна быть именно строка, а не число и т.д. Используйте функцию str , чтобы превратить что угодно в строку, вручную добавляйте пробелы и переводы строк (перевод строки записывается так: "\n" ).
Пример: пусть надо вывести два числа в одну строку:
open("output.txt", "w").write(str(a) + " " + str(b))
Пусть надо вывести два числа на отдельных строках:
open("output.txt", "w").write(str(a) + "\n" + str(b))
Пусть надо вывести массив чисел по одному числу на строке:
или проще, используя строковую магию:
Имейте в виду, что такой вызов должен быть только один раз. Если вы хотите вызывать функцию write несколько раз, то надо суметь вызвать функцию open только один раз. Рекомендуемый вариант — такой:
До этого при вводе-выводе данных мы работали со стандартными потоками — клавиатурой и монитором. Теперь рассмотрим, как в языке C реализовано получение данных из файлов и запись их туда. Перед тем как выполнять эти операции, надо открыть файл и получить доступ к нему.
В языке программирования C указатель на файл имеет тип FILE и его объявление выглядит так:
С другой стороны, функция fopen() открывает файл по указанному в качестве первого аргумента адресу в режиме чтения ("r"), записи ("w") или добавления ("a") и возвращает в программу указатель на него. Поэтому процесс открытия файла и подключения его к программе выглядит примерно так:
Примечание. В случае использования относительной адресации текущим/рабочим каталогом в момент исполнения программы должен быть тот, относительно которого указанный относительный адрес корректен. Место нахождения самого исполняемого файла не важно.
При чтении или записи данных в файл обращение к нему осуществляется посредством файлового указателя (в данном случае, myfile).
Если в силу тех или иных причин (нет файла по указанному адресу, запрещен доступ к нему) функция fopen() не может открыть файл, то она возвращает NULL. В реальных программах почти всегда обрабатывают ошибку открытия файла в ветке if , мы же далее опустим это.
Объявление функции fopen() содержится в заголовочном файле stdio.h, поэтому требуется его подключение. Также в stdio.h объявлен тип-структура FILE.
После того, как работа с файлом закончена, принято его закрывать, чтобы освободить буфер от данных и по другим причинам. Это особенно важно, если после работы с файлом программа продолжает выполняться. Разрыв связи между внешним файлом и указателем на него из программы выполняется с помощью функции fclose() . В качестве параметра ей передается указатель на файл:
В программе может быть открыт не один файл. В таком случае каждый файл должен быть связан со своим файловым указателем. Однако если программа сначала работает с одним файлом, потом закрывает его, то указатель можно использовать для открытия второго файла.
Чтение из текстового файла и запись в него
fscanf()
Функция fscanf() аналогична по смыслу функции scanf() , но в отличии от нее осуществляет форматированный ввод из файла, а не стандартного потока ввода. Функция fscanf() принимает параметры: файловый указатель, строку формата, адреса областей памяти для записи данных:
Возвращает количество удачно считанных данных или EOF. Пробелы, символы перехода на новую строку учитываются как разделители данных.
Допустим, у нас есть файл содержащий такое описание объектов:
Тогда, чтобы считать эти данные, мы можем написать такую программу:
В данном случае объявляется структура и массив структур. Каждая строка из файла соответствует одному элементу массива; элемент массива представляет собой структуру, содержащую строковое и два числовых поля. За одну итерацию цикл считывает одну строку. Когда встречается конец файла fscanf() возвращает значение EOF и цикл завершается.
fgets()
Функция fgets() аналогична функции gets() и осуществляет построчный ввод из файла. Один вызов fgets() позволят прочитать одну строку. При этом можно прочитать не всю строку, а лишь ее часть от начала. Параметры fgets() выглядят таким образом:
Такой вызов функции прочитает из файла, связанного с указателем myfile, одну строку текста полностью, если ее длина меньше 50 символов с учетом символа '\n', который функция также сохранит в массиве. Последним (50-ым) элементом массива str будет символ '\0', добавленный fgets() . Если строка окажется длиннее, то функция прочитает 49 символов и в конце запишет '\0'. В таком случае '\n' в считанной строке содержаться не будет.
В этой программе в отличие от предыдущей данные считываются строка за строкой в массив arr. Когда считывается следующая строка, предыдущая теряется. Функция fgets() возвращает NULL в случае, если не может прочитать следующую строку.
getc() или fgetc()
Функция getc() или fgetc() (работает и то и другое) позволяет получить из файла очередной один символ.
Приведенный в качестве примера код выводит данные из файла на экран.
Запись в текстовый файл
Также как и ввод, вывод в файл может быть различным.
- Форматированный вывод. Функция fprintf ( файловый_указатель, строка_формата, переменные ) .
- Посточный вывод. Функция fputs ( строка, файловый_указатель ) .
- Посимвольный вывод. Функция fputc() или putc( символ, файловый_указатель ) .
Ниже приводятся примеры кода, в которых используются три способа вывода данных в файл.
Запись в каждую строку файла полей одной структуры:
Построчный вывод в файл ( fputs() , в отличие от puts() сама не помещает в конце строки '\n'):
Пример посимвольного вывода:
Чтение из двоичного файла и запись в него
С файлом можно работать не как с последовательностью символов, а как с последовательностью байтов. В принципе, с нетекстовыми файлами работать по-другому не возможно. Однако так можно читать и писать и в текстовые файлы. Преимущество такого способа доступа к файлу заключается в скорости чтения-записи: за одно обращение можно считать/записать существенный блок информации.
При открытии файла для двоичного доступа, вторым параметром функции fopen() является строка "rb" или "wb".
Тема о работе с двоичными файлами достаточно сложная, для ее изучения требуется отдельный урок. Здесь будут отмечены только особенности функций чтения-записи в файл, который рассматривается как поток байтов.
Функции fread() и fwrite() принимают в качестве параметров:
- адрес области памяти, куда данные записываются или откуда считываются,
- размер одного данного какого-либо типа,
- количество считываемых данных указанного размера,
- файловый указатель.
Эти функции возвращают количество успешно прочитанных или записанных данных. Т.е. можно "заказать" считывание 50 элементов данных, а получить только 10. Ошибки при этом не возникнет.
Пример использования функций fread() и fwrite() :
Здесь осуществляется попытка чтения из первого файла 50-ти символов. В n сохраняется количество реально считанных символов. Значение n может быть равно 50 или меньше. Данные помещаются в строку. То же самое происходит со вторым файлом. Далее первая строка присоединяется ко второй, и данные сбрасываются в третий файл.
Читайте также: