2 Character Strings: An Introduction
2.3 The strlen() function
The previous chapter unleashed the sizeof operator, which gives the size of things in bytes. The strlen() function gives the length of a string in characters. Because it takes one byte to hold one character, you might suppose that both would give the same result when applied to a string, but they don't. Add a few lines to the example, as shown in Listing 4.3 , and see why.
Listing 4.3 The praise2.c Program
c
/* praise2.c */
// try the %u or %lu specifiers if your implementation
// does not recognize the %zd specifier
#include <stdio.h>
#include <string.h> /* provides strlen() prototype */
#define PRAISE "You are an extraordinary being."
int main(void){
char name[40];
printf("What's your name? ");
scanf("%s", name);
printf("Hello, %s. %s\n", name, PRAISE);
printf("Your name of %zd letters occupies %zd memory cells.\n",
strlen(name), sizeof name);
printf("The phrase of praise has %zd letters ",
strlen(PRAISE));
printf("and occupies %zd memory cells.\n", sizeof PRAISE);
return 0;
}
If you are using a pre-ANSI C compiler, you might have to remove the following line:
c
#include <string.h>
The string.h file contains function prototypes for several string-related functions, including strlen(). Chapter 11 , "Character Strings and String Functions," discusses this header file more
fully. (By the way, some pre-ANSI Unix systems use strings.h instead of string.h to contain declarations for string functions.)
More generally, C divides the C function library into families of related functions and provides a header file for each family. For example, printf() and scanf() belong to a family of standard input and output functions and use the stdio.h header file. The strlen() function joins several other string-related functions, such as functions to copy strings and to search through strings, in a family served by the string.h header.
Notice that Listing 4.3 uses two methods to handle long printf() statements. The first method spreads one printf() statement over two lines. (You can break a line between arguments to printf() but not in the middle of a string---that is, not between the quotation marks.) The second method uses two printf() statements to print just one line. The newline
character ( \n) appears only in the second statement. Running the program could produce the
following interchange:
c
What's your name? Serendipity Chance
Hello, Serendipity. You are an extraordinary being.
Your name of 11 letters occupies 40 memory cells.
The phrase of praise has 31 letters and occupies 32 memory cells.
See what happens. The array name has 40 memory cells, and that is what the sizeof operator reports. Only the first 11 cells are needed to hold Serendipity, however, and that is what
strlen() reports. The twelfth cell in the array name contains the null character, and its presence tells strlen() when to stop counting. Figure 4.4illustrates this concept with a shorter
string.
When you get to PRAISE, you find that strlen() again gives you the exact number of characters (including spaces and punctuation) in the string. The sizeof operator gives you a
number one larger because it also counts the invisible null character used to end the string. The
program didn't tell the computer how much memory to set aside to store the phrase. It had to
count the number of characters between the double quotes itself.
As mentioned in Chapter 3 , "Data and C," the C99 and C11 standards use a %zd specifier for
the type used by the sizeof operator. This also applies for type returned by strlen(). For
earlier versions of C you need to know the actual type returned by sizeof and strlen(); typically that would be unsigned or unsigned long .
One other point: The preceding chapter used sizeof with parentheses, but this example
doesn't. Whether you use parentheses depends on whether you want the size of a type or the
size of a particular quantity. Parentheses are required for types but are optional for particular
quantities. That is, you would use sizeof(char) or sizeof(float) but can use sizeof name
or sizeof 6.28. However, it is all right to use parentheses in these cases, too, as in sizeof
(6.28) .
The last example used strlen() and sizeof for the rather trivial purpose of satisfying a user's
potential curiosity. Actually, however, strlen() and sizeof are important programming
tools. For example, strlen() is useful in all sorts of character-string programs, as you'll see in
Chapter 11
3 常量和C预处理器
Sometimes you need to use a constant in a program. For example, you could give the circumference of a circle as follows:
c
circumference = 3.14159 * diameter;
Here, the constant 3.14159 represents the world-famous constant pi (π). To use a constant,
just type in the actual value, as in the example. However, there are good reasons to use a
symbolic constant instead. That is, you could use a statement such as the following and have the
computer substitute in the actual value later:
c
circumference = pi * diameter;
Why is it better to use a symbolic constant? First, a name tells you more than a number does.
Compare the following two statements:
c
owed = 0.015 * housevalue;
owed = taxrate * housevalue;
If you read through a long program, the meaning of the second version is plainer.
Also, suppose you have used a constant in several places, and it becomes necessary to change its value. After all, tax rates do change. Then you only need to alter the definition of the
symbolic constant, rather than find and change every occurrence of the constant in the
program.
Okay, how do you set up a symbolic constant? One way is to declare a variable and set it equal
to the desired constant. You could write this:
c
float taxrate;
taxrate = 0.015;
This provides a symbolic name, but taxrate
is a variable, so your program might change its value accidentally. Fortunately, C has a couple better ideas.
The original better idea is the C preprocessor. todo:替换为链接 In Chapter 2 , "Introducing C," you saw how the preprocessor uses #include
to incorporate information from another file. The preprocessor also lets you define constants. Just add a line like the following at the top of the file containing your program:
c
#define TAXRATE 0.015
When your program is compiled, the value 0.015
will be substituted everywhere you have used TAXRATE
. This is called a compile-time substitution . By the time you run the program, all the substitutions have already been made. Such defined constants are often termed manifest constants .
Note the format. First comes #define
. Next comes the symbolic name ( TAXRATE
) for the constant and then the value ( 0.015
) for the constant. (Note that this construction does not use the =
sign.) So the general form is as follows:
c
#define NAME value
You would substitute the symbolic name of your choice for NAME
and the appropriate value for value. No semicolon is used because this is a substitution mechanism handled by the preprocessor, not a C statement. Why is TAXRATE
capitalized? It is a sensible C tradition to type constants in uppercase. Then, when you encounter one in the depths of a program, you know immediately that it is a constant, not a variable. Capitalizing constants is just another technique to make programs more readable. Your programs will still work if you don't capitalize the constants, but capitalizing them is a reasonable habit to cultivate.
The names you use for symbolic constants must satisfy the same rules that the names of variables do. You can use uppercase and lowercase letters, digits, and the underscore character. The first character cannot be a digit.
The #define
statement can be used for character and string constants, too. Just use single quotes for the former and double quotes for the latter. The following examples are valid:
c
#define BEEP '\a'
#define TEE 'T'
#define ESC '\033'
#define OOPS "Now you have done it!"
Remember that everything following the symbolic name is substituted for it. Don't make this common error:
c
/* the following is wrong */
#define TOES = 20
If you do this, TOES is replaced by = 20, not just 20. In that case, a statement such as
c
digits = fingers + TOES;
is converted to the following misrepresentation:
c
digits = fingers + = 20;
3.1 The const Modifier
C90 added a second way to create symbolic constants---using the const
keyword to convert a declaration for a variable into a declaration for a constant:
c
const int MONTHS = 12; // MONTHS a symbolic constant for 12
This makes MONTHS
into a read-only value. That is, you can display MONTHS
and use it in calculations, but you cannot alter the value of MONTHS
. This newer approach is more flexible than using #define
; it lets you declare a type, and it allows better control over which parts of a program can use the constant. Chapter 12 , "Storage Classes, Linkage, and Memory Management" discusses this and other uses of const
.
Actually, C has yet a third way to create symbolic constants, and that is the enum
facility discussed in Chapter 14 , "Structures and Other Data Forms."