Notes on Strings (Chapter 9) Basics (section 9.1) A string literal is a sequence of characters enclosed with double quotes, e.g. "Brevity is the soul of wit." "This is a short message." "Have fun!" Format strings in calls of ''printf'' and ''scanf'' e.g. printf("Enter the input file name >"); scanf("%c%d",&id,&quan); Declaring and initalizing a string variable C implements the string data structure using arrays of type char (distinction between characters and strings, 'Q' vs. "Q") --- #define STR_LEN 20 char str[STR_LEN]; char str[STR_LEN] = "November 10"; char str[] = "November 10"; str[0]=`N', str[1]='o', ... str[10]='0', str[11] = '\0' or char str[STR_LEN] = {'N', 'o', 'v', 'e', 'm', 'b', 'e', 'r', ' ', '1', '0', '\0'}; null character '\0' marks the end of a string --- #define NUM_PEOPLE 30 #define NAME_LEN 10 .... char names[NUM_PEOPLE][NAME_LEN]; --- char month[12][10] = {"January","February", .... "December"}; or char month[][10] = {"January","February", .... "December"}; or by using the concept of array of pointers, char *month[12] = {"January","February", .... "December"}; --- Questions: what if the initializer is too short to fill the string variable? the compiler adds extra null characters '\0'. what if the initializer is longer than the string variable? it's illegal, just as it's illegal for other arrays. However, ... sometimes, C does allow the initializer to have exactly the same length as the varilable. Reading and writing with printf and scanf printf("%s",str); scanf("%s",str); note: whitespace issue, more later. Example programs: strings.c courses.c names_ages.c Using the C String library -- string.h (section 9.2) The strcpy function (string copy) The strncpy function (string copy - specify the num. of chars to copy) The strlen function (string length, not counting the '\0' characther) code: string2.c (strcpy, strlen) string3.c (strncpy) -- prevent overflow, but could end up with an invalid string (without the null char at the end) correct way: strncpy(dest, source, n); dest[n] = '\0'; components.c (substrings) How to join (concatenate) two strings to form a longer string (section 9.3) The strcat function The strncat function code: strings5.c (strcat) Two critial questions for using strcpy, strncpy, strcat, strncat (1) Is there enough space in the output parameter for the entire string being created ? (2) Does the created string end in '\0' ? More on writing and reading with strings Writing strings printf("%s",str); printf("%.3s",str); // print just part of a string Reading strings / Scanning a full line (section 9.3) (1) scanf("%s",str); // no need to put the & operator, like any array // name, str is treated as a pointer when // passed to a function note: when scanf is called, it skips whitespace (blank, newline, tabs). then reads characters and stores them in str unitl it encounters a whitespace (see page 436). (2) To read an entire line of input at a time, we can use the gets function (in stdio.h) the fgets function is the file version of gets (3) scanf vs. gets Like scanf, the gets function reads input characters into an array, then stores a null character. In other respects, however, gets is somewhat different from scanf: gets doesn't skip whitespace before starting to read the string (scanf does) gets reads unitl it finds a newline character (scanf stops at any whitespace). Incidentially, gets discards the newline character instead of storing it in the array; the null character takes its place. see code: lineinput_scanf.c lineinput_gets.c (4) fgets function: code: filereading.c input file name: proglang.txt output file name: proglang2.txt (5) reading strings character by character using getchar code: scanline0.c (c.f. code length.c, length2.c) int read_line(char str[], int n) { int ch, i = 0; while ( (ch = getchar()) != '\n') if (i < n) str[i++] = ch; str[i]='\0'; return i } Note that: ch has int type rather than char type, because getchar returns character that it reads as an int value. An advanced version: scanline.c String comparison (section 9.4) C string lib functions: strcmp recall: uses rational and equality operators to compare characters. e.g. ch == 'C' ch1 < ch2 -- true if if the numeric characters code value of ch1 is less than the code in ch2. Extension: two strings: str1, str2 strcmp(str1,str2) < 0 (''str1 < str2"): (1) if the first n characters of str1 and str2 match and str1[n] and str2[n] are the first nonmatching corresponding characters, str1 is less than str2 if str1[n] < str2[n] e.g. str1 = "thrill" str2 = "throw" str1[3] < str2[3] (2) if str1 is shorter than str2 and all the characters of str1 match the corresponding characters of str2, then str1 is less than str2. e.g. str1 = "Joy" str2 = "Joyous" code: string6.c (strcmp) Array of pointers (section 9.5) char *alphap[5] = {"rose","tulip","marigold","daisy","petunia"} apphap[0]: address of string "daisy" apphap[1]: address of string "tulip" apphap[2]: address of string "marigold" apphap[3]: address of string "daisy" apphap[4]: address of string "petunia" example codes: alphaorder0.c alphaorder.c (note: depending on upper/lower case) Character operations (section 9.6) work with the individual characters that make up the string. Character input/output: ch = getchar(); putchar('a') putc('a',outfilep); (file version) codes: scanline1.c (cf. scanline0.c) scanline2.c (use type char *, to be consistent with declaration in the C standard string library) Character classification and conversion tools in ctype library isalpha isdigit islower, isupper ispunct isspace tolower, toupper code: caseignored.c Exercise: modify the program alphaorder.c to ignore case String-to-number and number-to-string conversions (section 9.7) printf scanf string "3.14159" <--> type double number value it represents Extensions: sprintf char str[20]; sprintf(str,"%d + %d = %d", x,y,x+y); if x is 3, y is 4, builds and returns the string "3 + 4 = 7" in str sprintf(s,"%d/%d/%d", mon,day,year); if mon is 11, day is 19, year is 2008, builds and returns the string "11/19/2008" in str sscanf sscanf("14.3 -5", "%lf%d", &p, &n); stores 14.4 in p and -5 in n sscanf("85 96.2 Hello", "%d%lf%s", &num, &val, str); stores 85 in num, and 96.2 in value, and Hello in str