Skip to content

Commit 9a86a37

Browse files
committed
add character array example
1 parent 1653937 commit 9a86a37

File tree

11 files changed

+80
-43
lines changed

11 files changed

+80
-43
lines changed

character/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
add_executable(ascii ascii.f90)
22
add_test(NAME char:AsciiSpecial COMMAND ascii)
33

4+
add_executable(character_array character_array.f90)
5+
add_test(NAME char:array COMMAND character_array)
6+
47
add_executable(split split_string.f90)
58
add_test(NAME char:SplitString COMMAND split)
69

character/README.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,22 @@
11
# Strings
22

3+
Strings / character in Fortran is often easier than is commonly thought, as long as the characteristic particular to Fortran are kept in mind.
4+
These examples aim to raise awareness of how to use `character` type in Fortran.
5+
6+
## character array with dissimilar length
7+
8+
Although it is possible to use `allocatable` character array, the
9+
[character_array.f90](./character_array.f90)
10+
example shows the use of fixed lengh `character` array with each element having a distinct length.
11+
312
## Split strings about delimiter
413

514
This splits a string once around a delimiter:
615

716
./split
817

918
And notes that it is probably best to use fixed length CHARACTER longer
10-
than you'll need. If you're trying to load and parse a complicated text
19+
than you'll need.
20+
If you're trying to load and parse a complicated text
1121
file, it is perhaps better to load that file first in Python, parse it,
1222
then pass it to Fortran via f2py (load Fortran code as a Python module).

character/ascii.f90

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
program ascii
2+
!! prints a couple special characters
3+
4+
implicit none
5+
16
print *,'next is a form feed',achar(12)
27
print *,'that was a form feed'
38

character/character_array.f90

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
program character_array
2+
!! examples of using dissimilar character elements in an array
3+
!! the general concept is to make the character(len=) the length of the
4+
!! longest string you will need.
5+
!! trim() each element when actually used if needed.
6+
implicit none
7+
8+
!> specify (*) or maximum len=, else each will be length one.
9+
character(*), parameter :: foo(3) = [character(9) :: 'hi', 'hello', 'greetings']
10+
!! notice how you have to specify the length inside the array.
11+
!! this sometimes has to be done for numerical e.g.
12+
!! mixed integer / real in an array that's actually meant to be real
13+
real, parameter :: mixed(4) = [real :: 27.232, 1, 2, 5.234]
14+
15+
character(9) :: bar(3)
16+
17+
bar = foo
18+
19+
if (.not. all(bar==foo)) error stop
20+
21+
22+
end program

character/charlen.f90

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
1-
! shows how to properly specify character length and character array
1+
program charlen
2+
!! shows how to properly specify character length and character array
3+
implicit none
24

3-
character*(5) :: cb5 ! obsolete, don't use
4-
character(5) :: c5 ! good to use
5-
character(*),parameter :: ca(2)='hello'
5+
character*(5) :: cb5 !< obsolete, don't use
66

7-
if (.not.all([len(cb5)==5,len(c5)==5,len(ca)==5,size(ca)==2])) error stop
7+
!> good to use
8+
character(5) :: c5
9+
character(*), parameter :: ca(2) = ['hello', 'sorry']
10+
11+
if (.not.all([len(cb5)==5, len(c5)==5, len(ca)==5, size(ca)==2])) error stop
812
print *, ca
913

1014
end program

character/meson.build

Lines changed: 10 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,24 @@
11
ascii = executable('ascii', 'ascii.f90')
2-
test('Ascii Special', ascii,
3-
suite: 'char',
4-
timeout: 10)
2+
test('Ascii Special', ascii, suite: 'char', timeout: 10)
3+
4+
char_array = executable('character_array', 'character_array.f90')
5+
test('CharacterArray', char_array, suite: 'char', timeout: 10)
56

67
split = executable('split', 'split_string.f90')
7-
test('Split Character', split,
8-
suite: 'char',
9-
timeout: 10)
8+
test('Split Character', split, suite: 'char', timeout: 10)
109

1110
printorwrite = executable('printorwrite', 'print_vs_write.f90')
12-
test('UTF8', printorwrite,
13-
suite: 'char',
14-
timeout: 10)
11+
test('UTF8', printorwrite, suite: 'char', timeout: 10)
1512

1613
str2int = executable('str2int', 'str2int.f90')
17-
test('Str2Int', str2int,
18-
suite: 'char',
19-
timeout: 10)
14+
test('Str2Int', str2int, suite: 'char', timeout: 10)
2015

2116
special_char = executable('special_char', 'special_characters.f90')
22-
test('Special Characters', special_char,
23-
suite: 'char',
24-
timeout: 10)
17+
test('Special Characters', special_char, suite: 'char', timeout: 10)
2518

2619
charlen = executable('charlen', 'charlen.f90')
27-
test('Character Len', charlen,
28-
suite: 'char',
29-
timeout: 10)
20+
test('Character Len', charlen, suite: 'char', timeout: 10)
3021

3122
overwrite_stdout = executable('overwrite_stdout', 'overwrite_stdout.f90',
3223
link_with: sleep_std)
33-
test('Overwrite Stdout', overwrite_stdout,
34-
suite: 'char',
35-
timeout: 10)
24+
test('Overwrite Stdout', overwrite_stdout, suite: 'char', timeout: 10)

character/overwrite_stdout.f90

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
! overwrites terminal stdout in place e.g. for update status
2-
! char(13) is carriage return
1+
program overwrite_stdout
2+
!! overwrites terminal stdout in place e.g. for update status
3+
!! char(13) is carriage return
34
use, intrinsic:: iso_c_binding, only: c_int
45
use, intrinsic:: iso_fortran_env, only: stdout=>output_unit
56
use sleep_std, only : sleep

character/print_vs_write.f90

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
program print_vs_write
12
!! Fortran 2003 standard states that
23
!! print *,
34
!! write (*,*)

character/special_characters.f90

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1+
program special_characters
12
!! This program shows a few special ASCII characters in Fortran.
23
!! https://en.wikipedia.org/wiki/ASCII#Character_groups
34

45
use iso_c_binding, only: c_null_char
6+
implicit none
7+
58
character, parameter :: &
69
nul = c_null_char, &
710
etx = char(3), &

character/split_string.f90

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,4 @@
1-
! split a string about a delimiter token, return part before delim
2-
!
3-
! with regard to length of CHARACTER, it's probably best to pick a length longer than you'll need
4-
! and trim rather than using assumed size, particularly if interfacing with other languages
5-
! CHARACTER assumed size seems to work, but is not reliable in diverse enviroments.
6-
! Your time is more valueable than a few bytes of RAM.
1+
!! split a string about a delimiter token, return part before delim
72

83
module strutils
94

@@ -27,14 +22,16 @@ end function split
2722
end module strutils
2823

2924

25+
program split_string
3026
use strutils, only: split
27+
implicit none
3128

3229
character(*),parameter :: mystr="hello.txt"
3330
character(:),allocatable :: stem
3431

3532
stem = split(mystr,'.')
3633
print '(A)', stem
3734

38-
if(len(stem) /= 5) error stop 'allocatable character of unexpected length'
35+
if (len(stem) /= 5) error stop 'allocatable character of unexpected length'
3936

4037
end program

0 commit comments

Comments
 (0)