# String split in gfortran

**URL:** https://fortran-lang.discourse.group/t/string-split-in-gfortran/10682
**Category:** GNU
**Created:** [February 1, 2026, 11:35am UTC](https://fortran-lang.discourse.group/t/string-split-in-gfortran/10682 "2026-02-01T11:35:29Z")
**Posts on this page:** 6
**Page:** 1

<div class="post-metadata">

### Author: ![agisteg](https://avatars.discourse-cdn.com/v4/letter/a/73ab20/32.png) [@agisteg](https://fortran-lang.discourse.group/u/agisteg)
#### Post date: [February 1, 2026, 11:35am UTC](https://fortran-lang.discourse.group/t/string-split-in-gfortran/10682/1 "2026-02-01T11:35:29Z")

</div>

Is the new 2023 standard string split subroutine (16.9.196) not implemented in gfortran? I scanned the gcc source code and found that string\_split was defined in `gcc/libgfortran/intrinsics/string_intrinsics_inc.c` and gfortran has the it in the [documentation.](https://gcc.gnu.org/onlinedocs/gfortran/SPLIT.html)

On gcc/gfortran 15.2.1, I can’t compile the program (undefined reference). I can compile on the intel ifx compiler. Here’s the sample I was trying to test it out with.

```fortran
program main

    implicit none

    integer :: i, j, p, n
    character(*), parameter :: input = "a,b,c,d,"

    n = 0
    p = 0
    do while(p <= len(input))

        i = p + 1
        call split(input, ",", p)
        j = p - 1
        n = n + 1
        print "(I0,4x,A)", n, input(i:j)
        
    end do

end program main

```

---

<div class="post-metadata">

### Author: ![wspector](https://avatars.discourse-cdn.com/v4/letter/w/47e85d/32.png) [@wspector](https://fortran-lang.discourse.group/u/wspector)
#### Post date: [February 1, 2026, 5:42pm UTC](https://fortran-lang.discourse.group/t/string-split-in-gfortran/10682/2 "2026-02-01T17:42:46Z")

</div>

It is in the latest builds. My version isn’t quite up to date, but your example seems to work fine:

```auto
$ gfortran string_split.f90
$ ./a.out
1 a
2 b
3 c
4 d
5    
$ gfortran --version
GNU Fortran (GCC) 16.0.0 20251209 (experimental)
Copyright (C) 2025 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$

```

---

<div class="post-metadata">

### Author: ![urbanjost](https://avatars.discourse-cdn.com/v4/letter/u/0ea827/32.png) [@urbanjost](https://fortran-lang.discourse.group/u/urbanjost)
#### Post date: [February 4, 2026, 4:57am UTC](https://fortran-lang.discourse.group/t/string-split-in-gfortran/10682/3 "2026-02-04T04:57:00Z")

</div>

A split procedure from 2020 by @milancurcic if needed that can be contained or placed in a module

> **split.f90**
>
> ```fortran
> !!##AUTHOR
> !! Milan Curcic, "milancurcic@hey.com"
> !!
> !!##LICENSE
> !! Public Domain
> !!
> !!##VERSION
> !! version 0.1.0, copyright 2020, Milan Curcic
> pure subroutine split(string, set, pos, back)
> ! If back is absent, computes the leftmost token delimiter in string whose
> ! position is > pos. If back is present and true, computes the rightmost
> ! token delimiter in string whose position is < pos. The result is stored
> ! in pos.
> character(*), intent(in) :: string
> character(*), intent(in) :: set
> integer, intent(in out) :: pos
> logical, intent(in), optional :: back
> 
> logical :: backward
> character :: set_array(len(set))
> integer :: n, result_pos
> 
> !TODO use optval when implemented in stdlib
> !backward = optval(back, .false.)
> backward = .false.
> if (present(back)) backward = back
> 
> do concurrent(n=1:len(set))
> set_array(n) = set(n:n)
> enddo
> 
> if (backward) then
> result_pos = 0
> do n = pos - 1, 1, -1
> if (any(string(n:n) == set_array)) then
> result_pos = n
> exit
> endif
> enddo
> else
> result_pos = len(string) + 1
> do n = pos + 1, len(string)
> if (any(string(n:n) == set_array)) then
> result_pos = n
> exit
> endif
> enddo
> endif
> 
> pos = result_pos
> 
> end subroutine split
> 
> ```

---

<div class="post-metadata">

### Author: ![Jweber](https://avatars.discourse-cdn.com/v4/letter/j/e95f7d/32.png) [@Jweber](https://fortran-lang.discourse.group/u/Jweber)
#### Post date: [February 4, 2026, 11:41am UTC](https://fortran-lang.discourse.group/t/string-split-in-gfortran/10682/4 "2026-02-04T11:41:40Z")

</div>

According to the changelog on the GCC site,

> **[GCC 16 Release Series — Changes, New Features, and Fixes
- GNU Project](https://gcc.gnu.org/gcc-16/changes.html)**

Version 16 (which will probably officially released the next spring) will be the first version to support it.

---

<div class="post-metadata">

### Author: ![agisteg](https://avatars.discourse-cdn.com/v4/letter/a/73ab20/32.png) [@agisteg](https://fortran-lang.discourse.group/u/agisteg)
#### Post date: [February 7, 2026, 3:02am UTC](https://fortran-lang.discourse.group/t/string-split-in-gfortran/10682/5 "2026-02-07T03:02:14Z")

</div>

Thanks! I must have been looking at the wrong version of the source code.

---

<div class="post-metadata">

### Author: ![agisteg](https://avatars.discourse-cdn.com/v4/letter/a/73ab20/32.png) [@agisteg](https://fortran-lang.discourse.group/u/agisteg)
#### Post date: [February 7, 2026, 3:54am UTC](https://fortran-lang.discourse.group/t/string-split-in-gfortran/10682/6 "2026-02-07T03:54:22Z")

</div>

Thanks I was using a crude strtok-like function that I wrote with another function to aggregate the records to an array.

```fortran
    subroutine strtok(input_string, substring, delimiter)
        character(:), allocatable, intent(in out) :: input_string
        character(:), allocatable, intent(out) :: substring
        character(*), intent(in) :: delimiter
        integer :: i

        i = index(input_string, delimiter)

        if (i < 1) then
            substring = input_string
        else if (i == 1) then
            substring = ""
        else
            substring = input_string(1:i - 1)
        end if

        if (substring == input_string .or. (substring == "" .and. len(input_string) == 0)) then
            deallocate(input_string)
        else
            input_string = input_string(i + len(delimiter):)
        end if

    end subroutine strtok
    
    function tokenize(input_string, delimiter) result(tokens)
        character(*), intent(in) :: input_string, delimiter
        character(:), allocatable :: tmp_string, tokens(:), substring
        integer :: elements, max_len, i

        tmp_string = input_string
        
        elements = 0
        
        max_len = 0
        
        do while (allocated(tmp_string))
        
            call strtok(tmp_string, substring, delimiter)
            
            max_len = max(max_len, len(substring))
            elements = elements + 1
        
        end do
        
        allocate(character(max_len) :: tokens(elements))
        
        tmp_string = input_string

        if (elements > 0) then

            do i = 1, elements

                call strtok(tmp_string, substring, delimiter)

                tokens(i) = substring

            end do

        else
            tokens(1) = input_string
        end if

    end function tokenize

```
