C Primer Plu学习笔记【7-8章节】

第7章 C控制语句:分支和跳转

 

7.1 if语句

示例代码

#include <stdio.h>
int main(void)
{
    const int FREEZING = 0;
    float temperature;
    int cold_days = 0;
    int all_days = 0;
    
    printf("Enter the list of daily low temperatures.\n");
    printf("Use Celsius and enter q to quit.\n");
    while (scanf("%f", &temperature) == 1) {
        all_days++;
        if (temperature < FREEZING) {
            cold_days++;
        }
    }
    if (all_days != 0) {
        printf("%d days total: %.1f%% were below freezing.\n",
               all_days, 100.0 * (float) cold_days / all_days);
    }
    if (all_days == 0) {
        printf("No data entered!\n");
    }
    
    return 0;
}

输出:

Enter the list of daily low temperatures.

Use Celsius and enter q to quit.

12 5 -2.5 0 6 8 -3 -10 10 q

9 days total: 33.3% were below freezing.

比较简单的格式

if (expression)

    statement

 

7.2if else语句

if (expression)

  statement

else

   statement

二选一的if else表达式

 

7.2.1 另一示例:介绍getchar与putchar()

getchar()与putchar()定义在stdio.h头文件中。在处理字符的时候,用起来比较方便

示例代码

#include <stdio.h>
#define SPACE ' '
int main(void)
{
    char ch;
    
    ch = getchar();
    while (ch != '\n') {      // 对输入进行判断
        if (ch == SPACE) {
            putchar(ch);
        }
        else
        {
            putchar(++ch);
        }
        ch = getchar();     /*   循环接受字符*/
    }
    putchar(ch);    // 打印换行符号
    
    return 0;
}

输出

CALL ME HAL

DBMM NF IBM

改进的C语言程序员写法

#include <stdio.h>
#define SPACE ' '
int main(void)
{
    char ch;
    
    while ((ch = getchar()) != '\n') {      // 对输入进行判断
        if (ch == SPACE) {
            putchar(ch);
        }
        else
        {
            putchar(++ch);
        }
    }
    putchar(ch);    // 打印换行符号
    
    return 0;
}

7.2.2 ctype.h系列的字符函数

介绍了一些ctype.h头文件中判断字符的函数

#include <stdio.h>
#include <ctype.h>
int main(void)
{
    char ch;
    
    while ((ch = getchar()) != '\n') {      // 对输入进行判断
        if (isalnum(ch)) {         // 是字符就处理
            putchar(++ch);
        }
        else
        {
            putchar(ch);
        }
    }
    putchar(ch);    // 打印换行符号
    
    return 0;
}

输出

LOOK! It's a programmer!

MPPL! Ju't b qsphsbnnfs!

Program ended with exit code: 0

7.2.3多重选择else if

示例代码

#include <stdio.h>
#define RATE1 0.13230
#define RATE2 0.15040     // 定义不同档次的电费价格
#define RATE3 0.30025
#define RATE4 0.34025
#define BREAK1 360.0      // 定义了每档的用电度数
#define BREAK2 468.0
#define BREAK3 720.0
// 这个定义设计的很好,定义第一档用到的时候电费价格
#define BASE1 (RATE1 * BREAK1)
#define BASE2 (BASE1 + (RATE2 * (BREAK2 - BREAK1)))
#define BASE3 (BASE1 + BASE2 + (RATE3 * (BREAK3 - BREAK2)))

int main(void)
{
    double kwh;
    double bill;
    
    printf("Please enter the kwh used.\n");
    scanf("%lf", &kwh);
    if (kwh <= BREAK1) {
        bill = RATE1 * kwh;
    }
    else if (kwh <= BREAK2) {
        bill = BASE1 + (RATE2 * (kwh - BREAK1));
    }
    else if (kwh <= BREAK3)
        bill = BASE2 + (RATE3 * (kwh - BREAK2));
    else
        bill = BASE3 + (RATE4 * (kwh - BREAK3));
    printf("The charge for %.1f kwh is $%1.2f.\n", kwh, bill);
    
    return 0;
}

输出

Please enter the kwh used.

580

The charge for 580.0 kwh is $97.50.

Program ended with exit code: 0

整个代码使用了预处理很好的定义了一些常量,思路还是非常不错的。

 

7.2.4 else与if配对

没有大括号的情况下,else与最近的if配对。

 

7.2.5 多层嵌套的if语句

示例代码

#include <stdio.h>
#include <stdbool.h>
int main(void)
{
    unsigned long num;
    unsigned long div;
    bool isPrime;
    
    printf("Please enter an integer for analysis; ");
    printf("Enter q to quit.\n");
    while (scanf("%lu", &num) == 1) {
        for (div = 2, isPrime = true; (div * div) <= num; div++) {
            if (num % div ==0){
                if ((div * div) != num) {
                    printf("%lu is divisible by %lu and %lu.\n",
                           num, div, num/div);
                }
                else
                {printf("%lu is divisible by %lu.\n",
                        num, div);}
                isPrime = false;   // 不是素数
            }
        }
        if (isPrime) {
            printf("%lu is prime.\n", num);
        }
        printf("Please enter anpther integer for analysis; ");
        printf("Enter q to quit.\n");
    }
    printf("Bye.\n");
    
    return 0;
    
}

输出

Please enter an integer for analysis; Enter q to quit.

25

25 is divisible by 5.

Please enter anpther integer for analysis; Enter q to quit.

149

149 is prime.

Please enter anpther integer for analysis; Enter q to quit.

81

81 is divisible by 3 and 27.

81 is divisible by 9.

Please enter anpther integer for analysis; Enter q to quit.

q

Bye.

Program ended with exit code: 0

7.3逻辑运算符

这个就是Python中的and or not

示例代码

#include <stdio.h>
#define PERIOD '.'
int main(void)
{
    char ch;
    int charcount = 0;
    
    
    while ((ch = getchar()) != PERIOD) {
        // 书中的if (ch != '"' and ch != '\'')
        if (!(ch == '"' || ch == '\'')) {
            charcount++;
        }
    }
    printf("There are %d non-quote characters.\n", charcount);
    
    return 0;
}

I didn't read the "I'm a Programming Fool" best seller.

There are 50 non-quote characters.

&&表示and 

||表示or

!表示not

 

7.3.1 备选拼写: iso646.h头文件

导入这个头文件就可以用and or not 来代替&& || !了

#include <stdio.h>
#include <iso646.h>
#define PERIOD '.'
int main(void)
{
    char ch;
    int charcount = 0;
    
    
    while ((ch = getchar()) != PERIOD) {
        // 书中的if (ch != '"' and ch != '\'')
        if (!(ch == '"' or ch == '\'')) {
            charcount++;
        }
    }
    printf("There are %d non-quote characters.\n", charcount);
    
    return 0;
}

7.3.2

优先级!的运算符优先级很高,比乘法远算符还高。&&比||高,但比< >等关系远算符要低。

写的时候最好用上小括号,表示各个比较逻辑。

 

7.3.3 求值顺序

C保证逻辑表达式的求值顺序是从左向右。 &&和||运算符都是序列点,所有程序在从一个运算对象到下一个运算对象之前,所有的副作用都会生效。

书中介绍了求值顺序,与短路原则

x != 0 && (20 / x) <5 当写这个条件的时候,短路原则可以剔除了x为0 的情况。

7

7.3.4 范围

写条件的时候

if (range >= 90 && range <= 100)

  printf("ok");

不要写成

if (90 <= range <= 100)

  printf("ok");

这个会永远成立,因为逻辑表达式是从左向右执行的。

(90 <= range) <= 100

前面无论如何返回的都是0或1,这个条件永远成立。

 

7.4 一个统计单词的程序,设计的非常好的逻辑算法

#include <stdio.h>
#include <ctype.h>
#include <stdbool.h>
#define STOP '|'
int main(void)
{
    
    char c;
    char prev;
    long n_chars = 0L;
    int n_lines = 0;
    int n_words = 0;
    int p_lines = 0;
    bool inword = false;
    
    printf("Enter text to br analyzed (| to terminate):\n");
    prev = '\n';
    while ((c = getchar()) != STOP) {     // 循环读取输入的字符
        n_chars++;        // 统计字符数量
        if (c == '\n') {    // 统计换行数量
            n_lines++;
        }
        if (!isspace(c) && !inword) {      //只要出现字母就统计第一个单次,且后面的字母忽略
            inword = true;
            n_words++;
        }
        if (isspace(c) && inword) {    //只要在字母中,出现空格就设置inword不在字母中,给前面的统计创建条件
            inword = false;
        }
        prev = c;
    }
    if (prev != '\n') {   // 统计最后一行是否有换行符
        p_lines = 1;
    }
    printf("characters = %ld, words = %d, lines = %d, ",
           n_chars, n_words, n_lines);
    printf("partial lines = %d\n", p_lines);
    return 0;
}

输出

Enter text to br analyzed (| to terminate):

I   love you   

see you tormorrow!|

characters = 34, words = 6, lines = 1, partial lines = 1

Program ended with exit code: 0

 

7.5 条件远算符

 到了所谓的三目表达式了,C语言的写法是

expression ? expression2 : expression3

示例代码

#include <stdio.h>
#define COVERAGE 350      // 整桶油漆可用面积
int main(void)
{
    int sq_feet;
    int cans;
    
    printf("Enter number of square feet to be painted:\n");
    while (scanf("%d", &sq_feet) == 1) {
        cans = sq_feet / COVERAGE;
        cans += (sq_feet % COVERAGE == 0) ? 0 : 1;
        printf("You need %d %s of plait.\n", cans,
               cans == 1 ? "can" : "cans");
        printf("Enter next value (q to quit):\n");
        
    }
    
    
    return 0;
}

输出

Enter number of square feet to be painted:

349

You need 1 can of plait.

Enter next value (q to quit):

351

You need 2 cans of plait.

Enter next value (q to quit):

q

 

7.6循环辅助:continue和break

 这个跟Python中的用法差不多,首相上示例代码:

#include <stdio.h>
int main(void)
{
    const float MIN = 0.0f;
    const float MAX = 100.f;
    
    float score;
    float total = 0.0f;
    int n = 0;
    float min = MAX;
    float max = MIN;     /* 很好的一种初始值的丁回忆方式 */
    
    printf("Enter the first score (q to quit): ");
    while (scanf("%f", &score) == 1) {
        if (score < MIN || score > MAX) {
            printf("%.1f is an invalid value. Try again: ", score);
            continue;
        }
        printf("Accepting %.1f:\n", score);
        min = (score < min) ? score: min;
        max = (score > max) ? score: max;
        total += score;
        n++;
        printf("Enter next score (q to quit): ");
    }
    if (n > 0) {
        printf("Average of %d scores is %.1f.\n", n, total / n);
        printf("Low = %.1f, high = %.1f\n", min, max);
    }
    else
        printf("No valid scores were entered.\n");
    
    return 0;
    
}

输出

12 45 100

Enter the first score (q to quit): Accepting 12.0:

Enter next score (q to quit): Accepting 45.0:

Enter next score (q to quit): Accepting 100.0:

Enter next score (q to quit): q

Average of 3 scores is 52.3.

Low = 12.0, high = 100.0

Program ended with exit code: 0

其实这种代码分割我是不会写的,一般我写的代码也很少用到continue,书中也说明了很多另外的写法可以替代continue

有一处书中写了,可以用来当占位符还算最有意思的解释了

while (getchar() != '\n')
    continue;

另外书中就没有什么有意思的东西了。

 

7.6.2 break语句

这个其实跟Python的用法也差不多,书中特意强调了,只会停止内部的循环,不会停止外部的。

示例代码是一个求面积的函数

#include <stdio.h>
int main(void)
{
    float length, width;
    
    printf("Enter the length of the rectangle:\n");
    while (scanf("%f", &length) == 1) {
        printf("Length = %.2f:\n", length);
        printf("Enter its width:\n");
        if (scanf("%f", &width) != 1) {
            break;
        }
        printf("Width = %.2f:\n", width);
        printf("Area = %.2f:\n", length * width);
        printf("Enter the length of the rectangle:\n");
    }
    printf("Done.\n");
    
    return 0;
}

输出

Enter the length of the rectangle:

1.2

Length = 1.20:

Enter its width:

3.3

Width = 3.30:

Area = 3.96:

Enter the length of the rectangle:

1.5

Length = 1.50:

Enter its width:

q

Done.

7.7 多重选择: switch和break

#include <stdio.h>
#include <ctype.h>
int main(void)
{
    char ch;
    
    printf("Give me a letter of the alphabet, and I will give ");
    printf("an animal name\nbeginning with that letter.\n");
    printf("Please type in a letter; tyoe # to end my act.\n");
    while ((ch = getchar()) != '#') {
        if ('\n' == ch) {     // 回车不退出
            continue;
        }
        if (islower(ch)) {
            switch (ch) {       // stitch 使用
                case 'a':
                    printf("argali, a wild sheep of Asia\n");
                    break;
                case 'b':
                    printf("babirusa, a wild pig of Malay\n");
                    break;
                case 'c':
                    printf("coati racoonlike manmal\n");
                    break;
                case 'd':
                    printf("desman, aquatic, molelike critter \n");
                    break;
                case 'e':
                    printf("echidna, the spiny anteacher\n");
                    break;
                case 'f':
                    printf("fisher, browish marten\n");
                    break;
                default:
                    printf("That's a stumper!\n");
                    break;
            }
        }
        else
            printf("I recognize only lowercase letters.\n");
        while (getchar() != '\n') {     // 输入多个字符串后面的全部忽略掉
            continue;
        }
        printf("Please type another letter or a #.\n");
        
    }
    printf("Bye!\n");
    
    return 0;
}

输出:

Give me a letter of the alphabet, and I will give an animal name

beginning with that letter.

Please type in a letter; tyoe # to end my act.

abc#

argali, a wild sheep of Asia

Please type another letter or a #.

cd

coati racoonlike manmal

Please type another letter or a #.

#

Bye!

 这是一个设计非常逻辑精密的代码,让我感觉到了作者大神就是大神。

 

7.7.1switch语句

switch作为我刚接触新的关键字,书中介绍C语言的case一般指定一个值,不能使用一个范围。switch在圆括号中的测试表达式的值应该是一个整数值(包括char类型。)case标签必须是整数类型(包括char类型)的常量或者整形常量表达式(既,表达式中只包含整数常量)。不能用变量作为case的便签

格式:

switch (整数表达式)

{

  case 常量1:

     语句;

      case 常量2:

               语句

}

7.7.2只读每行的首字符

书中用了case的穿透功能,有点小意思

#include <stdio.h>
int main(void)
{
    char ch;
    int a_ct, e_ct, i_ct, o_ct, u_ct;
    
    a_ct = e_ct = i_ct = o_ct = u_ct =0;
    
    printf("Enter some text; enter # to quit.\n");
    while ((ch = getchar()) != '#') {
        switch (ch) {
            case 'a':     // 这里就演示了穿透
            case 'A':
                a_ct++;
                break;
            case 'e':
            case 'E':
                e_ct++;
                break;
            case 'i':
            case 'I':
                i_ct++;
                break;
            case 'o':
            case 'O':
                o_ct++;
                break;
            case 'u':
            case 'U':
                u_ct++;
                break;
            default:
                break;
        }
    }
    printf("number og vowels:    A    E    I    O    U\n");
    printf("                  %4d%4d%4d%4d%4d\n", a_ct, e_ct, i_ct, o_ct, u_ct);
    
    return 0;
}

输出

Enter some text; enter # to quit.

I see under the oberseer.#

number og vowels:    A    E    I    O    U

                     0   7   1   1   1

Program ended with exit code: 0

书中后面自己也写了,可以在前面对输入条件先进行装换,那样会更加方便

头文件假如ctype 用过toupper(ch)的方式无论大小写转换成大写再判断更加方便。

 

7.7.4书中也介绍了,switch一般用的地方比较少,只有在整数的条件下采用。范围取值条件,if更加方便。

 

7.8 goto语句

第一次接触goto语句,但书中介绍要避免使用goto语句,且写法非常有意思

goto语句有两部分组成:goto 和标签名

goto:part2

要让这条语句正常工作,函数还必须包含另一条标为part2的语句,该语句以标签名后紧跟一个冒号开始:

part2: printf("Refined analysis:\n")

 

7.8.1避免使用goto

写代码需要尽量回避goto的用法,书中也没有整串的示例代码

只要理解一点。实际上,break和continue是goto的特殊形式。使用break和continue的好处是:其名称已经表明它们的用法,而且这些语句不使用标签,所以不用担心把标签放在错误的位置导致的危险。

#include <stdio.h>
int main(void)
{
    float length, width;
    
    printf("Enter the length of the rectangle:\n");
    while (scanf("%f", &length) == 1) {
        printf("Length = %.2f:\n", length);
        printf("Enter its width:\n");
        if (scanf("%f", &width) != 1) {
            goto end;
        }
        printf("Width = %.2f:\n", width);
        printf("Area = %.2f:\n", length * width);
        printf("Enter the length of the rectangle:\n");
    }
    end: printf("Done.\n");
    
    return 0;
}

上面我自己简单写了一个goto的示例,还蛮有意思的。

 

7.11 复习题

第一题

a false b true c false

第二题

a num >= 90 && num < 100 
b ch != 'q' && ch !='k'

c num>=1 && num <= 9 && num !=5

d num < 1 || num >9

第三题

抄书代码

#include <stdio.h>
int main(void)
{
    int weight, height;
    printf("Enter you weight in pounds and ");
    printf("your height in inches.\n");
    scanf("%d %d", &weight, &height);
    if (weight < 100 && height >64) {
        if (height >= 72) {
            printf("You are very taoll for your weight.\n");
        }
        else
            printf("You are tall for your weight.\n");
    }
    else if (weight > 300 && height < 48)
        printf("You are quite short for your weight.\n");
    else
        printf("Your weight is idels.\n");
    
    return 0;
}

第四题

a true

b false

c true

d 6

e 10

f false

第五题

*#%*#%*#$*#%*#%*#$*#%*#%*#$*#%    错了

第六题

hatcatOh no!catOh no!Oh no!

订正

hatcatOh no!

catOh no!

Oh no!

第七题    

#include <stdio.h>
int main(void)
{
    char ch;
    int lc, uc, oc;
    lc = uc = oc =0;
    
    while ((ch = getchar()) != '#') {
        if ('a' <= ch && ch <= 'z') {
            lc++;
        }
        else if ('A' <= ch && ch <= 'Z')
        {
            uc++;
        }
        else
            oc++;
    }
    printf("%d lowercase, %d uppercase %d other\n", lc, uc, oc);
    
    return 0;
}

答案用了Ctype头文件的判断字母大小写的函数

第八题

Your are 40,Here is a raise.

Your are 60,Here is a raise.

Your are 65,Here is a yuor gold watch.

订正,上当了

后面的if条件是个赋值语句,返回值本身。

第九题

1 2 1 1 3 1 Done    记住 带了标签的还是一个正常的语句,该如何顺序执行还是如何执行

第十题

#include <stdio.h>
int main(void)
{
    char ch;
    
    while ((ch=getchar()) != '#') {
        if (ch != '\n') {
            printf("Step 1\n");
            if (ch == 'b') {
                break;
            }
            else if (ch == 'h') {
                printf("Step 3\n");
            }
            else if (ch != 'c')
                printf("Step 2\n");
        }
    }
    printf("Done\n");
    
    return 0;
}

输出

q

Step 1

Step 2

c

Step 1

h

Step 1

Step 3

b

Step 1

Done

订正的逻辑

#include <stdio.h>
int main(void)
{
    char ch;
    
    while ((ch=getchar()) != '#') {
        if (ch != '\n') {
            printf("Step 1\n");
            if (ch == 'b') {
                break;
            }
            else if (ch == 'h') {
                printf("Step 3\n");
            }
            else if (ch != 'c'){
                printf("Step 2\n");
                printf("Step 3\n");
            }
        }
    }
    printf("Done\n");
    
    return 0;
}

没有书中的代码逻辑好。

 

 7.12 编程练习

第一题

#include <stdio.h>

int main()
{
    char ch;
    int space_num, enter_num, other_num;
    space_num = enter_num = other_num = 0;
    
    printf("Please inpout a series string:\n");
    while ((ch = getchar()) != '#') {
        switch (ch) {
            case ' ':
                space_num++;
                break;
            case '\n':
                enter_num++;
                break;
            default:
                other_num++;
                break;
        }
    }
    printf("The series string space num is %d, enter num is %d, other num is %d.\n",
           space_num, enter_num, other_num);
    
    return 0;
}

输出

Please inpout a series string:

Hello every.

My name is sidian.

#

The series string space num is 4, enter num is 2, other num is 26.

Program ended with exit code: 0

第二题

#include <stdio.h>
#include <string.h>

int main()
{
    char ch, ch_l[100];
    int count = 0, my_index = 0;
    while ((ch = getchar()) != '#') {
        ch_l[count] = ch;
        count++;
    }
    while (my_index < strlen(ch_l)) {
        printf("\"%c\"->%3d ", ch_l[my_index], ch_l[my_index]);
        my_index++;
        if (my_index % 8 == 0) {
            printf("\n");
        }
    }
    
    return 0;
}

感觉中间输入\n有点小问题。

 

第三题

#include <stdio.h>

int main(void)
{
    char ch;
    int even_num, odd_num, even_sum, odd_sum;
    even_num = odd_num = even_sum = odd_sum = 0;
    
    while ((ch = getchar()) != '0') {
        if ((ch - '0') % 2) {
            even_num++;
            even_sum += (ch - 48);
        }
        else{
            odd_num++;
            odd_sum += (ch - 48);
        }
    }

    printf("even number is %d ,average is %.3f,\neven number is %d ,average is %.3f.\n",
           even_num, (double)even_sum / even_num, odd_num, (double)odd_sum / odd_num);
    
    return 0;
}

输出

1110

even number is 3 ,average is 1.000,

even number is 0 ,average is nan.

Program ended with exit code: 0

第四题

 

#include <stdio.h>

int main(void)
{
    char ch, ch_l[1000];
    int c_index, count,change_count;
    c_index = count = change_count = 0;
    
    while ((ch = getchar()) != '#') {
        if (ch == '.') {
            ch_l[c_index] = '!';
            change_count++;
        }
        else if (ch == '!'){
            ch_l[c_index] = ch;
            c_index++;
            ch_l[c_index] = ch;
            change_count++;
        }
        else{
            ch_l[c_index] = ch;
        }
        c_index++;
    }
    printf("Out message is: \"%s\"; change num is %d.\n", ch_l, change_count);
    
    return 0;
}

输出

I love you.

You love me!

#

Out message is: "I love you!

You love me!!

"; change num is 2.

Program ended with exit code: 0

 第五题

 

#include <stdio.h>

int main(void)
{
    char ch, ch_l[1000];
    int c_index, count,change_count;
    c_index = count = change_count = 0;
    
    while ((ch = getchar()) != '#') {
        switch (ch) {
            case '.':
                ch_l[c_index] = '!';
                change_count++;
                break;
            case '!':
                ch_l[c_index] = ch;
                c_index++;
                ch_l[c_index] = ch;
                change_count++;
                break;
            default:
                ch_l[c_index] = ch;;
        }
        c_index++;
        
    }
    printf("Out message is: \"%s\"; change num is %d.\n", ch_l, change_count);
    
    return 0;
}

 

第六题

#include <stdio.h>
#include <stdbool.h>

int main(void)
{
    char ch;
    bool is_e;
    int count = 0;
    is_e = false;
    while ((ch=getchar()) != '#') {
        switch (ch) {
            case 'e':
                is_e = true;
                break;
            case 'i':
                if (is_e)
                    count++;
                is_e = false;
            default:
                break;
        }
    }
    printf("ei count number is %d.\n", count);
    return 0;
    
}

输出

Receice your eieio award.#

ei count number is 3.

Program ended with exit code: 0

第七题

#include <stdio.h>

#define TAX300 300 * 0.15
#define TAX450 TAX300 + 150 * 0.2

int main(void)
{
    const double hour_salary = 10.0;
    double work_hour, salary, tax;
    printf("Please enter your working hours per week.\n");
    
    if (scanf("%lf", &work_hour)) {
        if (work_hour > 40.0) {
            work_hour = (work_hour - 40) * 1.5 + 40;}
        salary = work_hour * hour_salary;
        if (salary <= 300.0) {
            tax = salary * 0.15;
        }
        else if (salary <= 450.0){
            tax = TAX300 + (salary - 300) * 0.2;
        }
        else
            tax = TAX450 + (salary - 450) * 0.25;
        printf("Your all_salary is %.2f, tax is %.2f, net income is %.2f.\n",
               salary, tax, salary - tax);
        
    }
    else
        printf("You have typed in the wrong information.\n");
    
    
    return 0;
    
}

输出

Please enter your working hours per week.

60

Your all_salary is 700.00, tax is 137.50, net income is 562.50.

Program ended with exit code: 0

第八题

#include <stdio.h>
#include <ctype.h>

#define TAX300 300 * 0.15
#define TAX450 TAX300 + 150 * 0.2
#define FIRST_WAGE 8.75
#define SECOND_WAGE 9.33
#define THIRD_WAGE 10.0
#define FOURTH_WAGE 11.2


int main(void)
{
    double hour_salary = .0;
    double work_hour, salary, tax;
    char in_num;
    _Bool my_condittion = 1;
    
    while (my_condittion) {
        
        printf("*****************************************************************\n");
        printf("Enter the number corresponding to the desired pay rate of action\n");
        printf("1) $8.75/hr                            2) $9.33/hr\n");
        printf("3) $10.00/hr                           4) $11.20/hr\n");
        printf("5) quit\n");
        printf("*****************************************************************\n");
        
    thisway:if (isdigit(in_num = getchar())){
        switch (in_num) {
            case '1':
                hour_salary = FIRST_WAGE;
                break;
            case '2':
                hour_salary = SECOND_WAGE;
                break;
            case '3':
                hour_salary = THIRD_WAGE;
                break;
            case '4':
                hour_salary = FOURTH_WAGE;
                break;
            case '5':
                goto end;      // 在case条件下无法break循环,又用了goto
                break;
            default:
                printf("Please re-enter the correct option.\n");
                break;
            }
            if (hour_salary) {
                printf("Please enter your working hours per week.\n");
                if (scanf("%lf", &work_hour)) {
                    if (work_hour > 40.0) {
                        work_hour = (work_hour - 40) * 1.5 + 40;}
                    salary = work_hour * hour_salary;
                    if (salary <= 300.0) {
                        tax = salary * 0.15;
                    }
                    else if (salary <= 450.0){
                        tax = TAX300 + (salary - 300) * 0.2;
                    }
                    else
                        tax = TAX450 + (salary - 450) * 0.25;
                    printf("Your all_salary is %.2f, tax is %.2f, net income is %.2f.\n",
                           salary, tax, salary - tax);
                    
                }
                else
                    printf("You have typed in the wrong information.\n");
            }
        }
        else if(in_num == '\n')
            goto thisway;        /* 因为只能5号退出,所以没有能力有限只能用了goto */
        else{
            printf("Please re-enter the correct option.\n");
        }
    }
    
end: printf("Bye,Bye\n");
    
    return 0;
    
}

输出

*****************************************************************

Enter the number corresponding to the desired pay rate of action

1) $8.75/hr                            2) $9.33/hr

3) $10.00/hr                           4) $11.20/hr

5) quit

*****************************************************************

a

Please re-enter the correct option.

*****************************************************************

Enter the number corresponding to the desired pay rate of action

1) $8.75/hr                            2) $9.33/hr

3) $10.00/hr                           4) $11.20/hr

5) quit

*****************************************************************

6

Please re-enter the correct option.

*****************************************************************

Enter the number corresponding to the desired pay rate of action

1) $8.75/hr                            2) $9.33/hr

3) $10.00/hr                           4) $11.20/hr

5) quit

*****************************************************************

3

Please enter your working hours per week.

60

Your all_salary is 700.00, tax is 137.50, net income is 562.50.

*****************************************************************

Enter the number corresponding to the desired pay rate of action

1) $8.75/hr                            2) $9.33/hr

3) $10.00/hr                           4) $11.20/hr

5) quit

*****************************************************************

4

Please enter your working hours per week.

60

Your all_salary is 784.00, tax is 158.50, net income is 625.50.

*****************************************************************

Enter the number corresponding to the desired pay rate of action

1) $8.75/hr                            2) $9.33/hr

3) $10.00/hr                           4) $11.20/hr

5) quit

*****************************************************************

第九题

#include <stdio.h>
#include <ctype.h>
#include <math.h>

int main(void)
{
    int number, other = 2, n_index = 0, init_index;
    long true_number = 0;
    char ch[80];
    _Bool not_prime_number_signal = 0;
    printf("Please enter a number:");
    while (isdigit(number = getchar())){
        ch[n_index] = number;
        n_index++;
    }
//    printf("ch = %s\n", ch);
    for (init_index=0; init_index < n_index; init_index++) {
        true_number += (ch[init_index] - 48) * pow(10, (n_index - init_index -1));
//        printf("true_name %ld\n", true_number);
    }
    
    printf("Input number is %ld\n", true_number);
    printf("All prime numbers are: ");
    while (true_number > 2) {
        while (other * other <= true_number) {
            if (true_number % other == 0) {
                not_prime_number_signal = 1;
                break;
            }
            else
                other++;
        }
        if (!not_prime_number_signal) {
            printf("%ld, ", true_number);
        }
        not_prime_number_signal = 0;
        other = 2;
        true_number--;
    }
    if (true_number >= 3) {
        printf("3, 2 ," );
    }
    if (true_number == 2) {
        printf("2, ");
    }
        
    printf("\nDone\n");
    return 0;
}

输出

Please enter a number:987

Input number is 987

All prime numbers are: 983, 977, 971, 967, 953, 947, 941, 937, 929, 919, 911, 907, 887, 883, 881, 877, 863, 859, 857, 853, 839, 829, 827, 823, 821, 811, 809, 797, 787, 773, 769, 761, 757, 751, 743, 739, 733, 727, 719, 709, 701, 691, 683, 677, 673, 661, 659, 653, 647, 643, 641, 631, 619, 617, 613, 607, 601, 599, 593, 587, 577, 571, 569, 563, 557, 547, 541, 523, 521, 509, 503, 499, 491, 487, 479, 467, 463, 461, 457, 449, 443, 439, 433, 431, 421, 419, 409, 401, 397, 389, 383, 379, 373, 367, 359, 353, 349, 347, 337, 331, 317, 313, 311, 307, 293, 283, 281, 277, 271, 269, 263, 257, 251, 241, 239, 233, 229, 227, 223, 211, 199, 197, 193, 191, 181, 179, 173, 167, 163, 157, 151, 149, 139, 137, 131, 127, 113, 109, 107, 103, 101, 97, 89, 83, 79, 73, 71, 67, 61, 59, 53, 47, 43, 41, 37, 31, 29, 23, 19, 17, 13, 11, 7, 5, 3, 2, 

Done

Program ended with exit code: 0

上面这道题目,我真的是又点脑子不好使,学的绝对不扎实,明明可以用scanf接受参数的.

scanf前面忘的差不多,跟getchar搞混了,真的不应该,再次反省。

 

第十题 

#include <stdio.h>
#include <ctype.h>
#define SINGLE 17850
#define MASTER 23900
#define MARRIED 29750
#define DIVORCED 14875

int main(void)
{
    char ch;
    double threshold, taxes, income;
    
    printf("******************************************\n");
    printf("Please enter your personal information(Q is Quit):\n");
    printf("A: single              B: master  \n");
    printf("C: married             D: divorced  \n");
    printf("Q: quit\n");
    printf("******************************************\n");
    while ((ch = toupper(getchar())) != ('Q')) {
        switch (ch) {
            case 'A':
                threshold = SINGLE;
                break;
            case 'B':
                threshold = MASTER;
                break;
            case 'C':
                threshold = MARRIED;
                break;
            case 'D':
                threshold = DIVORCED;
                break;
            default:
                threshold = 0;
        }
        if (threshold) {
            printf("Please enter your income:");
            scanf("%lf", &income);
            if (income > threshold) {
                taxes = 0.15 * income + (income - threshold) * 0.28;
            }
            else
                taxes = 0.15 * income;
            printf("Your tax payable is %.2f.\n", taxes);
            printf("******************************************\n");
            printf("Please enter your personal information(Q is Quit):\n");
            printf("A: single              B: master  \n");
            printf("C: married             D: divorced  \n");
            printf("Q: quit\n");
            printf("******************************************\n");
        }
        else
            if (ch != '\n') {
                printf("Please input as requested:\n");
            }
    }
    printf("Bye Bye !!\n");
    
    return 0;
}

输出

******************************************

Please enter your personal information(Q is Quit):

A: single              B: master  

C: married             D: divorced  

Q: quit

******************************************

f

Please input as requested:

z

Please input as requested:

b

Please enter your income:600

Your tax payable is 90.00.

******************************************

Please enter your personal information(Q is Quit):

A: single              B: master  

C: married             D: divorced  

Q: quit

******************************************

q

Bye Bye !!

Program ended with exit code: 0

 

第十一题

#include <stdio.h>
#include <ctype.h>
#include <math.h>
#define BYE_QUESTION printf("Please enter the weight you want to buy:\n")
#define SELECT_QUESTION printf("Please enter the variety you want to select(Q is Quit):\n");

int main(void)
{
    const double artichoke = 2.05;
    const double beet = 1.15;
    const double carrot = 1.09;
    const double discount = 0.95;
    
    char ch;
    float a_weight, b_weight, c_weight, all_weight, in_weight, all_total, freight;
    a_weight = b_weight = c_weight = all_weight = .0;
    
    
    printf("******************************************\n");
    printf("Please enter the variety you want to select(Q is Quit):\n");
    printf("A: artichoke        B: beet  \n");
    printf("C: carrot           Q: quit\n");
    printf("******************************************\n");
    
    while ((ch = toupper(getchar())) != 'Q'){
        switch (ch) {
            case 'A':
                BYE_QUESTION;
                scanf("%f", &in_weight);
                a_weight += in_weight;
                all_weight += in_weight;
                printf("The artichoke weight is %.2f, All weight is %.2f\n", a_weight, all_weight);
                SELECT_QUESTION;
                break;
            case 'B':
                BYE_QUESTION;
                scanf("%f", &in_weight);
                b_weight += in_weight;
                all_weight += in_weight;
                printf("The beet weight is %.2f, All weight is %.2f\n", b_weight, all_weight);
                SELECT_QUESTION;
                break;
            case 'C':
                BYE_QUESTION;
                scanf("%f", &in_weight);
                c_weight += in_weight;
                all_weight += in_weight;
                printf("The carrot weight is %.2f, All weight is %.2f\n", c_weight, all_weight);
                SELECT_QUESTION;
                break;
            default:
                if (ch != '\n') {
                    SELECT_QUESTION;
                }
                break;
        }
    }
    if (a_weight) {
        printf("artichoke price: %4.2f, weight:  %3.2f,  total:  $%4.2f.\n",
               artichoke, a_weight, artichoke * a_weight);
    }
    if (b_weight) {
        printf("beet      price: %4.2f, weight:  %3.2f,  total:  $%4.2f.\n",
               beet, b_weight, beet * b_weight);
    }
    if (c_weight) {
        printf("carrot    price: %4.2f, weight:  %3.2f,  total:  $%4.2f.\n",
               carrot, c_weight, carrot * c_weight);
    }
    all_total = artichoke * a_weight + beet * b_weight + carrot * c_weight;
    // 总价
    if (all_total >= 100) {
        all_total *= discount;
        printf("You get a %.2f discount, all_total: $%4.2f.\n", discount, all_total);
    }
    else
        printf("all_total: $%4.2f.\n", all_total);
    if (all_weight <= 5.0) {
        freight = 6.5;
        printf("The freight of the goods is $%.2f.\n", freight);
    }
    else if (all_weight > 5 && all_weight <= 20){
        freight = 14;
        printf("The freight of the goods is $%.2f.\n", freight);
    }
    else{
        freight = 14 + ceil(all_weight - 20) * 0.5;
        printf("The freight of the goods is $%.2f.\n", freight);
    }
    // 所有的总费用
    printf("The total cost of this order is %4.2f.\n", all_total + freight);
        
    return 0;
}

输出

******************************************

Please enter the variety you want to select(Q is Quit):

A: artichoke        B: beet  

C: carrot           Q: quit

******************************************

a

Please enter the weight you want to buy:

30.3

The artichoke weight is 30.30, All weight is 30.30

Please enter the variety you want to select(Q is Quit):

b

Please enter the weight you want to buy:

40.4

The beet weight is 40.40, All weight is 70.70

Please enter the variety you want to select(Q is Quit):

c

Please enter the weight you want to buy:

50.5

The carrot weight is 50.50, All weight is 121.20

Please enter the variety you want to select(Q is Quit):

c

Please enter the weight you want to buy:

5

The carrot weight is 55.50, All weight is 126.20

Please enter the variety you want to select(Q is Quit):

q

artichoke price: 2.05, weight:  30.30,  total:  $62.11.

beet      price: 1.15, weight:  40.40,  total:  $46.46.

carrot    price: 1.09, weight:  55.50,  total:  $60.50.

You get a 0.95 discount, all_total: $160.62.

The freight of the goods is $67.50.

The total cost of this order is 228.12.

Program ended with exit code: 0

 

第八章

字符输入/输出和输入验证

书中主要介绍所有系统都通用的标准I/O函数,用这些函数编写的可移植成勋很容易从一个系统移植到另一个系统。

8.1 单字符I/O:getchar()和putchar()

getchar与putchar的方法非常适合计算机

示例代码:

#include <stdio.h>
int main(void)
{
    signed char ch;
    while ((ch = getchar()) != '#') {
        putchar(ch);
    }
    return 0;
}

输出

sd

sd

sidianhao#lala

sidianhao

 8.2缓存区

书中详细的介绍了缓存的说明,在没有缓存区的情况下,计算机读取一个信息,想上面的函数会直接输出这个信息。

有缓存区的会进行缓存,一般分为完全缓存I/O和行缓冲I/O,缓存区大小一般为512字节或者4096字节。行缓存区一般在按下Enter才刷新缓冲区。

后续章节在介绍,控制缓冲的一些方法。

8.3结束键盘输入

上面的代码用'#'当结束符不是很合适,因为你不能使用这个'#'的输出了。

8.3.1 文件、流和键盘输入

文件(file)是存储器中存储信息的区域。

C使用标准的I/O标准包,可以让用户不用考虑处理不同操作系统文件的差异。

流(stream)是一种实际输入或输出映射的理想化数据流。这意味着不同属性和不同种类的输入,由属性更同一的流来表示。于是,代开文件的过程就是把流与文件相关联,而且读写都通过流来完成。

本章着重理解C把输入和输出设备视为存储设备上的普通文件,尤其是把键盘和显式设备视为每个C程序自动打开的文件。stdin流表示键盘输入,stdout流表示屏幕输出。getchar(),putchar(),printf(),scanf()函数都是标准I/O包的成员,处理这两个流。

8.3.2 文件结尾

那既然讲到文件,既必须要学如何标记文件结尾。检查文件结尾的一种方法是,在文件末尾放一个特殊的字符标记文件结尾。

文件结束可以通过Ctrl-Z来标志文件结尾,也可以通过判断存储文件大小的信息来判断是否读到文件结尾。

无论用哪一种,在C语言中,用getcahr()读取文件检测检测到文件结尾时候将返回一个特殊的值,即EOF(end of file的缩写)。scanf()函数检测到文件结尾时也返回EOF

EOF定义为-1

#include <stdio.h>
int main(void)
{
    signed char ch;
   // int ch;也可以有,必须是一个有符号的整形,因为char默认是无符号的。
while ((ch = getchar()) != EOF) { putchar(ch); } return 0; }

所以我们可以通过读取的字符是否=EOF来定义是否读取到文件的底部。

Unix与Linux用Ctrl+D来传入文件结尾信号。许多微型计算机系统都把一行开始处的Ctrl+Z识别为文件结尾信号(mac就是),一些系统把任意位置的Ctrl+Z解释成文件结尾信号

 

8.4 重定向和文件。

> < 的重定向标识有用过,但从来不知道具体的原理,这次学习让我更好的理解了重定向的原理。

程序可以通过两种方式使用文件。第1种方法是,显式使用特定函数打开文件、关闭文件、读取文件、写入文件,诸如此类。

第二种是设计能与键盘和屏幕互动的程序,通过不同的渠道重定向输入至文件和从文件输出。

 

组合重定向

(base) shijianongdeMBP:sd shijianzhong$ ./a.out > myfile2 < mywords 
(base) shijianongdeMBP:sd shijianzhong$ cat myfile2 
nihao
wohao
tahao
you
(base) shijianongdeMBP:sd shijianzhong$ 

重定向的输入、输出谁先谁后没有关系,输入文件名和输出文件名不能重名,这将导致输入文件在输入之前长度已被截断为0。

 

如果用不了重定向,可以用程序直接打开文件。示例代码。

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    int ch;
    FILE * fp;
    char fname[50];
    
    printf("Enter the name of the file: ");
    scanf("%s", fname);
    fp = fopen(fname, "r");
    if (fp == NULL) {
        printf("Failed to open file. Bye\n");
        exit(1);
    }
    
    while ((ch=getc(fp)) != EOF) {
        putchar(ch);
    }
    fclose(fp);
    
    return 0;
}

代码用了一些我没学过的类似指针的。

 

8.5创建更友好的用户界面

8.5.1 使用缓存输入

使用缓存输入的弊端是在输入的时候会把\n带进去,前面我写代码的时候需要进行判断,书中用了更好的while循环。

示例代码:

#include <stdio.h>

int main(void)
{
    int guess = 1;
    
    printf("Pick an integer from 1 to 100. I will try to guess");
    printf("it.\nRespond with a y if my guess is right and with");
    printf("\nan n if it is wrong.\n");
    printf("Uh...is your number %d?\n", guess);
    while (getchar() != 'y') {
        printf("Well, then, is it %d?\n", ++guess);
    }
    printf("I knew I cound do it!\n");
    
    return 0;
}

输出

Pick an integer from 1 to 100. I will try to guessit.

Respond with a y if my guess is right and with

an n if it is wrong.

Uh...is your number 1?

n

Well, then, is it 2?

Well, then, is it 3?

n

Well, then, is it 4?

Well, then, is it 5?

y

I knew I cound do it!

Program ended with exit code: 0

 很明显看到了,\n的输入干扰。书中很聪明,再次用了getchar外加while循环,处理数据

#include <stdio.h>

int main(void)
{
    int guess = 1;
    
    printf("Pick an integer from 1 to 100. I will try to guess");
    printf("it.\nRespond with a y if my guess is right and with");
    printf("\nan n if it is wrong.\n");
    printf("Uh...is your number %d?\n", guess);
    while (getchar() != 'y') {
        printf("Well, then, is it %d?\n", ++guess);
        // 输入的一行就处理首字符,后续的全部掉过,知道读取到\n才到外围的while循环重新读取。
        while (getchar() !='\n') {
            continue;
        }
    }
    printf("I knew I cound do it!\n");
    
    return 0;
}

输出

Pick an integer from 1 to 100. I will try to guessit.

Respond with a y if my guess is right and with

an n if it is wrong.

Uh...is your number 1?

n

Well, then, is it 2?

n

Well, then, is it 3?

y

I knew I cound do it!

Program ended with exit code: 0

 这个脚本还有一个小瑕疵,就是除了y和以外的首字符输入都当成了n的意思,处理一下

#include <stdio.h>

int main(void)
{
    int guess = 1;
    char response;
    
    printf("Pick an integer from 1 to 100. I will try to guess");
    printf("it.\nRespond with a y if my guess is right and with");
    printf("\nan n if it is wrong.\n");
    printf("Uh...is your number %d?\n", guess);
    while ((response = getchar()) != 'y') {
        if (response == 'n')
            printf("Well, then, is it %d?\n", ++guess);
        else
            printf("Sorry I understand only y or n.\n");
        // 输入的一行就处理首字符,后续的全部掉过,知道读取到\n才到外围的while循环重新读取。
        while (getchar() !='\n') {
            continue;
        }
    }
    printf("I knew I cound do it!\n");
    
    return 0;
}

输出

Pick an integer from 1 to 100. I will try to guessit.

Respond with a y if my guess is right and with

an n if it is wrong.

Uh...is your number 1?

x

Sorry I understand only y or n.

n

Well, then, is it 2?

y

I knew I cound do it!

Program ended with exit code: 0

书中的代码还是有瑕疵的,就是第一次输入直接是enter的时候,内部的循环getchar直接没有数据可以读取了。改进代码

#include <stdio.h>

int main(void)
{
    int guess = 1;
    char response;
    
    printf("Pick an integer from 1 to 100. I will try to guess");
    printf("it.\nRespond with a y if my guess is right and with");
    printf("\nan n if it is wrong.\n");
    printf("Uh...is your number %d?\n", guess);
    while ((response = getchar()) != 'y') {
        if (response == 'n')
            printf("Well, then, is it %d?\n", ++guess);
        else
            printf("Sorry I understand only y or n.\n");
        // 输入的一行就处理首字符,后续的全部掉过,知道读取到\n才到外围的while循环重新读取。
        if (response != '\n') {
            while (getchar() !='\n') {
                continue;
            }
        }
    }
    printf("I knew I cound do it!\n");
    
    return 0;
}

 

 

8.5.2 混合数值和字符输入

示例代码

#include <stdio.h>

void display(char cr, int lines, int width);

int main(void)
{
    int ch;
    int rows, cols;
    printf("Enter a character and two integers:\n");
    while ((ch = getchar()) != '\n') {
        scanf("%d %d", &rows, &cols);
        display(ch, rows, cols);
        printf("Enter another character and two integers;\n");
        printf("Enter a newline to quit.\n");
    }
    
    printf("Bye.\n");
    
    return 0;
}

void display(char cr, int lines, int width)
{
    int row, col;
    for (row = 1; row <= lines; row++) {
        for (col = 1; col <= width; col++) {
            putchar(cr);
        }
        putchar('\n');
    }
}

输出

Enter a character and two integers:

c 2 3

ccc

ccc

Enter another character and two integers;

Enter a newline to quit.

Bye.

由于enter按下\n的影响,一下子就输出了。同前面一样,改进这个代码,通过while 循环与getchar的配合

#include <stdio.h>

void display(char cr, int lines, int width);

int main(void)
{
    int ch;
    int rows, cols;
    printf("Enter a character and two integers:\n");
    while ((ch = getchar()) != '\n') {
        // 当无法读取到两个数字直接跳出循环
        if (scanf("%d %d", &rows, &cols) != 2)
            break;
        display(ch, rows, cols);
        // 忽略读取到两个数字后面的输入
        while (getchar() != '\n') {
            continue;
        }
        printf("Enter another character and two integers;\n");
        printf("Enter a newline to quit.\n");
    }
    
    printf("Bye.\n");
    
    return 0;
}

void display(char cr, int lines, int width)
{
    int row, col;
    for (row = 1; row <= lines; row++) {
        for (col = 1; col <= width; col++) {
            putchar(cr);
        }
        putchar('\n');
    }
}

输出

Enter a character and two integers:

c 2 3 4 

ccc

ccc

Enter another character and two integers;

Enter a newline to quit.

c a 2 3 4

Bye.

Program ended with exit code: 0

 

8.6输入验证

 主要介绍了,scanf可以获取数据,但如果获取的数据形式不对,输入的字符流内容并不会少,他只有在读取到了自己想到的数据,才会减少字符流的数据。但getchar不一样,他会一个一个处理字符,直到没有字符流,阻塞等待用户输入。

示例代码:

 

#include <stdio.h>
#include <stdbool.h>

// 验证输入是否是一个整数
long get_long(void);

// 验证上面范围是否有效
bool bad_limits(long begin, long end,
                long low, long high);

// 计算两数之间的平方和
double sum_squares(long a, long b);

int main(void)
{
    const long MIN = -10000000;
    const long MAX = +10000000;
    
    long start, stop;
    double answer;
    
    printf("This program computes the sum of the squares of "
           "integers in a range.\nThe lower bound should not "
           "be less than -10000000 and\nthe upper bound "
           "should not be more than +10000000.\nEnter the "
           "limits (enter 0 for both limits to quit):\n"
           "lower limit: ");
    start = get_long();
    printf("upper limit: ");
    stop = get_long();
    while (start != 0 || stop != 0) {
        if (bad_limits(start, stop, MIN, MAX)) {
            printf("Please try again.\n");
        }
        else
        {
            answer = sum_squares(start, stop);
            printf("The sum of the squares of the integers");
            printf("from %ld to %ld is %g\n",
                   start, stop, answer);
        }
        printf("Enter the limits (enter 0 for both limits to quit):\n"
               "lower limit: ");
        start = get_long();
        printf("upper limit: ");
        stop = get_long();
    }
    printf("Done.\n");
    
    return 0;
}

// 处理输入的字符
long get_long(void)
{
    long input;
    char ch;
    
    while (scanf("%ld", &input) != 1) {
        while ((ch = getchar()) != '\n') {
            putchar(ch);
        }
        printf(" is not an integer.\nPlease enter an ");
        printf("integer value, such as  25, 178, or 3: ");
    }
    
    return input;
}

double sum_squares(long a, long b){
    double total = 0;
    long i;
    
    // 类型强制装换
    for (i = a; i <= b; i++) {
        total += (double) i * (double) i;
    }
    return total;
}

bool bad_limits(long begin, long end, long low, long high){
    // 默认是通过指标的
    bool not_good = false;
    
    if (begin > end) {
        printf("%ld isn't smaller than %ld.\n", begin, end);
        not_good = true;
    }
    if (begin < low || end < low ) {
        printf("Values must be %ld or greater.\n", low);
        not_good = true;
    }
    if (begin > high || end > high) {
        printf("Values must be %ld or less.\n", high);
        not_good = true;
    }
    
    return not_good;
}

输出

This program computes the sum of the squares of integers in a range.

The lower bound should not be less than -10000000 and

the upper bound should not be more than +10000000.

Enter the limits (enter 0 for both limits to quit):

lower limit: low

low is not an integer.

Please enter an integer value, such as  25, 178, or 3: 3

upper limit: a bing number

a bing number is not an integer.

Please enter an integer value, such as  25, 178, or 3: 12

The sum of the squares of the integersfrom 3 to 12 is 645

Enter the limits (enter 0 for both limits to quit):

lower limit: 80

upper limit: 10

80 isn't smaller than 10.

Please try again.

Enter the limits (enter 0 for both limits to quit):

lower limit: 0

upper limit: 0

Done.

Program ended with exit code: 0

抄写的时候感觉不够用心,其实这真的是比较好的,模块拆分思路。

 

8.6.1分析程序

 

8.6.2 输入流和数字

书中介绍了scanf()通过%d,%f可以将传入的字符转换成整数或者浮点数,而getchar与%c则接收所有字符。

话说C语言对处理输入字符确实让我学到很多。

 

8.7 菜单浏览

就是设计一份菜单让用户使用,书中介绍了具体操作思路。

 

8.7.1

准备用while 外加 switch

8.7.2 使执行更顺利

8.7.3 混合字符和数值输入

示例代码

#include <stdio.h>
char get_choice(void);
char get_first(void);
int get_int(void);
void count(void);

int main(void){
    int choice;
    // 书中这里又申明了一次函数,不知道为什么还要声明一次?
//    void count(void);
    
    while ((choice = get_choice()) != 'q') {
        switch (choice) {
            case 'a':
                printf("Buy low, sell high.\n");
                break;
            case 'b':
                putchar('\a');
                break;
            case 'c':
                count();
                break;
            default:
                printf("Program error!\n");
                break;
        }
    }
    printf("Bye.\n");
    
    return 0;
}

void count(void)
{
    int n, i;
    
    printf("Count how far ? Enter am integer:\n");
    // 再次调用函数
    n = get_int();
    for (i = 1; i <= n; i++) {
        printf("%d\n", i);
    }
    while (getchar() != '\n') {
        continue;
    }
}

char get_choice(void)
{
    int ch;
    
    printf("Enter the letter og your choice:\n");
    printf("a. advice        b. bell\n");
    printf("c. count         q. quit\n");
    // 再次调用函数
    ch = get_first();
    while ((ch < 'a' || ch > 'c') && ch != 'q') {
        printf("Please respond with a, b, c, or q.\n");
        ch = get_first();
    }
    return ch;
}

char get_first(void)
{
    int ch;
    
    ch = getchar();
    while (getchar() != '\n') {
        continue;
    }
    
    return ch;
}

int get_int(void){
    int input;
    char ch;
    
    while (scanf("%d", &input) != 1) {
        while ((ch = getchar() != '\n')) {
            putchar(ch);
        }
        printf(" is not an integer.\nPlwase enter an ");
        printf("integer value, such as 25, -178, or 3");
    }
    
    return input;
}

输出

Enter the letter og your choice:

a. advice        b. bell

c. count         q. quit

a

Buy low, sell high.

Enter the letter og your choice:

a. advice        b. bell

c. count         q. quit

count

Count how far ? Enter am integer:

two

 is not an integer.

Plwase enter an integer value, such as 25, -178, or 33

1

2

3

Enter the letter og your choice:

a. advice        b. bell

c. count         q. quit

d

Please respond with a, b, c, or q.

q

Bye.

主要的疑问使主函数内部为什么还要申明一次函数。等后面学习到函数的时候再看了。

 

8.8 关键概念

C程序把输入作为传入的字节流。getchar()函数把每个字符解释成一个字符编码。scanf()函数以同样的方式看待输入,但是根据装换说明,它可以把字符输入转换成数值。许多操作系统都提供重定向,允许用文件代替简单输入,用文件代替显示器输出。

程序通常接受特殊形式的输入。可以在设计程序时考虑用户在输入时肯能犯的错误,在输入验证部分处理这些错误情况,让程序更强健更友好。

对于一个小型程序,输入验证可能时代码中最复杂的部分。处理这种问题有多种方案。列如,如果用户输入错误类型的信息,可以终止程序,也可以给用户提供有限次或无限次机会重新输入。

 

8.9 本章小结

略。

 

8.10 复习题

 第一题

抄答案:表达式putchar(getchar())使程序读取下一个输入字符并打印出来。getchar()的返回值时putchar()的参数。但getchar(putchar())是无效的表达式,因为getchar()不需要参数,而putchar()需要一个参数。

第二题

输出H,输出逼一声,输出换行,输出退格

第三题

count < essay > saaayct

第四题

都不是

第五题

EOF是End Of File的简称,意思为读取到文件的结尾,赋值为-1

标准答案:EOF是由getchar()scanf()返回的信号(一个特殊值),表明函数检测到文件结尾。

第六题

a:

If you qu

b:

HJac

第七题

约定为\n

书中描述:C程序处理的是流而不是直接处理文件。流(stream)是一个实际输入或输出映射的理想化数据流。这意味这不同属性和不同种类的输入,由属性更统一的流来辩识。于是,打开文件的过程就是把流与文件相关联,而且读写都通过流来完成。

标准答案: C的标准I/O库把不同的文件映射为统一的流来统一处理。

第八题

答案主要介绍了处理输入的enter符号信号,还有书中的答案示例代码由一点bug%s应该为%d

 

8.11 编程练习

第一题

(base) shijianongdeMBP:sd shijianzhong$ cat t

(base) shijianongdeMBP:sd shijianzhong$ cat main.c 
#include <stdio.h>

int main(void)
{
    unsigned count=0;
    while (getchar() != EOF) {
        count++;
    }
    printf("%u\n", count-1);
return 0; } (
base) shijianongdeMBP:sd shijianzhong$ ./a.out < t 0 (base) shijianongdeMBP:sd shijianzhong$ ./a.out < main.c 149 (base) shijianongdeMBP:sd shijianzhong$

第二题

#include <stdio.h>
#include <iso646.h>

int main(void)
{
    int i_ch, index=0;
    while ((i_ch = getchar()) != EOF) {
        if (i_ch < ' ' and i_ch != 10 and i_ch != 9) {
            printf("^%c->%d ",i_ch + 64, i_ch);
        }
        else if (i_ch >= ' '){
            printf("%c->%d ",i_ch, i_ch);
        }
        else if (i_ch == 10)
            printf("\\n->10 ");
        else if (i_ch == 9)
            printf("\\t->9 ");
        index++;
        while (index % 10 == 0) {
            printf("\n");
            break;
        }
    }
    
    return 0;
}

输出

1234567890 qwertyuiasdfghj zxcvbnm

1->49 2->50 3->51 4->52 5->53 6->54 7->55 8->56 9->57 0->48 

\t->9 q->113 w->119 e->101 r->114 t->116 y->121 u->117 i->105 a->97 

s->115 d->100 f->102 g->103 h->104 j->106 \t->9 z->122 x->120 c->99 

v->118 b->98 n->110 m->109 \n->10 Program ended with exit code: 0

第三题

#include <stdio.h>
#include <ctype.h>

int main(void)
{
    int ch;
    int upper, lower;
    upper = lower = 0;
    while ((ch = getchar()) != EOF) {
        if (isupper(ch)) {
            upper++;
        }
        else
            lower++;
    }
    printf("uppers: %d, lowers: %d\n", upper, lower);
    
    return 0;
}

输出

(base) shijianongdeMBP:sd shijianzhong$ ./a.out < t.txt 

uppers: 7, lowers: 8

 第四题

  

#include <stdio.h>
#include <ctype.h>
#include <iso646.h>

int main(void)
{
    
    int ch;
    double char_num, word_num;
    _Bool start = 1;
    
    char_num = word_num = .0;
    while ((ch = getchar()) != EOF) {
        if (isalpha(ch)) {
            char_num++;
            start = 1;
        }
        else
            if (start) {
                word_num++;
                start = 0;
            }
            
    }
    
    printf("The average word has %.2f character.\n", (char_num / word_num));
    
    return 0;
}

(base) shijianongdeMBP:sd shijianzhong$ ./a.out < main.c 

The average word has 3.87 character.

第五题

 

#include <stdio.h>

int main(void)
{
    int max = 100;
    int min = 1;
    int guess = 50;
    char answer;
    
    printf("Pick an integer from 1 to 100.I will try to guess");
    printf("it.\nResponse with a y if my guess is right and with");
    printf("\nan n if it is wrong.\n");
    printf("Un... is you number %d?\n", guess);
    while ((answer = getchar()) != 'y') {
        switch (answer) {
            case 'u':
                max = guess;
                guess = (min + max) / 2;
                printf("Un... is you number %d?\n", guess);
                break;
            case 'l':
                min = guess;
                guess = (min + max) / 2;
                printf("Un... is you number %d?\n", guess);
            default:
                break;
        }
        
    }
    
    printf("I knew I could do it!\n");
    
    return 0;
}

输出

Pick an integer from 1 to 100.I will try to guessit.

Response with a y if my guess is right and with

an n if it is wrong.

Un... is you number 50?

l

Un... is you number 75?

u

Un... is you number 62?

l

Un... is you number 68?

l

Un... is you number 71?

u

Un... is you number 69?

l

Un... is you number 70?

y

I knew I could do it!

Program ended with exit code: 0

 第六题

 

#include <stdio.h>
#include <ctype.h>

char get_first(void);


int main(void)
{
    char ch = get_first();
    printf("The resule char is \"%c\"\n", ch);
    
    return 0;
}


char get_first(void)
{
    int ch;
    
    while (1) {
        ch = getchar();
        if (! isblank(ch)){
            break;
        }
    }
    while (getchar() != '\n') {
        continue;
    }
    
    return ch;
}

输出

bc 12 d

The resule char is "b"

 第七题

#include <stdio.h>
#include <ctype.h>
#include <string.h>

#define TAX300 300 * 0.15
#define TAX450 TAX300 + 150 * 0.2
#define FIRST_WAGE 8.75
#define SECOND_WAGE 9.33
#define THIRD_WAGE 10.0
#define FOURTH_WAGE 11.2


int main(void)
{
    double hour_salary = .0;
    double work_hour, salary, tax;
    char in_char;
    _Bool my_condittion = 1;
    
    while (my_condittion) {
        
        printf("*****************************************************************\n");
        printf("Enter the number corresponding to the desired pay rate of action\n");
        printf("a) $8.75/hr                            b) $9.33/hr\n");
        printf("c) $10.00/hr                           d) $11.20/hr\n");
        printf("q) quit\n");
        printf("*****************************************************************\n");
        
    thisway:if (isalpha(in_char = getchar())){
        switch (tolower(in_char)) {
            case 'a':
                hour_salary = FIRST_WAGE;
                break;
            case 'b':
                hour_salary = SECOND_WAGE;
                break;
            case 'c':
                hour_salary = THIRD_WAGE;
                break;
            case 'd':
                hour_salary = FOURTH_WAGE;
                break;
            case 'q':
                goto end;      // 在case条件下无法break循环,又用了goto
                break;
            default:
                printf("Please re-enter the correct option.\n");
                break;
            }
            while (getchar() != '\n') {
                ;
            }
            if (hour_salary) {
                printf("Please enter your working hours per week.\n");
                if (scanf("%lf", &work_hour)) {
                    if (work_hour > 40.0) {
                        work_hour = (work_hour - 40) * 1.5 + 40;}
                    salary = work_hour * hour_salary;
                    if (salary <= 300.0) {
                        tax = salary * 0.15;
                    }
                    else if (salary <= 450.0){
                        tax = TAX300 + (salary - 300) * 0.2;
                    }
                    else
                        tax = TAX450 + (salary - 450) * 0.25;
                    printf("Your all_salary is %.2f, tax is %.2f, net income is %.2f.\n",
                           salary, tax, salary - tax);
                    while (getchar() != '\n') {
                        continue;;
                    }
                    
                }
                else
                    printf("You have typed in the wrong information.\n");
            }
       
        }

        else{
            printf("Please re-enter the correct option.\n");
        }
    }
    
end: printf("Bye,Bye\n");
    
    return 0;
    
}

输出

*****************************************************************

Enter the number corresponding to the desired pay rate of action

a) $8.75/hr                            b) $9.33/hr

c) $10.00/hr                           d) $11.20/hr

q) quit

*****************************************************************

abc

Please enter your working hours per week.

40

Your all_salary is 350.00, tax is 55.00, net income is 295.00.

*****************************************************************

Enter the number corresponding to the desired pay rate of action

a) $8.75/hr                            b) $9.33/hr

c) $10.00/hr                           d) $11.20/hr

q) quit

*****************************************************************

bcd

Please enter your working hours per week.

40

Your all_salary is 373.20, tax is 59.64, net income is 313.56.

*****************************************************************

Enter the number corresponding to the desired pay rate of action

a) $8.75/hr                            b) $9.33/hr

c) $10.00/hr                           d) $11.20/hr

q) quit

*****************************************************************

q

Bye,Bye

Program ended with exit code: 0

第八题

 

#include <stdio.h>
#include <ctype.h>

float re_float(void);

int main(void)
{
    float num1, num2;
    char select_ch;
    
    while (1) {
        printf("Enter the operation of your choise:\n");
        printf("a.add            s.subtract\n");
        printf("m.multiply       d.divide\n");
        printf("q.quit\n");
        select_ch = getchar();
        if (select_ch == 'q') {
            printf("Bye.\n");
            break;
        }
        switch (select_ch) {
            case 'a':
                printf("Enter first number: ");
                num1 = re_float();
                printf("Enter second number: ");
                num2 = re_float();
                printf("%g + %g = %g\n", num1, num2, num1 + num2);
                break;
            case 's':
                printf("Enter first number: ");
                num1 = re_float();
                printf("Enter second number: ");
                num2 = re_float();
                printf("%g - %g = %g\n", num1, num2, num1 - num2);
                break;
            case 'm':
                printf("Enter first number: ");
                num1 = re_float();
                printf("Enter second number: ");
                num2 = re_float();
                printf("%g X %g = %g\n", num1, num2, num1 * num2);
                break;
            case 'd':
                printf("Enter first number: ");
                num1 = re_float();
                printf("Enter second number: ");
                while ((num2 = re_float()) == 0) {
                    printf("Enter a number other than 0: ");
                }
                printf("%g / %g = %g\n", num1, num2, num1 / num2);
                break;
            default:
                break;
        }
    }
    
    
    
    return 0;

}


// 必须要返回一个正确的浮点数
float re_float(void){
    float num;
    char ch;
    
    // 处理输入不正确的时候
    while (scanf("%f", &num) != 1) {
        while ((ch = getchar()) != '\n') {
            putchar(ch);
        }
        printf(" is not an number.");
        printf("Please enter a number, such as 2.5, -1.78E8, or 3: ");
    }
    while (getchar() != '\n') {
        continue;;
    }
    
    return num;
}

输出

Enter the operation of your choise:

a.add            s.subtract

m.multiply       d.divide

q.quit

a

Enter first number: 22.4

Enter second number: one

one is not an number.Please enter a number, such as 2.5, -1.78E8, or 3: 1

22.4 + 1 = 23.4

Enter the operation of your choise:

a.add            s.subtract

m.multiply       d.divide

q.quit

d

Enter first number: 18.4

Enter second number: 0

Enter a number other than 0: 0.2

18.4 / 0.2 = 92

Enter the operation of your choise:

a.add            s.subtract

m.multiply       d.divide

q.quit

q

Bye.

Program ended with exit code: 0

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

posted @ 2020-12-07 00:28  就是想学习  阅读(192)  评论(0)    收藏  举报