FIle handling in Eiffel - file-io

Given a file input.txt, which consists of a number of elements in arrays and elements in the arrays, I should read the data and copy it to arrays in Eiffel. For example, for
3
3 4 5
2 3 1
I should get len = 3, a1 = {3,4,5}, a2 = {2,3,1}.
I have tried the following but it was not successful
take_input
-- Read user's input.
local
input: PLAIN_TEXT_FILE
output: PLAIN_TEXT_FILE
itr: INTEGER
do
create input.make_open_read ("input.txt")
input.read_integer
len := input.last_integer
create output.make_open_write ("output.txt")
create num.make_filled (0, 1, len)
create rem.make_filled (0, 1, len)
from
input.start
input.read_integer
itr := 0
until
input.off
loop
itr := itr + 1
if itr <= len then
num [itr] := input.last_integer
input.read_integer
else
rem [itr - len] := input.last_integer
input.read_integer
end
end
input.close
end
Here Is there any way I can continously read the inputs rather than again starting from the Begginning of the file?

There is no need to go to the beginning of the file after reading the number of elements. Therefore, removing input.start right after from will do the trick.
As a sanity check (in case it matters for your program), it makes sense to test whether len is positive before starting the loop.

Related

How do you detect blank lines in Fortran?

Given an input that looks like the following:
123
456
789
42
23
1337
3117
I want to iterate over this file in whitespace-separated chunks in Fortran (any version is fine). For example, let's say I wanted to take the average of each chunk (e.g. mean(123, 456, 789) then mean(42, 23, 1337) then mean(31337)).
I've tried iterating through the file normally (e.g. READ), reading in each line as a string and then converting to an int and doing whatever math I want to do on each chunk. The trouble here is that Fortran "helpfully" ignores blank lines in my text file - so when I try and compare against the empty string to check for the blank line, I never actually get a .True. on that comparison.
I feel like I'm missing something basic here, since this is a typical functionality in every other modern language, I'd be surprised if Fortran didn't somehow have it.
If you're using so-called "list-directed" input (format = '*'), Fortran does special handling to spaces, commas, and blank lines.
To your point, there's a feature which is using the BLANK keyword with read
read(iunit,'(i10)',blank="ZERO",err=1,end=2) array
You can set:
blank="ZERO" will return a valid zero value if a blank is found;
blank="NULL" is the default behavior that skips blank/returns an error depending on the input format.
If all your input values are positive, you could use blank="ZERO" and then use the location of zero values to process your data.
EDIT as #vladimir-f has correctly pointed out, you not only have blanks in between lines, but also after the end of the numbers in most lines, so this strategy will not work.
You can instead load everything into an array, and process it afterwards:
program array_with_blanks
integer :: ierr,num,iunit
integer, allocatable :: array(:)
open(newunit=iunit,file='stackoverflow',form='formatted',iostat=ierr)
allocate(array(0))
do
read(iunit,'(i10)',iostat=ierr) num
if (is_iostat_end(ierr)) then
exit
else
array = [array,num]
endif
end do
close(iunit)
print *, array
end program
Just read each line as a character (but note Francescalus's comment on the format). Then read the character as an internal file.
program stuff
implicit none
integer io, n, value, sum
character (len=1000) line
n = 0
sum = 0
io = 0
open( 42, file="stuff.txt" )
do while( io == 0 )
read( 42, "( a )", iostat = io ) line
if ( io /= 0 .or. line == "" ) then
if ( n > 0 ) print *, ( sum + 0.0 ) / n
n = 0
sum = 0
else
read( line, * ) value
n = n + 1
sum = sum + value
end if
end do
close( 42 )
end program stuff
456.000000
467.333344
3117.00000

Confused Beginner learning Python

I am working on a problem in Python and don't understand the answer.
for number in range(1, 10):
if number % 2 == 0:
print(number)
The answer to this problem is 2,4,6,8
Can anyone explain this answer?
range is a function in python which generates a sequence of integers, for example:
r=range(3)
returns a iterable object range(0,3) which generates sequence of integers from 0 to 3-1(2),inorder for you to see the elements in it , you can loop through it:
for i in r:
print(i)
#prints number from 0 to 3-1
Or, wrap it in a list:
list(range(3)) //returns [0,1,2]
range can take 3 params as input start,end and optionally step.The parameters start and end are basically lower and upper bounds to the sequence.In the above example since we have given only one integer range considers start as 0 and end as 3. This function range(start,end,[step]) generates integers in the following manner: start,start+1....end-1 considering the above example 0,0+1...3-1
if you give both the start and the end params to the range, the function generates integers from start upto but not including end, Example:
for i in range(3,8):print(i) #prints numbers from 3 to 8-1
if you give the third parameter which is the step(which is usually 1 by default), then range adds that number to the sequence :
list(range(3,8)) or list(range(3,8,1)) # will return [3,4,5,6,7],sequence generation will be like:3,3+1,(3+1)+1...
list(range(3,8,2)) #returns [3,5,7];3,3+2,(3+2)+2....
So , coming to your question now :
for number in range(1, 10): if number % 2 == 0: print(number)
In the above code you are basically telling python to loop over the sequence of integeres between 1 to 9 and print the numbers which are divisible by 2,which prints 2,4,6,8.
Hope this helped you :)

Halcon - Variable iconic variable name

I have follwoing code:
for i:=0 to num_stripes by 1
R := Row1 + 5*i
gen_rectangle1(TransStripe, R,Column1,R+4, Column2)
intersection(TransStripe, LabelSelcted, RegionIntersection)
smallest_rectangle1(RegionIntersection, dummy, BeginCol, dummy, EndCol)
inizio := BeginCol - 5
fine := EndCol + 5
area_center(RegionIntersection, dummy, centro_row, centro_col)
gen_rectangle1(Str, R, inizio, R+4, fine)
dev_set_color('red')
dev_display(Str)
endfor
In the last few lines, I create a rectangle named Str. Is there a way to create names on the fly, so that i have a variable for each rectangle? Str1, Str2 ...
Unfortunately, there isn't a direct way to do this. There are a few workarounds:
Concatenating objects:
gen_empty_obj (EmptyObject)
for Index := 1 to 5 by 1
gen_rectangle1 (Rectangle, 30, 20, 100, 200*Index)
concat_obj (EmptyObject, Rectangle, EmptyObject)
endfor
** Selecting
select_obj (EmptyObject, ObjectSelected, 3)
Using vectors (Halcon 12+ version required)
for Index := 0 to 4 by 1
gen_rectangle1 (Rectangle.at(Index), 30, 20, 100, 200*(Index+1))
endfor
** Selecting
Object := Rectangle.at(2)
It is also possible to use vectors as structures and adding multiple levels, where one level would be the names and other objects or values. If you'd like to read more about it, I wrote an article: https://subpixel.hr/halcon-is-like-a-box-of-chocolates/

How to load 2D array from a text(csv) file into Octave?

Consider the following text(csv) file:
1, Some text
2, More text
3, Text with comma, more text
How to load the data into a 2D array in Octave? The number can go into the first column, and all text to the right of the first comma (including other commas) goes into the second text column.
If necessary, I can replace the first comma with a different delimiter character.
AFAIK you cannot put stings of different size into an array. You need to create a so called cell array.
A possible way to read the data from your question stored in a file Test.txt into a cell array is
t1 = textread("Test.txt", "%s", "delimiter", "\n");
for i = 1:length(t1)
j = findstr(t1{i}, ",")(1);
T{i,1} = t1{i}(1:j - 1);
T{i,2} = strtrim(t1{i}(j + 1:end));
end
Now
T{3,1} gives you 3 and
T{3,2} gives you Text with comma, more text.
After many long hours of searching and debugging, here's how I got it to work on Octave 3.2.4. Using | as the delimiter (instead of comma).
The data file now looks like:
1|Some text
2|More text
3|Text with comma, more text
Here's how to call it: data = load_data('data/data_file.csv', NUMBER_OF_LINES);
Limitation: You need to know how many lines you want to get. If you want to get all, then you will need to write a function to count the number of lines in the file in order to initialize the cell_array. It's all very clunky and primitive. So much for "high level languages like Octave".
Note: After the unpleasant exercise of getting this to work, it seems that Octave is not very useful unless you enjoy wasting your time writing code to do the simplest things. Better choices seems to be R, Python, or C#/Java with a Machine Learning or Matrix library.
function all_messages = load_data(filename, NUMBER_OF_LINES)
fid = fopen(filename, "r");
all_messages = cell (NUMBER_OF_LINES, 2 );
counter = 1;
line = fgetl(fid);
while line != -1
separator_index = index(line, '|');
all_messages {counter, 1} = substr(line, 1, separator_index - 1); % Up to the separator
all_messages {counter, 2} = substr(line, separator_index + 1, length(line) - separator_index); % After the separator
counter++;
line = fgetl(fid);
endwhile
fprintf("Processed %i lines.\n", counter -1);
fclose(fid);
end

Do .. While Loop/Textfile/Operation Problem

Hi I have a problem with the following code:
int skp = 1;
do{
file.seekp(skp);
file>>s;
cout<<s;
stats[s]++;
skp++;
skp++;
}while(skp <= 10);
The Textfile has the following:
0
1
2
3
0
1
0
1
0
What I want this programming to do is start from reading the second number which it does, then skip one read next, skip one read the next etc. etc. what it's doing is read the second number which is good, then reads it again for 2 times, then read the next number for 3 times and the next for 3 times. So the output i receive from the above textfile is
1112223330.
Can any one help me please!
Thank you!
That's because your lines are separated by line feeds (actually CR and LF). Also, file >> s will skip leading white space, so you end up with
<CR><LF>1
<LF>1
1
All of which result in s being 1.
The same is repeated for 2, 3 and so on.
Forget yout seekp() and simply use
while (file.good()) {
file >> s; // skip line
if (!file.good()) break;
file >> s;
cout << s;
stats[s]++;
}