- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I am reading in input files from a text file. Sometimes the inputs would contain tabs. How do I either ignore the tabs, or recognize them as spaces instead? I am just doing a regular READ statement, but somehow the tabs seems to screw up the READ statement. Fortran doesn't seem to skip over the tabs to the next data point, but instead reads in the tab AS a data point, thus screwing up the rest of the table.
thanks.
thanks.
Link Copied
6 Replies
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You have my sympathy! I once received a data file that had been incompetently passed through a spreadsheet, with the result that it finished up with tabs inside the first number, splitting it into two.
I have always maintained that Fortran should include a Left-justifying function that removes not just leading spaces (as ADJUSTL does), but all leading non-printing characters - which would include tabs. Similarly an addition to TRIM & LEN_TRIM, for trailing, non-printing characters.
I use a function LENGTH that gives the length without trailing, non-printing characters, and a Subroutine JUSTIFY_L that removes leading spaces and tabs. After reading the discussion on "Assumed-length character functions" (which now should be near the top of the pile because I have just posted a reply), I am about to turn JUSTIFY_L into a function. If you are interested, I will post it on this message.
In the mean time it might help you if you first read in each data line as a character string and then search from the start for the first character that is not a space or tab, then read in the next value from there.
Bear of little brain
I have always maintained that Fortran should include a Left-justifying function that removes not just leading spaces (as ADJUSTL does), but all leading non-printing characters - which would include tabs. Similarly an addition to TRIM & LEN_TRIM, for trailing, non-printing characters.
I use a function LENGTH that gives the length without trailing, non-printing characters, and a Subroutine JUSTIFY_L that removes leading spaces and tabs. After reading the discussion on "Assumed-length character functions" (which now should be near the top of the pile because I have just posted a reply), I am about to turn JUSTIFY_L into a function. If you are interested, I will post it on this message.
In the mean time it might help you if you first read in each data line as a character string and then search from the start for the first character that is not a space or tab, then read in the next value from there.
Bear of little brain
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
CVF numeric formatted input treats a tab as if it were a blank. However, a problem can appear if you are using formatted input with specific columns, and the user entered a tab to move to "the next tab stop". Fortran doesn't know about tab stops - a tab is just a single character.
Consider using list-directed input (FMT=*), which is much more forgiving.
Steve
Consider using list-directed input (FMT=*), which is much more forgiving.
Steve
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I am sure that Steve has the correct analysis here, but FWIW I have written a function JUSTIFYL that removes leading spaces and tabs and replaces them with trailing spaces. The length of the string is unchanged, which simplifies the programming. It has not been tested very much, having only just been written, so would anyone brave (or foolhardy) enough to use it please flag up any problems.
C File justifyl.f
MODULE STRINGFNS
CONTAINS
C
FUNCTION JUSTIFYL(STRING)
IMPLICIT NONE
CHARACTER(LEN = *), INTENT(IN) :: STRING
CHARACTER(LEN = LEN(STRING)) JUSTIFYL
INTEGER I, L
L=LEN(STRING)
JUSTIFYL = REPEAT(' ',L) ! Clear out any rubbish (try leaving this out)
I=1
DO WHILE ((STRING(I:I) == ' ' .OR. STRING(I:I) == CHAR(9))
1 .AND. I < L) ! Look for first non-(space or tab) character
I=I+1
END DO
JUSTIFYL(1:L-I+1) = STRING(I:L) ! Shift left
JUSTIFYL(L-I+2:L) = REPEAT(' ',I-1) ! Replace end with spaces
END FUNCTION JUSTIFYL
END MODULE STRINGFNS
C
PROGRAM LJUSTIFY
USE STRINGFNS
IMPLICIT NONE
CHARACTER*30 INSTRING
CHARACTER*1, PARAMETER :: TAB = CHAR(9)
INSTRING = ' '//TAB//' '//TAB//'Test Justifyl'
WRITE(*,'(A)') '#'//INSTRING//'#'
WRITE(*,'(A)') '#'//JUSTIFYL(INSTRING)//'#'
INSTRING = ' Z'
WRITE(*,'(A)') '#'//INSTRING//'#'
WRITE(*,'(A)') '#'//JUSTIFYL(INSTRING)//'#'
INSTRING = TAB//'Z'
WRITE(*,'(A)') '#'//INSTRING//'#'
WRITE(*,'(A)') '#'//JUSTIFYL(INSTRING)//'#'
INSTRING = ''
WRITE(*,'(A)') '#'//INSTRING//'#'
WRITE(*,'(A)') '#'//JUSTIFYL(INSTRING)//'#'
PAUSE
END PROGRAM ljustify
C END OF FILE justifyl.f
Output looks like this, depending on tab settings
# Test Justifyl #
#Test Justifyl #
# Z #
#Z #
# Z #
#Z #
# #
# #
Bear of little brain
C File justifyl.f
MODULE STRINGFNS
CONTAINS
C
FUNCTION JUSTIFYL(STRING)
IMPLICIT NONE
CHARACTER(LEN = *), INTENT(IN) :: STRING
CHARACTER(LEN = LEN(STRING)) JUSTIFYL
INTEGER I, L
L=LEN(STRING)
JUSTIFYL = REPEAT(' ',L) ! Clear out any rubbish (try leaving this out)
I=1
DO WHILE ((STRING(I:I) == ' ' .OR. STRING(I:I) == CHAR(9))
1 .AND. I < L) ! Look for first non-(space or tab) character
I=I+1
END DO
JUSTIFYL(1:L-I+1) = STRING(I:L) ! Shift left
JUSTIFYL(L-I+2:L) = REPEAT(' ',I-1) ! Replace end with spaces
END FUNCTION JUSTIFYL
END MODULE STRINGFNS
C
PROGRAM LJUSTIFY
USE STRINGFNS
IMPLICIT NONE
CHARACTER*30 INSTRING
CHARACTER*1, PARAMETER :: TAB = CHAR(9)
INSTRING = ' '//TAB//' '//TAB//'Test Justifyl'
WRITE(*,'(A)') '#'//INSTRING//'#'
WRITE(*,'(A)') '#'//JUSTIFYL(INSTRING)//'#'
INSTRING = ' Z'
WRITE(*,'(A)') '#'//INSTRING//'#'
WRITE(*,'(A)') '#'//JUSTIFYL(INSTRING)//'#'
INSTRING = TAB//'Z'
WRITE(*,'(A)') '#'//INSTRING//'#'
WRITE(*,'(A)') '#'//JUSTIFYL(INSTRING)//'#'
INSTRING = ''
WRITE(*,'(A)') '#'//INSTRING//'#'
WRITE(*,'(A)') '#'//JUSTIFYL(INSTRING)//'#'
PAUSE
END PROGRAM ljustify
C END OF FILE justifyl.f
Output looks like this, depending on tab settings
# Test Justifyl #
#Test Justifyl #
# Z #
#Z #
# Z #
#Z #
# #
# #
Bear of little brain
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Apologies for that - I had hoped that the magic instructions were no longer necessary after the change of the appearance of the forum. I'll try again.
Bear of little brain
C File justifyl.f MODULE STRINGFNS CONTAINS C FUNCTION JUSTIFYL(STRING) IMPLICIT NONE CHARACTER(LEN = *), INTENT(IN) :: STRING CHARACTER(LEN = LEN(STRING)) JUSTIFYL INTEGER I, L L=LEN(STRING) JUSTIFYL = REPEAT(' ',L) ! Clear out any rubbish (try leaving this out) I=1 DO WHILE ((STRING(I:I) == ' ' .OR. STRING(I:I) == CHAR(9)) 1 .AND. I < L) ! Look for first non-(space or tab) character I=I+1 END DO JUSTIFYL(1:L-I+1) = STRING(I:L) ! Shift left JUSTIFYL(L-I+2:L) = REPEAT(' ',I-1) ! Replace end with spaces END FUNCTION JUSTIFYL END MODULE STRINGFNS C PROGRAM LJUSTIFY USE STRINGFNS IMPLICIT NONE CHARACTER*30 INSTRING CHARACTER*1, PARAMETER :: TAB = CHAR(9) INSTRING = ' '//TAB//' '//TAB//'Test Justifyl' WRITE(*,'(A)') '#'//INSTRING//'#' WRITE(*,'(A)') '#'//JUSTIFYL(INSTRING)//'#' INSTRING = ' Z' WRITE(*,'(A)') '#'//INSTRING//'#' WRITE(*,'(A)') '#'//JUSTIFYL(INSTRING)//'#' INSTRING = TAB//'Z' WRITE(*,'(A)') '#'//INSTRING//'#' WRITE(*,'(A)') '#'//JUSTIFYL(INSTRING)//'#' INSTRING = '' WRITE(*,'(A)') '#'//INSTRING//'#' WRITE(*,'(A)') '#'//JUSTIFYL(INSTRING)//'#' PAUSE END PROGRAM ljustify C END OF FILE justifyl.f Output looks like this, depending on tab settings # Test Justifyl # #Test Justifyl # # Z # #Z # # Z # #Z # # # # #
Bear of little brain
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I'm not quite sure what you're trying to achieve here. If you want to eliminate any leading block of tabs and spaces, you could simplify your function body a bit with:
If you want to turn all tabs to spaces, you could cast the string into a character array and use array intrinsics:
Or if you wanted to squeeze out all the tabs,
None of the above seem entirely inconsistent with your description of the problem. You may wan to look up the topics "Character assignment statements" and "Character functions, categories of" in the online docs.
i = verify(string, achar(20)//achar(9)) if(i == 0) then justifyl = ' ' else justifyl = string(i:) end if
If you want to turn all tabs to spaces, you could cast the string into a character array and use array intrinsics:
character temp(len(string)) temp = transfer(string, temp) temp = merge(temp, ' ', temp /= achar(9)) justifyl = transfer(temp, justifyl) ! And now perhaps justifyl = adjustl(justifyl)
Or if you wanted to squeeze out all the tabs,
character temp(len(string)) temp = transfer(string, temp) temp = pack(temp, temp /= achar(9), spread(' ', 1, len(string))) justifyl = transfer(temp, justifyl) ! And now perhaps justifyl = adjustl(justifyl)
None of the above seem entirely inconsistent with your description of the problem. You may wan to look up the topics "Character assignment statements" and "Character functions, categories of" in the online docs.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Among other possible errors in my untested code above, achar(20) should be changed to achar(32) -- I always think about ASCII codes in hex.

Reply
Topic Options
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page