当前位置: 首页 > news >正文

伊吖学C笔记(3、字符、分支结构)

一、字符(串)

如果说“加减乘除余”是C语言中的数学,那字符(或字符串)就是C语言中的语文。

1.定义

用“char ch;”来定义单个字符变量,用“char str[20];”定义字符串,用“char *str;”也可定义字符串。

字符的双重属性,即:既表字符又表数字。为了弄清这个问题,我们先看看ASCII表:

表中,一个8位二进制对应特殊的功能或字符,比如00001010(10)代表换行(\n),00001101(13)代表回车(\r),00110000(48)代表字符0,00110001(49)代表字符1,010000001(65)代表A,01100001(97)代表a,等等。

一个字符默认的数值就是它ASCII的十进制数,用%c输出是字符,用%d输出是数字。

当然,ASCII码还有扩展部分:

输出扩展字符需要加上:

#include <windows.h>和SetConsoleOutputCP(437);

比如实线表格线,就要用到这些字符:

但是要与下面这个中文表格的区别:

这是中文双字节制表符,在word或excel里通过插入符号实现。

单个字符的处理要用单引号,一个个处理太麻烦,通常我们用字符串来处理文字。字符串定义常用到字符数组和指针。

我们发现定义字符串数组,输出时出了问题,数组st、s都出现不必要的尾巴。那是因为:集中定义时,用双引号时,字符串会自动加上结束标志“\0”,本例str[]、*p就是。而单个定义时,没有“\0”,输出时循环遍历输出。如要把它当作串输出,需多定义一位长度。

多行文本定义:

2.字符输入

2.1、getchar()

getchar()支持一次输入字符串,多次调用,每次一个字符。

与getchar()相对应的是putchar(ch),输出字符。

2.2、getch()

对比getchar(),getch()无缓冲无回显立即响应;有时在程序执行过程中需要暂停,可加一句getch();意思是等待键盘输入一个字符继续。getch()也可用于密码保护:

也有getche(),类似getch(),但有回显。

2.3、gets()

字符串输入函数,空格一起计算字符。

对应的put(a)为输出字符串函数。

另外还有fgets()、fgetc(),也可以读串,后说。

2.4、scanf()

格式:scanf("格式控制",变量地址列表)

scanf()有点眼盲,空格后面就不认了。看样子字符串,还是gets()好用。

scanf()运行完成一次后,键盘缓冲区还留了一个结束标志,对后续输入造成了影响。

当输入单个字符时,前面有没有输入,如果有则要空一格,抵消结束符。另外,scanf()参数后半截是变量地址列表,不是变量列表,如果是变量,一定要作地址引用,加&。数组、指针不用加&,默认就是地址的意思。

3.字符操作

3.1、字符串连接strcat(a,b)

3.2、字符串复制strcpy(a,b)

无论长短,皆是复制品。

也可以通过程序实现:

3.3、字符串比较strcmp(a,b)

相等才是0,要注意,第一个长:1,第一个短:-1。

3.4、字符串截取strncpy(a,b+n,m)

3.5、其他

strlen(a)字符串的长度

strlwr(a)大写字母变小写

strupr(a)小写变大写

二、分支

我们设计的程序在执行过程中,不可能是一帆风顺,遇到一些十字路口,要进行选择,走哪条路?这就是程序的分支结构。

1.单分支

if(条件)操作语句;

如果只关心一个条件(比如,班里叫张三的同学),或一类条件(比如,考试成绩在90分以上),并且只对满足条件的对象进行操作或运算,其他不管,就用if(条件)操作语句;,最简单的if,满足条件即运行,根据条件选择执行。

题目:输入一个字符串,统计有多少数字?

2.双分支

if(条件)操作语句1;

else操作语句2;

如果同时关心满足条件的和不满足条件的两类情况(比如:班上及格的同学和不及格的同学),要进行两种不同的操作或运算,就用双分支。

题目:输入字符串,分别输出是数字还是不是数字,并分别统计个数?

3.多分支

if(条件1)操作语句1;

else if(条件2)操作语句2;

...

else if(条件n)操作语句n;

else操作语句n+1;

如果关心的条件有多个(比如考核结果分为:优秀、称职、基本称职、不称职),并且进行不同的操作,这时就可以用到多分支。看个一个打折的例子:

题目:输入字符,如果输入是大写字母直接输出;如果是小写,转换为大写输出;如果是其他,输出不是字母。

字母大小写转化的问题,先看ASCII字符表,如下:

从表中可以看出:大写字母A-Z的ascii编号从65到90,小写字母的编号从97到122,这是固定的。

大写变小写,只需要把编号增加32就行。有些编程用的是:+'a'-'A',也就是+97-65,也是加32,一个意思。小写变大写,减32就行,总之,小写的编号比大写的大。

题目:由键盘输入一个3位的整数,判断该数是否为升序数。若输入的不是3位数,输出“Enter error”。升序数是指高位数依次小于其低位数的数。如,359为升序数。

设计思路:首先是判断是不是三位数?这是一层意思,然后再在三位数里判断是升序还是不是升序,这是第二层意思。用if...else if...else...这个语句可以解决。

if(a<100||a>999)

//判断非三位数:如果小于100或大于999,那就一定不是三位数了。

else if(a/100<a/10%10&&a/10%10<a%10)

//判断是否升序:a是三位整数,a/100的结果取整,即为百位数字。比如358/100=3,865/100=8,整数除整数,结果只取整数。个位数,a%10,即除以10的余数,比如358%10=8、865%10=5。中间的十位数还是有点麻烦,先除以10取出前两位,再除以10取余数,即a/10%10。比如:358/10%10=5、865/10%10=6。

升序要同时满足:百位数<十位数<个位数,所以中间要用逻辑与&&。如果同时满足条件,即百位数<十位数成立,并且十位数<个位数也成立。

题目:输入三个整数x,y,z,请把这三个数由小到大输出。

思考:三个数的排序,当然先比较2个,分出大小。再用第三个数去分别比较,比小的小,放在最前面;比大的大,放在最后面;否则放中间。这是最常规的思路(方法1)。

键盘输入(三板斧):

int x,y,z;

printf("请输入三个整数,中间用空格格开:");

scanf("%d %d %d",&x,&y,&z);

排序如下:

if(x>y)  //先排出x>y的可能排列组合:3种

   if(y>z)printf("%d %d %d",z,y,x);//小于小的

   else if (z>x)printf("%d %d %d", y,x,z);

        else printf("%d %d %d", y,z,x);

else  //再排出x<y的可能,也是3种

   if(x>z)printf("%d %d %d",z,x,y);

   else if (z>y)printf("%d %d %d", x,y,z);

        else printf("%d %d %d",x,z,y);

这种思路好理解,不改变xyz原来的赋值,就是编程有些烦琐,用到了5个if、5个else、6个printf(因为有6种可能的排列组合)。

有没有更好更简洁的方法呢?有。交换法(方法2),xyz的顺序始终不变,小的值往前换,大的往后换,换3次。

if(x>y){t=x;x=y;y=t;} //保持x<y,如果x>y则互换

if(y>z){t=y;y=z;z=t;} //用z比较y,看谁最大,如果y>z则互换,保持y<z,此时z最大

if(x>y){t=x;x=y;y=t;} //再比较xy,再次确保x<y

我们发现第一个if与第三个if一模一样,没搞错吧?我们这样理解排序过程:

 

x

y

z

举例

开始

852

528

582

if(x>y){t=x;x=y;y=t;}

582

258

582

if(y>z){t=y;y=z;z=t;}

小1

小2

528

258

528

if(x>y){t=x;x=y;y=t;}

258

258

258

这个比较后交换的顺序是:先是1、2位,再是2、3位(确定最大值),最后是1、2位。

有些书上的答案稍有区别:先是1、2位,再是1、3位(确定最小值),最后是2、3位,如下:

 

x

y

z

举例

开始

852

528

582

if(x>y){t=x;x=y;y=t;}

582

258

582

if(x>z){t=x;x=z;z=t;}

大1

大2

285

258

285

if(y>z){t=y;y=z;z=t;}

258

258

258

程序运行结果如下:

上面就是if的基本框架及应用举例。if框架都可以嵌套,建议嵌套层级3-5层。

4.开关语句switch

最简单的理解:对号入座。

switch(开关){

case 1:...;

case 2:...;

...;

case n:...;

default:...;}

根据开关的值,决定到哪运行,就相当于,你是几班,就进几班的教室,case后面的值就是班号,如果你还没分班,前面都不是,就到default(缺省)报到。

case后面最后一般都会加上break,跳出switch,否则会顺序执行下面的case。

default:...也可以没有。

运行流程图如下:

下面看个例子:

首先 x=1,执行 case 1:a++;这句,结果a=1了;由于后面没有break;继续执行case 2:a++;b++;break;这句,结果a=2,b=1了。执行完这句后,后面有break;跳出,结束switch。

再看个例子:

题目:输入某年某月某日,判断这一天是这一年的第几天?

思考:年有平年365、闰年366之分;月有31、30、29、28天的区别。第几天怎么确定?先从第一个月捋一捋,一月无论什么时候都是31天,那一月日期数就是这一年的第几天。比如1月5日,就是全年第5天;二月呢:就是二月的日期数加上31,就是这一年的第几天。比如2月3日就是全年第34天;三月呢:平年是三月的日期数+31+28,闰年是日期数+31+29...依此类推,后面的月份都是两种可能,但有同一规律:闰年比平年多一天。是不是我们就可以:先只管平年,完成平年的计算;最后加上一个if判断,如果闰年,且月份数大于2,则平年的结果+1。

如何完成平年的第几天计算呢?我们先找找规律看:1-12月的月长分别为:31、28、31、30、31、30、31、31、30、31、30、31。虽然主要为30、31两个数,但规律并不明显,7月、8月连续两个31天,奇偶关系也变了。那我们就用比较老实的办法了,用switch()语句,设计12种可能性来完成。

闰年的判断:如果是世纪年,除以400等于0就是闰年即y%400==0;如果是非世纪年(y%100!=0),除以4等于0才是闰年,即y%4==0。综合起来就是

y%400==0||y%4==0&&y%100!=0

因为“&&”(逻辑与)的优先级高于“||”(逻辑或),比如:A&&B||C&&D,等价于(A&&B)||(C&&D)。

如果是分步判断,流程如下:

  

相关文章:

  • Unreal渲染源码简读(一)RHI/Shader
  • Minecraft Fabric - java.lang.NoClassDefFoundError HttpUriRequest
  • Spring Boot是什么?MybatisPlus常用注解,LambdaQueryWrapper常用方法
  • OpenHarmony 4.1版本应用升级到5.0版本问题记录及解决方案
  • vue开发中常用方法笔记
  • 在公司快速查看与固定内网IP地址的完整指南
  • 全链路解析:影刀RPA+Coze API自动化工作流实战指南
  • 2025电工杯A题数据-光伏电站发电功率预测数据 收集策略
  • Docker 与 Kubernetes 部署 RabbitMQ 集群(二)
  • docker初学
  • w~大模型~合集4
  • 【Linux系列】EVS 与 VBD 的对比
  • nvidia Thor U与qualcomm 8295 DMPIS算力测试对比
  • 用matlab提取abaqus odb文件中的节点信息
  • 谢飞机的Spring WebFlux面试之旅:从基础到深入
  • 服务接口鉴权与内部认证:自定义注解与AOP实现的企业级实践
  • 免杀一 线程加载
  • Excel 打开密码:守护数据安全的 “钥匙”
  • MySQL:备份还原数据库(mysqldump)
  • c# 解码 encodeURIComponent
  • 上传视频网站开发/百度手机快速排名点击软件
  • 东莞万江做网站/长沙seo关键词
  • 给企业做网站的公司西安/谷歌安装器
  • 更合网站制作公司/cpa推广接单平台
  • 网站制作属于什么行业/品牌广告语
  • 网站说服力营销型网站策划/推广普通话文字素材