How are input lines defined for I/0 statements? - io

I want to read some values from a file called Input.txt. The input file looks like this:
1 2 3 4
1 2 3 4
1 2 3 4
1 2 3 4
1 2 3 4
1 2 3 4
....
in total its 36 lines of 1,2,3 and 4s
then I use the following code to read from the file:
program outputtest
implicit none
double precision, allocatable, dimension(:) :: A,B,C,D
integer :: counter,ii, ierror
ierror=0
counter=1
open(39, action='read', name='input.txt', status='old')
do
read(39,100, IOSTAT=Ierror)
100 Format(T8,I1)
If (Ierror>0) then
print *, 'error when reading'
stop
end if
If (ierror<0) then
print*, 'end of file reached'
exit
end if
counter=counter+1
end do
If (.not.allocated(A)) ALLocate(A(counter))
If (.not.allocated(b)) ALLocate(b(counter))
If (.not.allocated(c)) ALLocate(c(counter))
If (.not.allocated(d)) ALLocate(d(counter))
do ii=1, counter-1
read(39,110, IOSTAT=ierror) A(ii), B(ii), C(ii), D(ii)
110 Format(T8, I4, T16, I4, T24, I4, T32, I4)
If (ierror.neqv.0) exit
end do
close(39)
write (*,120) A
write (*,120) B
write (*,120) C
write (*,120) D
120 Format('result:', 1x,I2)
end program outputtest
The problem is now that the A,B,C,D are all equal to zero, i.e. my output is:
result: 0
result: 0
result: 0
....
This means that I do not read either from the correct lines or I make another mistake. I used in vim the option ruler to see what lines those entries are in and used those lines together with T. I created the file Input.txt by using tabs. What is my mistake?

A two things:
You don't do a rewind in your file. At first you read through the whole file to get the number of lines, but without a rewind, you start reading at the end -- which means nothing gets actually read into the arrays.
read with explicit formats is dangerous. You have to be really certain that the input file matches the format precisely. In your case, I'd to as #high-performance-mark suggested and use fmt=*. Your input file should easily be read automatically.
That's what I can gleam from a quick browse. See if that helps.

Related

Format of marks in viminfo

I'm trying to find information on how file marks are stored in the 'viminfo' file. For example, here is an entry I have:
'0 3 11 ~/.vim/hello
|4,48,3,11,1592944829,"~/.vim/hello"
The only obvious things from the above seem to be the filepath the mark is saved, ~/.vim/hello and the timestamp it was created 1592944829. What are the other items, and why are some of the items listed multiple times (3, 11, filename).
you are reading the wrong block.
In the viminfo file, search for the lines beginning with >, they are mark histories.
And there is usually comment in the file.
For example:
# History of marks within files (newest to oldest):
> /tmp/test/whatevertestfile.txt
* 1592998167 0
" 4 0
^ 1 0
. 1 0
+ 1 0
a 4 0
b 9 0
update
Oh, I just noticed you mentioned file marks in the question. Then you are looking at the right block.
The positions in the two lines are always the same because the write_one_filemark() function reads the same values for the two lines.
The first 4 is an index in the viminfo file, it indicates the mark type.
The 48 is the ascii code of the numbered mark 0 .
Then come the position + ts + filename
If you want to know more detailed, why it is so defined and so on, you can read the related part of this file
https://github.com/vim/vim/blob/master/src/viminfo.c

How to use loops to print the below pattern?

I am trying to produce this pattern:
1
12
123
1234
12345
Currently, I represent a row with range(1,6) and I get five rows with the outer loop. I use an inner loop that represents j with range(1,i) five columns.
But I am not getting the desired outcome as above.
This is what i have started with:
for i in range(1,6):#where i represents 5 Rows
print('list of int inside range:',i)
for j in range(1,i):#where j represents 5 columns
print(j)
2 things:
You need to avoid printing a newline on each print, and instead print it at the end of each outer loop. Use the end parameter to print to do this.
Your use of range() isn't quite right -- for example, in the first loop you'd be doing range(1,1) which has no values. This is called an 'off by one' error. Instead, start it at 0 and print one higher than the value of j.
With the above changes, and removing the debug print that you were doing:
for i in range(1,6):#where i represents 5 Rows
for j in range(0,i):#where j represents 5 columns
print(j+1, end='')
print();

is it possible to index character strings pulled from an external .txt file?

I'm in a basic MATLAB college course, and need some help with my code.
theres an external .txt file with names in it, with corresponding numbers assigned to each name. my goal is to place all the first names, last names, and numbers into arrays, find the lowest number in the 'number' array, get the corresponding indexer number, and print the first and last name related with that number.
the text file reads 25 different names and numbers
(i.e.:
Bob
Smith
17
Jane
Doe
23
Bill
Johnson
13
...etc...)
here is my general code so far:
1 clear
2
3 clc
4
5
6 fid1=fopen('facedata.txt','rt');
7
8 for index = 1:1:25
9 firstn(index) = fgetl(fid1);
10 lastn(index) = fgetl(fid1);
11 number(index) = fscanf(fid1,'%f');
12 end
13
14 [distmin,I] = min(dist);
15 fprintf('%5.4f %10s %10.0f', distmin, firstn(I), I);
My hope is for the code to run through, get matlab to recognize '13' as the lowest number, and print 'bill johnson' to the screen, but if I run the code, matlab says there are errors
Subscripted assignment dimension mismatch.' # line 9.
and
Index exceeds matrix dimensions.' # the firstn**(I)** in line 15.
any ideas?? i know this is crazy long, but any help would be appreciated! :]
The command fgetl means read a line from the text file. Therefore your code is reading 2x25 = 50 lines of text. How do you know that your file has this many lines in it? You should read a new line, process it, and repeat until you reach the end of the file:
fid = fopen('fgetl.m');
tline = fgetl(fid);
while ischar(tline)
disp(tline)
tline = fgetl(fid);
end
fclose(fid);
However, this would not do what you want. You should rather use fscanf to read data in the format you want. You want to read two consecutive strings (first name, last name) and an integer number. So you can use
A = fscanf(fid, '%s %s %d', [3 inf]);
to read three items at a time and repeat until the end of the file.
I answered my own question earlier today, but here's what I found if anyone is interested:
you have to index a line of string by using curly brackets instead of straight ones.
i.e.:
for index = 1:1:25
firstname{index} = fgetl(fid1);
end
fprintf('%10s', firstn{index});
fprintf will print whichever number index is supplied.
thanks anyway kavka :]

How to column-ify an output from a certain program?

I have a program that generates and outputs a sequence of simple sample math homework tasks, like:
1 + 1 = ...
3 + 3 = ...
2 + 5 = ...
3 + 7 = ...
4 + 2 = ...
a sequence can be quite long, and I'd like to save space when this sequence is printed by converting it as follows:
1 + 1 = ... 3 + 7 = ...
3 + 3 = ... 4 + 2 = ...
2 + 5 = ...
that is, wrapping the lines into the two or more columns. I was expecting the column linux utility to do the job using the -c N option witn N=2, however, it still outputs the lines in one column whatever the N is.
How would I do the column-ifying of the sequence of lines?
Believe it or not, the utility you want is pr, not columns. If you want your file turned into 3 columns:
pr -3 textfile.txt
If you want to fill in rows first, then columns:
pr -l1 -t -3 textfile.txt
I got these sample invocations from the ever-so-useful UNIX Power Tools. This is Recipe 21.16.
The -c parameter to column is used to specify the number of "columns" your display has, counted in characters. The column tool then figures out the number of "output columns" that fits in the given number of "character columns". Passing a small number of "character columns" will almost always yield a single "output column", because more won't fit in the given number of characters. There does not seem to be a way to pass the number of ouput columns on the command line.

Reading a line whose contents depends on the first character

In Fortran, what would be the practical way to read:
A 1. 2. 3.
if the first character is an "A", but to not read the:
Z
rest if the first character is a "Z" for example.
If I try to read the line at whole:
read(1,*)char, number1, number2, number3
then an error will occur if the numbers are missing. So I need a way to read an "A" stay on that line, and depending on the "A" or a "Z" read, if needed the rest.
Here is a good trick you may not know. You can put a character variable in place where the unit number is in the read statement. You would be reading from the variable instead of the file.
Start by declaring a character variable long enough to read the longest line. Read the whole line into this variable. From the variable, read that first character. If it is an A, read in the numbers. It would look like this:
character*130 :: MyLine
read(1,'(a130)') MyLine
read(MyLine,*) char
if (char == 'A') then
read(MyLine,*) char, number1, number2, number3
endif
You can always read the flag and use an expression in the iolist to determine whether you want to read any more stuff.
az.f90:
program az
implicit none
real number1, number2, number3
character azflag
integer iunit
integer i
open(newunit=iunit,file='az.txt',status='old')
do
number1 = -1
number2 = -1
number3 = -1
read(iunit,*,end=10) azflag, (number1,number2,number3 &
,i=1,merge(1,0,any(azflag==['A','a'])))
if(any(azflag==['A','a'])) then
write(*,*) 'numbers read!'
else
write(*,*) 'nothing read'
end if
write(*,*) number1, number2, number3
end do
10 continue
end program az
az.txt:
A 1. 2. 3.
Z
a 4. 5. 6.
z
Output:
numbers read!
1.000000 2.000000 3.000000
nothing read
-1.000000 -1.000000 -1.000000
numbers read!
4.000000 5.000000 6.000000
nothing read
-1.000000 -1.000000 -1.000000
A slight deviation from what you want would be to replace the first letter by the number of numbers to read, like
3 1. 2. 3.
0
2 3.14 -1.
Then if the maximum number of elements you want to read in each row is nmax then declare
integer::i,n
real(dimension=nmax)::number
and use
read(1,*) n, (number(i), i=1,n)
If you really want to keep using letters, you can hack something using iachar() to get the ASCII value of the character converted into the number of reals to read.

Resources