Skip to content

Commit 5089a40

Browse files
authored
Merge pull request #444 from St-Maxwell/zoziha/feature/format_string
Add format_string routine to format other types to strings
2 parents 590adbe + 3e31220 commit 5089a40

14 files changed

+458
-245
lines changed

doc/specs/stdlib_ascii.md

+1-39
Original file line numberDiff line numberDiff line change
@@ -212,42 +212,4 @@ program demo_reverse
212212
implicit none
213213
print'(a)', reverse("Hello, World!") ! returns "!dlroW ,olleH"
214214
end program demo_reverse
215-
```
216-
217-
### `to_string`
218-
219-
#### Status
220-
221-
Experimental
222-
223-
#### Description
224-
225-
Create a character string representing the value of the provided variable.
226-
227-
#### Syntax
228-
229-
`res = [[stdlib_ascii(module):to_string(interface)]] (string)`
230-
231-
#### Class
232-
233-
Pure function.
234-
235-
#### Argument
236-
237-
`val`: shall be an intrinsic integer or logical type. It is an `intent(in)` argument.
238-
239-
#### Result value
240-
241-
The result is an intrinsic character type.
242-
243-
#### Example
244-
245-
```fortran
246-
program demo_string_value
247-
use stdlib_ascii, only : to_string
248-
implicit none
249-
print'(a)', to_string(-3) ! returns "-3"
250-
print'(a)', to_string(.true.) ! returns "T"
251-
print'(a)', to_string(42) ! returns "42"
252-
end program demo_string_value
253-
```
215+
```

doc/specs/stdlib_strings.md

+69
Original file line numberDiff line numberDiff line change
@@ -538,3 +538,72 @@ program demo_count
538538
539539
end program demo_count
540540
```
541+
542+
<!-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -->
543+
### `to_string`
544+
545+
#### Description
546+
547+
Format or transfer a `integer/real/complex/logical` scalar as a string.
548+
Input a wrong `format` that cause the internal-IO to fail, the result value is a string of `[*]`.
549+
550+
#### Syntax
551+
552+
`string = [[stdlib_strings(module):to_string(interface)]] (value [, format])`
553+
554+
#### Status
555+
556+
Experimental
557+
558+
#### Class
559+
560+
Pure function.
561+
562+
#### Argument
563+
564+
- `value`: Shall be an `integer/real/complex/logical` scalar.
565+
This is an `intent(in)` argument.
566+
- `format`: Shall be a `character(len=*)` scalar like `'(F6.2)'` or just `'F6.2'`.
567+
This is an `intent(in)` and `optional` argument.
568+
Contains the edit descriptor to format `value` into a string, for example `'(F6.2)'` or `'(f6.2)'`.
569+
`to_string` will automatically enclose `format` in a set of parentheses, so passing `F6.2` or `f6.2` as `format` is possible as well.
570+
571+
#### Result value
572+
573+
The result is an `allocatable` length `character` scalar with up to `128` cached `character` length.
574+
575+
#### Example
576+
577+
```fortran
578+
program demo_to_string
579+
use stdlib_strings, only: to_string
580+
581+
!> Example for `complex` type
582+
print *, to_string((1, 1)) !! "(1.00000000,1.00000000)"
583+
print *, to_string((1, 1), '(F6.2)') !! "( 1.00, 1.00)"
584+
print *, to_string((1000, 1), '(ES0.2)'), to_string((1000, 1), '(SP,F6.3)')
585+
!! "(1.00E+3,1.00)""(******,+1.000)"
586+
!! Too narrow formatter for real number
587+
!! Normal demonstration(`******` from Fortran Standard)
588+
589+
!> Example for `integer` type
590+
print *, to_string(-3) !! "-3"
591+
print *, to_string(42, '(I4)') !! " 42"
592+
print *, to_string(1, '(I0.4)'), to_string(2, '(B4)') !! "0001"" 10"
593+
594+
!> Example for `real` type
595+
print *, to_string(1.) !! "1.00000000"
596+
print *, to_string(1., '(F6.2)') !! " 1.00"
597+
print *, to_string(1., 'F6.2') !! " 1.00"
598+
print *, to_string(1., '(SP,ES9.2)'), to_string(1, '(F7.3)') !! "+1.00E+00""[*]"
599+
!! 1 wrong demonstration (`[*]` from `to_string`)
600+
601+
!> Example for `logical` type
602+
print *, to_string(.true.) !! "T"
603+
print *, to_string(.true., '(L2)') !! " T"
604+
print *, to_string(.true., 'L2') !! " T"
605+
print *, to_string(.false., '(I5)') !! "[*]"
606+
!! 1 wrong demonstrations(`[*]` from `to_string`)
607+
608+
end program demo_to_string
609+
```

src/CMakeLists.txt

+3-1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ set(fppFiles
3434
stdlib_math_logspace.fypp
3535
stdlib_math_arange.fypp
3636
stdlib_string_type.fypp
37+
stdlib_string_type_constructor.fypp
38+
stdlib_strings_to_string.fypp
39+
stdlib_strings.fypp
3740
)
3841

3942

@@ -52,7 +55,6 @@ set(SRC
5255
stdlib_error.f90
5356
stdlib_kinds.f90
5457
stdlib_logger.f90
55-
stdlib_strings.f90
5658
stdlib_system.F90
5759
stdlib_specialfunctions.f90
5860
stdlib_specialfunctions_legendre.f90

src/Makefile.manual

+59-53
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
SRCFYPP =\
1+
SRCFYPP = \
22
stdlib_ascii.fypp \
33
stdlib_bitsets_64.fypp \
44
stdlib_bitsets_large.fypp \
@@ -27,10 +27,13 @@ SRCFYPP =\
2727
stdlib_stats_moment_scalar.fypp \
2828
stdlib_stats_var.fypp \
2929
stdlib_math.fypp \
30-
stdlib_math_linspace.fypp \
31-
stdlib_math_logspace.fypp \
30+
stdlib_math_linspace.fypp \
31+
stdlib_math_logspace.fypp \
3232
stdlib_stats_distribution_PRNG.fypp \
33-
stdlib_string_type.fypp
33+
stdlib_string_type.fypp \
34+
stdlib_string_type_constructor.fypp \
35+
stdlib_strings.fypp \
36+
stdlib_strings_to_string.fypp
3437

3538
SRC = f18estop.f90 \
3639
stdlib_error.f90 \
@@ -40,7 +43,6 @@ SRC = f18estop.f90 \
4043
stdlib_kinds.f90 \
4144
stdlib_logger.f90 \
4245
stdlib_quadrature_gauss.f90 \
43-
stdlib_strings.f90 \
4446
$(SRCGEN)
4547

4648
LIB = libstdlib.a
@@ -77,85 +79,89 @@ stdlib_error.o: stdlib_optval.o
7779
stdlib_specialfunctions.o: stdlib_kinds.o
7880
stdlib_specialfunctions_legendre.o: stdlib_kinds.o stdlib_specialfunctions.o
7981
stdlib_io.o: \
80-
stdlib_ascii.o \
81-
stdlib_error.o \
82-
stdlib_optval.o \
83-
stdlib_kinds.o
82+
stdlib_ascii.o \
83+
stdlib_error.o \
84+
stdlib_optval.o \
85+
stdlib_kinds.o \
86+
stdlib_ascii.o
8487
stdlib_linalg.o: \
85-
stdlib_kinds.o
88+
stdlib_kinds.o
8689
stdlib_linalg_diag.o: \
87-
stdlib_linalg.o \
88-
stdlib_kinds.o
90+
stdlib_linalg.o \
91+
stdlib_kinds.o
8992
stdlib_logger.o: stdlib_ascii.o stdlib_optval.o
9093
stdlib_optval.o: stdlib_kinds.o
9194
stdlib_quadrature.o: stdlib_kinds.o
92-
9395
stdlib_quadrature_gauss.o: stdlib_kinds.o stdlib_quadrature.o
94-
9596
stdlib_quadrature_simps.o: \
96-
stdlib_quadrature.o \
97-
stdlib_error.o \
98-
stdlib_kinds.o
97+
stdlib_quadrature.o \
98+
stdlib_error.o \
99+
stdlib_kinds.o
99100
stdlib_quadrature_trapz.o: \
100-
stdlib_quadrature.o \
101-
stdlib_error.o \
102-
stdlib_kinds.o
101+
stdlib_quadrature.o \
102+
stdlib_error.o \
103+
stdlib_kinds.o
103104
stdlib_sorting.o: \
104-
stdlib_kinds.o \
105-
stdlib_string_type.o
105+
stdlib_kinds.o \
106+
stdlib_string_type.o
106107
stdlib_sorting_ord_sort.o: \
107-
stdlib_sorting.o
108+
stdlib_sorting.o
108109
stdlib_sorting_sort.o: \
109-
stdlib_sorting.o
110+
stdlib_sorting.o
110111
stdlib_sorting_sort_index.o: \
111-
stdlib_sorting.o
112+
stdlib_sorting.o
112113
stdlib_stats.o: \
113-
stdlib_kinds.o
114+
stdlib_kinds.o
114115
stdlib_stats_corr.o: \
115-
stdlib_optval.o \
116-
stdlib_kinds.o \
117-
stdlib_stats.o
116+
stdlib_optval.o \
117+
stdlib_kinds.o \
118+
stdlib_stats.o
118119
stdlib_stats_cov.o: \
119-
stdlib_optval.o \
120-
stdlib_kinds.o \
121-
stdlib_stats.o
120+
stdlib_optval.o \
121+
stdlib_kinds.o \
122+
stdlib_stats.o
122123
stdlib_stats_mean.o: \
123-
stdlib_optval.o \
124-
stdlib_kinds.o \
125-
stdlib_stats.o
124+
stdlib_optval.o \
125+
stdlib_kinds.o \
126+
stdlib_stats.o
126127
stdlib_stats_median.o: \
127-
stdlib_optval.o \
128-
stdlib_kinds.o \
129-
stdlib_sorting.o \
130-
stdlib_stats.o
128+
stdlib_optval.o \
129+
stdlib_kinds.o \
130+
stdlib_sorting.o \
131+
stdlib_stats.o
131132
stdlib_stats_moment.o: \
132-
stdlib_optval.o \
133-
stdlib_kinds.o \
134-
stdlib_stats.o
133+
stdlib_optval.o \
134+
stdlib_kinds.o \
135+
stdlib_stats.o
135136
stdlib_stats_moment_all.o: \
136-
stdlib_stats_moment.o
137+
stdlib_stats_moment.o
137138
stdlib_stats_moment_mask.o: \
138-
stdlib_stats_moment.o
139+
stdlib_stats_moment.o
139140
stdlib_stats_moment_scalar.o: \
140-
stdlib_stats_moment.o
141+
stdlib_stats_moment.o
141142
stdlib_stats_var.o: \
142-
stdlib_optval.o \
143-
stdlib_kinds.o \
144-
stdlib_stats.o
143+
stdlib_optval.o \
144+
stdlib_kinds.o \
145+
stdlib_stats.o
145146
stdlib_stats_distribution_PRNG.o: \
146-
stdlib_kinds.o \
147-
stdlib_error.o
147+
stdlib_kinds.o \
148+
stdlib_error.o
148149
stdlib_string_type.o: stdlib_ascii.o \
149150
stdlib_kinds.o
151+
stdlib_string_type_constructor.o: stdlib_string_type.o \
152+
stdlib_strings_to_string.o \
153+
stdlib_strings.o
150154
stdlib_strings.o: stdlib_ascii.o \
151155
stdlib_string_type.o \
152-
stdlib_optval.o
156+
stdlib_optval.o \
157+
stdlib_kinds.o
158+
stdlib_strings_to_string.o: stdlib_strings.o
153159
stdlib_math.o: stdlib_kinds.o \
154160
stdlib_optval.o
155161
stdlib_math_linspace.o: \
156-
stdlib_math.o
162+
stdlib_math.o
157163
stdlib_math_logspace.o: \
158-
stdlib_math_linspace.o
164+
stdlib_math_linspace.o
159165
stdlib_math_arange.o: \
160166
stdlib_math.o
161167
stdlib_linalg_outer_product.o: stdlib_linalg.o

src/stdlib_ascii.fypp

-60
Original file line numberDiff line numberDiff line change
@@ -20,19 +20,6 @@ module stdlib_ascii
2020

2121
! Character conversion functions
2222
public :: to_lower, to_upper, to_title, to_sentence, reverse
23-
public :: to_string
24-
25-
!> Version: experimental
26-
!>
27-
!> Create a character string representing the value of the provided variable.
28-
interface to_string
29-
#:for kind in INT_KINDS
30-
module procedure :: to_string_integer_${kind}$
31-
#:endfor
32-
#:for kind in LOG_KINDS
33-
module procedure :: to_string_logical_${kind}$
34-
#:endfor
35-
end interface to_string
3623

3724
! All control characters in the ASCII table (see www.asciitable.com).
3825
character(len=1), public, parameter :: NUL = achar(int(z'00')) !! Null
@@ -362,51 +349,4 @@ contains
362349

363350
end function reverse
364351

365-
#:for kind in INT_KINDS
366-
!> Represent an integer of kind ${kind}$ as character sequence
367-
pure function to_string_integer_${kind}$(val) result(string)
368-
integer, parameter :: ik = ${kind}$
369-
integer(ik), intent(in) :: val
370-
character(len=:), allocatable :: string
371-
integer, parameter :: buffer_len = range(val)+2
372-
character(len=buffer_len) :: buffer
373-
integer :: pos
374-
integer(ik) :: n
375-
character(len=1), parameter :: numbers(0:9) = &
376-
["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]
377-
378-
if (val == 0_ik) then
379-
string = numbers(0)
380-
return
381-
end if
382-
383-
n = abs(val)
384-
buffer = ""
385-
386-
pos = buffer_len + 1
387-
do while (n > 0_ik)
388-
pos = pos - 1
389-
buffer(pos:pos) = numbers(mod(n, 10_ik))
390-
n = n/10_ik
391-
end do
392-
if (val < 0_ik) then
393-
pos = pos - 1
394-
buffer(pos:pos) = '-'
395-
end if
396-
397-
string = buffer(pos:)
398-
end function to_string_integer_${kind}$
399-
#:endfor
400-
401-
#:for kind in LOG_KINDS
402-
!> Represent an logical of kind ${kind}$ as character sequence
403-
pure function to_string_logical_${kind}$(val) result(string)
404-
integer, parameter :: ik = ${kind}$
405-
logical(ik), intent(in) :: val
406-
character(len=1) :: string
407-
408-
string = merge("T", "F", val)
409-
end function to_string_logical_${kind}$
410-
#:endfor
411-
412352
end module stdlib_ascii

0 commit comments

Comments
 (0)