Michael wrote:
> Here is a string from the input file:
>
> Кристалл(микросхема) № 1 Пластина № 0000 Партия № 7
In UTF-8 encoding, every Cyrillic letter and "№" needs more than a byte,
the 0, 1, 7, " ", "(" and ")" need one byte.
> The program reads the number of the element:
> read(1,'(A)',err=31,end=31)str
> if(index(trim(str),'Кристалл(микросхема)').ne.0) then
> el_cnt=el_cnt+1
> j=index(str,'№')
> read(str(j+2:),*)numbers(el_cnt)
Trying your code shows, it works if you use "j+3" instead of "j+2". You
can see it yourself if you write:
write(*,*) str(j+2:)
or
write(*,*) str(j+3:)
In principle, it would be better to use Fortran 2003's Unicode support.
In that case, the compiler already knows that the input is in UTF-8 and
one character in the string matches a single character - without the
need to worry about the the number of bytes.
gfortran (since GCC 4.4) handles Unicode; unfortunately, it currently
does not allow one to enter Unicode characters directly in the input.
The following program works, but I admit it is a bit ugly with the
backslashes - and the backslash notation is admittedly also not fully
standard conform (but more readable that char(...,kind=...)).
The support of directly inputting UTF-8 characters is on the to-do list,
but unfortunately, that list is rather long. (Additional contributors
are highly welcome; thus, if you (or someone else) is interested …)
Tobias
! compile with "gfortran -fbackslash"
program test
use iso_fortran_env, only: output_unit
implicit none
integer, parameter :: ucs4 = selected_char_kind ('ISO_10646')
character(kind=ucs4), parameter :: &
No_char = char(int(z'2116'),kind=ucs4) ! = №
character(kind=ucs4, len=100) :: str
integer :: j, numbers
open (output_unit, encoding='UTF-8')
open (99, file="test.dat", encoding='UTF-8')
read(99,'(A)')str
if(index(trim(str), & ! 'Кристалл(микросхема)'
ucs4_'\u041A\u0440\u0438\u0441\u0442\u0430\u043B\u043B(' &
//ucs4_'\u043C\u0438\u043A\u0440\u043E\u0441\u0445\u0435\u043C\u0430)'&
).ne.0) then
j=index(str,No_char)
! print *, 'Debug output:',trim(str(j+2:))
read(str(j+2:),*)numbers
end if
print *, numbers
end