# include # include # include # include # include # include "chrpak.h" /******************************************************************************/ int a_to_i4 ( char ch ) /******************************************************************************/ /* Purpose: a_to_i4() returns the index of an alphabetic character. Example: CH A_TO_I4 'A' 1 'B' 2 ... 'Z' 26 'a' 27 'b' 28 ... 'z' 52 '$' 0 Licensing: This code is distributed under the MIT license. Modified: 01 July 2008 Author: John Burkardt Input: char CH, a character. Output: int A_TO_I4, is the alphabetic index of the character, between 1 and 26 if the character is a capital letter, between 27 and 52 if it is lower case, and 0 otherwise. */ { if ( 'A' <= ch && ch <= 'Z' ) { return ( ( int ) ( ch - 'A' + 1 ) ); } else if ( 'a' <= ch && ch <= 'z' ) { return ( ( int ) ( ch - 'a' + 26 + 1 ) ); } else { return 0; } } /******************************************************************************/ int base_to_i4 ( char *s, int base ) /******************************************************************************/ /* Purpose: base_to_i4() returns the value of an integer represented in some base. Discussion: BASE = 1 is allowed, in which case we allow the digits '1' and '0', and we simply count the '1' digits for the result. Negative bases between -16 and -2 are allowed. The base -1 is allowed, and essentially does a parity check on a string of 1's. Example: Input Output ------------- ------ S BASE I ------ ----- ------ '101' 2 5 '-1000' 3 -27 '100' 4 16 '111111' 2 63 '111111' -2 21 '111111' 1 6 '111111' -1 0 Licensing: This code is distributed under the MIT license. Modified: 27 July 2000 Author: John Burkardt Input: char *S, the string. The elements of S are blanks, a plus or minus sign, and digits. Normally, the digits are representations of integers between 0 and |BASE-1|. In the special case of base 1 or base -1, we allow both 0 and 1 as digits. int BASE, the base in which the representation is given. Normally, 2 <= BASE <= 16. However, there are two exceptions. Output: int BASE_TO_I4, the integer. */ { char c; int i; int ichr; int idig; int isgn; int istate; int nchar; nchar = s_len_trim ( s ); if ( base == 0 ) { printf ( "\n" ); printf ( "BASE_TO_I4 - Serious error!\n" ); printf ( " The input base is zero.\n" ); i = -1; return i; } if ( 16 < abs ( base ) ) { printf ( "\n" ); printf ( "BASE_TO_I4 - Serious error!\n" ); printf ( " The input base is greater than 16!\n" ); i = -1; return i; } i = 0; istate = 0; isgn = 1 ; ichr = 1; while ( ichr <= nchar ) { c = s[ichr-1]; // // Blank. // if ( c == ' ' ) { if ( istate == 2 ) { break; } } // // Sign, + or -. // else if ( c == '-' ) { if ( istate != 0 ) { break; } istate = 1; isgn = -1; } else if ( c == '+' ) { if ( istate != 0 ) { break; } istate = 1; } else /* Digit? */ { idig = hex_digit_to_i4 ( c ); if ( abs ( base ) == 1 && ( idig == 0 || idig == 1 ) ) { i = base * i + idig; istate = 2; } else if ( 0 <= idig && idig < abs ( base ) ) { i = base * i + idig; istate = 2; } else { printf ( "\n" ); printf ( "BASE_TO_I4 - Serious error!\n" ); printf ( " Illegal digit = \"%c\"\n", c ); printf ( " Conversion halted prematurely!\n" ); i = -1; return i; } } ichr = ichr + 1; } /* Once we're done reading information, we expect to be in state 2. */ if ( istate != 2 ) { printf ( "\n" ); printf ( "BASE_TO_I4 - Serious error!\n" ); printf ( " Unable to decipher input!\n" ); i = -1; return i; } /* Account for the sign. */ i = isgn * i; return i; } /******************************************************************************/ void byte_to_int ( unsigned char *bvec, unsigned int *ival ) /******************************************************************************/ /* Purpose: byte_to_int() converts 4 bytes into an unsigned integer. Licensing: This code is distributed under the MIT license. Modified: 22 November 2010 Author: John Burkardt Input: unsigned char *BVEC, is a pointer to a character string. The contents of BVEC through BVEC+3 are the bytes of IVAL, from high order to low. Output: unsigned int IVAL, the integer represented by the bytes. */ { int i; *ival = 0; for ( i = 0; i < 4; i++ ) { *ival = *ival << 8; *ival = *ival + *bvec; bvec = bvec + 1; } return; } /******************************************************************************/ char *boolean_to_string ( bool b ) /******************************************************************************/ /* Purpose: boolean_to_string() returns 'True' or 'False' depending on a boolean value. Licensing: This code is distributed under the MIT license. Modified: 25 June 2024 Author: John Burkardt Input: boolean B: the boolean value. Output: string S: the corresponding string. */ { static char true_string[5] = "True"; static char false_string[6] = "False"; if ( b ) { return true_string; } else { return false_string; } } /******************************************************************************/ char ch_cap ( char ch ) /******************************************************************************/ /* Purpose: ch_cap() capitalizes a single character. Discussion: This routine should be equivalent to the library "toupper" function. Licensing: This code is distributed under the MIT license. Modified: 19 July 1998 Author: John Burkardt Input: char CH, the character to capitalize. Output: char CH_CAP, the capitalized character. */ { if ( 97 <= ch && ch <= 122 ) { ch = ch - 32; } return ch; } /******************************************************************************/ void ch_count_cvec_add ( int n, unsigned char cvec[], int count[256] ) /******************************************************************************/ /* Purpose: ch_count_cvec_add() adds a character vector to a character count. Licensing: This code is distributed under the MIT license. Modified: 01 July 2008 Author: John Burkardt Input: int N, the number of entries in the vector. unsigned char CVEC[n], a vector of characters. int COUNT[256], the character counts. Output: int COUNT[256]: updated character counts. */ { int i; for ( i = 0; i < n; i++ ) { count[cvec[i]] = count[cvec[i]] + 1; } return; } /******************************************************************************/ int ch_eqi ( char ch1, char ch2 ) /******************************************************************************/ /* Purpose: ch_eqi() is TRUE (1) if two characters are equal, disregarding case. Licensing: This code is distributed under the MIT license. Modified: 13 June 2003 Author: John Burkardt Input: char CH1, CH2, the characters to compare. Output: int CH_EQI, is TRUE (1) if the two characters are equal, disregarding case and FALSE (0) otherwise. */ { int value; if ( 97 <= ch1 && ch1 <= 122 ) { ch1 = ch1 - 32; } if ( 97 <= ch2 && ch2 <= 122 ) { ch2 = ch2 - 32; } if ( ch1 == ch2 ) { value = 1; } else { value = 0; } return value; } /******************************************************************************/ int ch_index_first ( char *s, char c ) /******************************************************************************/ /* Purpose: ch_index_first() finds the first occurrence of a character in a string. Licensing: This code is distributed under the MIT license. Modified: 03 June 2008 Author: John Burkardt Input: char *S, a pointer to a string to be searched. char C, the character to be searched for in the string. Output: int CH_INDEX_FIRST, the index in S of the first occurrence of c, or -1 if C does not occur in S. */ { int i; int nchar; nchar = strlen ( s ); for ( i = 0; i < nchar; i++ ) { if ( s[i] == c ) { return i; } } return -1; } /******************************************************************************/ int ch_index_last ( char *s, char c ) /******************************************************************************/ /* Purpose: ch_index_last() finds the last occurrence of a character in a string. Licensing: This code is distributed under the MIT license. Modified: 01 July 2008 Author: John Burkardt Input: char *S, a pointer to a string to be searched. char C, the character to be searched for in s. Output: int CH_INDEX_LAST, the index in s of the last occurrence of C, or -1 if c does not occur in s. */ { int i; int j; int nchar; j = -1; nchar = strlen ( s ); for ( i = 0; i < nchar; i++ ) { if ( s[i] == c ) { j = i; } } return j; } /******************************************************************************/ int ch_is_alpha ( char ch ) /******************************************************************************/ /* Purpose: ch_is_alpha() is TRUE if a charaacter is alphabetic. Licensing: This code is distributed under the MIT license. Modified: 01 July 2008 Author: John Burkardt Input: char CH, a character to check. Output: int CH_IS_ALPHA is TRUE if the character is alphabetic. */ { int value; if ( ( 'a' <= ch && ch <= 'z' ) || ( 'A' <= ch && ch <= 'Z' ) ) { value = 1; } else { value = 0; } return value; } /******************************************************************************/ int ch_is_alphanumeric ( char ch ) /******************************************************************************/ /* Purpose: ch_is_alphanumeric() is TRUE if a character is alphanumeric. Licensing: This code is distributed under the MIT license. Modified: 01 July 2008 Author: John Burkardt Input: char CH, a character to check. Output: int CH_IS_ALPHANUMERIC is TRUE if the character is alphanumeric. */ { int value; if ( ( 'a' <= ch && ch <= 'z' ) || ( 'A' <= ch && ch <= 'Z' ) || ( '0' <= ch && ch <= '9' ) ) { value = 1; } else { value = 0; } return value; } /******************************************************************************/ int ch_is_control ( char ch ) /******************************************************************************/ /* Purpose: ch_is_control() is TRUE if a character is a control character. Discussion: A "control character" has ASCII code <= 31 or 127 <= ASCII code. Licensing: This code is distributed under the MIT license. Modified: 27 September 2008 Author: John Burkardt Input: char CH, the character to be tested. Output: int CH_IS_CONTROL, TRUE if the character is a control character, and FALSE otherwise. */ { int value; if ( ch <= 31 || 127 <= ch ) { value = 1; } else { value = 0; } return value; } /******************************************************************************/ int ch_is_digit ( char c ) /******************************************************************************/ /* Purpose: ch_is_digit() returns TRUE if a character is a decimal digit. Licensing: This code is distributed under the MIT license. Modified: 22 January 2014 Author: John Burkardt Input: char C, the character to be analyzed. Output: int CH_IS_DIGIT, is TRUE if C is a digit. */ { int value; if ( '0' <= c && c <= '9' ) { value = 1; } else { value = 0; } return value; } /******************************************************************************/ int ch_is_format_code ( char c ) /******************************************************************************/ /* Purpose: ch_is_format_code() returns TRUE (1) if a character is a FORTRAN format code. Discussion: The format codes accepted here are not the only legal format codes in FORTRAN90. However, they are more than sufficient for my needs! Table: A Character B Binary digits D Real number, exponential representation E Real number, exponential representation F Real number, fixed point G General format I Integer L Logical variable O Octal digits Z Hexadecimal digits * Free format Licensing: This code is distributed under the MIT license. Modified: 22 January 2014 Author: John Burkardt Input: char C, the character to be analyzed. Output: int CH_IS_FORMAT_CODE, is 1 if C is a FORTRAN format code. */ { int value; if ( ch_eqi ( c, 'A' ) ) { value = 1; } else if ( ch_eqi ( c, 'B' ) ) { value = 1; } else if ( ch_eqi ( c, 'D' ) ) { value = 1; } else if ( ch_eqi ( c, 'E' ) ) { value = 1; } else if ( ch_eqi ( c, 'F' ) ) { value = 1; } else if ( ch_eqi ( c, 'G' ) ) { value = 1; } else if ( ch_eqi ( c, 'I' ) ) { value = 1; } else if ( ch_eqi ( c, 'L' ) ) { value = 1; } else if ( ch_eqi ( c, 'O' ) ) { value = 1; } else if ( ch_eqi ( c, 'Z' ) ) { value = 1; } else if ( c == '*' ) { value = 1; } else { value = 0; } return value; } /******************************************************************************/ int ch_is_isbn_digit ( char c ) /******************************************************************************/ /* Purpose: ch_is_isbn_digit() returns TRUE if a character is an ISBN digit. Licensing: This code is distributed under the MIT license. Modified: 15 September 2015 Author: John Burkardt Input: char C, the character to be analyzed. Output: int CH_IS_ISBN_DIGIT, is TRUE if C is an ISBN digit. */ { int value; if ( '0' <= c && c <= '9' ) { value = 1; } else if ( c == 'X' || c == 'x' ) { value = 1; } else { value = 0; } return value; } /******************************************************************************/ int ch_is_lower ( char c ) /******************************************************************************/ /* Purpose: ch_is_lower() is TRUE if C is a lowercase alphabetic character. Licensing: This code is distributed under the MIT license. Modified: 22 November 2010 Author: John Burkardt Input: char C, a character to check. Output: int CH_IS_LOWER is TRUE if C is a lowercase alphabetic character. */ { int value; if ( ( 'a' <= c && c <= 'z' ) ) { value = 1; } else { value = 0; } return value; } /******************************************************************************/ int ch_is_space ( char c ) /******************************************************************************/ /* Purpose: ch_is_space() is TRUE if a character represents "white space". Discussion: A white space character is a space, a form feed, a newline, a carriage return, a horizontal tab, or a vertical tab. Licensing: This code is distributed under the MIT license. Modified: 03 June 2008 Author: John Burkardt Input: char C, the character to be analyzed. Output: int CH_IS_SPACE, is TRUE if C is a whitespace character. */ { int value; if ( c == ' ' ) { value = 1; } else if ( c == '\f' ) { value = 1; } else if ( c == '\n' ) { value = 1; } else if ( c == '\r' ) { value = 1; } else if ( c == '\t' ) { value = 1; } else if ( c == '\v' ) { value = 1; } else { value = 0; } return value; } /******************************************************************************/ char ch_low ( char ch ) /******************************************************************************/ /* Purpose: ch_low() lowercases a single character. Licensing: This code is distributed under the MIT license. Modified: 30 November 2009 Author: John Burkardt Input: char CH, the character. Output: char CH_LOW, the lowercase character. */ { char value; if ( 65 <= ch && ch <= 90 ) { value = ch + 32; } else { value = ch; } return value; } /******************************************************************************/ char ch_read ( FILE *filein ) /******************************************************************************/ /* Purpose: ch_read() reads one character from a binary file. Licensing: This code is distributed under the MIT license. Modified: 24 May 1999 Author: John Burkardt Input: FILE *FILEIN, a pointer to the file. Output: char CH_READ, the character that was read. */ { char value; value = ( char ) fgetc ( filein ); return value; } /******************************************************************************/ int ch_roman_to_i4 ( char ch ) /******************************************************************************/ /* Purpose: ch_roman_to_i4() returns the integer value of a single Roman digit. Licensing: This code is distributed under the MIT license. Modified: 03 June 2008 Author: John Burkardt Input: char CH, a Roman digit. Output: int CH_ROMAN_TO_I4, the value of the Roman numeral. If the Roman numeral was not recognized, 0 is returned. */ { int value; if ( ch == 'M' || ch == 'm' ) { value = 1000; } else if ( ch == 'D' || ch == 'd' ) { value = 500; } else if ( ch == 'C' || ch == 'c' ) { value = 100; } else if ( ch == 'L' || ch == 'l' ) { value = 50; } else if ( ch == 'X' || ch == 'x' ) { value = 10; } else if ( ch == 'V' || ch == 'v' ) { value = 5; } else if ( ch == 'I' || ch == 'i' || ch == 'J' || ch == 'j' ) { value = 1; } else { value = 0; } return value; } /******************************************************************************/ char ch_scrabble ( int tile ) /******************************************************************************/ /* Purpose: ch_scrabble() returns the character on a given Scrabble tile. Discussion: The tiles are numbered 1 to 100, and are labeled 'A' through 'Z', plus two blanks. Licensing: This code is distributed under the MIT license. Modified: 02 January 2009 Author: John Burkardt Input: int TILE, the index of the desired Scrabble tile, between 1 and 100. Output: char CH_SCRABBLE, the character on the given tile. */ { char scrabble[100] = { 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'B', 'B', 'C', 'C', 'D', 'D', 'D', 'D', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'F', 'F', 'G', 'G', 'G', 'H', 'H', 'I', 'I', 'I', 'I', 'I', 'I', 'I', 'I', 'I', 'J', 'K', 'L', 'L', 'L', 'L', 'M', 'M', 'N', 'N', 'N', 'N', 'N', 'N', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'P', 'P', 'Q', 'R', 'R', 'R', 'R', 'R', 'R', 'S', 'S', 'S', 'S', 'T', 'T', 'T', 'T', 'T', 'T', 'U', 'U', 'U', 'U', 'V', 'V', 'W', 'W', 'X', 'X', 'Y', 'Z', ' ', ' ' }; int value; if ( 1 <= tile && tile <= 100 ) { value = scrabble[tile-1]; } else { value = '?'; } return value; } /******************************************************************************/ int ch_scrabble_frequency ( char ch ) /******************************************************************************/ /* Purpose: ch_scrabble_frequency() returns the Scrabble frequency of a character. Licensing: This code is distributed under the MIT license. Modified: 15 January 2013 Author: John Burkardt Input: char CH, the character. Output: int CH_SCRABBLE_FREQUENCY, the frequency of the character. */ { int frequency[27] = { 9, 2, 2, 4, 12, 2, 3, 2, 9, 1, 1, 4, 2, 6, 8, 2, 1, 6, 4, 6, 4, 2, 2, 1, 2, 1, 2 }; int ic; int value; /* Convert character to a Scrabble character index. */ ic = ch_to_scrabble ( ch ); if ( 1 <= ic && ic <= 27 ) { value = frequency[ic-1]; } else { value = 0; } return value; } /******************************************************************************/ int ch_scrabble_points ( char ch ) /******************************************************************************/ /* Purpose: ch_scrabble_points() returns the Scrabble point value of a character. Licensing: This code is distributed under the MIT license. Modified: 15 January 2013 Author: John Burkardt Input: char CH, the character. Output: int CH_SCRABBLE_POINTS, the point value of the character. */ { int ic; int points[27] = { 1, 3, 3, 2, 1, 4, 2, 4, 1, 8, 5, 1, 3, 1, 1, 3, 10, 1, 1, 1, 1, 4, 4, 8, 4, 10, 0 }; int value; /* Convert character to a Scrabble character index. */ ic = ch_to_scrabble ( ch ); if ( 1 <= ic && ic <= 27 ) { value = points[ic-1]; } else { value = 0; } return value; } /******************************************************************************/ char ch_scrabble_select ( int *seed ) /******************************************************************************/ /* Purpose: ch_scrabble_select() selects a character with the Scrabble probability. Discussion: There are 100 Scrabble tiles, including two blanks. Licensing: This code is distributed under the MIT license. Modified: 16 September 2015 Author: John Burkardt Input: int *SEED, a seed for the random number generator. Output: int *SEED: an updated seed. char CH_SCRABBLE_SELECT, the character on a randomly chosen Scrabble tile. */ { int tile; char value; /* Choose a tile between 1 and 100. */ tile = i4_uniform_ab ( 1, 100, seed ); /* Retrieve the character on that tile. */ value = ch_scrabble ( tile ); return value; } /******************************************************************************/ void ch_swap ( char *ch1, char *ch2 ) /******************************************************************************/ /* Purpose: ch_swap() swaps two characters. Licensing: This code is distributed under the MIT license. Modified: 06 December 2003 Author: John Burkardt Input: char *CH1, *CH2: the values to interchange. Output: char *CH1, *CH2: the interchanged values. */ { char ch3; ch3 = *ch1; *ch1 = *ch2; *ch2 = ch3; return; } /******************************************************************************/ int ch_to_digit ( char ch ) /******************************************************************************/ /* Purpose: ch_to_digit() returns the integer value of a base 10 digit. Example: CH DIGIT --- ----- '0' 0 '1' 1 ... ... '9' 9 ' ' -1 'X' -1 Licensing: This code is distributed under the MIT license. Modified: 13 June 2003 Author: John Burkardt Input: char CH, the decimal digit, '0' through '9'. Output: int CH_TO_DIGIT, the corresponding integer value. If the character was 'illegal', then DIGIT is -1. */ { int digit; if ( '0' <= ch && ch <= '9' ) { digit = ch - '0'; } else { digit = -1; } return digit; } /******************************************************************************/ int ch_to_digit_bin ( char c ) /******************************************************************************/ /* Purpose: ch_to_digit_bin() returns the integer value of a binary digit. Discussion: This routine handles other traditional binary pairs of "digits" besides '0' and '1'. Example: C DIGIT --- ----- '0' 0 '1' 1 'T' 1 'F' 0 'Y' 1 'N' 0 '+' 1 '-' 0 Licensing: This code is distributed under the MIT license. Modified: 22 November 2010 Author: John Burkardt Input: char C, the binary digit. Output: int CH_TO_DIGIT_BIN, the corresponding integer value. If C was 'illegal', then DIGIT is -1. */ { int digit; if ( c == '0' || c == 'F' || c == 'f' || c == '-' || c == 'N' || c == 'n' ) { digit = 0; } else if ( c == '1' || c == 'T' || c == 't' || c == '+' || c == 'Y' || c == 'y' ) { digit = 1; } else { digit = -1; } return digit; } /******************************************************************************/ char ch_to_rot13 ( char ch ) /******************************************************************************/ /* Purpose: ch_to_rot13() converts a character to its ROT13 equivalent. Discussion: Two applications of CH_TO_ROT13 to a character will return the original.! As a further scrambling, digits are similarly rotated using a "ROT5" scheme. Example: Input: Output: a n C P J W 1 6 5 0 Licensing: This code is distributed under the MIT license. Modified: 03 June 2008 Author: John Burkardt Input: char CH, the character to be converted. Output: char CH_TO_ROT13, the ROT13 equivalent of the character. */ { char rot13; /* [0:4] -> [5:9] */ if ( '0' <= ch && ch <= '4' ) { rot13 = ch + 5; } /* [5:9] -> [0:4] */ else if ( '5' <= ch && ch <= '9' ) { rot13 = ch - 5; } /* [A:M] -> [N:Z] */ else if ( 'A' <= ch && ch <= 'M' ) { rot13 = ch + 13; } /* [N:Z] -> [A:M] */ else if ( 'N' <= ch && ch <= 'Z' ) { rot13 = ch - 13; } /* [a:m] -> [n:z] */ else if ( 'a' <= ch && ch <= 'm' ) { rot13 = ch + 13; } /* [n:z] -> [a:m] */ else if ( 'n' <= ch && ch <= 'z' ) { rot13 = ch - 13; } else { rot13 = ch; } return rot13; } /******************************************************************************/ int ch_to_scrabble ( char ch ) /******************************************************************************/ /* Purpose: ch_to_scrabble() returns the Scrabble index of a character. Discussion: 'A' through 'Z' have indices 1 through 26, and blank is index 27. Case is ignored. All other characters return index -1. Licensing: This code is distributed under the MIT license. Modified: 15 January 2013 Author: John Burkardt Input: char CH, the character. Output: int CH_TO_SCRABBLE, the Scrabble index of the character. */ { int ic; int value; if ( ch == ' ' ) { value = 27; return value; } ch = ch_cap ( ch ); ic = a_to_i4 ( ch ); if ( 1 <= ic && ic <= 26 ) { value = ic; } else { value = -1; } return value; } /******************************************************************************/ char ch_uniform ( char clo, char chi, int *seed ) /******************************************************************************/ /* Purpose: ch_uniform() returns a random character in a given range. Licensing: This code is distributed under the MIT license. Modified: 04 May 2005 Author: John Burkardt Input: char CLO, CHI, the minimum and maximum acceptable characters. int *SEED, a seed for the random number generator. Output: int *SEED: an updated seed. char CH_UNIFORM, the randomly chosen character. */ { char c; double d; d = r8_uniform_01 ( seed ); c = ( char ) ( ( 1.0 - d ) * ( double ) clo + d * ( double ) chi ); return c; } /******************************************************************************/ char digit_inc ( char c ) /******************************************************************************/ /* Purpose: digit_inc() increments a decimal digit. Example: Input Output ----- ------ '0' '1' '1' '2' ... '8' '9' '9' '0' 'A' 'A' Licensing: This code is distributed under the MIT license. Modified: 01 July 2008 Author: John Burkardt Input: char C, a digit to be incremented. Output: char DIGIT_INC, the incremented digit. */ { if ( '0' <= c && c <= '8' ) { return ( c + 1 ); } else if ( c == '9' ) { return '0'; } else { return c; } } /******************************************************************************/ char digit_to_ch ( int digit ) /******************************************************************************/ /* Purpose: digit_to_ch() returns the character representation of a decimal digit. Example: DIGIT C ----- --- 0 '0' 1 '1' ... ... 9 '9' 17 '*' Licensing: This code is distributed under the MIT license. Modified: 01 June 2015 Author: John Burkardt Input: int DIGIT, the digit value between 0 and 9. Output: char DIGIT_TO_CH, the corresponding character, or '*' if DIGIT was illegal. */ { char value; if ( 0 <= digit && digit <= 9 ) { value = digit + 48; } else { value = '*'; } return value; } /******************************************************************************/ int hex_digit_to_i4 ( char c ) /******************************************************************************/ /* Purpose: hex_digit_to_i4() converts a hexadecimal digit to an I4. Licensing: This code is distributed under the MIT license. Modified: 22 November 2010 Author: John Burkardt Input: char C, the hexadecimal digit, '0' through '9', or 'A' through 'F', or also 'a' through 'f' are allowed. Output: int HEX_DIGIT_TO_I4, the corresponding integer, or -1 if C was illegal. */ { int i; if ( '0' <= c && c <= '9' ) { i = ( int ) ( c - '0' ); } else if ( 'A' <= c && c <= 'F' ) { i = 10 + ( int ) ( c - 'A' ); } else if ( 'a' <= c && c <= 'f' ) { i = 10 + ( int ) ( c - 'a' ); } else if ( c == ' ' ) { i = 0; } else { i = -1; } return i; } /******************************************************************************/ int i4_huge ( ) /******************************************************************************/ /* Purpose: i4_huge() returns a "huge" I4. Licensing: This code is distributed under the MIT license. Modified: 29 August 2006 Author: John Burkardt Output: int I4_HUGE, a "huge" integer. */ { return 2147483647; } /******************************************************************************/ int i4_log_10 ( int i ) /******************************************************************************/ /* Purpose: i4_log_10() returns the integer part of the logarithm base 10 of an I4. Example: I I4_LOG_10 ----- -------- 0 0 1 0 2 0 9 0 10 1 11 1 99 1 100 2 101 2 999 2 1000 3 1001 3 9999 3 10000 4 Discussion: I4_LOG_10 ( I ) + 1 is the number of decimal digits in I. Licensing: This code is distributed under the MIT license. Modified: 23 October 2007 Author: John Burkardt Input: int I, the number whose logarithm base 10 is desired. Output: int I4_LOG_10, the integer part of the logarithm base 10 of the absolute value of X. */ { int i_abs; int ten_pow; int value; if ( i == 0 ) { value = 0; } else { value = 0; ten_pow = 10; i_abs = abs ( i ); while ( ten_pow <= i_abs ) { value = value + 1; ten_pow = ten_pow * 10; } } return value; } /******************************************************************************/ int i4_max ( int i1, int i2 ) /******************************************************************************/ /* Purpose: i4_max() returns the maximum of two I4's. Licensing: This code is distributed under the MIT license. Modified: 29 August 2006 Author: John Burkardt Input: int I1, I2, are two integers to be compared. Output: int I4_MAX, the larger of I1 and I2. */ { int value; if ( i2 < i1 ) { value = i1; } else { value = i2; } return value; } /******************************************************************************/ int i4_min ( int i1, int i2 ) /******************************************************************************/ /* Purpose: i4_min() returns the smaller of two I4's. Licensing: This code is distributed under the MIT license. Modified: 29 August 2006 Author: John Burkardt Input: int I1, I2, two integers to be compared. Output: int I4_MIN, the smaller of I1 and I2. */ { int value; if ( i1 < i2 ) { value = i1; } else { value = i2; } return value; } /******************************************************************************/ int i4_modp ( int i, int j ) /******************************************************************************/ /* Purpose: i4_modp() returns the nonnegative remainder of I4 division. Discussion: If NREM = I4_MODP ( I, J ) NMULT = ( I - NREM ) / J then I = J * NMULT + NREM where NREM is always nonnegative. The MOD function computes a result with the same sign as the quantity being divided. Thus, suppose you had an angle A, and you wanted to ensure that it was between 0 and 360. Then mod(A,360) would do, if A was positive, but if A was negative, your result would be between -360 and 0. On the other hand, I4_MODP(A,360) is between 0 and 360, always. Example: I J MOD I4_MODP I4_MODP Factorization 107 50 7 7 107 = 2 * 50 + 7 107 -50 7 7 107 = -2 * -50 + 7 -107 50 -7 43 -107 = -3 * 50 + 43 -107 -50 -7 43 -107 = 3 * -50 + 43 Licensing: This code is distributed under the MIT license. Modified: 12 January 2007 Author: John Burkardt Input: int I, the number to be divided. int J, the number that divides I. Output: int I4_MODP, the nonnegative remainder when I is divided by J. */ { int value; if ( j == 0 ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "I4_MODP - Fatal error!\n" ); fprintf ( stderr, " I4_MODP ( I, J ) called with J = %d\n", j ); exit ( 1 ); } value = i % j; if ( value < 0 ) { value = value + abs ( j ); } return value; } /******************************************************************************/ void i4_swap ( int *i, int *j ) /******************************************************************************/ /* Purpose: i4_swap() switches two I4's. Licensing: This code is distributed under the MIT license. Modified: 07 January 2002 Author: John Burkardt Input: int *I, *J: the values to interchange. Output: int *I, *J: the interchanged values. */ { int k; k = *i; *i = *j; *j = k; return; } /******************************************************************************/ char i4_to_a ( int i ) /******************************************************************************/ /* Purpose: i4_to_a() returns the I-th alphabetic character. Example: I I4_TO_A -8 ' ' 0 ' ' 1 'A' 2 'B' .. 26 'Z' 27 'a' 52 'z' 53 ' ' 99 ' ' Licensing: This code is distributed under the MIT license. Modified: 01 July 2008 Author: John Burkardt Input: int I, the index of the letter to be returned. 0 is a space; 1 through 26 requests 'A' through 'Z', (ASCII 65:90); 27 through 52 requests 'a' through 'z', (ASCII 97:122); Output: char I4_TO_A, the requested alphabetic letter. */ { if ( i <= 0 ) { return ( ' ' ); } else if ( 1 <= i && i <= 26 ) { return ( 'A' + i - 1 ); } else if ( 27 <= i && i <= 52 ) { return ( 'a' + i - 27 ); } else { return ( ' ' ); } } /******************************************************************************/ char i4_to_amino_code ( int i ) /******************************************************************************/ /* Purpose: i4_to_amino_code() converts an integer to an amino code. Licensing: This code is distributed under the MIT license. Modified: 02 January 2009 Author: John Burkardt Reference: Carl Branden, John Tooze, Introduction to Protein Structure, Garland Publishing, 1991. Input: int I, the index of an amino acid, between 1 and 23. Output: char I4_TO_AMINO_CODE, the one letter code for an amino acid. */ { # define N 23 char c; static char ch_table[N] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'V', 'W', 'X', 'Y', 'Z' }; if ( 1 <= i && i <= N ) { c = ch_table[i-1]; } else { c = '?'; } return c; # undef N } /******************************************************************************/ char i4_to_hex_digit ( int i ) /******************************************************************************/ /* Purpose: i4_to_hex_digit() converts a (small) I4 to a hexadecimal digit. Licensing: This code is distributed under the MIT license. Modified: 31 August 2009 Author: John Burkardt Input: int I, the integer, between 0 and 15. Output: char I4_TO_HEX_DIGIT, the hexadecimal digit corresponding to the integer. */ { char value; if ( 0 <= i && i <= 9 ) { value = '0' + i; } else if ( 10 <= i && i <= 15 ) { value = 'a' + ( i - 10 ); } else { value = '*'; } return value; } /******************************************************************************/ char i4_to_isbn_digit ( int i ) /******************************************************************************/ /* Purpose: i4_to_isbn_digit() converts an I4 to an ISBN digit. Discussion: Only the integers 0 through 10 can be input. The representation of 10 is 'X'. Licensing: This code is distributed under the MIT license. Modified: 31 January 2016 Author: John Burkardt Input: int I, an integer between 0 and 10. Output: char I4_TO_ISBN_DIGIT, the ISBN character code of the integer. If I is illegal, then the value is set to '?'. */ { if ( i == 0 ) { return '0'; } else if ( i == 1 ) { return '1'; } else if ( i == 2 ) { return '2'; } else if ( i == 3 ) { return '3'; } else if ( i == 4 ) { return '4'; } else if ( i == 5 ) { return '5'; } else if ( i == 6 ) { return '6'; } else if ( i == 7 ) { return '7'; } else if ( i == 8 ) { return '8'; } else if ( i == 9 ) { return '9'; } else if ( i == 10 ) { return 'X'; } else { return '?'; } } /******************************************************************************/ char *i4_to_month_abb ( int i ) /******************************************************************************/ /* Purpose: i4_to_month_abb() returns an abbreviated month name. Licensing: This code is distributed under the MIT license. Modified: 02 January 2009 Author: John Burkardt Input: int I, the number of the desired month. Output: char *I4_TO_MONTH_ABB, a 3 character abbreviation for the month, such as 'Jan', 'Feb', 'Mar', and so on. */ { static char *month_list[13] = { "???", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; if ( 1 <= i && i <= 12 ) { return month_list[i]; } else { return month_list[0]; } } /******************************************************************************/ char *i4_to_month_name ( int i ) /******************************************************************************/ /* Purpose: i4_to_month_name() returns a month name. Licensing: This code is distributed under the MIT license. Modified: 15 January 2013 Author: John Burkardt Input: int I, the number of the desired month. 1 <= I <= 12. Output: char *I4_TO_MONTH_NAME, the name of the month. */ { int l; char *value; if ( i == 1 ) { l = 8; value = ( char * ) malloc ( l * sizeof ( char ) ); strcpy ( value, "January" ); } else if ( i == 2 ) { l = 9; value = ( char * ) malloc ( l * sizeof ( char ) ); strcpy ( value, "February" ); } else if ( i == 3 ) { l = 6; value = ( char * ) malloc ( l * sizeof ( char ) ); strcpy ( value, "March" ); } else if ( i == 4 ) { l = 6; value = ( char * ) malloc ( l * sizeof ( char ) ); strcpy ( value, "April" ); } else if ( i == 5 ) { l = 4; value = ( char * ) malloc ( l * sizeof ( char ) ); strcpy ( value, "May" ); } else if ( i == 6 ) { l = 5; value = ( char * ) malloc ( l * sizeof ( char ) ); strcpy ( value, "June" ); } else if ( i == 7 ) { l = 5; value = ( char * ) malloc ( l * sizeof ( char ) ); strcpy ( value, "July" ); } else if ( i == 8 ) { l = 7; value = ( char * ) malloc ( l * sizeof ( char ) ); strcpy ( value, "August" ); } else if ( i == 9 ) { l = 10; value = ( char * ) malloc ( l * sizeof ( char ) ); strcpy ( value, "September" ); } else if ( i == 10 ) { l = 8; value = ( char * ) malloc ( l * sizeof ( char ) ); strcpy ( value, "October" ); } else if ( i == 11 ) { l = 9; value = ( char * ) malloc ( l * sizeof ( char ) ); strcpy ( value, "November" ); } else if ( i == 12 ) { l = 9; value = ( char * ) malloc ( l * sizeof ( char ) ); strcpy ( value, "December" ); } else { l = 4; value = ( char * ) malloc ( l * sizeof ( char ) ); strcpy ( value, "???" ); } return value; } /******************************************************************************/ char *i4_to_s ( int i ) /******************************************************************************/ /* Purpose: i4_to_s() converts an I4 to a string. Example: INTVAL S 1 1 -1 -1 0 0 1952 1952 123456 123456 1234567 1234567 Licensing: This code is distributed under the MIT license. Modified: 02 May 2011 Author: John Burkardt Input: int I, an integer to be converted. Output: char *I4_TO_S, the representation of the integer. */ { int digit; int j; int length; int ten_power; char *s; static double ten = 10.0; length = i4_log_10 ( i ); ten_power = ( int ) ( pow ( ten, length ) ); if ( i < 0 ) { length = length + 1; } /* Add one position for the trailing null. */ length = length + 1; s = ( char * ) malloc ( length * sizeof ( char ) ); if ( i == 0 ) { s[0] = '0'; s[1] = '\0'; return s; } /* Now take care of the sign. */ j = 0; if ( i < 0 ) { s[j] = '-'; j = j + 1; i = abs ( i ); } /* Find the leading digit of I, strip it off, and stick it into the string. */ while ( 0 < ten_power ) { digit = i / ten_power; s[j] = digit_to_ch ( digit ); j = j + 1; i = i - digit * ten_power; ten_power = ten_power / 10; } /* Tack on the trailing NULL. */ s[j] = '\0'; j = j + 1; return s; } /******************************************************************************/ int i4_uniform_ab ( int a, int b, int *seed ) /******************************************************************************/ /* Purpose: i4_uniform_ab() returns a scaled pseudorandom I4 between A and B. Discussion: The pseudorandom number should be uniformly distributed between A and B. Licensing: This code is distributed under the MIT license. Modified: 24 May 2012 Author: John Burkardt Reference: Paul Bratley, Bennett Fox, Linus Schrage, A Guide to Simulation, Second Edition, Springer, 1987, ISBN: 0387964673, LC: QA76.9.C65.B73. Bennett Fox, Algorithm 647: Implementation and Relative Efficiency of Quasirandom Sequence Generators, ACM Transactions on Mathematical Software, Volume 12, Number 4, December 1986, pages 362-376. Pierre L'Ecuyer, Random Number Generation, in Handbook of Simulation, edited by Jerry Banks, Wiley, 1998, ISBN: 0471134031, LC: T57.62.H37. Peter Lewis, Allen Goodman, James Miller, A Pseudo-Random Number Generator for the System/360, IBM Systems Journal, Volume 8, Number 2, 1969, pages 136-143. Input: int A, B, the limits of the interval. int *SEED, the "seed" value, which should NOT be 0. Output: int *SEED: an updated seed. int I4_UNIFORM_AB, a number between A and B. */ { int c; const int i4_huge = 2147483647; int k; float r; int value; if ( *seed == 0 ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "I4_UNIFORM_AB - Fatal error!\n" ); fprintf ( stderr, " Input value of SEED = 0.\n" ); exit ( 1 ); } /* Guaranteee A <= B. */ if ( b < a ) { c = a; a = b; b = c; } k = *seed / 127773; *seed = 16807 * ( *seed - k * 127773 ) - k * 2836; if ( *seed < 0 ) { *seed = *seed + i4_huge; } r = ( float ) ( *seed ) * 4.656612875E-10; /* Scale R to lie between A-0.5 and B+0.5. */ r = ( 1.0 - r ) * ( ( float ) ( a ) - 0.5 ) + r * ( ( float ) ( b ) + 0.5 ); /* Round R to the nearest integer. */ value = round ( r ); /* Guarantee that A <= VALUE <= B. */ if ( value < a ) { value = a; } if ( b < value ) { value = b; } return value; } /******************************************************************************/ void i4vec_print ( int n, int a[], char *title ) /******************************************************************************/ /* Purpose: i4vec_print() prints an I4VEC. Discussion: An I4VEC is a vector of I4's. Licensing: This code is distributed under the MIT license. Modified: 14 November 2003 Author: John Burkardt Input: int N, the number of components of the vector. int A[N], the vector to be printed. char *TITLE, a title. */ { int i; fprintf ( stdout, "\n" ); fprintf ( stdout, "%s\n", title ); fprintf ( stdout, "\n" ); for ( i = 0; i < n; i++ ) { fprintf ( stdout, " %6d: %8d\n", i, a[i] ); } return; } /******************************************************************************/ int isbn_digit_to_i4 ( char c ) /******************************************************************************/ /* Purpose: isbn_digit_to_i4() converts an ISBN digit into an I4. Discussion: The characters '0' through '9' stand for themselves, but the character 'X' or 'x' stands for 10. Licensing: This code is distributed under the MIT license. Modified: 16 September 2015 Author: John Burkardt Input: char C, the ISBN character code to be converted. Output: int ISBN_DIGIT_TO_I4, the numeric value of the character code, between 0 and 10. This value is returned as -1 if C is not a valid character code. */ { int value; if ( '0' <= c && c <= '9' ) { value = c - '0'; } else if ( c == 'X' || c == 'x' ) { value = 10; } else { value = -1; } return value; } /******************************************************************************/ int r4_nint ( float x ) /******************************************************************************/ /* Purpose: r4_nint() returns the nearest integer to an R4. Example: X R4_NINT 1.3 1 1.4 1 1.5 1 or 2 1.6 2 0.0 0 -0.7 -1 -1.1 -1 -1.6 -2 Licensing: This code is distributed under the MIT license. Modified: 05 May 2006 Author: John Burkardt Input: float X, the value. Output: int R4_NINT, the nearest integer to X. */ { int s; int value; if ( x < 0.0 ) { s = - 1; } else { s = + 1; } value = s * ( int ) ( fabs ( x ) + 0.5 ); return value; } /******************************************************************************/ double r8_uniform_01 ( int *seed ) /******************************************************************************/ /* Purpose: r8_uniform_01() returns a unit pseudorandom R8. Discussion: This routine implements the recursion seed = 16807 * seed mod ( 2^31 - 1 ) r8_uniform_01 = seed / ( 2^31 - 1 ) The integer arithmetic never requires more than 32 bits, including a sign bit. If the initial seed is 12345, then the first three computations are Input Output R8_UNIFORM_01 SEED SEED 12345 207482415 0.096616 207482415 1790989824 0.833995 1790989824 2035175616 0.947702 Licensing: This code is distributed under the MIT license. Modified: 11 August 2004 Author: John Burkardt Reference: Paul Bratley, Bennett Fox, Linus Schrage, A Guide to Simulation, Springer Verlag, pages 201-202, 1983. Pierre L'Ecuyer, Random Number Generation, in Handbook of Simulation edited by Jerry Banks, Wiley Interscience, page 95, 1998. Bennett Fox, Algorithm 647: Implementation and Relative Efficiency of Quasirandom Sequence Generators, ACM Transactions on Mathematical Software, Volume 12, Number 4, pages 362-376, 1986. P A Lewis, A S Goodman, J M Miller, A Pseudo-Random Number Generator for the System/360, IBM Systems Journal, Volume 8, pages 136-143, 1969. Input: int *SEED, the "seed" value. Output: int *SEED: an updated seed. double R8_UNIFORM_01, a new pseudorandom variate, strictly between 0 and 1. */ { int k; double r; k = *seed / 127773; *seed = 16807 * ( *seed - k * 127773 ) - k * 2836; if ( *seed < 0 ) { *seed = *seed + 2147483647; } /* Although SEED can be represented exactly as a 32 bit integer, it generally cannot be represented exactly as a 32 bit real number! */ r = ( ( double ) ( *seed ) ) * 4.656612875E-10; return r; } /******************************************************************************/ void s_adjustl ( char *s ) /******************************************************************************/ /* Purpose: s_adjustl() flushes a string left. Discussion: Both blanks and tabs are treated as "white space". This routine is similar to the FORTRAN90 ADJUSTL routine. Example: Input Output ' Hello' 'Hello' ' Hi there! ' 'Hi there!' 'Fred ' 'Fred' Licensing: This code is distributed under the MIT license. Modified: 16 June 2003 Author: John Burkardt Input: char *S: a string of characters. Output: char *S: any initial blank or tab characters have been cut. */ { int i; int length; int nonb; char TAB = 9; /* Check the length of the string to the last nonblank. If nonpositive, return. */ length = s_len_trim ( s ); if ( length <= 0 ) { return; } /* Find NONB, the location of the first nonblank, nontab. */ nonb = 0; for ( i = 0; i < length; i++ ) { if ( s[i] != ' ' && s[i] != TAB ) { nonb = i; break; } } if ( 0 < nonb ) { for ( i = nonb; i < length; i++ ) { s[i-nonb] = s[i]; } s[length-nonb] = '\0'; } return; } /******************************************************************************/ int s_begin ( char *s1, char *s2 ) /******************************************************************************/ /* Purpose: s_begin() reports whether string 1 begins with string 2. Licensing: This code is distributed under the MIT license. Modified: 22 November 2010 Author: John Burkardt Input: char *S1, char *S2, two strings. Output: int S_BEGIN, is true if S1 is the same as S2 up to the end of S2, and false otherwise. */ { int i; int n1; int n2; n1 = strlen ( s1 ); n2 = strlen ( s2 ); if ( n1 < n2 ) { return 0; } for ( i = 0; i < n2; i++ ) { if ( ch_cap ( s1[i] ) != ch_cap ( s2[i] ) ) { return 0; } } return 1; } /******************************************************************************/ void s_blank_delete ( char *s ) /******************************************************************************/ /* Purpose: s_blank_delete() removes blanks and left justifies the remainder. Discussion: All TAB characters are also removed. Licensing: This code is distributed under the MIT license. Modified: 01 July 2008 Author: John Burkardt Input: char *S, the string to be transformed. Output: char *S: the transformed string. */ { char *get; char *put; char TAB = 9; put = s; get = s; while ( *get != '\0' ) { if ( *get != ' ' && *get != TAB ) { *put = *get; put = put + 1; } get = get + 1; } *put = *get; return; } /******************************************************************************/ void s_blanks_delete ( char *s ) /******************************************************************************/ /* Purpose: s_blanks_delete() replaces consecutive blanks by one blank. Discussion: The remaining characters are left justified and right padded with blanks. TAB characters are converted to spaces. Licensing: This code is distributed under the MIT license. Modified: 03 June 2008 Author: John Burkardt Input: char *S, the string to be transformed. Output: char *S: the transformed string. */ { int blank; char *get; char *put; put = s; get = s; blank = 1; while ( *get != '\0' ) { if ( *get != ' ' ) { *put = *get; put = put + 1; blank = 0; } else if ( !blank ) { *put = *get; put = put + 1; blank = 1; } get = get + 1; } *put = '\0'; return; } /******************************************************************************/ void s_cap ( char *s ) /******************************************************************************/ /* Purpose: s_cap() capitalizes all the characters in a string. Licensing: This code is distributed under the MIT license. Modified: 03 June 2008 Author: John Burkardt Input: char *S: a string to be capitalized. Output: char *S: the capitalized string. */ { int i; int nchar; nchar = strlen ( s ); for ( i = 0; i < nchar; i++ ) { s[i] = ch_cap ( s[i] ); } return; } /******************************************************************************/ char *s_cat ( char *s1, char *s2 ) /******************************************************************************/ /* Purpose: s_cat() concatenates two strings to make a third string. Licensing: This code is distributed under the MIT license. Modified: 02 January 2009 Author: John Burkardt Input: char *S1, the "prefix" string. char *S2, the "postfix" string. Output: char *S_CAT, the string made by concatenating S1 and S2, ignoring any trailing blanks. */ { int i; int l1; int l2; char *s3; l1 = s_len_trim ( s1 ); l2 = s_len_trim ( s2 ); if ( l1 == 0 && l2 == 0 ) { s3 = NULL; return s3; } s3 = ( char * ) malloc ( ( l1 + l2 + 1 ) * sizeof ( char ) ); for ( i = 0; i < l1; i++ ) { s3[i] = s1[i]; } for ( i = 0; i < l2; i++ ) { s3[l1+i] = s2[i]; } s3[l1+l2] = '\0'; return s3; } /******************************************************************************/ int s_ch_count ( char *s, char ch ) /******************************************************************************/ /* Purpose: s_ch_count() counts occurrences of a particular character in a string. Licensing: This code is distributed under the MIT license. Modified: 08 November 2011 Author: John Burkardt Input: char *S, the string. char CH, the character to be counted. Output: int S_CH_COUNT, the number of occurrences. */ { int ch_count; int i; int s_length; ch_count = 0; s_length = strlen ( s ); for ( i = 0; i < s_length; i++ ) { if ( s[i] == ch ) { ch_count = ch_count + 1; } } return ch_count; } /******************************************************************************/ char *s_ch_delete ( char *s, char ch ) /******************************************************************************/ /* Purpose: s_ch_delete() removes all occurrences of a character from a string. Discussion: Each time the given character is found in the string, the characters to the right of the string are shifted over one position. Licensing: This code is distributed under the MIT license. Modified: 08 November 2011 Author: John Burkardt Input: char *S, the string to be transformed. char CH, the character to be removed. Output: char *S_CH_DELETE, a copy of the string with the character removed. */ { int ch_num; int get; int put; int s_length; char *s2; s_length = strlen ( s ); ch_num = s_ch_count ( s, ch ); s2 = ( char * ) malloc ( ( s_length - ch_num + 1 ) * sizeof ( char ) ); put = 0; for ( get = 0; get < s_length; get++ ) { if ( s2[get] != ch ) { s2[put] = s[get]; put = put + 1; } } return s2; } /******************************************************************************/ void s_control_blank ( char *s ) /******************************************************************************/ /* Purpose: s_control_blank() replaces control characters with blanks. Discussion: A "control character" has ASCII code <= 31 or 127 <= ASCII code. Licensing: This code is distributed under the MIT license. Modified: 27 September 2008 Author: John Burkardt Input: char *S, the string to be transformed. Output: char *S: the transformed string. */ { char *get; get = s; while ( *get != '\0' ) { if ( ch_is_control ( *get ) ) { *get = ' '; } get = get + 1; } return; } /******************************************************************************/ int s_digits_count ( char *s ) /******************************************************************************/ /* Purpose: s_digits_count() counts the digits in a string. Discussion: The string may include spaces, letters, and dashes, but only the digits 0 through 9 will be counted. Example: S => 34E94-70.6 N <= 7 Licensing: This code is distributed under the MIT license. Modified: 08 September 2015 Author: John Burkardt Input: char *S, the string. Output: int S_DIGITS_COUNT, the number of digits. */ { char c; int n; int s_len; int s_pos; s_len = strlen ( s ); s_pos = 0; n = 0; while ( s_pos < s_len ) { c = s[s_pos]; s_pos = s_pos + 1; if ( ch_is_digit ( c ) ) { n = n + 1; } } return n; } /******************************************************************************/ int s_eqi ( char *s1, char *s2 ) /******************************************************************************/ /* Purpose: s_eqi() reports whether two strings are equal, ignoring case. Licensing: This code is distributed under the MIT license. Modified: 03 June 2008 Author: John Burkardt Input: char *S1, char *S2, pointers to two strings. Output: int S_EQI, is true if the strings are equal. */ { int i; int nchar; int nchar1; int nchar2; nchar1 = strlen ( s1 ); nchar2 = strlen ( s2 ); if ( nchar1 < nchar2 ) { nchar = nchar1; } else { nchar = nchar2; } /* The strings are not equal if they differ over their common length. */ for ( i = 0; i < nchar; i++ ) { if ( ch_cap ( s1[i] ) != ch_cap ( s2[i] ) ) { return 0; } } /* The strings are not equal if the longer one includes nonblanks in the tail. */ if ( nchar < nchar1 ) { for ( i = nchar; i < nchar1; i++ ) { if ( s1[i] != ' ' ) { return 0; } } } else if ( nchar < nchar2 ) { for ( i = nchar; i < nchar2; i++ ) { if ( s2[i] != ' ' ) { return 0; } } } return 1; } /******************************************************************************/ char *s_escape_tex ( char *s1 ) /******************************************************************************/ /* Purpose: s_escape_tex() de-escapes TeX escape sequences. Discussion: In particular, every occurrence of the characters '\', '_', '^', '{' and '}' will be replaced by '\\', '\_', '\^', '\{' and '\}'. A TeX interpreter, on seeing these character strings, is then likely to return the original characters. Licensing: This code is distributed under the MIT license. Modified: 19 January 2007 Author: John Burkardt Input: char *S1, the string to be de-escaped. Output: char *S_ESCAPE_TEX, a copy of the string, modified to avoid TeX escapes. */ { char ch; int s1_length; int s1_pos; char *s2; int s2_length; int s2_pos; int slash_count; s1_length = strlen ( s1 ); /* We need to know how many slashes occur in S1, so we can allocate S2. Note that, alas, the backslash is also the escape in C++, so we have to say '\\' when we mean '\'! */ slash_count = 0; for ( s1_pos = 0; s1_pos < s1_length; s1_pos++ ) { ch = s1[s1_pos]; if ( ch == '\\' || ch == '_' || ch == '^' || ch == '{' || ch == '}' ) { slash_count = slash_count + 1; } } s2_length = s1_length + slash_count; s2 = ( char * ) malloc ( ( s2_length + 1 ) * sizeof ( char ) ); /* Now copy S1 into S2. */ s1_pos = 0; s2_pos = 0; for ( s1_pos = 0; s1_pos < s1_length; s1_pos++ ) { ch = s1[s1_pos]; if ( ch == '\\' || ch == '_' || ch == '^' || ch == '{' || ch == '}' ) { s2[s2_pos] = '\\'; s2_pos = s2_pos + 1; } s2[s2_pos] = ch; s2_pos = s2_pos + 1; } s2[s2_pos] = '\0'; s2_pos = s2_pos + 1; return s2; } /******************************************************************************/ char *s_first_ch ( char *s, char ch ) /******************************************************************************/ /* Purpose: s_first_ch() points to the first occurrence of a character in a string. Licensing: This code is distributed under the MIT license. Modified: 02 January 2009 Author: John Burkardt Input: char *S, a pointer to a string. char CH, a character. Output: char *S_FIRST_CH, a pointer to the first occurrence of the character in the string, or NULL if the character does not occur. */ { while ( *s != ch ) { if ( *s == '\0' ) { return NULL; } s++; } return s; } /******************************************************************************/ char *s_first_nonblank ( char *s ) /******************************************************************************/ /* Purpose: s_first_nonblank() points to the first nonblank character in a string. Licensing: This code is distributed under the MIT license. Modified: 16 November 2002 Author: John Burkardt Input: char *S, a pointer to a string. Output: char *S_FIRST_NONBLANK, a pointer to the first nonblank character in the string, or NULL if the entire string is blank. */ { char *t = NULL; while ( *s != '\0' ) { if ( *s != ' ' ) { t = s; break; } s++; } return t; } /******************************************************************************/ int s_index_last_c ( char *s, char c ) /******************************************************************************/ /* Purpose: s_index_last_c() points to the last occurrence of a given character. Licensing: This code is distributed under the MIT license. Modified: 02 January 2009 Author: John Burkardt Input: char *S, a pointer to a string. char C, the character to search for. Output: int S_INDEX_LAST_C, the index in S of the last occurrence of the character, or -1 if it does not occur. */ { int n; char *t; n = strlen ( s ) - 1; t = s + strlen ( s ) - 1; while ( 0 <= n ) { if ( *t == c ) { return n; } t--; n--; } return (-1); } /******************************************************************************/ int s_len_trim ( char *s ) /******************************************************************************/ /* Purpose: s_len_trim() returns the length of a string to the last nonblank. Discussion: It turns out that I also want to ignore the '\n' character! Licensing: This code is distributed under the MIT license. Modified: 05 October 2014 Author: John Burkardt Input: char *S, a pointer to a string. Output: int S_LEN_TRIM, the length of the string to the last nonblank. If S_LEN_TRIM is 0, then the string is entirely blank. */ { int n; char *t; n = strlen ( s ); t = s + strlen ( s ) - 1; while ( 0 < n ) { if ( *t != ' ' && *t != '\n' ) { return n; } t--; n--; } return n; } /******************************************************************************/ void s_low ( char *s ) /******************************************************************************/ /* Purpose: s_low() replaces all uppercase characters by lowercase ones. Licensing: This code is distributed under the MIT license. Modified: 30 November 2009 Author: John Burkardt Input: char *S: a string. Output: char *S: all the characters in the string are uppercase. */ { char ch; while ( *s != '\0' ) { ch = *s; *s = ch_low ( ch ); s++; } return; } /******************************************************************************/ void s_newline_to_null ( char *s ) /******************************************************************************/ /* Purpose: s_newline_to_null() replaces carriage returns or newlines by nulls. Discussion: The function FGETS will read a string containing a line of text read from input. However, the string will include the linefeed character '/n', or, for a PC-formatted file, the carriage return and linefeed pair '/r' + '/n'. It may be desirable that the string not contain these characters. The easiest way to deal with this is simply to replace the first instance of '/r' or '/n' by a null character, which terminates the string. Licensing: This code is distributed under the MIT license. Modified: 29 November 2010 Author: John Burkardt Input: char *S: a string. Output: char *S: the first carriage return or line feed encountered has been replaced by a null. */ { int i; int n; n = strlen ( s ); for ( i = 0; i < n; i++ ) { /* Handle carriage return. */ if ( s[i] == '\r' ) { s[i] = '\0'; return; } /* Handle linefeed. */ if ( s[i] == '\n' ) { s[i] = '\0'; return; } } return; } /******************************************************************************/ void s_replace_ch ( char *s, char c1, char c2 ) /******************************************************************************/ /* Purpose: s_replace_ch() replaces all occurrences of one character by another. Licensing: This code is distributed under the MIT license. Modified: 22 November 2010 Author: John Burkardt Input: char *S, the string. char C1, C2, the character to be replaced, and the replacement character. Output: char *S: the transformed string. */ { int i; int s_length; s_length = strlen ( s ); for ( i = 0; i < s_length; i++ ) { if ( s[i] == c1 ) { s[i] = c2; } } return; } /******************************************************************************/ char *s_reverse ( char *s ) /******************************************************************************/ /* Purpose: s_reverse() reverses the characters in a string. Example: Input Output ' Cat' 'taC ' 'Goo gol ' 'log ooG ' Licensing: This code is distributed under the MIT license. Modified: 25 January 2010 Author: John Burkardt Input: char *S, the string to reverse. Output: char *S_REVERSE, the reversed string. */ { int j; int n; char *s2; n = strlen ( s ); s2 = ( char * ) malloc ( ( n + 1 ) * sizeof ( char ) ); for ( j = 0; j < n; j++ ) { *(s2+j) = *(s+n-j-1); } return s2; } /******************************************************************************/ int s_scrabble_points ( char *s ) /******************************************************************************/ /* Purpose: s_scrabble_points() returns the Scrabble point value of a string. Licensing: This code is distributed under the MIT license. Modified: 16 January 2013 Author: John Burkardt Input: char *S, the string. Output: int S_SCRABBLE_POINTS, the point value of the string. */ { int i; int s_length; int value; s_length = strlen ( s ); value = 0; for ( i = 0; i < s_length; i++ ) { value = value + ch_scrabble_points ( s[i] ); } return value; } /******************************************************************************/ void s_sort_a ( char *s ) /******************************************************************************/ /* Purpose: s_sort_a() sorts a string into ascending order. Discussion: The string is assumed to be short, and so a simple bubble sort is used. ALL the characters are sorted, including blanks and punctuation. Licensing: This code is distributed under the MIT license. Modified: 01 July 2008 Author: John Burkardt Input: char *S, the string to be sorted. Output: char *S: the sorted string. */ { char c; int i; int j; int k; int s_length; s_length = strlen ( s ); for ( i = 0; i < s_length - 1; i++ ) { c = s[i]; j = i; for ( k = i + 1; k < s_length; k++ ) { if ( s[k] < s[j] ) { j = k; } } if ( i != j ) { s[i] = s[j]; s[j] = c; } } return; } /******************************************************************************/ char *s_substring ( char *s, int a, int b ) /******************************************************************************/ /* Purpose: s_substring() returns a substring of a given string. Licensing: This code is distributed under the MIT license. Modified: 21 January 2014 Author: John Burkardt Input: char *S, a pointer to a string. int A, B, the indices of the first and last character of S to copy. These are 1-based indices! B should be Output: char *S_SUBSTRING, a pointer to the substring. */ { int i; int j; char *t; t = ( char * ) malloc ( ( b + 2 - a ) * sizeof ( char ) ); j = 0; for ( i = a; i <= b; i++ ) { t[j] = s[i-1]; j = j + 1; } t[j] = '\0'; return t; } /******************************************************************************/ char *s_to_caesar ( char *s1, int k ) /******************************************************************************/ /* Purpose: s_to_caesar() applies a Caesar shift cipher to a string. Discussion: The Caesar shift cipher incremented each letter by 1, with Z going to A. This function can apply a Caesar shift cipher to a string of characters, using an arbitrary shift K, which can be positive, negative or zero. Letters A through Z will be shifted by K, mod 26. Letters a through z will be shifted by K, mod 26. Non-alphabetic characters are unchanged. s2 = s_to_caesar ( s1, 1 ) will apply the traditional Caesar shift cipher. s3 = s_to_caesar ( s2, -1 ) will decipher the result. Licensing: This code is distributed under the MIT license. Modified: 31 January 2016 Author: John Burkardt Input: char *S1, a string of characters. int K, the increment. Output: char *S2, the string of enciphered characters. */ { int s_len; char *s2; char *c2; s_len = strlen ( s1 ); s2 = ( char * ) malloc ( ( s_len + 1 ) * sizeof ( char ) ); c2 = s2; while ( *s1 != 0 ) { if ( 'A' <= *s1 && *s1 <= 'A' + 25 ) { *c2 = i4_modp ( *s1 + k - 'A', 26 ) + 'A'; } else if ( 'a' <= *s1 && *s1 <= 'a' + 25 ) { *c2 = i4_modp ( *s1 + k - 'a', 26 ) + 'a'; } else { *c2 = *s1; } s1++; c2++; } *c2 = '\0'; return s2; } /******************************************************************************/ int *s_to_digits ( char *s, int n ) /******************************************************************************/ /* Purpose: s_to_digits() extracts N digits from a string. Discussion: The string may include spaces, letters, and dashes, but only the digits 0 through 9 will be extracted. Example: S => 34E94-70.6 N => 5 D <= (/ 3, 4, 9, 4, 7 /) Licensing: This code is distributed under the MIT license. Modified: 09 September 2015 Author: John Burkardt Input: char *S, the string. int N, the number of digits to extract. Output: int S_TO_DIGITS[N], the extracted digits. */ { char c; int d; int d_pos; int *dvec; int s_len; int s_pos; dvec = ( int * ) malloc ( n * sizeof ( int ) ); s_len = strlen ( s ); s_pos = 0; d_pos = 0; while ( d_pos < n ) { if ( s_len <= s_pos ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "S_TO_DIGITS(): Fatal error!\n" ); fprintf ( stderr, " Could not read enough data from string.\n" ); exit ( 1 ); } c = s[s_pos]; s_pos = s_pos + 1; if ( ch_is_digit ( c ) ) { d = ch_to_digit ( c ); dvec[d_pos] = d; d_pos = d_pos + 1; } } return dvec; } /******************************************************************************/ int s_to_i4 ( char *s, int *last, int *error ) /******************************************************************************/ /* Purpose: s_to_i4() reads an I4 from a string. Licensing: This code is distributed under the MIT license. Modified: 13 June 2003 Author: John Burkardt Input: char *S, a string to be examined. Output: int *LAST, the last character of S used to make IVAL. int *ERROR is TRUE (1) if an error occurred and FALSE (0) otherwise. int *S_TO_I4, the integer value read from the string. If the string is blank, then IVAL will be returned 0. */ { char c; int i; int isgn; int istate; int ival; *error = 0; istate = 0; isgn = 1; i = 0; ival = 0; while ( *s ) { c = s[i]; i = i + 1; /* Haven't read anything. */ if ( istate == 0 ) { if ( c == ' ' ) { } else if ( c == '-' ) { istate = 1; isgn = -1; } else if ( c == '+' ) { istate = 1; isgn = + 1; } else if ( '0' <= c && c <= '9' ) { istate = 2; ival = c - '0'; } else { *error = 1; return ival; } } /* Have read the sign, expecting digits. */ else if ( istate == 1 ) { if ( c == ' ' ) { } else if ( '0' <= c && c <= '9' ) { istate = 2; ival = c - '0'; } else { *error = 1; return ival; } } /* Have read at least one digit, expecting more. */ else if ( istate == 2 ) { if ( '0' <= c && c <= '9' ) { ival = 10 * (ival) + c - '0'; } else { ival = isgn * ival; *last = i - 1; return ival; } } } /* If we read all the characters in the string, see if we're OK. */ if ( istate == 2 ) { ival = isgn * ival; *last = s_len_trim ( s ); } else { *error = 1; *last = 0; } return ival; } /******************************************************************************/ int s_to_i4vec ( char *s, int n, int ivec[] ) /******************************************************************************/ /* Purpose: s_to_i4vec() reads an I4VEC from a string. Licensing: This code is distributed under the MIT license. Modified: 19 February 2001 Author: John Burkardt Input: char *S, the string to be read. int N, the number of values expected. Output: int IVEC[N], the values read from the string. int S_TO_I4VEC, is TRUE (1) if an error occurred and FALSE (0) otherwise. */ { int error; int i; int lchar; error = 0; for ( i = 0; i < n; i++ ) { ivec[i] = s_to_i4 ( s, &lchar, &error ); if ( error ) { return error; } s = s + lchar; } return error; } /******************************************************************************/ int *s_to_isbn_digits ( char *s, int n ) /******************************************************************************/ /* Purpose: s_to_isbn_digits() extracts N ISBN digits from a string. Discussion: The string may include spaces, letters, and dashes, but only the digits 0 through 9 and 'X' or 'x' will be extracted. Example: S => 34E9X-70.6 N => 5 D <= (/ 3, 4, 9, 10, 7 /) Licensing: This code is distributed under the MIT license. Modified: 16 September 2015 Author: John Burkardt Input: char *S, the string. int N, the number of digits to extract. Output: int S_TO_ISBN_DIGITS[N], the extracted digits. */ { char c; int d; int d_pos; int *dvec; int s_len; int s_pos; dvec = ( int * ) malloc ( n * sizeof ( int ) ); s_len = strlen ( s ); s_pos = 0; d_pos = 0; while ( d_pos < n ) { if ( s_len <= s_pos ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "S_TO_ISBN_DIGITS - Fatal error!\n" ); fprintf ( stderr, " Could not read enough data from string.\n" ); exit ( 1 ); } c = s[s_pos]; s_pos = s_pos + 1; if ( ch_is_isbn_digit ( c ) ) { d = isbn_digit_to_i4 ( c ); dvec[d_pos] = d; d_pos = d_pos + 1; } } return dvec; } /******************************************************************************/ int s_to_l4 ( char *s ) /******************************************************************************/ /* Purpose: s_to_l4() reads an L4 from a string. Discussion: An L4 is a logical variable. Licensing: This code is distributed under the MIT license. Modified: 03 December 2010 Author: John Burkardt Input: char *S, the string to be read. Output: int S_TO_L4, the logical value. */ { int i; int l4; int length; length = strlen ( s ); if ( length < 1 ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "S_TO_L4 - Fatal error!\n" ); fprintf ( stderr, " Input string is empty.\n" ); exit ( 1 ); } for ( i = 0; i < length; i++ ) { if ( s[i] == '0' || s[i] == 'f' || s[i] == 'F' ) { l4 = 0; return l4; } else if ( s[i] == '1' || s[i] == 't' || s[i] == 'T' ) { l4 = 1; return 14; } } fprintf ( stderr, "\n" ); fprintf ( stderr, "S_TO_L4 - Fatal error!\n" ); fprintf ( stderr, " Input did not contain boolean data.\n" ); exit ( 1 ); } /******************************************************************************/ float s_to_r4 ( char *s, int *lchar, int *error ) /******************************************************************************/ /* Purpose: s_to_r4() reads an R4 value from a string. Discussion: We have had some trouble with input of the form 1.0E-312. For now, let's assume anything less than 1.0E-20 is zero. This routine will read as many characters as possible until it reaches the end of the string, or encounters a character which cannot be part of the real number. Legal input is: 1 blanks, 2 '+' or '-' sign, 2.5 spaces 3 integer part, 4 decimal point, 5 fraction part, 6 'E' or 'e' or 'D' or 'd', exponent marker, 7 exponent sign, 8 exponent integer part, 9 exponent decimal point, 10 exponent fraction part, 11 blanks, 12 final comma or semicolon. with most quantities optional. Example: S R '1' 1.0 ' 1 ' 1.0 '1A' 1.0 '12,34,56' 12.0 ' 34 7' 34.0 '-1E2ABCD' -100.0 '-1X2ABCD' -1.0 ' 2E-1' 0.2 '23.45' 23.45 '-4.2E+2' -420.0 '17d2' 1700.0 '-14e-2' -0.14 'e2' 100.0 '-12.73e-9.23' -12.73 * 10.0^(-9.23) Licensing: This code is distributed under the MIT license. Modified: 27 April 2011 Author: John Burkardt Input: char *S, the string containing the data to be read. Reading will begin at position 1 and terminate at the end of the string, or when no more characters can be read to form a legal real. Blanks, commas, or other nonnumeric data will, in particular, cause the conversion to halt. Output: int *LCHAR, the number of characters read from the string to form the number, including any terminating characters such as a trailing comma or blanks. int *ERROR, is TRUE (1) if an error occurred and FALSE (0) otherwise. float S_TO_R4, the value that was read from the string. */ { char c; int ihave; int isgn; int iterm; int jbot; int jsgn; int jtop; int nchar; int ndig; float r; float rbot; float rexp; float rtop; char TAB = 9; static float ten = 10.0; nchar = s_len_trim ( s ); *error = 0; r = 0.0; *lchar = -1; isgn = 1; rtop = 0.0; rbot = 1.0; jsgn = 1; jtop = 0; jbot = 1; ihave = 1; iterm = 0; for ( ; ; ) { c = s[*lchar+1]; *lchar = *lchar + 1; /* Blank or TAB character. */ if ( c == ' ' || c == TAB ) { if ( ihave == 2 ) { } else if ( ihave == 6 || ihave == 7 ) { iterm = 1; } else if ( 1 < ihave ) { ihave = 11; } } /* Comma. */ else if ( c == ',' || c == ';' ) { if ( ihave != 1 ) { iterm = 1; ihave = 12; *lchar = *lchar + 1; } } /* Minus sign. */ else if ( c == '-' ) { if ( ihave == 1 ) { ihave = 2; isgn = -1; } else if ( ihave == 6 ) { ihave = 7; jsgn = -1; } else { iterm = 1; } } /* Plus sign. */ else if ( c == '+' ) { if ( ihave == 1 ) { ihave = 2; } else if ( ihave == 6 ) { ihave = 7; } else { iterm = 1; } } /* Decimal point. */ else if ( c == '.' ) { if ( ihave < 4 ) { ihave = 4; } else if ( 6 <= ihave && ihave <= 8 ) { ihave = 9; } else { iterm = 1; } } /* Exponent marker. */ else if ( ch_eqi ( c, 'E' ) || ch_eqi ( c, 'D' ) ) { if ( ihave < 6 ) { ihave = 6; } else { iterm = 1; } } /* Digit. */ else if ( ihave < 11 && '0' <= c && c <= '9' ) { if ( ihave <= 2 ) { ihave = 3; } else if ( ihave == 4 ) { ihave = 5; } else if ( ihave == 6 || ihave == 7 ) { ihave = 8; } else if ( ihave == 9 ) { ihave = 10; } ndig = ch_to_digit ( c ); if ( ihave == 3 ) { rtop = 10.0 * rtop + ( float ) ndig; } else if ( ihave == 5 ) { rtop = 10.0 * rtop + ( float ) ndig; rbot = 10.0 * rbot; } else if ( ihave == 8 ) { jtop = 10 * jtop + ndig; } else if ( ihave == 10 ) { jtop = 10 * jtop + ndig; jbot = 10 * jbot; } } /* Anything else is regarded as a terminator. */ else { iterm = 1; } /* If we haven't seen a terminator, and we haven't examined the entire string, go get the next character. */ if ( iterm == 1 || nchar <= *lchar + 1 ) { break; } } /* If we haven't seen a terminator, and we have examined the entire string, then we're done, and LCHAR is equal to NCHAR. */ if ( iterm != 1 && (*lchar) + 1 == nchar ) { *lchar = nchar; } /* Number seems to have terminated. Have we got a legal number? Not if we terminated in states 1, 2, 6 or 7! */ if ( ihave == 1 || ihave == 2 || ihave == 6 || ihave == 7 ) { *error = 1; return r; } /* Number seems OK. Form it. We have had some trouble with input of the form 1.0E-312. For now, let's assume anything less than 1.0E-20 is zero. */ if ( jtop == 0 ) { rexp = 1.0; } else { if ( jbot == 1 ) { if ( jsgn * jtop < -20 ) { rexp = 0.0; } else { rexp = pow ( ten, jsgn * jtop ); } } else { if ( jsgn * jtop < -20 * jbot ) { rexp = 0.0; } else { rexp = jsgn * jtop; rexp = rexp / jbot; rexp = pow ( ten, rexp ); } } } r = isgn * rexp * rtop / rbot; return r; } /******************************************************************************/ int s_to_r4vec ( char *s, int n, float rvec[] ) /******************************************************************************/ /* Purpose: s_to_r4vec() reads an R4VEC from a string. Licensing: This code is distributed under the MIT license. Modified: 27 April 2011 Author: John Burkardt Input: char *S, the string to be read. int N, the number of values expected. Output: float RVEC[N], the values read from the string. int S_TO_R4VEC, is TRUE (1) if an error occurred and FALSE (0) otherwise. */ { int error; int i; int lchar; error = 0; for ( i = 0; i < n; i++ ) { rvec[i] = s_to_r4 ( s, &lchar, &error ); if ( error ) { return error; } s = s + lchar; } return error; } /******************************************************************************/ double s_to_r8 ( char *s, int *lchar, int *error ) /******************************************************************************/ /* Purpose: s_to_r8() reads an R8 value from a string. Discussion: We have had some trouble with input of the form 1.0E-312. For now, let's assume anything less than 1.0E-20 is zero. This routine will read as many characters as possible until it reaches the end of the string, or encounters a character which cannot be part of the real number. Legal input is: 1 blanks, 2 '+' or '-' sign, 2.5 spaces 3 integer part, 4 decimal point, 5 fraction part, 6 'E' or 'e' or 'D' or 'd', exponent marker, 7 exponent sign, 8 exponent integer part, 9 exponent decimal point, 10 exponent fraction part, 11 blanks, 12 final comma or semicolon. with most quantities optional. Example: S R '1' 1.0 ' 1 ' 1.0 '1A' 1.0 '12,34,56' 12.0 ' 34 7' 34.0 '-1E2ABCD' -100.0 '-1X2ABCD' -1.0 ' 2E-1' 0.2 '23.45' 23.45 '-4.2E+2' -420.0 '17d2' 1700.0 '-14e-2' -0.14 'e2' 100.0 '-12.73e-9.23' -12.73 * 10.0^(-9.23) Licensing: This code is distributed under the MIT license. Modified: 02 May 2011 Author: John Burkardt Input: char *S, the string containing the data to be read. Reading will begin at position 1 and terminate at the end of the string, or when no more characters can be read to form a legal real. Blanks, commas, or other nonnumeric data will, in particular, cause the conversion to halt. Output: int *LCHAR, the number of characters read from the string to form the number, including any terminating characters such as a trailing comma or blanks. int *ERROR, is TRUE (1) if an error occurred and FALSE (0) otherwise. double S_TO_R8, the value that was read from the string. */ { char c; int ihave; int isgn; int iterm; int jbot; int jsgn; int jtop; int nchar; int ndig; double r; double rbot; double rexp; double rtop; char TAB = 9; static double ten = 10.0; nchar = s_len_trim ( s ); *error = 0; r = 0.0; *lchar = -1; isgn = 1; rtop = 0.0; rbot = 1.0; jsgn = 1; jtop = 0; jbot = 1; ihave = 1; iterm = 0; for ( ; ; ) { c = s[*lchar+1]; *lchar = *lchar + 1; /* Blank or TAB character. */ if ( c == ' ' || c == TAB ) { if ( ihave == 2 ) { } else if ( ihave == 6 || ihave == 7 ) { iterm = 1; } else if ( 1 < ihave ) { ihave = 11; } } /* Comma. */ else if ( c == ',' || c == ';' ) { if ( ihave != 1 ) { iterm = 1; ihave = 12; *lchar = *lchar + 1; } } /* Minus sign. */ else if ( c == '-' ) { if ( ihave == 1 ) { ihave = 2; isgn = -1; } else if ( ihave == 6 ) { ihave = 7; jsgn = -1; } else { iterm = 1; } } /* Plus sign. */ else if ( c == '+' ) { if ( ihave == 1 ) { ihave = 2; } else if ( ihave == 6 ) { ihave = 7; } else { iterm = 1; } } /* Decimal point. */ else if ( c == '.' ) { if ( ihave < 4 ) { ihave = 4; } else if ( 6 <= ihave && ihave <= 8 ) { ihave = 9; } else { iterm = 1; } } /* Exponent marker. */ else if ( ch_eqi ( c, 'E' ) || ch_eqi ( c, 'D' ) ) { if ( ihave < 6 ) { ihave = 6; } else { iterm = 1; } } /* Digit. */ else if ( ihave < 11 && '0' <= c && c <= '9' ) { if ( ihave <= 2 ) { ihave = 3; } else if ( ihave == 4 ) { ihave = 5; } else if ( ihave == 6 || ihave == 7 ) { ihave = 8; } else if ( ihave == 9 ) { ihave = 10; } ndig = ch_to_digit ( c ); if ( ihave == 3 ) { rtop = 10.0 * rtop + ( double ) ndig; } else if ( ihave == 5 ) { rtop = 10.0 * rtop + ( double ) ndig; rbot = 10.0 * rbot; } else if ( ihave == 8 ) { jtop = 10 * jtop + ndig; } else if ( ihave == 10 ) { jtop = 10 * jtop + ndig; jbot = 10 * jbot; } } /* Anything else is regarded as a terminator. */ else { iterm = 1; } /* If we haven't seen a terminator, and we haven't examined the entire string, go get the next character. */ if ( iterm == 1 || nchar <= *lchar + 1 ) { break; } } /* If we haven't seen a terminator, and we have examined the entire string, then we're done, and LCHAR is equal to NCHAR. */ if ( iterm != 1 && (*lchar) + 1 == nchar ) { *lchar = nchar; } /* Number seems to have terminated. Have we got a legal number? Not if we terminated in states 1, 2, 6 or 7! */ if ( ihave == 1 || ihave == 2 || ihave == 6 || ihave == 7 ) { *error = 1; return r; } /* Number seems OK. Form it. We have had some trouble with input of the form 1.0E-312. For now, let's assume anything less than 1.0E-20 is zero. */ if ( jtop == 0 ) { rexp = 1.0; } else { if ( jbot == 1 ) { if ( jsgn * jtop < -20 ) { rexp = 0.0; } else { rexp = pow ( ten, jsgn * jtop ); } } else { if ( jsgn * jtop < -20 * jbot ) { rexp = 0.0; } else { rexp = jsgn * jtop; rexp = rexp / jbot; rexp = pow ( ten, rexp ); } } } r = isgn * rexp * rtop / rbot; return r; } /******************************************************************************/ int s_to_r8vec ( char *s, int n, double rvec[] ) /******************************************************************************/ /* Purpose: s_to_r8vec() reads an R8VEC from a string. Licensing: This code is distributed under the MIT license. Modified: 19 February 2001 Author: John Burkardt Input: char *S, the string to be read. int N, the number of values expected. Output: double RVEC[N], the values read from the string. int S_TO_R8VEC, is TRUE (1) if an error occurred and FALSE (0) otherwise. */ { int error; int i; int lchar; error = 0; for ( i = 0; i < n; i++ ) { rvec[i] = s_to_r8 ( s, &lchar, &error ); if ( error ) { return error; } s = s + lchar; } return error; } /******************************************************************************/ char *s_to_rot13 ( char *s1 ) /******************************************************************************/ /* Purpose: s_to_rot13() "rotates" the alphabetical characters in a string by 13 positions. Discussion: Two applications of the routine will return the original string. Example: Input: Output: abcdefghijklmnopqrstuvwxyz nopqrstuvwxyzabcdefghijklm Cher Pure James Thurston Howell Wnzrf Guhefgba Ubjryy 0123456789 5678901234 Licensing: This code is distributed under the MIT license. Modified: 29 January 2016 Author: John Burkardt Input: char *S1, a string to be "rotated". Output: char *S_TO_ROT13, the rotated string. */ { int s_len; char *s2; char *c2; s_len = strlen ( s1 ); s2 = ( char * ) malloc ( ( s_len + 1 ) * sizeof ( char ) ); c2 = s2; while ( *s1 != 0 ) { *c2 = ch_to_rot13 ( *s1 ); s1++; c2++; } *c2 = '\0'; return s2; } /******************************************************************************/ void s_trim ( char *s ) /******************************************************************************/ /* Purpose: s_trim() promotes the final null forward through trailing blanks. Discussion: What we're trying to say is that we reposition the null character so that trailing blanks are no longer visible. Licensing: This code is distributed under the MIT license. Modified: 21 January 2014 Author: John Burkardt Input: char *S, the string to be trimmed. Output: char *S: the trimmed string. */ { char c; int n; char *t; n = strlen ( s ); t = s + strlen ( s ) - 1; while ( 0 < n ) { if ( *t != ' ' ) { return; } c = *t; *t = *(t+1); *(t+1) = c; t--; n--; } return; } /******************************************************************************/ void s_word_cap ( char *s ) /******************************************************************************/ /* Purpose: s_word_cap() capitalizes the first character of each word in a string. Licensing: This code is distributed under the MIT license. Modified: 22 November 2010 Author: John Burkardt Input: char *S, the string to be capitalized. Output: char *S: the capitalized string. */ { int blank; int i; int s_length; s_length = strlen ( s ); blank = 1; for ( i = 0; i < s_length; i++ ) { if ( blank ) { s[i] = ch_cap ( s[i] ); } else { s[i] = ch_low ( s[i] ); } blank = ( s[i] == ' ' ); } return; } /******************************************************************************/ int s_word_count ( char *s ) /******************************************************************************/ /* Purpose: s_word_count() counts the number of "words" in a string. Licensing: This code is distributed under the MIT license. Modified: 16 September 2015 Author: John Burkardt Input: char *S, the string to be examined. Output: int S_WORD_COUNT, the number of "words" in the string. Words are presumed to be separated by one or more blanks. */ { int blank; int word_num; char *t; word_num = 0; blank = 1; t = s; while ( *t ) { if ( *t == ' ' || *t == '\n' ) { blank = 1; } else if ( blank ) { word_num = word_num + 1; blank = 0; } t++; } return word_num; } /******************************************************************************/ char *s_word_extract_first ( char *s ) /******************************************************************************/ /* Purpose: s_word_extract_first() extracts the first word from a string. Discussion: A "word" is a string of characters terminated by a blank or the end of the string. Licensing: This code is distributed under the MIT license. Modified: 02 January 2009 Author: John Burkardt Input: char *S, the string. Output: char *S: the first word has been removed, and the remaining string has been shifted left. char *S_WORD_EXTRACT_FIRST, the leading word of the string. NULL is returned if there are no more words to read. */ { int get1; int get2; int i; int s_len; char *w; s_len = s_len_trim ( s ); if ( s_len < 1 ) { return NULL; } /* Find the first nonblank. */ get1 = 0; for ( ; ; ) { if ( s_len <= get1 ) { return NULL; } if ( *(s+get1) != ' ' ) { break; } get1 = get1 + 1; } /* Look for the last contiguous nonblank. */ get2 = get1; for ( ; ; ) { if ( s_len <= get2 + 1 ) { break; } if ( *(s+get2+1) == ' ' ) { break; } get2 = get2 + 1; } /* Copy the word. */ w = ( char * ) malloc ( ( get2 + 2 - get1 ) * sizeof ( char ) ); for ( i = 0; i < get2+1-get1; i++ ) { *(w+i) = *(s+get1+i); *(s+get1+i) = ' '; } *(w+get2+2-get1) = '\0'; /* Shift the string. */ s_adjustl ( s ); return w; } /******************************************************************************/ void sort_heap_external ( int n, int *indx, int *i, int *j, int isgn ) /******************************************************************************/ /* Purpose: sort_heap_external() externally sorts a list of items into ascending order. Discussion: The actual list is not passed to the routine. Hence it may consist of integers, reals, numbers, names, etc. The user, after each return from the routine, will be asked to compare or interchange two items. The current version of this code mimics the FORTRAN version, so the values of I and J, in particular, are FORTRAN indices. Licensing: This code is distributed under the MIT license. Modified: 05 February 2004 Author: FORTRAN77 original version by Albert Nijenhuis, Herbert Wilf. This version by John Burkardt Reference: Albert Nijenhuis, Herbert Wilf, Combinatorial Algorithms, Academic Press, 1978, second edition, ISBN 0-12-519260-6. Input: int N, the length of the input list. int *INDX: The user must set INDX to 0 before the first call. int ISGN. On return with INDX negative, the user should compare elements I and J of the list. If item I is to precede item J, set ISGN negative, otherwise set ISGN positive. Output: int *INDX. if INDX is greater than 0, the user must interchange items I and J and recall the routine. If INDX is less than 0, the user is to compare items I and J and return in ISGN a negative value if I is to precede J, and a positive value otherwise. If INDX is 0, the sorting is done. int *I, *J. On return with INDX positive, elements I and J of the user's list should be interchanged. On return with INDX negative, elements I and J are to be compared by the user. */ { static int i_save = 0; static int j_save = 0; static int k = 0; static int k1 = 0; static int n1 = 0; /* INDX = 0: This is the first call. */ if ( *indx == 0 ) { i_save = 0; j_save = 0; k = n / 2; k1 = k; n1 = n; } /* INDX < 0: The user is returning the results of a comparison. */ else if ( *indx < 0 ) { if ( *indx == -2 ) { if ( isgn < 0 ) { i_save = i_save + 1; } j_save = k1; k1 = i_save; *indx = -1; *i = i_save; *j = j_save; return; } if ( 0 < isgn ) { *indx = 2; *i = i_save; *j = j_save; return; } if ( k <= 1 ) { if ( n1 == 1 ) { i_save = 0; j_save = 0; *indx = 0; } else { i_save = n1; j_save = 1; n1 = n1 - 1; *indx = 1; } *i = i_save; *j = j_save; return; } k = k - 1; k1 = k; } /* 0 < INDX: the user was asked to make an interchange. */ else if ( *indx == 1 ) { k1 = k; } for ( ; ; ) { i_save = 2 * k1; if ( i_save == n1 ) { j_save = k1; k1 = i_save; *indx = -1; *i = i_save; *j = j_save; return; } else if ( i_save <= n1 ) { j_save = i_save + 1; *indx = -2; *i = i_save; *j = j_save; return; } if ( k <= 1 ) { break; } k = k - 1; k1 = k; } if ( n1 == 1 ) { i_save = 0; j_save = 0; *indx = 0; *i = i_save; *j = j_save; } else { i_save = n1; j_save = 1; n1 = n1 - 1; *indx = 1; *i = i_save; *j = j_save; } return; }