C-Style Strings
Total Page:16
File Type:pdf, Size:1020Kb
Introduction to printf and scanf A conceptual model of a C-string String handling functions in the C standard library String parsing functions Stuff to learn on your own C-Style Strings Mike Closson Dept of Computing Science University of Alberta Small modifications: Michael Buro Feb.2006 22nd February 2006 Mike Closson C-Style Strings Introduction to printf and scanf A conceptual model of a C-string String handling functions in the C standard library String parsing functions Stuff to learn on your own Introduction to printf, fprintf. Printing Strings: /* Print to standard output */ printf( "Hello, World!\n" ); /* Print to file associated with filepointer fp */ fprintf( fp, "Hello, World!\n" ); Mike Closson C-Style Strings Introduction to printf and scanf A conceptual model of a C-string String handling functions in the C standard library String parsing functions Stuff to learn on your own Flushing an I/O stream with fflush. For performance reasons, data written with the stream functions (fwrite, printf, fprintf) may not always appear on the terminal or file after the printf function returns. To force the data to be written, use the fflush function. printf("Enter your password: "); fflush( stdout ); Usually, fflush is not needed. Mike Closson C-Style Strings Introduction to printf and scanf A conceptual model of a C-string String handling functions in the C standard library String parsing functions Stuff to learn on your own Reading data with scanf. Data is written with printf, and data is read with scanf. char password[100]; printf( "Enter your password: " ); fflush( stdout ); if (scanf( "%99s", password ) != 1) // Error ... Note that we asked scanf to read at most 99 characters, this prevents a potential buffer overflow. Mike Closson C-Style Strings Introduction to printf and scanf A conceptual model of a C-string String handling functions in the C standard library String parsing functions Stuff to learn on your own Reading integers and doubles with scanf. The scanf family of functions can also be used to read integers and doubles. The number of successfully read data items is returned. int i; double d; if (scanf( "%d", &i ) != 1) // Error ... if (scanf( "%lf", &d ) != 1) // Error ... Note that for ints and doubles, use &i instead of just i (likewise, &d instead of just d). When reading strings with scanf, you don’t need the &. Mike Closson C-Style Strings Introduction to printf and scanf A conceptual model of a C-string String handling functions in the C standard library String parsing functions Stuff to learn on your own Reading a whole line with fgets. You can use scanf to read a whitespace delimited string. If you want to read a whole line (i.e., a newline delimited string) use fgets. char string[100]; FILE *f; f = fopen("data.txt", "r" ); if (!f) { perror("Error"); exit(10); } while( fgets( string, 100, f ) != NULL ) { /* process line */ .... } fclose( f ); Mike Closson C-Style Strings Introduction to printf and scanf A conceptual model of a C-string String handling functions in the C standard library String parsing functions Stuff to learn on your own The Gory Details. C assumes that the programmer means what he/she says. in other words C makes it easy for the programmer to shoot him/herself in the foot. Mike Closson C-Style Strings Introduction to printf and scanf A conceptual model of a C-string String handling functions in the C standard library String parsing functions Stuff to learn on your own Introduction C-strings can be thought of as a bounded array of characters. The compiler and run-time environment don’t do automatic bounds checking or automatic overwrite detection. The programmer must take care to avoid memory corruption! C-strings (and more generally, memory management) are a frequent source of bizarre programming errors. Seemingly unrelated bugs are often caused by improper string handling. Intel CPU’s and Unix use byte addressable memory. (So do pretty much all CPU/OS combinations.) Mike Closson C-Style Strings Introduction to printf and scanf A conceptual model of a C-string String handling functions in the C standard library String parsing functions Stuff to learn on your own A Simple String. Note: This isn’t exactly how things Memory Address Memory Contents Variable Name work in memory, but it works for our 0x1000 0x5000 buf purposes. 0x1004 char buf[10] = "Hello!\n"; The variable buf is actually a ”pointer” to where, in memory, the string is located. 0x5000 H In C, a string ends with a NULL e (’\0’) character. Some string l l operations, like the string o declaration above, will ! automatically append the NULL \n \0 terminator. Sometimes though, we have to NULL-terminate a string ourselves. Mike Closson C-Style Strings Introduction to printf and scanf A conceptual model of a C-string String handling functions in the C standard library String parsing functions Stuff to learn on your own Copying a string. You must use a function like strncpy to copy a string. The assignment operator will do a ”pointer copy”, it won’t copy the contents of the string. char *buf1 = "Hello"; char buf2[100]; buf2 = buf1; /* incorrect */ strncpy( buf2, buf1, 100 ); /* correct */ Mike Closson C-Style Strings Introduction to printf and scanf A conceptual model of a C-string String handling functions in the C standard library String parsing functions Stuff to learn on your own Multiple Strings that use the same memory. Consider the following code: Memory Address Memory Contents Variable Name 1000 5000 buf char buf[20] = "Hello, World!\n"; 1004 5007 buf2 5000 H char *buf2 = buf + 7; 5001 e 5002 l 5003 l printf("buf: %s\n", buf); 5004 o 5005 , printf("buf2: %s\n", buf2); 5006 ' ' 5007 W 5008 o buf2[0] = ’M’; 5009 r 5010 l printf("buf: %s\n", buf); 5011 d 5012 ! 5013 \n What is the output? 5014 \0 5015 5016 5017 5018 Mike Closson C-Style Strings Introduction to printf and scanf A conceptual model of a C-string String handling functions in the C standard library String parsing functions Stuff to learn on your own ’char *’ versus ’char string[100]’. (1) char *no_space_buffer; (2) char buffer_with_space[100]; (3) char *class_name = "C201: Advanced Programming ..."; Often you will see strings declared in one of these ways. The difference is that ’char buffer with space[100]’ explicitly tells the compiler to allocate 100 bytes of storage. With the ’char *’ declaration, storage must come from somewhere else. Declaration (3) will cause the compiler to allocate space for this string on the string table. Mike Closson C-Style Strings Introduction to printf and scanf A conceptual model of a C-string String handling functions in the C standard library String parsing functions Stuff to learn on your own Access a single character in a string. Use the [] operator to access a single character in a string. char *str = "Hello"; printf( "The second character of %s is %c.\n", str, str[1] ); Notes: Use %c to print a single character with printf. Note that in C, like in Java, arrays start at 0, not 1. Mike Closson C-Style Strings Introduction to printf and scanf A conceptual model of a C-string String handling functions in the C standard library String parsing functions Stuff to learn on your own Character literals. Character literal are enclosed in single quotes (i.e., ’, not ”). char buf[10]; buf[0] = ’A’; /* correct */ buf[0] = "A"; /* incorrect */ buf[1] = 0; /* NULL terminator */ Mike Closson C-Style Strings Introduction to printf and scanf A conceptual model of a C-string String handling functions in the C standard library String parsing functions Stuff to learn on your own Multiple strings and Buffer overflow. Strings in C don’t ”grow” automatically. In- Memory Address Memory Contents Variable Name stead, the programmer must always be aware 1000 5000 s1 of how much space is available. Consider this 1004 5010 s2 example. 5000 T 5001 h char s1[10]; char s2[10]; 5002 i 5003 s strcpy( s1, 5004 ' ' "This string is to long!\n" ); 5005 s 5006 t We are copying 25 bytes into a 10 byte buffer! 5007 r 5008 i The compiler and run-time environment will not 5009 n detect this! We have overwritten string s2! 5010 g 5011 ' ' Since the string is 25 characters and s1 and s2 5012 i are 20 characters total, we have written off the 5013 s end of our own memory and have potentially 5014 ' ' 5015 t corrupted the program’s call stack! 5016 o 5017 ' ' 5018 l Mike Closson C-Style Strings Introduction to printf and scanf A conceptual model of a C-string String handling functions in the C standard library String parsing functions Stuff to learn on your own strncpy To make string handling safer, the C string library provides a function called strncpy. char global_name[100]; ... void save_name( const char *n ) { strncpy( global_name, n, 100 ); global_name[99] = 0; } Mike Closson C-Style Strings Introduction to printf and scanf A conceptual model of a C-string String handling functions in the C standard library String parsing functions Stuff to learn on your own More about strncpy If you carefully read the strncpy man-page, there are two (not-so-obvious) things to keep in mind. 1 If there is not enough space in the buffer, strncpy may not NULL terminate the string. 2 If you write 8 bytes to a 10 byte buffer, the remaining 2 bytes are set to the NULL character. The caveat is that if you have a 10 bytes buffer and you do a strncpy( buffer, stuff, 20 ); you will overflow 10 bytes off the end of buffer even if stuff will fit in buffer.