C Primer Plus 第7章——第二篇

你该逆袭了

三、逻辑运算符

#include <stdio.h>
#define PERIOD '.'     //PERIOD 相当于 单引号—句点—单引号

int main()
{
	char ch = 0;
	int charcount = 0;

	while ((ch = getchar()) != PERIOD)
	{
		if (ch != '"' && ch != '\'')
			charcount++;
	}
	printf("there are %d non_quoto characters.\n", charcount);

	return 0;
}

1、备选拼写:iso646.h 头文件

#include <stdio.h>
#include <iso646.h>    //and or not 代替 && || ! 的头文件
#define PERIOD '.'     //PERIOD 相当于 单引号—句点—单引号

int main()
{
	char ch = 0;
	int charcount = 0;

	while ((ch = getchar()) != PERIOD)      //用 and 代替 &&
	{
		if (ch != '"' and ch != '\'')
			charcount++;
	}
	printf("there are %d non_quoto characters.\n", charcount);

	return 0;
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2、优先级

优先级顺序:从上到下
( )

算数运算符
关系运算符
&&
||
赋值运算符
在这里插入图片描述

3、求值顺序

除了两个运算符共享一个运算对象的情况外,C 通常不保证先对复杂表达式中哪部分求值。
例如,下面的语句,可能先对表达式 5+3 求值,也可能先对表达式 9+6 求值:

apples = (5 + 3) * (9 + 6);

C 把先计算哪部分的决定权留给编译器的设计者,以便针对特定系统优化设计。
但是,对于 逻辑运算符 是个例外,C 保证 逻辑表达式 的 求值顺序 是 从左往右。
&& 和 || 运算符都属 序列点,所以程序在从一个运算对象执行到另一个运算对象之前,所有的副作用都会生效。
而且,C 保证一旦发现某个元素让整个表达式无效,便立即停止求值。

在这里插入图片描述

4、范围

在这里插入图片描述
在这里插入图片描述

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

int main()
{
	int i = 0;

	char str[] = "test string.\n";
	while (islower(str[i]))       //无论使用哪种特定的字符编码,islower()函数都能正常运行,是可移植的   
	{
		i++;
	}
	printf("%d\n", i);   // 4 

	return 0;
}

四、一个统计单词的程序

//P195 程序清单7.7
//统计字符数、单词数、行数

#include <stdio.h>
#include <ctype.h>   //为isspace( )提供函数原型
#include <stdbool.h> //为bool、true、false提供定义
#define STOP '|'     

int main()
{
	char c = 0;   //读入字符
	char prev = 0;  //读入的前一个字符
	long n_chars = 0L;  //字符数
	int n_lines = 0;  //行数
	int n_words = 0;  //单词数
	int p_lines = 0;  //不完整的行数
	bool inword = false;  //如果 c 在单词中,inword 等于 true

	printf("enter text to be analyzed ( | to terminate):\n");  //这里用 '|' 来作为 结束标志
	prev = '\n';  //用于识别完整的 行
	while ((c = getchar()) != STOP)
	{
		n_chars++;  // 统计 字符
		if (c == '\n') 
			n_lines++;  //统计 行
		if (!isspace(c) && !inword) //此时字符不是空格,并且inword为false,说明刚刚开始了一个单词,现在要改变inword的值为true,并且单词数量+1 
		{                           //!inword == false
			inword = true;          //inword == true
			n_words++;
		}
		if (isspace(c) && inword)  //此时字符为空格,并且inword为true,说明刚刚结束了一个单词,现在要改变inword的值为false。
			inword = false;
		prev = c;
	}
	if (prev != '\n')  //这里要注意 STOP 字符位于一行的中间的情况。是否递增行数计数?
					   //我们可以作为特殊行计数,即没有换行符的一行字符。
	{                  //可以通过记录之前读取的字符识别这种情况,即如果读取时发现 STOP 字符的上一个字符不是换行符,那么这行就是特殊行。
		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;
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

1、针对代码,提出疑问,第8章节进行讲解

问:检查代码,查看一下如果单词之间有多个空格时,程序是否能正常运行。
答:不能,第8章讲解了如何修正这个问题,让该程序能统计文件中的单词量。

2、我结合自己的理解,自己写的代码

#include <stdio.h>
#include <ctype.h>
#include <stdbool.h>
#define STOP '|'

int main()
{
	char c = 0;  //输入的每一个字符
	char pre = 0;  //上一个字符,如果上一个字符是 '\n',说明是一个完整的行
	               //如果上一个字符不是 '\n',说明是一个不完整的行
	int n_words = 0;  //单词个数
	int n_chars = 0;  //字符个数
	int n_lines = 0;  //完整的代码行数
	int p_lines = 0;  //不完整的代码行数
	bool inward = false;  //inward 从 false 变成 true ,说明新增了一个单词

	pre = '\n';
	inward = false;
	
	while ((c = getchar()) != STOP)
	{
		n_chars++;  //字符数量加 1 

		if (c == '\n')
		{
			n_lines++;  //新增了 1 行
		}

		if (!isspace(c) && !inward)  //始终记住:inward 从 false 变成 true ,说明新增了一个单词
		{                            //根据这个原则来理解这两段代码
			inward = true;  
			n_words++;
		}
		if (isspace(c) && inward)    //始终记住:inward 从 false 变成 true ,说明新增了一个单词
		{                            //根据这个原则来理解这两段代码
			inward = false;
		}
		pre = c;
	}
	if (pre != '\n')
	{
		p_lines = 1;  //遇到 STOP 就停止程序了,所以直接给 p_lines 赋值为 1 就可以了。 
	}

	printf("characters = %d,words = %d,lines = %d,p_lines = %d\n",
		n_chars, n_words, n_lines, p_lines);

	return 0;
}

五、条件运算符 ?:

在这里插入图片描述
在这里插入图片描述

//P197 程序清单7.8
//使用条件运算符
//重点:商店只卖整罐油漆,不会拆分来卖,所以如果计算结果是 1.7 罐,就需要 2 罐。
//因此,该程序计算得到带小数的结果时应该进 1 。
//条件运算符常用于处理这种情况,而且还要根据单复数分别打印 can 和 cans 。

#include <stdio.h>
#define COVERAGE 350    //每罐油漆可刷面积

int main()
{
	int sq_feet = 0;
	int cans = 0;

	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 paint.\n", cans,
			cans == 1 ? "can" : "cans");
		printf("enter next value (q to quit):\n");
	}

	return 0;
}

自己写了一遍

#include <stdio.h>
#define MEIGUAN 350  //每罐油漆可以粉刷的面积

int main()
{
	int mianji = 0;
	int cans = 0;

	printf("请输入你要粉刷的墙壁的面积:");
	while (scanf("%d", &mianji) == 1)
	{
		cans = mianji / MEIGUAN;
		cans += mianji % MEIGUAN == 0 ? 0 : 1;
		printf("需要的油漆的罐数是 %d %s\n", cans, cans == 1 ? "can" : "cans");  //这是这个程序的亮点!!!
		printf("请再次输入你要粉刷的墙壁的面积:");
	}

	return 0;
}

在这里插入图片描述
在这里插入图片描述

六、循环辅助:continue 和 break

1、continue 语句

在这里插入图片描述

//P198 程序清单7.9

#include <stdio.h>

int main()
{
	const double MIN = 0.0f;
	const double MAX = 100.0f;

	double score = 0;
	double min = 0;
	double max = 0;
	double total = 0;
	int n = 0;

	min = MAX;  //请注意理解
	max = MIN;  //请注意理解
	score = 0;
	total = 0;
	n = 0;  

	printf("请输入得分score:");
	while (scanf("%lf", &score) == 1)
	{
		if (score < MIN || score > MAX)
		{
			printf("数据无效,请重新输入数据:");
			continue;  //注意点
		}
		min = (score < min ? score : min);   //请注意理解
		max = (score > max ? score : max);   //请注意理解 
		n++;  //计算输入数据的个数
		total += score;
		printf("输入下一个数据:(输入非浮点数,退出程序)");
	}
	if (n > 0)
	{
		printf("%d 个数据的平均分是:%lf\n", n, total / n);
		printf("low=%0.1f  high=%0.1f\n", min, max);
	}
	else
	{
		printf("没有输入有效的数据。\n");
	}

	return 0;
}

在这里插入图片描述
上述代码的注意点:就是比较一组数据的最小值和最大值。

 	min = MAX;  //请注意理解
	max = MIN;  //请注意理解
	min = (score < min ? score : min);   //请注意理解
	max = (score > max ? score : max);   //请注意理解 

在这里插入图片描述
在这里插入图片描述

2、break 语句

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

七、多重选择:switch 和 break

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

int main()
{
	char ch = 0;
	printf("请输入小写字母,我会根据你所给的小写字母,来给定特定的语句:");
	while ((ch = getchar()) != '#')
	{
		if (ch == '\n')
		{
			continue;
		}
		if (islower(ch))
		{
			switch (ch)
			{
			case 'a':
				printf("你输入的是小写字母 a \n");
				break;  //跳出 switch 语句
			case 'b':
				printf("你输入的是小写字母 b \n");
				break;
			case 'c':
				printf("你输入的是小写字母 c \n");
				break;
			case 'd':
				printf("你输入的是小写字母 d \n");
				break;
			case 'e':
				printf("你输入的是小写字母 e \n");
				break;
			default:
				printf("可以了可以了\n");
				break;
			}
		}
		else
		{
			printf("我只认识小写字母。\n");
		}
		while (getchar() != '\n')
		{
			continue;  //用于清除多余的字母
		}
		printf("请输入下一个字母:");
	}
	printf("bye\n");

	return 0;
}

在这里插入图片描述

	while (getchar() != '\n')
		{
			continue;  //用于清除多余的字母
		}

在这里插入图片描述
在这里插入图片描述

1、switch 语句

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

八、goto语句(C不需要,不要用)

在这里插入图片描述
在这里插入图片描述

1、能不用就不用 goto 语句

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2、可以使用 goto 语句 的场合

在这里插入图片描述
在这里插入图片描述

九、关键概念

在这里插入图片描述

十、本章小结

在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值