How to skip a data line in fortran [duplicate] - fortran

This question already has answers here:
Skip a line from text file in Fortran90
(3 answers)
Closed 7 years ago.
enter image description here
I have this data file
and want to read this data without line 1,2,3,4,5
program example
real data(15,9)
OPEN ( unit=10, file='filename' )
do i = 1, 15
READ (10, *) (data(i,j), j=1,10)
enddo
print *, data(4,1), data(4,2), data(4,3)
stop
end
this is my fortran code.
how can i change this code

Looking something like this?
input file: data
line1
line2
line3
line4
line5
line6
line7
line8
line9
line10
fortran code:
implicit none
integer:: lskip,lread
character(len=20)::line
open(20, file = "data")
!skip first 5 line
do lskip = 1,5
read(20,*)
End do
! First 5 lines skiped
! Now read actual lines
do lread = 1,5
read(20,*)LINE
write(*,*)line
End do
close(20)
end
Result
$gfortran so.f90
$./a.out
line6
line7
line8
line9
line10
NB: This is a minimal example, just for showing the skipping. You will change the read inside lread loop to actually read your file according to your data format

One way to do this is to put in a READ statement for each line that you want to "skip". Each time a READ statement is encountered, it reads in the data and then moves the "pointer" in the file down to the next line. So, for example, to skip 3 lines of header information:
DO 50 ilines = 1,3
READ(1,*)
50 continue
This in effect READs and stores nothing, but moves the pointer in the file forward 3 lines.

Related

Read text file where the columns have specific format

I am working with Fortran and I need to read a file that have 3 columns. The problem is that the 3rd column is a combination of integers, e.g. 120120101, and I need to separate each single value in a different column.
Usually, I manually remove the first 2 columns so the file would look like:
Info
0120012545
1254875541
0122110000
2254879933
To read this file where each single value is in a different column, I can use the following Fortran subroutine:
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
I wonder if it is possible to read a file with the following content:
IDs Idx Info
ID001 1 125478521111
ID002 1 525478214147
ID003 2 985550004599
ID004 2 000478520002
and the results would looks like:
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
where the values in the 3rd column is spitted in m column.
The first row is the header, but I don't need it, so I start reading from the second line.
I tried to write use the following subroutine, but it didn't work:
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
Does anyone know how I could read that file without manually removing the first two columns?
Thank you.
I am going to guess what each of the variables mean and also try to explain some apparent mistakes.
I believe your do i=2,n is a mistake because I have seen some of my students make this mistake. Starting i at 2 does not mean you are reading in from the second line, it is just the value of i. Then, assuming you have n data lines, you will miss the last data line because you are reading in n-1 lines. What you want is a blank read statement before the loop. This skips the header line. Then you want i to go from 1 to n.
From the order of the variables in the read statement, I assume ind is the ID number, chip is the Idx number, and imp has the Info numbers of 1 integer each up to m of them.
Your i8 will take the first 8 columns of information and try to interpret them as an integer. Well, ID001 1 1 is the first 8 columns of the first data line and this is not an integer. You need to skip the 'ID' and read in '001' into ind. Then skip 1 character and read in 1 integer into chip, then skip 1 more character then read in the Info, 1 integer at a time. The x format specifier skips 1 character.
For each integer to go into imp separately, you need an implied do loop that goes from 1 to m. I used j there for that. If you do not know about implied do loops, please google it. It is quite standard in Fortran.
This code snippet will do just that:
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)
Additional answer to address the comment. I see you would have two options. First, get into line parsing. I would not choose this.
Second option is to read the line using unformatted input. Unformatted input uses blanks to separate the input items. I would make the third item a character variable long enough to accommodate a length of m. This character variable can be read with Fortran's read statement. This is called reading from an internal record. You would read each integer as before. This is what this would look like:
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)
The first read statement in the do loop is reading from the file. It sticks the entire first column into Dumb no matter its length, the second column into chip(i), and the entire 3rd column into a character string named Info.
The second read statement is reading from the "internal record" Info. You can use a read statement on a character string. Here I use the format specifiers and the implied do loop to extract 1 integer at a time.

How to read the lines of the input in arbitrary order?

I would like to ask how I can read the lines of the input in arbitrary order. In other words: how to read a given line of the input? I have written the next test program:
program main
implicit integer*4(i-n)
dimension ind(6)
do i=1,6
ind(i)=6-i
end do
open(7,file='test.inp',status='old')
do i=0,5
call fseek(7,ind(i+1),0)
read(7,*) m
write(*,*) m
call fseek(7,0,0)
end do
end
where test.inp contains:
1
2
3
4
5
6
My output given is:
4
5
6
2
3
4
What is the problem? I would expect
6
5
4
3
2
1
for a text file the simplest thing is to just use an empty read to advance lines. This will read the nth line of file opened with unit=iu
rewind(iu)
do i=1,n-1
read(iu,*)
enddo
read(iu,*)data
Note if you are doing a bunch of reads from the same file you should consider reading the whole file into a character array, then you can very simply access lines by index.
here is an example of reading in a whole file:
implicit none
integer::iu=20,i,n,io
character(len=:),allocatable::line(:)
real::x,y
open(iu,file='filename')
n=0
do while(.true.) ! pass through once to count the lines
read(iu,*,iostat=io)
if(io.ne.0)exit
n=n+1
enddo
write(*,*)'lines in file=',n
!allocate the character array. Here I'm hard coding a max line length
!of 130 characters (that can be fixed if its a problem.)
allocate(character(130)::line(n))
rewind(iu)
!read in entire file
do i=1,n
read(iu,'(a)')line(i)
enddo
!now we can random access the lines using internal reads:
read(line(55),*)x,y
! ( obviously use whatever format you need on the read )
write(*,*)x,y
end
One obvious drawback to this is you can not read data that spans multiple lines the same as if you were reading from the file.
Edit: my old version of gfortran doensn't like that allocatable character syntax.
This works:
character(len=130),allocatable::line(:)
...
allocate(line(n))

How to skip to next line after the last number found in each line when reading a text file?

My text file look something like this:
1 2 3 test//test
4 5 6 dummy//dummy
How can I read this file and only process the numbers present in each line?
Two ways:
By ignoring the rest of the line.
By reading the complete line into a string, put the string in an output string stream, and read only the leading three numbers from the output string stream.

Put "read" line back in file

I am wondering if it is possible to put a line back in a file if it has been read in.
Here is a sample of what I am doing:
string templine;
while(templine.at(0)!=">"){
getline(file,templine);
//do some stuff with string
}
So basically I want to keep reading in the file until the first character of the next line is ">". The amount of lines between each ">" is inconsistent. The way I am reading it in now it will read the next line with a ">" but I dont want to actually do anything with that line yet and want to "put it back" in the file so I can read it again later. I am working in C++ VS10
My files look something like
">"2013 11 24 //The date, had to put > in " "
1 2 3 4
5 6 7 8
">"2013 11 25
1 2 3 4
">"2013 11 26 etc...
You can do it like this:
while(file.peek() != '>'){
std::getline(file,templine);
//Do work
}
where file is your ifstream. That way, you will not read the line with > until you need it.

Cpp getline in a while loop works once, then reads until the end of the file

I am writing a program that take a command redirected file as the standard input, so instead of cin getting input from the keyboard, I run my program with ./teamBalancer < inputFile.txt > outputFile.txt.
The problem I'm having is that getline in the while loop reads the first line perfectly and outputs fine, but then it just reads the rest of the file in one line. I have tried everything from stringstreams to just getline and have read so many forums. Why is this happening?
Here is my code:
//USER INPUT--------------------------------------------------------------
while (cin) {
string attackString, defenseString;
getline(cin, attackString, ',');
getline(cin, defenseString);
int attack, defense;
attack = atoi(attackString.c_str());
defense = atoi(defenseString.c_str());
cout<<attack<<" "<<defense<<endl;
}
and the sample input is this:
5,1
9,1
7,4
1,3
1,3
10,4
4,5
7,4
and the corresponding output is...
5 1
9 1
0 0
Both of these are in txt files and the 0 0 for the last output is because the last line is empty? I don't understand why getline can't continue reading the file line by line like it does with the first one.
Thank you so much to anyone who helps and if you need any clarification please let me know! Thank you :)
the Code you presented looks good. I tested it under Windows without any changes and got the following result:
5 1
9 1
7 4
1 3
1 3
10 4
4 5
7 4
0 0
So it looks like your input file encoding is messed up.
Can you please check the line endings of your input txt. Are they all the same and are the EOL chars the default one for your system?
The 0 0 in the last row is that cin still contains something at the end (the EOF char) but it is not able to translate it to the wished numbers, to avoid this you can use this:
while (!cin.eof())
Now you are checking if you are on the end of a file.
Sorry currently i can not write comments.
br,
zinnjonas