C primer plus 一到五章

C primer plus 一到五章

C Primer Plus, Fifth Edition

By Stephen Prata

 

 

Publisher

: Sams

Pub Date

: November 23, 2004

ISBN

: 0-672-32696-5

Pages

: 984

 

 

1.6 使用C语言的7个步骤

Step 1: Define the Program Objectives

Step 2: Design the Program

Step 3: Write the Code

#include <stdio.h>
int main(void)
{
int dogs;
 
    printf("How many dogs do you have?/n");
    scanf("%d", &dogs);
    printf("So you have %d dog(s)!/n", dogs);
 
    return 0;
 
}

 

Step 4: Compile

Step 5: Run the Program

Step 6: Test and Debug the Program

Step 7: Maintain and Modify the Program

 

2.4 使程序可读的技巧

Tips on Making Your Programs Readable

Choose meaningful variable names and use comments.

Another technique involves using blank lines to separate one conceptual section of a function from another.

A fourth technique is to use one line per statement.

 

The following is legitimate, but ugly, code:

int main(  void  ) { int four; four

=

4

;

printf(

      "%d/n",

four); return 0;}

 

2.7 调试

Introducing Debugging

/*  nogood.c -- a program with errors */
#include <stdio.h>
int main(void)
(
    int n, int n2, int n3;
 
/* this program has several errors
    n = 5;
    n2 = n * n;
    n3 = n2 * n2;
    printf("n = %d, n squared = %d, n cubed = %d/n", n, n2, n3)
    return 0;
 
)
 

(1)       int n, n2, n3;

(2)       Next, the example omits the */ symbol pair necessary to complete a comment. (Alternatively, you could replace /* with the new // form.)

(3)       Finally, it omits the mandatory semicolon that should terminate the printf() statement.

Semantic Errors n3 = n2 * n2;

 

/* stillbad.c -- a program with its syntax errors fixed */
#include <stdio.h>
int main(void)
{
    int n, n2, n3;
/* this program has a semantic error */
    n = 5;
    n2 = n * n;
    n3 = n2 * n2;
    printf("n = %d, n squared = %d, n cubed = %d/n", n, n2, n3);
    return 0;
 
}
n = 5, n squared = 25, n cubed = 625

 

step-by-step manually

Another approach to locating semantic problems is to sprinkle extra printf()

A third method for examining the program states is to use a debugger.

 

3.2 变量与常量数据

Data Variables and Constants

The difference between a variable and a constant is that a variable can have its value assigned or changed while the program is running, and a constant can't.

 

3.6 参数和易犯的错误

Arguments and Pitfalls

The printf() and scanf() functions are unusual in that they aren't limited to a particular number of arguments.

/* badcount.c -- incorrect argument counts */
#include <stdio.h>
int main(void)
{
    int f = 4;
    int g = 5;
    float h = 5.0f;
 
    printf("%d/n", f, g);    /* too many arguments   */
    printf("%d %d/n",f);     /* too few arguments    */
    printf("%d %f/n", h, g); /* wrong kind of values */
 
    return 0;
 
}

 

 

3.7 另一个例子:转义序列

 

One More Example: Escape Sequences

/* escape.c -- uses escape characters */
#include <stdio.h>
int main(void)
{
    float salary;
 
    printf("/aEnter your desired monthly salary:");/* 1 */
    printf(" $_______/b/b/b/b/b/b/b");             /* 2 */
    scanf("%f", &salary);
    printf("/n/t$%.2f a month is $%.2f a year.", salary,
               salary * 12.0);                     /* 3 */
    printf("/rGee!/n");                            /* 4 */
 
    return 0;
}

 

(1)       Because there is no /n at the end of the string, the cursor is left positioned after the colon.

(2)       The effect of the seven backspace characters is to move the cursor seven positions to the left.

(3)       The third printf() statement output begins with /n/t.

(4)       The fourth printf() statement begins with /r. This positions the cursor at the beginning of the current line.

(5)       the /n moves the cursor to the next line.

Here is the final appearance of the screen:

Enter your desired monthly salary: $2000.00

 

Gee!    $2000.00 a month is $24000.00 a year.

 

4.3 常量和C预处理器

Constants and the C Preprocessor

The C preprocessor uses #include to incorporate information from another file.

The preprocessor also lets you define constants.

#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.

 

/* pizza.c -- uses defined constants in a pizza context */
#include <stdio.h>
#define PI 3.14159
int main(void)
{
    float area, circum, radius;
 
    printf("What is the radius of your pizza?/n");
    scanf("%f", &radius);
    area = PI * radius * radius;
    circum = 2.0 * PI *radius;
    printf("Your basic pizza parameters are as follows:/n");
    printf("circumference = %1.2f, area = %1.2f/n", circum,
           area);
    return 0;
}

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:

#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:

/* 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

digits = fingers + TOES;

is converted to the following misrepresentation:

digits = fingers + = 20;

A second way to create symbolic constants—using the const keyword to convert a declaration for a variable into a declaration for a constant:

const int MONTHS = 12;    // MONTHS a symbolic constant for 12

This newer approach is more flexible than using #define;

 

C has yet a third way to create symbolic constants ---- enum

 

// defines.c -- uses defined constants from limit.h and float.

#include <stdio.h>

#include <limits.h>    // integer limits

#include <float.h>     // floating-point limits

int main(void)

{

    printf("Some number limits for this system:/n");

    printf("Biggest int: %d/n", INT_MAX);

    printf("Smallest long long: %lld/n", LLONG_MIN);

    printf("One byte = %d bits on this system./n", CHAR_BIT);

    printf("Largest double: %e/n", DBL_MAX);

    printf("Smallest normal float: %e/n", FLT_MIN);

    printf("float precision = %d digits/n", FLT_DIG);

    printf("float epsilon = %e/n", FLT_EPSILON);

 

    return 0;

}

 

Here is the sample output:

 

Some number limits for this system:

Biggest int: 2147483647

Smallest long long: -9223372036854775808

One byte = 8 bits on this system.

Largest double: 1.797693e+308

Smallest normal float: 1.175494e-38

float precision = 6 digits

float epsilon = 1.192093e-07

 

4.4 研究和利用printf()和scanf()

 

Exploring and Exploiting printf() and scanf()

The printf() Function

Table 4.3. Conversion Specifiers and the Resulting Printed Output

Conversion Specification

utput

%a

Floating-point number, hexadecimal digits and p-notation (C99).

%A

Floating-point number, hexadecimal digits and P-notation (C99).

%c

Single character.

%d

Signed decimal integer.

%e

Floating-point number, e-notation.

%E

Floating-point number, e-notation.

%f

Floating-point number, decimal notation.

%g

Use %f or %e, depending on the value. The %e style is used if the exponent is less than –4 or greater than or equal to the precision.

%G

Use %f or %E, depending on the value. The %E style is used if the exponent is less than –4 or greater than or equal to the precision.

%i

Signed decimal integer (same as %d).

%o

Unsigned octal integer.

%p

A pointer.

%s

Character string.

%u

Unsigned decimal integer.

%x

Unsigned hexadecimal integer, using hex digits 0f.

%X

Unsigned hexadecimal integer, using hex digits 0F.

%%

Prints a percent sign.

 

Using printf()

Listing 4.6 contains a program that uses some of the conversion specifications.

Listing 4.6. The printout.c Program

/* printout.c -- uses conversion specifiers */

#include <stdio.h>

#define PI 3.141593

int main(void)

{

    int number = 5;

    float espresso = 13.5;

    int cost = 3100;

 

    printf("The %d CEOs drank %f cups of espresso./n", number,

         espresso);

    printf("The value of pi is %f./n", PI);

    printf("Farewell! thou art too dear for my possessing,/n");

    printf("%c%d/n", '$', 2 * cost);

 

    return 0;

}

The output, of course, is

The 5 CEOs drank 13.500000 cups of espresso.

The value of pi is 3.141593.

Farewell! thou art too dear for my possessing,

$6200

If you want to print only a phrase, you don't need any conversion specifications. If you just want to print data, you can dispense with the running commentary. Each of the following statements from Listing 4.6 is quite acceptable:

printf("Farewell! thou art too dear for my possessing,/n");

printf("%c%d/n", '$', 2 * cost);

 

 

Table 4.4. The printf() Modifiers

Modifier

Meaning

flag

The five flags (-, +, space, #, and 0) are described in Table 4.5. Zero or more flags may be present.

Example: "%-10d"

digit(s)

The minimum field width. A wider field will be used if the printed number or string won't fit in the field.

Example: "%4d"

.digit(s)

Precision. For %e, %E, and %f conversions, the number of digits to be printed to the right of the decimal. For %g and %G conversions, the maximum number of significant digits. For %s conversions, the maximum number of characters to be printed. For integer conversions, the minimum number of digits to appear; leading zeros are used if necessary to meet this minimum. Using only . implies a following zero, so %.f is the same as %.0f.

Example: "%5.2f" prints a float in a field five characters wide with two digits after the decimal point.

h

Used with an integer conversion specifier to indicate a short int or unsigned short int value.

Examples: "%hu", "%hx", and "%6.4hd"

hh

Used with an integer conversion specifier to indicate a signed char or unsigned char value.

Examples: "%hhu", "%hhx", and "%6.4hhd"

j

Used with an integer conversion specifier to indicate an intmax_t or uintmax_t value.

Examples: "%jd" and "%8jX"

l

Used with an integer conversion specifier to indicate a long int or unsigned long int.

Examples: "%ld" and "%8lu"

ll

Used with an integer conversion specifier to indicate a long long int or unsigned long long int. (C99)

Examples: "%lld" and "%8llu"

L

Used with a floating-point conversion specifier to indicate a long double value.

Examples: "%Lf" and "%10.4Le"

t

Used with an integer conversion specifier to indicate a ptrdiff_t value. This is the type corresponding to the difference between two pointers. (C99)

Examples: "%td" and "%12ti"

z

Used with an integer conversion specifier to indicate a size_t value. This is the type returned by sizeof. (C99).

Examples: "%zd" and "%12zx"

 

Table 4.5. The printf() Flags

Flag

Meaning

-

The item is left-justified; that is, it is printed beginning at the left of the field.

Example: "%-20s"

+

Signed values are displayed with a plus sign, if positive, and with a minus sign, if negative.

Example: "%+6.2f"

space

Signed values are displayed with a leading space (but no sign) if positive and with a minus sign if negative. A + flag overrides a space.

Example: "% 6.2f"

#

Use an alternative form for the conversion specification. Produces an initial 0 for the %o form and an initial 0x or 0X for the %x or %X form, respectively. For all floating-point forms, # guarantees that a decimal-point character is printed, even if no digits follow. For %g and %G forms, it prevents trailing zeros from being removed.

Examples: "%#o", "%#8.0f", and "%+#10.3E"

0

For numeric forms, pad the field width with leading zeros instead of with spaces. This flag is ignored if a - flag is present or if, for an integer form, a precision is specified.

Examples: "%010d" and "%08.3f"

 

Examples Using Modifiers and Flags

Let's put these modifiers to work, beginning with a look at the effect of the field width modifier on printing an integer. Consider the program in Listing 4.7.

Listing 4.7. The width.c Program

/* width.c -- field widths */

#include <stdio.h>

#define PAGES 931

int main(void)

{

    printf("*%d*/n", PAGES);

    printf("*%2d*/n", PAGES);

    printf("*%10d*/n", PAGES);

    printf("*%-10d*/n", PAGES);

 

    return 0;

}

 

Listing 4.7 prints the same quantity four times using four different conversion specifications. It uses an asterisk (*) to show you where each field begins and ends. The output looks as follows:

*931*

*931*

*       931*

*931       *

 

Now look at some floating-point formats. Enter, compile, and run the program in Listing 4.8.

Listing 4.8. The floats.c Program

// floats.c -- some floating-point combinations

#include <stdio.h>

int main(void)

{

const double RENT = 3852.99;  // const-style constant

 

    printf("*%f*/n", RENT);

    printf("*%e*/n", RENT);

    printf("*%4.2f*/n", RENT);

    printf("*%3.1f*/n", RENT);

    printf("*%10.3f*/n", RENT);

    printf("*%10.3e*/n", RENT);

    printf("*%+4.2f*/n", RENT);

    printf("*%010.2f*/n", RENT);

 

    return 0;

}

 

This time, the program uses the keyword const to create a symbolic constant. The output is

 

*3852.990000*

*3.852990e+03*

*3852.99*

*3853.0*

*  3852.990*

* 3.853e+03*

*+3852.99*

*0003852.99*

 

The example begins with the default version, %f. In this case, there are two defaults—the field width and the number of digits to the right of the decimal. The second default is six digits, and the field width is whatever it takes to hold the number.

Next is the default for %e. It prints one digit to the left of the decimal point and six places to the right. We're getting a lot of digits! The cure is to specify the number of decimal places to the right of the decimal, and the next four examples in this segment do that. Notice how the fourth and the sixth examples cause the output to be rounded off.

Finally, the + flag causes the result to be printed with its algebraic sign, which is a plus sign in this case, and the 0 flag produces leading zeros to pad the result to the full field width. Note that in the specifier %010, the first 0 is a flag, and the remaining digits (10) specify the field width.

You can modify the RENT value to see how variously sized values are printed. Listing 4.9 demonstrates a few more combinations.

Listing 4.9. The flags.c Program

/* flags.c -- illustrates some formatting flags */

#include <stdio.h>

int main(void)

{

    printf("%x %X %#x/n", 31, 31, 31);

    printf("**%d**% d**% d**/n", 42, 42, -42);

    printf("**%5d**%5.3d**%05d**%05.3d**/n", 6, 6, 6, 6);

 

    return 0;

}

 

The output looks as follows:

1f 1F 0x1f

**42** 42**-42**

**    6**  006**00006**  006**

 

First, 1f is the hex equivalent of 31. The x specifier yields 1f, and the X specifier yields 1F. Using the # flag provides an initial 0x.

The second line of output illustrates how using a space in the specifier produces a leading space for positive values, but not for negative values. This can produce a pleasing output because positive and negative values with the same number of significant digits are printed with the same field widths.

The third line illustrates how using a precision specifier (%5.3d) with an integer form produces enough leading zeros to pad the number to the minimum value of digits (three, in this case). Using the 0 flag, however, pads the number with enough leading zeros to fill the whole field width. Finally, if you provide both the 0 flag and the precision specifier, the 0 flag is ignored.

Now let's examine some of the string options. Consider the example in Listing 4.10.

Listing 4.10. The strings.c Program

/* strings.c -- string formatting */

#include <stdio.h>

#define BLURB "Authentic imitation!"

int main(void)

{

    printf("/%2s//n", BLURB);

    printf("/%24s//n", BLURB);

    printf("/%24.5s//n", BLURB);

    printf("/%-24.5s//n", BLURB);

 

    return 0;

}

Here is the output:

/Authentic imitation!/

/    Authentic imitation!/

/                   Authe/

/Authe                   /

 

Notice how the field is expanded to contain all the specified characters. Also notice how the precision specification limits the number of characters printed. The .5 in the format specifier tells printf() to print just five characters. Again, the - modifier left-justifies the text.

 

Naturally, you should match the conversion specification to the type of value being printed. Often, you have choices. For instance, if you want to print a type int value, you can use %d or %x or %o.

 

// input.c -- when to use &

#include <stdio.h>

int main(void)

{

    int age;             // variable

    float assets;        // variable

    char pet[30];        // string

 

    printf("Enter your age, assets, and favorite pet./n");

    scanf("%d %f", &age, &assets); // use the & here

    scanf("%s", pet);              // no & for char array

    printf("%d $%.2f %s/n", age, assets, pet);

 

    return 0;

}

 

Here is a sample exchange:

Enter your age, assets, and favorite pet.

38

92360.88 llama

38 $92360.88 llama

 

 

Table 4.6. ANSI C Conversion Specifiers for scanf()

Conversion Specifier

Meaning

%c

Interpret input as a character.

%d

Interpret input as a signed decimal integer.

%e, %f, %g, %a

Interpret input as a floating-point number (%a is C99).

%E, %F, %G, %A

Interpret input as a floating-point number (%A is C99).

%i

Interpret input as a signed decimal integer.

%o

Interpret input as a signed octal integer.

%p

Interpret input as a pointer (an address).

%s

Interpret input as a string. Input begins with the first non-whitespace character and includes everything up to the next whitespace character.

%u

Interpret input as an unsigned decimal integer.

%x, %X

Interpret input as a signed hexadecimal integer.

Table 4.7. Conversion Modifiers for scanf()

Modifier

Meaning

*

Suppress assignment (see text).

Example: "%*d"

digit(s)

Maximum field width. Input stops when the maximum field width is reached or when the first whitespace character is encountered, whichever comes first.

Example: "%10s"

hh

Read an integer as a signed char or unsigned char.

Examples: "%hhd" "%hhu"

ll

Read an integer as a long long or unsigned long long (C99).

Examples: "%lld" "%llu"

h, l, or L

"%hd" and "%hi" indicate that the value will be stored in a short int. "%ho", "%hx", and "%hu" indicate that the value will be stored in an unsigned short int. "%ld" and "%li" indicate that the value will be stored in a long. "%lo", "%lx", and "%lu" indicate that the value will be stored in unsigned long. "%le", "%lf", and "%lg" indicate that the value will be stored in type double. Using L instead of l with e, f, and g indicates that the value will be stored in type long double. In the absence of these modifiers, d, i, o, and x indicate type int, and e, f, and g indicate type float.

 

The * serves quite a different purpose for scanf(). When placed between the % and the specifier letter, it causes that function to skip over corresponding input. Listing 4.17 provides an example.

Listing 4.17. The skip2.c Program

/* skip2.c -- skips over first two integers of input */

#include <stdio.h>

int main(void)

{

    int n;

 

    printf("Please enter three integers:/n");

    scanf("%*d %*d %d", &n);

    printf("The last integer was %d/n", n);

 

    return 0;

}

The scanf() instruction in Listing 4.17 says, "Skip two integers and copy the third into n." Here is a sample run:

 

Please enter three integers:

2004 2005 2006

The last integer was 2006

 

This skipping facility is useful if, for example, a program needs to read a particular column of a file that has data arranged in uniform columns.

 

5.3 其他运算符

Some Additional Operators

The sizeof Operator and the size_t Type

 

C says that sizeof returns a value of type size_t. This is an unsigned integer type, but not a brand-new type. Instead, like the portable types (int32_t and so on), it is defined in terms of the standard types.

 

Modulus Operator: %

 

Increment and Decrement Operators: ++ and

 

Type Conversions

The basic rules are

1.    When appearing in an expression, char and short, both signed and unsigned, are automatically converted to int or, if necessary, to unsigned int. (If short is the same size as int, unsigned short is larger than int; in that case, unsigned short is converted to unsigned int.) Under K&R C, but not under current C, float is automatically converted to double. Because they are conversions to larger types, they are called promotions.

2.    In any operation involving two types, both values are converted to the higher ranking of the two types.

3.    The ranking of types, from highest to lowest, is long double, double, float, unsigned long long, long long, unsigned long, long, unsigned int, and int. One possible exception is when long and int are the same size, in which case unsigned int outranks long. The short and char types don't appear in this list because they would have been already promoted to int or perhaps unsigned int.

4.    In an assignment statement, the final result of the calculations is converted to the type of the variable being assigned a value. This process can result in promotion, as described in rule 1, or demotion, in which a value is converted to a lower-ranking type.

5.    When passed as function arguments, char and short are converted to int, and float is converted to double. This automatic promotion can be overridden by function prototyping, as discussed in Chapter 9, "Functions."

/* convert.c -- automatic type conversions */

#include <stdio.h>

int main(void)

{

    char ch;

    int i;

    float fl;

 

    fl = i = ch = 'C';                                  /* line 9  */

    printf("ch = %c, i = %d, fl = %2.2f/n", ch, i, fl); /* line 10 */

    ch = ch + 1;                                        /* line 11 */

    i = fl + 2 * ch;                                    /* line 12 */

    fl = 2.0 * ch + i;                                  /* line 13 */

    printf("ch = %c, i = %d, fl = %2.2f/n", ch, i, fl); /* line 14 */

    ch = 5212205.17;                                    /* line 15 */

    printf("Now ch = %c/n", ch);

 

    return 0;

}

Running convert.c produces the following output:

ch = C, i = 67, fl = 67.00

ch = D, i = 203, fl = 339.00

Now ch = -

On this system, which has an 8-bit char and a 32-bit int, here is what happened:

·         Lines 9 and 10— The character 'C' is stored as a 1-byte ASCII value in ch. The integer variable i receives the integer conversion of 'C', which is 67 stored as 4 bytes. Finally, fl receives the floating conversion of 67, which is 67.00.

·         Lines 11 and 14— The character variable 'C' is converted to the integer 67, which is then added to the 1. The resulting 4-byte integer 68 is truncated to 1 byte and stored in ch. When printed using the %c specifier, 68 is interpreted as the ASCII code for 'D'.

·         Lines 12 and 14— The value of ch is converted to a 4-byte integer (68) for the multiplication by 2. The resulting integer (136) is converted to floating point in order to be added to fl. The result (203.00f) is converted to int and stored in i.

·         Lines 13 and 14— The value of ch ('D', or 68) is converted to floating point for multiplication by 2.0. The value of i (203) is converted to floating point for the addition, and the result (339.00) is stored in fl.

·         Lines 15 and 16— Here the example tries a case of demotion, setting ch equal to a rather large number. After truncation takes place, ch winds up with the ASCII code for the hyphen character.

5.5 类型转换

The Cast Operator

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值