09-06-String Inputs (Source IPC notes) INPUT The functions that process string input are: scanf() - input under format control get_s() - line by line input (not universally implemented) Formatted Input The conversion specifiers for a string in scanf() are %s and %[]. The corresponding argument in each case is the address of the string to be populated from the input stream. %s The %s conversion specifier – what does scanf do with %s reads all characters until the first whitespace character – STOPS AT SPACE stores the characters read in the char array identified by the corresponding argument stores the null terminator in the char array after accepting the last character leaves the delimiting whitespace character and any subsequent characters in the input buffer For example of STOPS AT SPACE, char name[31]; scanf("%s", name); My name is Arnold stops accepting input after the character y and stores char name[31] 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 M y \0 The characters ' name is Arnold' remain in the input buffer. A qualifier on the conversion specifier limits the number of characters accepted. For instance, %10s reads no more than 10 characters char name[31]; scanf("%10s", name); Schwartzenegger stopping after the character n and storing Document1 by rt -- 19 March 2016 1 of 6 char name[31] 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 S c h w a r t z e n \0 By specifying the maximum number of characters to be read at less than 31, we ensure that scanf() does not exceed the memory allocated for the string. %s discards all leading whitespace characters. For example, char name[31]; scanf("%10s", name); Schwartzenegger stops at n and stores char name[31] 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 S c h w a r t z e n \0 Because %s discards leading whitespace, it cannot accept an empty string; that is, %s does not treat a '\n' in an otherwise empty input buffer as an empty string. If the buffer only contains '\n', scanf("%10s", name) discards the '\n' and waits for non-whitespace input followed by another '\n'. %[ ] The %[] conversion specifier accepts input consisting only of a set of pre-selected characters. The brackets contain the admissible and/or inadmissible characters. The symbol ^ prefaces the list of inadmissible characters. The symbol - identifies a range of characters in an inclusive set. For example, the %[^\n] conversion specifier reads all characters until the newline ('\n') stores the characters read in the char array identified by the corresponding argument stores the null terminator in the char array after accepting the last character leaves the delimiting character (here, '\n') in the input buffer For example, char name[31]; scanf("%[^\n]", name); My name is Arnold accepts the full line and stores char Document1 by rt -- 19 March 2016 2 of 6 name[31] 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 My n a m e i s A r n o l d \0 A qualifier on this conversion specifier before the opening bracket limits the number of characters accepted. For instance, %10[^\n] reads no more than 10 characters. char name[31]; scanf("%10[^\n]", name); My name is Arnold stores char name[31] 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 My n a m e i s \0 We specify the maximum number of characters as the qualifier to ensure that scanf() does not store more characters than room allows. %[ ], like %s, ignores any leading whitespace characters. For example, char name[31]; scanf("%10[^\n]", name); My name is Arnold stores char name[31] 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 My n a m e i s \0 Because %[ ] ignores leading whitespace, it cannot accept an empty string; that is, %[^\n] does not treat a '\n' in an otherwise empty input buffer as an empty string. If the input buffer only contains '\n', scanf("%[^\n]", name), unlike %s, returns 0 and leaves name unchanged. Line-Oriented Input (Optional) The library function gets_s() accepts an empty string assumes no more than a specified number of characters reads the '\n' as the delimiter replaces the delimiter with the null terminator Document1 by rt -- 19 March 2016 3 of 6 gets_s() takes two arguments. The first argument specifies the address of the string to be filled. The second argument specifies the maximum number of characters that can be stored including the null terminator. On success this function returns the address of the string filled. For example // Read and Display Lines // gets_s.c #include <stdio.h> int main(void) { char first_name[21]; char last_name[21]; printf("First Name : "); gets_s(first_name, 21); printf("Last Name : "); First Name : Arnold Last Name : Schwartzenegger Arnold Schwartzenegger gets_s(last_name, 21); puts(first_name); puts(last_name); return 0; } This function's behavior if the user inputs a line longer than the allocated string is undefined. On a Windows platform, the function crashes. Document1 by rt -- 19 March 2016 4 of 6 CUSTOM LINE-ORIENTED INPUT (OPTIONAL) Line-oriented input is useful in debugging. Consider a set of input lines some of which contain incorrect input. A one-to-one correspondence exists between the lines of input data and the lines read by the program. Even if the user inputs one line incorrectly, subsequent correct input may still be accepted. In other words, incorrect input on one line does not cause incorrect reading of subsequent lines. Ideally, line by line input should store characters only to a specified maximum accept an empty string read the '\n' as the line delimiter discard the delimiting character along with any characters that overflow memory append the null terminator to the set of characters stored The following code meets all of these conditions // Custom Line-Oriented Input // getline.c #include <stdio.h> // getline accepts a newline terminated // string s of up to max - 1 characters, // adds the null terminator and discards // the remaining characters in the input // buffer including terminating character // char *getline(char *s, int n) { int i, c; for (i = 0; i < n - 1 && (c = getchar()) != EOF && c != (int)'\n'; i++) s[i] = c; s[i] = '\0'; while (n > 1 && c != EOF && c != (int)'\n') c = getchar(); return c != EOF ? s : NULL; } First Name : Arnold Last Name Document1 by rt -- 19 March 2016 : Schwartzenegger 5 of 6 int main(void) { char first_name[11]; char last_name[11]; Arnold Schwartzen printf("First Name : "); getline(first_name, 11); printf("Last Name : "); getline(last_name, 11); puts(first_name); puts(last_name); return 0; } This function, unlike gets_s() has well-defined behavior if the number of characters entered exceeds the amount of memory available to store the string. Document1 by rt -- 19 March 2016 6 of 6