Skip to content

implemented pad function #441

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Jul 5, 2021
108 changes: 108 additions & 0 deletions doc/specs/stdlib_strings.md
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,114 @@ end program demo_replace_all
```


<!-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -->
### `padl`

#### Description

Returns a string of length `output_length` left padded with `pad_with` character if it is provided, otherwise with `" "` (1 whitespace).
If `output_length` is less than or equal to the length of `string`, padding is not performed.

#### Syntax

`string = [[stdlib_strings(module):padl(interface)]] (string, output_length [, pad_with])`

#### Status

Experimental

#### Class

Pure function

#### Argument

- `string`: Character scalar or [[stdlib_string_type(module):string_type(type)]].
This argument is intent(in).
- `output_length`: integer.
This argument is intent(in).
- `pad_with`: Character scalar of length 1.
This argument is intent(in) and optional.

#### Result value

The result is of the same type as `string`.

#### Example

```fortran
program demo_padl
use stdlib_string_type, only: string_type, assignment(=)
use stdlib_strings, only : padl
implicit none
string_type :: string

string = "left pad this string"
! string <-- "left pad this string"

print *, padl(string, 25, "$") ! "$$$$$left pad this string"

string = padl(string, 25)
! string <-- " left pad this string"

end program demo_padl
```


<!-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -->
### `padr`

#### Description

Returns a string of length `output_length` right padded with `pad_with` character if it is provided, otherwise with `" "` (1 whitespace).
If `output_length` is less than or equal to the length of `string`, padding is not performed.

#### Syntax

`string = [[stdlib_strings(module):padr(interface)]] (string, output_length [, pad_with])`

#### Status

Experimental

#### Class

Pure function

#### Argument

- `string`: Character scalar or [[stdlib_string_type(module):string_type(type)]].
This argument is intent(in).
- `output_length`: integer.
This argument is intent(in).
- `pad_with`: Character scalar of length 1.
This argument is intent(in) and optional.

#### Result value

The result is of the same type as `string`.

#### Example

```fortran
program demo_padr
use stdlib_string_type, only: string_type, assignment(=)
use stdlib_strings, only : padr
implicit none
string_type :: string

string = "right pad this string"
! string <-- "right pad this string"

print *, padr(string, 25, "$") ! "right pad this string$$$$"

string = padr(string, 25)
! string <-- "right pad this string "

end program demo_padr
```


<!-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -->
### `count`

Expand Down
147 changes: 145 additions & 2 deletions src/stdlib_strings.f90
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@
!> The specification of this module is available [here](../page/specs/stdlib_strings.html).
module stdlib_strings
use stdlib_ascii, only: whitespace
use stdlib_string_type, only: string_type, char, verify
use stdlib_string_type, only: string_type, char, verify, repeat, len
use stdlib_optval, only: optval
implicit none
private

public :: strip, chomp
public :: starts_with, ends_with
public :: slice, find, replace_all, count
public :: slice, find, replace_all, padl, padr, count


!> Remove leading and trailing whitespace characters.
Expand Down Expand Up @@ -93,6 +93,28 @@ module stdlib_strings
module procedure :: replace_all_char_char_char
end interface replace_all

!> Version: experimental
!>
!> Left pad the input string
!> [Specifications](../page/specs/stdlib_strings.html#padl)
interface padl
module procedure :: padl_string_default
module procedure :: padl_string_pad_with
module procedure :: padl_char_default
module procedure :: padl_char_pad_with
end interface padl

!> Version: experimental
!>
!> Right pad the input string
!> [Specifications](../page/specs/stdlib_strings.html#padr)
interface padr
module procedure :: padr_string_default
module procedure :: padr_string_pad_with
module procedure :: padr_char_default
module procedure :: padr_char_pad_with
end interface padr

!> Version: experimental
!>
!> Returns the number of times substring 'pattern' has appeared in the
Expand Down Expand Up @@ -659,6 +681,127 @@ pure function replace_all_char_char_char(string, pattern, replacement) result(re

end function replace_all_char_char_char

!> Left pad the input string with " " (1 whitespace)
!>
!> Returns a new string
pure function padl_string_default(string, output_length) result(res)
type(string_type), intent(in) :: string
integer, intent(in) :: output_length
type(string_type) :: res

res = string_type(padl(char(string), output_length, " "))

end function padl_string_default

!> Left pad the input string with the 'pad_with' character
!>
!> Returns a new string
pure function padl_string_pad_with(string, output_length, pad_with) result(res)
type(string_type), intent(in) :: string
integer, intent(in) :: output_length
character(len=1), intent(in) :: pad_with
type(string_type) :: res

res = string_type(padl(char(string), output_length, pad_with))

end function padl_string_pad_with

!> Left pad the input string with " " (1 whitespace)
!>
!> Returns a new string
pure function padl_char_default(string, output_length) result(res)
character(len=*), intent(in) :: string
integer, intent(in) :: output_length
character(len=max(len(string), output_length)) :: res

res = padl(string, output_length, " ")

end function padl_char_default

!> Left pad the input string with the 'pad_with' character
!>
!> Returns a new string
pure function padl_char_pad_with(string, output_length, pad_with) result(res)
character(len=*), intent(in) :: string
integer, intent(in) :: output_length
character(len=1), intent(in) :: pad_with
character(len=max(len(string), output_length)) :: res
integer :: string_length

string_length = len(string)

if (string_length < output_length) then
res = repeat(pad_with, output_length - string_length)
res(output_length - string_length + 1 : output_length) = string
else
res = string
end if

end function padl_char_pad_with

!> Right pad the input string with " " (1 whitespace)
!>
!> Returns a new string
pure function padr_string_default(string, output_length) result(res)
type(string_type), intent(in) :: string
integer, intent(in) :: output_length
character(len=max(len(string), output_length)) :: char_output
type(string_type) :: res

! We're taking advantage of `char_output` being longer than `string` and
! initialized with whitespaces. By casting `string` to a `character`
! type and back to `string_type`, we're effectively right-padding
! `string` with spaces, so we don't need to pad explicitly.
char_output = char(string)
res = string_type(char_output)

end function padr_string_default

!> Right pad the input string with the 'pad_with' character
!>
!> Returns a new string
pure function padr_string_pad_with(string, output_length, pad_with) result(res)
type(string_type), intent(in) :: string
integer, intent(in) :: output_length
character(len=1), intent(in) :: pad_with
type(string_type) :: res

res = string_type(padr(char(string), output_length, pad_with))

end function padr_string_pad_with

!> Right pad the input string with " " (1 whitespace)
!>
!> Returns a new string
pure function padr_char_default(string, output_length) result(res)
character(len=*), intent(in) :: string
integer, intent(in) :: output_length
character(len=max(len(string), output_length)) :: res

res = string

end function padr_char_default

!> Right pad the input string with the 'pad_with' character
!>
!> Returns a new string
pure function padr_char_pad_with(string, output_length, pad_with) result(res)
character(len=*), intent(in) :: string
integer, intent(in) :: output_length
character(len=1), intent(in) :: pad_with
character(len=max(len(string), output_length)) :: res
integer :: string_length

string_length = len(string)

res = string
if (string_length < output_length) then
res(string_length + 1 : output_length) = &
repeat(pad_with, output_length - string_length)
end if

end function padr_char_pad_with

!> Returns the number of times substring 'pattern' has appeared in the
!> input string 'string'
!> Returns an integer
Expand Down
78 changes: 77 additions & 1 deletion src/tests/string/test_string_functions.f90
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ module test_string_functions
use stdlib_error, only : check
use stdlib_string_type, only : string_type, assignment(=), operator(==), &
to_lower, to_upper, to_title, to_sentence, reverse
use stdlib_strings, only: slice, find, replace_all, count
use stdlib_strings, only: slice, find, replace_all, padl, padr, count
use stdlib_optval, only: optval
use stdlib_ascii, only : to_string
implicit none
Expand Down Expand Up @@ -378,6 +378,80 @@ subroutine test_replace_all

end subroutine test_replace_all

subroutine test_padl
type(string_type) :: test_string
character(len=:), allocatable :: test_char

test_string = "left pad this string"
test_char = " left pad this string "

! output_length > len(string)
call check(padl(test_string, 25, "#") == "#####left pad this string", &
& 'padl: output_length > len(string), test_case 1')
call check(padl(test_string, 22, "$") == "$$left pad this string", &
& 'padl: output_length > len(string), test_case 2')
call check(padl(test_string, 23) == " left pad this string", &
& 'padl: output_length > len(string), test_case 3')
call check(padl(test_char, 26) == " left pad this string ", &
& 'padl: output_length > len(string), test_case 4')
call check(padl(test_char, 26, "&") == "&& left pad this string ", &
& 'padl: output_length > len(string), test_case 5')
call check(padl("", 10, "!") == "!!!!!!!!!!", &
& 'padl: output_length > len(string), test_case 6')

! output_length <= len(string)
call check(padl(test_string, 18, "#") == "left pad this string", &
& 'padl: output_length <= len(string), test_case 1')
call check(padl(test_string, -4, "@") == "left pad this string", &
& 'padl: output_length <= len(string), test_case 2')
call check(padl(test_char, 20, "0") == " left pad this string ", &
& 'padl: output_length <= len(string), test_case 3')
call check(padl(test_char, 17) == " left pad this string ", &
& 'padl: output_length <= len(string), test_case 4')
call check(padl("", 0, "!") == "", &
& 'padl: output_length <= len(string), test_case 5')
call check(padl("", -12, "!") == "", &
& 'padl: output_length <= len(string), test_case 6')

end subroutine test_padl

subroutine test_padr
type(string_type) :: test_string
character(len=:), allocatable :: test_char

test_string = "right pad this string"
test_char = " right pad this string "

! output_length > len(string)
call check(padr(test_string, 25, "#") == "right pad this string####", &
& 'padr: output_length > len(string), test_case 1')
call check(padr(test_string, 22, "$") == "right pad this string$", &
& 'padr: output_length > len(string), test_case 2')
call check(padr(test_string, 24) == "right pad this string ", &
& 'padr: output_length > len(string), test_case 3')
call check(padr(test_char, 27) == " right pad this string ", &
& 'padr: output_length > len(string), test_case 4')
call check(padr(test_char, 27, "&") == " right pad this string &&", &
& 'padr: output_length > len(string), test_case 5')
call check(padr("", 10, "!") == "!!!!!!!!!!", &
& 'padr: output_length > len(string), test_case 6')

! output_length <= len(string)
call check(padr(test_string, 18, "#") == "right pad this string", &
& 'padr: output_length <= len(string), test_case 1')
call check(padr(test_string, -4, "@") == "right pad this string", &
& 'padr: output_length <= len(string), test_case 2')
call check(padr(test_char, 20, "0") == " right pad this string ", &
& 'padr: output_length <= len(string), test_case 3')
call check(padr(test_char, 17) == " right pad this string ", &
& 'padr: output_length <= len(string), test_case 4')
call check(padr("", 0, "!") == "", &
& 'padr: output_length <= len(string), test_case 5')
call check(padr("", -12, "!") == "", &
& 'padr: output_length <= len(string), test_case 6')

end subroutine test_padr

subroutine test_count
type(string_type) :: test_string_1, test_string_2, test_pattern_1, test_pattern_2
test_string_1 = "DNA sequence: AGAGAGAGTCCTGTCGAGA"
Expand Down Expand Up @@ -437,6 +511,8 @@ program tester
call test_slice_gen
call test_find
call test_replace_all
call test_padl
call test_padr
call test_count

end program tester