Position after nonadvancing read - io

In N2137 section 12.3.4.2 it says
An advancing input/output statement always positions a record file after the last record read or written, unless there is an error condition.
In section 12.3.4.4 it says
For nonadvancing input, if no error condition or end-of-file condition occurred, but an end-of-record condition (12.11) occurred, the file is positioned after the record just read.
So I would conclude that reading a record with advancing input and encountering an end-of-record condition reading the same record with nonadvancing input should leave the file position in the same place. Here is a sample program:
program testpos1
implicit none
integer iunit
character(80) lineout
character(:), allocatable :: linein
integer i
integer linelen
integer pos
integer size
open(newunit=iunit,file='testpos1.txt',status='replace')
do i = 1, 2
write(lineout,'(*(g0))') i,' line ',i
write(iunit,'(*(g0))') trim(lineout)
end do
close(iunit)
linelen = len_trim(lineout)
allocate(character(linelen) :: linein)
open(newunit=iunit,file='testpos1.txt',status='old',access='stream',form='formatted')
inquire(iunit,pos=pos)
write(*,'(*(g0))') 'Position on open = ',pos
read(iunit,'(a)',advance='no',eor=9999,size=size) linein
inquire(iunit,pos=pos)
write(*,'(*(g0))') 'Position after exact read of first line = ',pos
read(iunit,'(a)',advance='no',eor=10,size=size) linein
write(*,'(*(g0))') 'Catastrophic failure to hit EOR on line 1'
stop
10 continue
inquire(iunit,pos=pos)
write(*,'(*(g0))') 'Position reading past EOR on first line = ',pos
rewind(iunit)
inquire(iunit,pos=pos)
write(*,'(*(g0))') 'Position on rewind = ',pos
read(iunit,'()')
inquire(iunit,pos=pos)
write(*,'(*(g0))') 'Position after advancing read of first line = ',pos
rewind(iunit)
deallocate(linein)
allocate(character(linelen+1) :: linein)
inquire(iunit,pos=pos)
write(*,'(*(g0))') 'Position on rewind = ',pos
read(iunit,'(a)',advance='no',eor=20,size=size) linein
write(*,'(*(g0))') 'Catastrophic failure to hit EOR on line 1'
stop
20 continue
inquire(iunit,pos=pos)
write(*,'(*(g0))') 'Position reading past EOR on first line = ',pos
stop
9999 continue
write(*,'(*(g0))') 'Catastrophic EOR after reading ',size,' bytes'
end program testpos1
Output with gfortran 8.1.0
Position on open = 1
Position after exact read of first line = 9
Position reading past EOR on first line = 11
Position on rewind = 1
Position after advancing read of first line = 11
Position on rewind = 1
Position reading past EOR on first line = 11
This is what I expected. But ifort 16.0.2 says
Position on open = 1
Position after exact read of first line = 9
Position reading past EOR on first line = 9
Position on rewind = 1
Position after advancing read of first line = 11
Position on rewind = 1
Position reading past EOR on first line = 9
So I take it that this is a bug in ifort? Is it fixed in the latest version?

Related

character counter in Python 3 without built in functions

So I have to create a program that reads a paragraph from Romeo & Juliet and returns the number of characters, number of spaces, number of words, and the top 3 most common characters without the use of built in functions such as counter. I made this program to use parallel lists to count unique characters and add a tally into the second list. My problem lies in being able to pick out the top three and print the two lists (i.e. "A 3").
This is the txt file the program reads:
But soft what light through yonder window breaks
It is the east and Juliet is the sun
Arise fair sun and kill the envious moon
Who is already sick and pale with grief
This is the program I have so far:
charCount = []
uniqueChar = []
char_count = 0
word_Count = 0
space_count = 0
Open_File = open("romeo.txt")
for romeo in Open_File:
for char in romeo:
if (char == ' ' or char == '.'):
word_Count += 1
if (char == ' '):
space_count += 1
if (char != ' ' and char != '\n'):
char_count += 1
if (char not in uniqueChar):
uniqueChar.append(char)
charCount.append(1)
else:
for j in range(len(uniqueChar)):
if (uniqueChar[j] == char):
charCount[j] += 1
print("Spaces: ", space_count)
print("Char: ", char_count)
print("Words: ", word_Count)

Insert Charc into String in a Range where character X exist at Index - swift 2.0

Please could somebody help me.
I am trying to add a new line (\n) into an existing string.
Lets say the string is 20+ Characters long, I want to find a space " " between the range of 15 and 20 then inset a new line (\n) just after the index to where the char " " (space) is
I hope that makes sense :F
Code i have for this so far is as follows
var newString = string
newString[newString.startIndex..< newString.startIndex.advancedBy(16)]
/* let startIndex = newString.startIndex.advancedBy(16)
let endIndex = newString.endIndex
let newRange = startIndex ..< endIndex
print("start index = \(newRange)")*/
let range: Range<String.Index> = newString.rangeOfString(" ")!
let index: Int = newString.startIndex.distanceTo(range.startIndex)
newString.insert("\n", atIndex: newString.startIndex.advancedBy(index))
label.text = newString
if I try the following
let newIndex = name.startIndex.advancedBy(19).distanceTo(range.endIndex)
I get the error message
fatal error: can not increment endIndex
Ive got a feeling I'm on the right tracks but the above will inset a new line at the index where space first appears in the string and not between the index of e.g. 15 and 20
Thanks for your help in advance
Thomas
The following finds the first space in the range 15..<END_OF_YOUR_STRING, and replaces it with a new line (\n). In your question you stated you explicitly wanted to look for a space in range 15...20, and also insert a new line after the space. Below I have assumed that you actually want:
To replace the space by a new line, since you'll otherwise have a trailing space on the line following the line break.
To search for the first space starting at index 15, but continuing until you find one (otherwise: if you find no space within range 15...20, no line break should be inserted?).
Both of these deviations from your question can be quite easily reverted, so tell me if you'd prefer me to follow your instructions to specifically to the point (rather than including my own reason), and I'll update this answer.
Solution as follows:
var foo = "This is my somewhat long test string"
let bar = 15 /* find first space " " starting from index 'bar' */
if let replaceAtIndex = foo[foo.startIndex.advancedBy(bar)..<foo.endIndex]
.rangeOfString(" ")?.startIndex.advancedBy(bar) {
foo = foo.stringByReplacingCharactersInRange(
replaceAtIndex...replaceAtIndex, withString: "\n")
}
print(foo)
/* This is my somewhat
long test string */
Note that there is a off-by-one difference between finding a space in the range of 15 to 20 and the 15:th to 20:th character (the latter is in the range 14...19). Above, we search for the first space starting at the 16th character (index 15).
Thanks to dfri for pointing me in the right direction. Although his answer was correct for my problem specifically I've provided the following code to help
if string.characters.count >= 20
{
let bar = 15 // where to split the code to begin looking for the character
let beginString = string.substringWithRange(name.startIndex..<name.startIndex.advancedBy(bar))
var endString = string[string.startIndex.advancedBy(bar)..<name.endIndex]
if endString.containsString(" ")
{
let range = endString.rangeOfString(" ")
if let i = range
{
endString.insert("\n", atIndex:i.startIndex.advancedBy(1) )
let newString = "\(beginString)\(endString)"
label.text = newString
}
}
}

Fortran error: Program received signal SIGSEGV: Segmentation fault - invalid memory reference

I'm try to run an ocean temperature model for 25 years using the explicit method (parabolic differential equation).
If I run for a year a = 3600 or five years a = 18000 it works fine.
However, when I run it for 25 years a = 90000 it crashes.
a is the amount of time steps used. And a year is considered to be 360 days. The time step is 4320 seconds, delta_t = 4320..
Here is my code:
program task
!declare the variables
implicit none
! initial conditions
real,parameter :: initial_temp = 4.
! vertical resolution (delta_z) [m], vertical diffusion coefficient (av) [m^2/s], time step delta_t [s]
real,parameter :: delta_z = 2., av = 2.0E-04, delta_t = 4320.
! gamma
real,parameter :: y = (av * delta_t) / (delta_z**2)
! horizontal resolution (time) total points
integer,parameter :: a = 18000
!declaring vertical resolution
integer,parameter :: k = 101
! declaring pi
real, parameter :: pi = 4.0*atan(1.0)
! t = time [s], temp_a = temperature at upper boundary [°C]
real,dimension(0:a) :: t
real,dimension(0:a) :: temp_a
real,dimension(0:a,0:k) :: temp
integer :: i
integer :: n
integer :: j
t(0) = 0
do i = 1,a
t(i) = t(i-1) + delta_t
end do
! temperature of upper boundary
temp_a = 12. + 6. * sin((2. * t * pi) / 31104000.)
temp(:,0) = temp_a(:)
temp(0,1:k) = 4.
! Vertical resolution
do j = 1,a
do n = 1,k
temp(j,n) = temp(j-1,n) + (y * (temp(j-1,n+1) - (2. * temp(j-1,n)) + temp(j-1,n-1)))
end do
temp(:,101) = temp(:,100)
end do
print *, temp(:,:)
end program task
The variable a is on line 11 (integer,parameter :: a = 18000)
As said, a = 18000 works, a = 90000 doesn't.
At 90000 get I get:
Program received signal SIGSEGV: Segmentation fault - invalid memory reference.
Backtrace for this error:
RUN FAILED (exit value 1, total time: 15s)
I'm using a fortran on windows 8.1, NetBeans and Cygwin (which has gfortran built in).
I'm not sure if this problem is caused through bad compiler or anything else.
Does anybody have any ideas to this? It would help me a lot!
Regards
Take a look at the following lines from your code:
integer,parameter :: k = 101
real,dimension(0:a,0:k) :: temp
integer :: n
do n = 1,k
temp(j,n) = temp(j-1,n) + (y * (temp(j-1,n+1) - (2. * temp(j-1,n)) + temp(j-1,n-1)))
end do
Your array temp has bounds of 0:101, you loop n from 1 to 101 where in iteration n=101 you access temp(j-1,102), which is out of bounds.
This means you are writing to whatever memory lies beyond temp and while this makes your program always incorrect, it is only causing a crash sometimes which depends on various other things. Increasing a triggers this because column major ordering of your array means k changes contiguously and is strided by a, and as a increases your out of bounds access of the second dimension is further in memory beyond temp changing what is getting overwritten by your invalid access.
After your loop you set temp(:,101) = temp(:,100) meaning there is no need to calculate temp(:,101) in the above loop, so you can change its loop bounds from
do n = 1,k
to
do n = 1, k-1
which will fix the out of bounds access on temp.

Python reading from file line by line and char by char

Basically I need to read from file char by char and I need to know at which line that character was. So it's a loop inside a loop.
keyboard = open(default_layout, 'r')
with open(default_layout) as l:
for line in l:
queue=0
#i=i+1
while queue != max_chars_per_key:
c = l.read(1)
<...>
if (queue==0):
key_name=c
key[c] = [key_name, queue+1]
<...>
queue+=1
<...bunch of code...>
The problem is, with this code after passing parameters it gives me:
ValueError: Mixing iteration and read methods would lose data
Any ideas on workaround?
The simplest way to get what you want would be:
with open(...) as fh:
for line_num, line in enumerate(fh):
for col_num, char in enumerate(line):
...
To put that into context with your code, it would be roughly:
keyboard = open(default_layout, 'r')
with open(default_layout) as l:
for line in l:
queue = 0
for c in line[:max_chars_per_key]:
...
if queue == 0:
key_name=c
key[c] = [key_name, queue+1]
...
queue += 1
...

Search text file in MATLAB for a string to begin process

I have a fairly large text file and am trying to search for a particular term so that i can start a process after that point, but this doesn't seem to be working for me:
fileID = fopen(resfile,'r');
line = 0;
while 1
tline = fgetl(fileID);
line = line + 1;
if ischar(tline)
startRow = strfind(tline, 'OptimetricsResult');
if isfinite(startRow) == 1;
break
end
end
end
The answer I get is 9, but my text file:
$begin '$base_index$'
$begin 'properties'
all_levels=000000000000
time(year=000000002013, month=000000000006, day=000000000020, hour=000000000008, min=000000000033, sec=000000000033)
version=000000000000
$end 'properties'
$begin '$base_index$'
$index$(pos=000000492036, lin=000000009689, lvl=000000000000)
$end '$base_index$'
definitely doesn't have that in the first 9 rows?
If I ctrl+F the file, I know that OptimetricsResult only appears once, and that it's 6792 lines down
Any suggestions?
Thanks
I think your script somehow works, and you were just looking at the wrong variable. I assume that the answer you get is startRow = 9 and not line = 9. Check the variable line. By the way, note that you're not checking an End-of-File, so your while loop might run indefinitely the file doesn't contain your search string.
An alternative approach, (which is much simpler in my humble opinion) would be reading all lines at once (each one stored as a separate string) with textscan, and then applying regexp or strfind:
%// Read lines from input file
fid = fopen(filename, 'r');
C = textscan(fid, '%s', 'Delimiter', '\n');
fclose(fid);
%// Search a specific string and find all rows containing matches
C = strfind(C{1}, 'OptimetricsResult');
rows = find(~cellfun('isempty', C));
I can't reproduce your problem.
Are you sure you've properly closed the file before re-running this script? If not, the internal line counter in fgetl does not get reset, so you get false results. Just issue a fclose all on the MATLAB command prompt, and add a fclose(fileID); after the loop, and test again.
In any case, I suggest modifying your infinite-loop (with all sorts of pitfalls) to the following finite loop:
haystack = fopen(resfile,'r');
needle = 'OptimetricsResult';
line = 0;
found = false;
while ~feof(haystack)
tline = fgetl(haystack);
line = line + 1;
if ischar(tline) && ~isempty(strfind(tline, needle))
found = true;
break;
end
end
if ~found
line = NaN; end
fclose(fileID);
line
You could of course also leave the searching to more specialized tools, which come free with most operating systems:
haystack = 'resfile.txt';
needle = 'OptimetricsResult';
if ispc % Windows
[~,lines] = system(['find /n "' needle '" ' haystack]);
elseif isunix % Mac, Linux
[~,lines] = system(['grep -n "' needle '" ' haystack]);
else
error('Unknown operating system!');
end
You'd have to do a bit more parsing to extract the line number from C, but I trust this will be no issue.

Resources