7.1if语句

if语句称为分支语句,相当于一个分叉点;

if语句只能执行或测试一次;

C缩进有助于识别语句的所属和结构;

if和else之前只能有一个语句,多一个语句则要加钱(使用花括号构成代码块);

  1. /*colddays.c -- 找出0摄氏度以下天数占总天数的百分比*/
  2. #include <stdio.h>
  3. int main(void)
  4. {
  5. const int FREEZING = 0;
  6. float temperature;
  7. int cold_days = 0;
  8. int all_days = 0;
  9. // 提示输入
  10. printf("Enter the list of daily low termperature.\n");
  11. printf("Use Celsius, and enter q to interrupt input.\n");
  12. // 循环获取输入
  13. while (scanf_s("%f", &temperature) == 1)
  14. {
  15. all_days++;
  16. if (temperature < FREEZING)
  17. cold_days++;
  18. }
  19. // 计算输出结果
  20. if (all_days != 0)
  21. printf("%d days total: %.lf%% were below freezing.\n",
  22. all_days, 100.0 * (float) cold_days / all_days);
  23. // 判断是否为空
  24. if (all_days == 0)
  25. printf("No data entered!\n");
  26. return 0;
  27. }

image.png

7.21 putchar() & getchar()

注意循环语句中,处理数据分类之后,还需要获取下一次的输入,while循环是入口条件语句

通常使用getchar()语句会比scanf_s(“%c”, &object)更加高效

  1. #include <stdio.h>
  2. #define SPACE ' ' // SPACE 表示单引号 - 空格 - 单引号
  3. int main(void)
  4. {
  5. char ch;
  6. ch = getchar();// 读取字符
  7. while (ch != '\n') // 进行判断, 当一行未结束的时候
  8. {
  9. if (ch == SPACE) // 留下空格
  10. putchar(ch); // 该字符不变,直接输出
  11. else
  12. putchar(ch + 1); // 不是空格就加1再输出,查询ASCⅡ
  13. ch = getchar(); // 获取下一个字符
  14. }
  15. putchar(ch); // 打印换行符
  16. return 0;
  17. }

image.png

圆括号修改优先级—-两份代码的比较

运算顺序是:先获取输入字符,然后赋值给变量ch,最后判断输入符号时候为换行符

造成的问题是:输出的结果失去了空格。
比较括号修改优先级之后输出的不同png.png

7.2.2 ctype.h系列的字符函数

引入新的函数用于做字符判断。

输入和输出中,除了空格和标点之外,大小写字母都被替换了

ctype.h头文件解析

image.png

  1. #include <stdio.h>
  2. #include <ctype.h>
  3. int main(void)
  4. {
  5. char ch;
  6. while ((ch = getchar()) != '\n')
  7. {
  8. if (isalpha(ch))
  9. putchar(ch + 1);
  10. else
  11. putchar(ch);
  12. }
  13. return 0;
  14. }

image.png

image.png

7.2.4else与if配对(20210312)

语法

如果没有花括号,if与最近的else匹配,除非最近的if被花括号包含在内;
原理:编译器忽略缩进(这是C语言和Python不同的一点)

技巧

if else是单独的语句,无需使用花括号,但语句太长可以使用,提高代码的可读性,同时避免漏掉花括号;

代码

注意循环语句之外再次获取输入,这也是构成循环的一个条件;

通过乘方而不是开方减少重复计算(一次运算就可以得出的两个乘数);

什么是素数(质数)?标识位用来判断是否未素数,进入即改变标识位;

  1. //质数是指在大于1的自然数中,除了1和它本身以外不再有其他因数的自然数
  2. #include <stdio.h>
  3. #include <stdbool.h>
  4. int main(void)
  5. {
  6. unsigned long num;
  7. unsigned long div;
  8. bool isPrime;
  9. printf("Please enter an integer to analysis:");
  10. printf("Enter q to quit.\n");
  11. while (scanf_s("%lu", &num) == 1) // 循环获取输入
  12. {
  13. for (div = 2, isPrime = true; (div * div) <= num; div++) // isPrime是一个标识位,验证平方,不再重复计算已经在一次乘法运算中得出的两个乘数,
  14. {
  15. if (num % div == 0) //只获取能够被2整除的数字
  16. {
  17. if ((div * div) != num) //
  18. printf("%lu is divisible by %lu and %lu.\n", num, div, num / div);
  19. else
  20. printf("%lu is divisible by %lu.\n", num, div);
  21. isPrime = false; // 进入if语句才修改标识位,if语句判断素数,如果不是素数则进入循环
  22. }
  23. }
  24. if (isPrime)
  25. printf("%lu is prime.\n", num);
  26. printf("Please enter another integer for analysis:");
  27. printf("Enter q to quit.\n");
  28. }
  29. printf("Bye.\n");
  30. return 0;
  31. }

image.png

7.3逻辑运算符

语法

逻辑运算符比关系运算符的优先级低,所以无需再之表达式两侧加圆括号;

iso646.h头文件可以替换这些逻辑运算符为and or not

image.png

  1. #include <stdio.h>
  2. #define PERIOD '.'
  3. int main(void)
  4. {
  5. char ch;
  6. int charcount = 0;
  7. while ((ch = getchar() != PERIOD))
  8. {
  9. if (ch != '"' && ch != '\'') // 一假为假,全真为真
  10. charcount++;
  11. }
  12. printf("There are %d non-quote characters.\n", charcount);
  13. return 0;
  14. }

image.png

7.4一个统计单词的程序

程序设计

如何标记输出的结束?

|

如何定义一个单词?

不包含空白字符,回车符,换行符,制表符

如何判断空白字符?

ctype.h中的isspace()函数

语句转换
!=inword // inword == false

  1. #include <stdio.h>
  2. #include <stdbool.h> // 为bool, true, flase提供定义
  3. #include <ctype.h> // 为isspace()函数提供原型
  4. #define STOP '|'
  5. int main(void)
  6. {
  7. char c; // 读入字符
  8. char prev; // 读入前一个字符
  9. long n_chars = 0L; // 字符数统计
  10. int n_lines = 0; // 行数
  11. int n_words = 0; // 单词数
  12. int p_lines = 0; // 不完整的行数
  13. bool inword = false; // 如果c在单词中,inword等于true
  14. printf("Enter text to be analyzed (| to terminate) : \n");
  15. prev = '\n'; // 用于识别完整的行
  16. while ((c = getchar()) != STOP)
  17. {
  18. n_chars++; // 统计字符
  19. if (c == '\n')
  20. n_lines++; //统计行
  21. if (!isspace(c) && !inword)
  22. {
  23. inword = true; //开始一个新单词
  24. n_words++; // 统计单词数
  25. }
  26. if (isspace(c) && inword)
  27. inword = false; // 打到单词的末尾
  28. prev = c; //保存字符的值
  29. }
  30. if (prev != '\n')
  31. p_lines = 1;
  32. printf("characters = %ld, words = %d, lines = %d\n", n_chars, n_words, n_lines);
  33. printf("partial lines = %d\n", p_lines);
  34. return 0;
  35. }

image.png

7.5条件运算符

程序如何实现向上取整?

首先整除得到一个值,然后求模运算,求模成功说明完全整除不必加一。求模失败说明又余数,自动加一

  1. #include <stdio.h>
  2. #define COVERAGE 350
  3. int main(void)
  4. {
  5. int sq_feet;
  6. int cans;
  7. printf("Enter number pf square feet to be painted:\n");
  8. printf("整除的结果是%d\n", 370 / 250);
  9. while (scanf_s("%d", &sq_feet) == 1)
  10. {
  11. cans = sq_feet / COVERAGE;
  12. cans += ((sq_feet % COVERAGE == 0)) ? 0 : 1; // 实现向上取整,在整除的结果上,取模也成功则不叠加数字,取模不成功就再加一
  13. printf("You need %d %s of paint.\n", cans, cans == 1 ? "can" : "cans"); // 赋值语句,如果cans的值是1,那么%s对应can,否则对应cans(因为对输入的数字以350取模,只会存在整除和有余数的情况,只要有余数就向上取整)
  14. printf("Enter next value (q to quit):\n");
  15. }
  16. return 0;
  17. }

image.png
7.6辅助循环:continue 和 break

continue和break语句都只对当前语句有效(也就是内循环)

continue等于你想要的条件取相反的时候,用于继续执行程序

使用continue语句可以减少主语句中的一级缩进,但语句很长或者嵌套多的时候,使得语句更加紧凑,提高了代码

  1. #include <stdio.h>
  2. // 20210315
  3. int main(void)
  4. {
  5. const float MIN = 0.0f;
  6. const float MAX = 100.0f;
  7. float score;
  8. float total = 0.0f; //前一个零指的是最小宽度,第二个零指的是精度
  9. int n = 0;
  10. float min = MAX;
  11. float max = MIN;
  12. printf("Enter the first score(q to quit):");
  13. while (scanf_s("%f", &score) == 1) // 输入的内容必须是数字
  14. {
  15. if (score < MIN || score > MAX)
  16. {
  17. printf("%0.1f is an invalid value.Try again: ", score);
  18. continue;
  19. }
  20. // MIN<=socre <= MAX
  21. printf("Accepting %0.1f:\n", score);
  22. min = (score < min) ? score : min; // 如果在输入的数字小于最小值,则将值传递给便俩个:最小值
  23. max = (score > max) ? score : max; // 如果在输入的数字中出现大于最小值,则将值传递给变量:最大值
  24. total += score;
  25. n++;
  26. printf("Enter next score (q to quit) : ");
  27. }
  28. if (n > 0)
  29. {
  30. printf("Average of %d score is %0.1f.\n", n, total / n);
  31. printf("Low = %0.1f, high = %0.1f\n", min, max);
  32. }
  33. else
  34. printf("No valid scores were entered.\n");
  35. return 0;
  36. }

image.png

image.png

7.6.2break语句

  1. #include <stdio.h>
  2. int main(void)
  3. {
  4. float length, width;
  5. printf("Enter the length of rectangle:\n");
  6. while (scanf_s("%f", &length) == 1)
  7. {
  8. printf("Length = %0.2f:\n", length);
  9. printf("Enter its width:\n");
  10. if (scanf_s("%f", &width) != 1)
  11. break;
  12. printf("Width = %0.2f:\n", width);
  13. printf("Area = %0.2f:\n", length * width);
  14. printf("Enter the length of rectangle:\n");
  15. }
  16. printf("All is done!");
  17. return 0;
  18. }

image.png

7.7 多重选择: switch 和break

  1. #include <stdio.h>
  2. #include <ctype.h>
  3. int main(void)
  4. {
  5. char ch;
  6. printf("Give me a letter of the alphabet, and I will give ");
  7. printf("an animal name\nbeginning with that letter.\n");
  8. printf("Please type in a letter; type # to end my act.\n");
  9. while ((ch = getchar()) != '#') // 仅仅读取首字母
  10. {
  11. if ('\n' == ch) // 如果输入为回车符,那么循环获取输入
  12. continue;
  13. if (islower(ch)) // 只接受小写字母
  14. switch (ch)
  15. {
  16. case 'a':
  17. printf("argali, a wild sheep of Asia\n");
  18. break;
  19. case 'b':
  20. printf("babirusa, a wild pig of Malay\n");
  21. break;
  22. case 'c':
  23. printf("coati, recoonlike mammal\n");
  24. break;
  25. case 'd':
  26. printf("desman, aquatic, molelike critter\n");
  27. break;
  28. case 'e':
  29. printf("echidna, the spiny anteater\n");
  30. break;
  31. case 'f':
  32. printf("fisher, brownish marten\n");
  33. break;
  34. default:
  35. printf("That's a stumper!\n"); // switch结束
  36. }
  37. else
  38. printf("I recognize only lowcase letters.\n");
  39. while (getchar() != '\n')
  40. continue;
  41. printf("Please type another letter or a #.\n"); // while循环结束
  42. }
  43. printf("Bye!\n");
  44. return 0;
  45. }

image.png
image.png

7.7.3多重标签

  1. // vowels -- switch many cases //
  2. #include <stdio.h>
  3. int main(void)
  4. {
  5. char ch;
  6. int a_ct, e_ct, i_ct, o_ct, u_ct;
  7. a_ct = e_ct = i_ct = o_ct = u_ct = 0;
  8. printf("Enter some text; enter # to quit.\n");
  9. while ((ch = getchar()) != '#')
  10. {
  11. switch (ch)
  12. {
  13. case 'a':
  14. case 'A':
  15. a_ct++;
  16. break;
  17. case 'e':
  18. case 'E':
  19. e_ct++;
  20. break;
  21. case 'i':
  22. case 'I':
  23. i_ct++;
  24. break;
  25. case 'o':
  26. case 'O':
  27. o_ct++;
  28. break;
  29. case 'u':
  30. u_ct++;
  31. break;
  32. default:
  33. break;
  34. } // switch结束
  35. }
  36. printf("number of vowels: A, E, I, O, U\n");
  37. printf(" %4d, %4d, %4d, %4d, %4d\n", a_ct, e_ct, i_ct, o_ct, u_ct);
  38. return 0;
  39. }

image.png

7.7.4 switch & if else语句的比较

适用于那种情况呢?观察代码可以知道,if else可以用在表示范围的的条件中,浮点变量或者表达式都可以。但是switch case用于确定的选项。

7.8 goto语句

为何避免使用goto语句?

goto语句在程序执行中跳来跳去,一般程序都是顺序执行,该语句可能会打乱程序的执行;

其次该语句只能标识该语句的功能,但不具备准确的意义,比如continue和break语句都可以跳出内部循环

章末总结

所有的循环和switch语句都可以使用break语句,所有的循环都可以使用continue语句,但是switch语句不行;

条件运算符;

关系表达式,满足条件执行的时问号前面的语句;

ctype.h是字符函数;

switch用整数作为标签语句的条件用于匹配输入;

break, continue, goto都可以作为跳转语句;