Прочитать текстовый файл, где столбцы имеют определенный формат - PullRequest
0 голосов
/ 04 июня 2019

Я работаю с Фортраном, и мне нужно прочитать файл с 3 столбцами. Проблема в том, что 3-й столбец представляет собой комбинацию целых чисел, например 120120101, и мне нужно разделить каждое отдельное значение в отдельном столбце.

Обычно я вручную удаляю первые 2 столбца, чтобы файл выглядел так:

Info
0120012545
1254875541
0122110000
2254879933

Чтобы прочитать этот файл, где каждое отдельное значение находится в отдельном столбце, я могу использовать следующую подпрограмму Fortran:

subroutine readF(imp, m, n)
  implicit none
  integer :: n,m,i,imp(n,m)
  open(unit=100, file='file.txt', status='old', action='read')
  do i=2,n
    read(100,'(*(i1))') imp(i,1:m)
    end do
  close(unit=100)
end subroutine readF

Интересно, можно ли прочитать файл со следующим содержанием:

IDs Idx Info
ID001 1 125478521111
ID002 1 525478214147
ID003 2 985550004599
ID004 2 000478520002

и результаты будут выглядеть так:

ID001 1 1 2 5 4 7 8 5 2 1 1 1 1
ID002 1 5 2 5 4 7 8 2 1 4 1 4 7
ID003 2 9 8 5 5 5 0 0 0 4 5 9 9
ID004 2 0 0 0 4 7 8 5 2 0 0 0 2

где значения в 3-м столбце разбиты на столбцы m.

Первая строка - это заголовок, но он мне не нужен, поэтому я начинаю читать со второй строки.

Я пытался написать, используя следующую подпрограмму, но она не сработала:

subroutine readF(imp, ind, m, n)
  implicit none
  integer :: n,m,i,imp(n,m),ind(n),chip(n)
  open(unit=100, file='file.txt', status='old', action='read')
  do i=2,n
    read(100,'(i8,i1,*(i1))') ind(i),chip(i),imp(i,1:m)
  end do
  close(unit=100)
end subroutine readF

Кто-нибудь знает, как я мог прочитать этот файл, не удаляя первые два столбца вручную?

Спасибо.

1 Ответ

1 голос
/ 05 июня 2019

Я собираюсь угадать, что означает каждая из переменных, а также попытаюсь объяснить некоторые очевидные ошибки.

Я считаю, что ваша do i=2,n - ошибка, потому что я видел, как некоторые из моих учеников совершали эту ошибку. Начало i в 2 не означает, что вы читаете со второй строки, это просто значение i. Затем, если у вас есть n строк данных, вы пропустите последнюю строку данных, потому что вы читаете в n-1 строк. То, что вы хотите, это пустой оператор чтения перед циклом. Это пропускает строку заголовка. Тогда вы хотите, чтобы я пошел от 1 до п.

Из порядка переменных в операторе чтения я предполагаю, что ind - это номер идентификатора, chip - это номер Idx, а imp имеет номера Info от 1 целого до каждой из m.

Ваш i8 возьмет первые 8 столбцов информации и попытается интерпретировать их как целое число. Ну, ID001 1 1 - это первые 8 столбцов первой строки данных, и это не целое число. Вам нужно пропустить «ID» и прочитать «001» в ind. Затем пропустите 1 символ и прочитайте 1 целое число в чип, затем пропустите еще 1 символ, затем прочитайте в Info, 1 целое число за раз. Спецификатор формата x пропускает 1 символ.

Чтобы каждое целое число входило в imp отдельно, вам нужен подразумеваемый цикл do, который идет от 1 до m. Я использовал J там для этого. Если вы не знаете о предполагаемых циклах do, пожалуйста, поищите в Google. Это вполне стандартно в Фортране.

Этот фрагмент кода сделает именно это:

open(unit=100, file='file.txt', status='old', action='read')
read(100,*)  ! This skips the header line.
do i=1,n     ! Read in n data lines.
  read(100,'(2x,i3,1x,i1,1x,*(i1))') ind(i),chip(i),(imp(i,j),j=1,m)
end do
close(unit=100)

Дополнительный ответ на адрес комментария. Я вижу, у тебя было бы два варианта. Во-первых, попадаем в разбор строк. Я бы не выбрал это.

Второй вариант - прочитать строку, используя неформатированный ввод. Неформатированный ввод использует пробелы для разделения элементов ввода. Я бы сделал третий элемент символьной переменной, достаточно длинной, чтобы соответствовать длине m. Эту символьную переменную можно прочитать с помощью оператора Fortran read. Это называется чтением из внутренней записи. Вы читали бы каждое целое число, как и раньше. Вот как это будет выглядеть:

character(len=m) :: Info
character(len=:),allocatable :: Dumb
open(unit=100, file='file.txt', status='old', action='read')
read(100,*)  ! This skips the header line.
do i=1,n     ! Read in n data lines.
  read(100,*) Dumb, chip(i), Info
  read(Info,'(*(i1))') (imp(i,j),j=1,m)
end do
close(unit=100)

Первый оператор read в цикле do читает из файла. Он вставляет весь первый столбец в Dumb независимо от его длины, второй столбец - в микросхему (i), а весь 3-й столбец - в строку символов с именем Info.

Вторым оператором чтения является чтение из "внутренней записи" Info. Вы можете использовать оператор read для символьной строки. Здесь я использую спецификаторы формата и подразумеваемый цикл do для извлечения 1 целого числа за раз.

...