热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

偷学C语言第二天

目录补码字符类型VS整型字符串算数运算符类型转换分支结构关系运算符逻辑运算符if语句switch-case语句if和switch语句嵌套循环结构while循

目录

补码

 字符类型 VS 整型

字符串

算数运算符

类型转换

分支结构

关系运算符

逻辑运算符

if语句

switch-case语句 

if和switch语句嵌套

循环结构

while循环

do...while循环

for循环

continue

多学一点

for VS while

goto

条件运算符

彩蛋



第一天忘了跟大家说C环境的配置,点击这里查看C语言初学者如何配置开发环境。


补码

计算机是用补码的形式存储整型数据的。正数的原返补都是一样的,负数的补码需要三步才能得到:


  1. 先把该数的绝对值转换成二进制形式,也就是该数的源码 ------ 源码就是原来的样子
  2. 再把数值位按位取反,得到反码 ------ 反码就是反着干,0变1,1变0;
  3. 最后将第2步的值加一就得到了补码 ------ 补码就是补1。

为什么会引入补码?详情见:计算机中数的表示 & 使用补码的好处


字符类型 VS 整型

先看个例子:

#include
int main()
{char c = 'A';printf("%c = %d\n",c,c);
}

运行结果:

字符'A'为什么以整型输出时是65?还记得第一天在讲转义字符时提到的ASCII表吗,对的,这里就是通过查ASCII表查到字符'A'对应的十进制数是“65”,所以字符类型是特殊的整型。

再来看个例子:

#include
int main()
{char height = 175;printf("我的海拔是%dcm\n",height);
}

 

哎呀我去,不得了了,咋还长到地底下去了,我又不是胡萝卜(´•༝•`) 这又是咋回事呢?还记得第一天学C时提到char的取值范围是-128到127或0到255,为什么还有个或呢?这是因为C标准中没有规定char默认是signed还是unsigned,而是由编译系统决定它的默认限定符,signed char的取值范围是 -128 ~ 127;unsigned char的取值范围是 0 ~ 255。所以我们应该手动指定char的限定符。


字符串

C没有专门为存储字符串设计一个单独的类型,因为没必要。字符串事实上就是一串字符。所以只需要在内存中开辟一块连续空间,然后存放一串字符类型的变量即可。


  • 声明字符串的语法:char 变量名[字符的数量];
  • 赋值:事实上就是对这一块连续空间里边的每一个字符变量进行赋值。我们通过索引号来获得每个字符变量的空间,语法格式:变量名[索引号] = 字符;

    #include
    int main() {char words[12];words[0] = 'I';words[1] = ' ';words[2] = 'L';words[3] = 'o';words[4] = 'v';words[5] = 'e';words[6] = ' ';words[7] = 'C';words[8] = 'h';words[9] = 'i';words[10] = 'n';words[11] = 'a';/*'\0'是字符串结束的标记,不可以省掉*/words[12] = '\0';/*声明和赋值放在一块,称为初始化,[]中的数量可以省掉,编译期会自动帮我们计算*/char words2[] = {'I',' ','L','o','v','e',' ','C','h','i','n','a','\0'};/*字符串常量可以用双引号直接括起来,不必在末尾追加'\0',系统会自动追加*/char words3[] = {"I Love China"};/*字符串常量可以把大括号也省掉*/char words4[] = "I Love China";printf("%s\n",words);printf("%s\n",words2);printf("%s\n",words3);printf("%s\n",words4);return 0;
    }


算数运算符

假设A的值是10,B的值是20


运算符描述实例
+把两个操作数相加(双目)A + B 将得到 30
-从第一个操作数中减去第二个操作数(双目)A - B 将得到 -10
*把两个操作数相乘(双目)A * B 将得到 200
/分子除以分母(双目)B / A 将得到 2
%取模运算符,整除后的余数(双目)B % A 将得到 0
++自增运算符,整数值增加 1(单目)A++ 将得到 11
--自减运算符,整数值减少 1(单目)A-- 将得到 9

代码示例:

#include
int main() {int a = 10,b = 20;printf("a + b = %d\n",a + b);printf("a - b = %d\n",a - b);printf("a * b = %d\n",a * b);printf("b / a= %d\n",b / a);/*对于整型类型数据的除法运算,是采取直接舍弃小数部分的方式,而不是什么四舍五入。*/printf("a / b= %d\n",a / b);printf("b %% a = %d\n",b % a);/*++在前,先自增再赋值;++在后,先赋值再自增;自减同理。*/printf("a++ = %d\n",a++);//a++的值是10printf("++a = %d\n",++a);//经过上一步运算a的值就变成11了,++a在11的基础上先自增1变成12,再赋值,所以此时a的值是12printf("a-- = %d\n",a--);printf("--a = %d\n",--a);return 0;
}

需要注意的几点问题:


  • 因为键盘上没有乘号和除号两个按键,所以用星号(*)和斜杠(/)代替,几乎所有编程语言都是如此。
  • 对于整数间的除法是采取直接舍弃小数部分的方式,而不是什么四舍五入。
  • 对于浮点数间的除法则能获得一个相对逼近结果的值(如果除不尽或位数特别多的话)。
  • 百分号(%)取模(求余)运算符要求两边的操作数必须都是整数,其结果也是整数。
  • 双目单目指的是运算符有几个操作数。

类型转换

#include
#include
int main() {/*自动转换:两种不同类型的数据做运算,容量小的类型会自动向上转型成容量大的类型再做运算,所以3+3.0得到的是浮点型,以整型格式输出,结果肯定不对*/printf("整型输出:%d\n",3+3.0);printf("浮点输出:%f\n",3.0+3.0);/*强制转换:语法格式:(目标类型)原数据强制类型转换会损失精度*/printf("强制类型转换:%d\n",3+(int)3.6);//浮点型的3.6强转成int后变成3了}

分支结构

之前我们写的代码都是顺序结构,即按代码编写顺序依次执行。但我们生活中会存在一种“如果怎样就怎样否则会怎样”的情况,所以就有了分支结构,在学习分支结构之前,我们得先了解关系运算符和逻辑运算符。


关系运算符

关系运算符用于比较两个数或者两个表达式的大小关系,包含>(大于)、<(小于)、=(等于)、>=(大于或等于)、<=(小于或等于)、==(等于)、!=(不等于),关系运算符的优先级低于算数运算符,结合性都是从左到右。关系运算符是双目运算符,用关系运算符将两边的变量、数据或表达式连接起来,称之为关系表达式。关系表达式的结果是一个逻辑值,或真(1)或假(0)。

#include
int main() {int a = 6,b = 8;printf("a > b结果是%d\n",a > b);printf("a = b结果是%d\n",a >= b);printf("a <= b结果是%d\n",a <= b);printf("a != b结果是%d\n",a != b);
}

逻辑运算符

逻辑运算符包含&&(与)、||(或)、!(非),优先级:!>&&>||。逻辑运算符存在短路求值,详情参见下面代码示例:

#include
int main() {int a = 6,b = 8;/*我们输入非0数,C语言就会判断为真,否则为假;C语言反馈给我们的值只有0和1,0表示假,1表示真。*//*&&:两边同为真结果才为真,否则皆为假。*/printf("a && b = %d\n",a && b);/*||:两边同为假结果才为假,否则皆为真。*/printf("(a = 0) || b = %d\n",(a = 0) || b);/*!:单目运算符,原数据为真,结果则为假,否则为真,即取反。*/printf("!0 || a }

if语句

if语句有三种形态:


  1. if(逻辑数据){//业务代码} ;

    #include
    int main() {int age;printf("阁下贵庚:");scanf("%d",&age);if(age >=18) {printf("欢迎光临,祝您玩的开心!");}return 0;
    }

     

  2. if(逻辑数据){//业务代码}else{//业务代码};

    #include
    int main() {int age;printf("阁下贵庚:");scanf("%d",&age);if(age >=18) {printf("欢迎光临,祝您玩的开心!");} else {printf("未成年人禁止入内,谢谢配合!");}return 0;
    }

     

  3. if(逻辑数据){//业务代码}else if(逻辑值){//业务代码}else if(逻辑值){//业务代码}...else{//业务代码}。

    #include
    int main() {float score;char grade;printf("请输入学生成绩:");scanf("%f",&score);/*输入的是浮点型,以整型打印,结果为0*/printf("用户输入的成绩是(以整型格式输出):%d\n",score);if(score >=90) {grade = &#39;A&#39;;} else if(score >= 80 && score <90) {grade = &#39;B&#39;;} else if(score >= 70 && score <80) {grade = &#39;C&#39;;} else if(score >= 60 && score <70) {grade = &#39;D&#39;;} else if(score >= 0 && score <60) {grade = &#39;E&#39;;} else {printf("学生分数不能给负数,太打击学生自信心了!");return 0;}printf("该学生分数等级是%c\n",grade);return 0;
    }

     


switch-case语句 

可以认为switch-case语句是if语句第三种形态的优化版本,因为它的语法更简洁。语法如下:

switch (表达式)
{case 常量表达式1: 语句或程序块case 常量表达式2: 语句或程序块……case 常量表达式n:语句或程序块default: 语句或程序块
}

示例代码: 

#include
int main() {char grade;printf("请输入学生成绩评级:");scanf("%c",&grade);switch(grade) {case &#39;A&#39;:printf("该学生分数是90分以上。\n");/*break关键字用于跳出switch语句*/ break;case &#39;B&#39;:printf("该学生分数是80分以上。\n");break;case &#39;C&#39;:printf("该学生分数是70分以上。\n");break;case &#39;D&#39;:printf("该学生分数是60分以上。\n");break;case &#39;E&#39;:printf("该学生分数未及格。\n");break;/*default语句是可选的,即可以不写,不过最好写上*/ default:printf("输出成绩评级不合法,请输入(&#39;A&#39;/&#39;B&#39;/&#39;C&#39;/&#39;D&#39;/&#39;E&#39;)。\n");break;}return 0;
}

 可以看出我们在switch语句中增加了break关键字用于跳出switch语句,如果不加break,switch语句就会从匹配到的case开始执行,一直执行到default才会退出,这种现象叫做“case穿透”。switch语句中的 case和 default 事实上都是“标签”,用来标志一个位置而已。当 switch 跳到某个位置之后,就会一直往下执行,所以我们这里还需要配合一个 break语句,让代码在适当的位置跳出 switch。

来看一个利用case穿透的示例:

#include
/*根据用户输入的月份,匹配相应的季节
*/
int main() {/*月份*/int month;/*季节*/char* season;printf("请输入月份:");scanf("%d",&month);switch(month) {case 3:case 4:case 5:season = "春季";break;case 6:case 7:case 8:season = "夏季";break;case 9:case 10:case 11:season = "秋季";break;case 12:case 1:case 2:season = "冬季";break;default:printf("输出月份不合法。\n");return 0;}printf("输出的月份对应%s。\n",season);return 0;
}

if和switch语句嵌套

#include
/*根据用户输入的月份,匹配相应的季节
*/
int main() {/*月份*/int month;/*季节*/char* season;printf("请输入月份:");scanf("%d",&month);if(month >= 1 && month <= 12) {switch(month) {case 3:case 4:case 5:season = "春季";break;case 6:case 7:case 8:season = "夏季";break;case 9:case 10:case 11:season = "秋季";break;case 12:case 1:case 2:season = "冬季";break;default:break;}printf("输出的月份对应%s。\n",season);} else {printf("输出的月份不合法!\n");}return 0;
}

if语句也可以与if嵌套,大家自行练习。


循环结构


while循环

语法:while(逻辑表达式){循环体} ------ 只要逻辑表达式的结果为真,就会一直循环执行循环体中的语句。

/*统计用户输入的字符个数:
*/
#include
int main() {int count = 0;printf("请输入你想说的话:");/*getchar()------从标准输入流中获取字符*/while(getchar() != &#39;\n&#39;) {count++;}printf("您总共输入了%d个字符。\n",count);
}

do...while循环

语法:do{循环体}while(逻辑表达式); ------ 先会执行一次循环体,然后进入while,只要逻辑表达式为真,就会一直循环执行。do...while循环语句不是很常用。


for循环

语法格式:

for (表达式1; 表达式2; 表达式3){循环体;
}

表达式1是初始化循环变量;表达式2是循环的条件,满足条件就会执行循环体;最后执行表达式3,表达式3是改变循环变量的值。下面是一个判断用户输入的自然数是否是素数的案例:

/*判断用户输入的数字是否是素数:<1>质数又称素数。一个大于1的自然数,除了1和它自身外,不能被其他自然数整除的数叫做质数;否则称为合数。<2>0和1既不是质数也不是合数,最小的质数是2。
*/
#include
int main() {/*接收用户输入的自然数*/int num;/*标记是否是素数,默认不是素数*/_Bool isPrimer = 1;printf("请输入一个自然数:");scanf("%d",&num);if(num == 0 || num == 1) {printf("您输入的%d既不是素数也不是合数~\n",num);return 0;}/*已知2和3是素数,所以这里只对大于3的自然数做处理*/if(num > 3) {int i;/*能整除一个数的数,肯定小于或等于被除数的一半,所以这里取 num/2 */for(i = 2; i <= num / 2; i++) {if(num % i == 0) {isPrimer = 0;/*只要找到一个可以整除num的除数就跳出循环*/break;}}}if(isPrimer)printf("您输入的自然数%d是素数\n",num);elseprintf("您输入的自然数%d不是素数\n",num);return 0;
}

另外,for 语句的表达式1,表达式2和表达式3都可以按需省略(但分号不能省):


  • for ( ; 表达式2; 表达式3)
  • for (表达式1; 表达式2; )
  • for (表达式1; ; )
  • for ( ; ; )
  • ……

C99允许在 for语句的表达式1中定义变量,比如如下代码:

for (int i=0, int j=10; i }

增加这个新特性的原因主要是考虑到循环通常需要一个循环变量(计数器),而这个循环变量只需要在for循环中有效即可。所以在表达式1的位置定义的循环变量,作用域仅限于循环中,出了循环,它就无效了。

ps:循环结构同意可以嵌套,如下中的for循环嵌套案例,先执行内层循环,再执行外层循环。

/*打印九九乘法表
*/
#include
int main() {int i,j;for(i=1; i<10; i++) {for(j=1; j<=i; j++) {printf("%d * %d = %d\t",j,i,j*i);}printf("\n");}return 0;
}

continue

continue与break都是用于跳出循环,continue是跳出本轮循环继续下一轮循环,break是跳出所在的那一层循环(当循环嵌套时如果要跳出整个循环可以借助goto语句,其他场景慎用goto)。

/*去掉用户输入的空格
*/
#include
int main() {char ch;while((ch = getchar()) != &#39;\n&#39;) {if(ch == &#39; &#39;) {continue;}putchar(ch);}putchar(&#39;\n&#39;);return 0;
}

多学一点


for VS while

for语句和 while语句执行过程是有区别的,它们的区别在于出现 continue语句时。在 for语句中,continue语句跳过循环的剩余部分,直接回到调整循环变量部分。在 while语句中,由于调整部分是循环体的一部分,因此 continue语句会把它也跳过,稍不注意就会出现问题。比如如下案例中:使用while改造for循环实现的功能,结果死循环了{T_T}

/*for VS while
*/
#include
int main() {int i,j;for(i = 0,j = 10; i<10; i++,j--) {if(i > j) {continue;}}printf("for循环执行完成后i和j的值分别是:%d、%d\n",i,j);/*使用while改造上面的for循环 */ i = 0;j = 10;while(i<10) {if(i > j) {continue;}i++;j--;}printf("while循环执行完成后i和j的值分别是:%d、%d\n",i,j);return 0;
}

goto

goto用于跳到指定标签的位置。

/*goto语句使用案例
*/
#include
int main() {int i = 6;while (i++) {if (i > 8) {goto Label;}}Label:printf("第%d次发牢骚:\n从来表白多白表,\n自古情书难书情,\n笑谈年少多少年,\n常与生人道人生。 \n", i);return 0;
}

条件运算符

条件运算符是C语言中唯一一个三目运算符,语法格式:exp1 ? exp2 : exp3; exp1是逻辑表达式,如果结果为真,则取exp2的值,否则取exp3的值。其实它就是为了简化 if...else...这种简单的语句。

/*条件运算符简化if-else语句,实现求两个数中的最大值。
*/
#include
int main() {int i = 6,j = 8,max;if(i > j)max = i;elsemax = j;/*使用条件表达式简化上述语句*/max = i > j ? i:j;printf("最大值是%d。\n",max);return 0;
}

彩蛋

<1>思考如下代码运行结果是什么,并解释说明。

#include
int main()
{
int a = 3;
printf("%d,%d\n",a++,a++);
printf("\n%d",a);return 0;
}

<2>还记得上一篇博文留的思考题吗?就是关于 unsigned short j = -1; 输出结果为什么是65535。这个问题就跟我们文章开头讲的补码有关系了,CPU运算整型是通过补码运算的,unsigned short 占用两个字节(16位),所以此时 -1的补码是1111 1111 1111 1111,转换成十进制就是65535。

你要学会猥琐发育,不鸣则已,一鸣惊人!


推荐阅读
  • 我举个例子,C代码如下:#include<stdio.h>main(){charx;printf(本程序功能:任意输入一个字符,如果是字母字符,将其ASCII ... [详细]
  • 本文介绍了在多平台下进行条件编译的必要性,以及具体的实现方法。通过示例代码展示了如何使用条件编译来实现不同平台的功能。最后总结了只要接口相同,不同平台下的编译运行结果也会相同。 ... [详细]
  • 我从来没有学过c语言,学不会C语言
    本文目录一览:1、我从没学过计算机C语言,怎么准备考二级C? ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • 本文讨论了使用差分约束系统求解House Man跳跃问题的思路与方法。给定一组不同高度,要求从最低点跳跃到最高点,每次跳跃的距离不超过D,并且不能改变给定的顺序。通过建立差分约束系统,将问题转化为图的建立和查询距离的问题。文章详细介绍了建立约束条件的方法,并使用SPFA算法判环并输出结果。同时还讨论了建边方向和跳跃顺序的关系。 ... [详细]
  • switch语句的一些用法及注意事项
    本文介绍了使用switch语句时的一些用法和注意事项,包括如何实现"fall through"、default语句的作用、在case语句中定义变量时可能出现的问题以及解决方法。同时也提到了C#严格控制switch分支不允许贯穿的规定。通过本文的介绍,读者可以更好地理解和使用switch语句。 ... [详细]
  • 3.223.28周学习总结中的贪心作业收获及困惑
    本文是对3.223.28周学习总结中的贪心作业进行总结,作者在解题过程中参考了他人的代码,但前提是要先理解题目并有解题思路。作者分享了自己在贪心作业中的收获,同时提到了一道让他困惑的题目,即input details部分引发的疑惑。 ... [详细]
  • Go Cobra命令行工具入门教程
    本文介绍了Go语言实现的命令行工具Cobra的基本概念、安装方法和入门实践。Cobra被广泛应用于各种项目中,如Kubernetes、Hugo和Github CLI等。通过使用Cobra,我们可以快速创建命令行工具,适用于写测试脚本和各种服务的Admin CLI。文章还通过一个简单的demo演示了Cobra的使用方法。 ... [详细]
  • Java SE从入门到放弃(三)的逻辑运算符详解
    本文详细介绍了Java SE中的逻辑运算符,包括逻辑运算符的操作和运算结果,以及与运算符的不同之处。通过代码演示,展示了逻辑运算符的使用方法和注意事项。文章以Java SE从入门到放弃(三)为背景,对逻辑运算符进行了深入的解析。 ... [详细]
  • 使用圣杯布局模式实现网站首页的内容布局
    本文介绍了使用圣杯布局模式实现网站首页的内容布局的方法,包括HTML部分代码和实例。同时还提供了公司新闻、最新产品、关于我们、联系我们等页面的布局示例。商品展示区包括了车里子和农家生态土鸡蛋等产品的价格信息。 ... [详细]
  • 本文整理了315道Python基础题目及答案,帮助读者检验学习成果。文章介绍了学习Python的途径、Python与其他编程语言的对比、解释型和编译型编程语言的简述、Python解释器的种类和特点、位和字节的关系、以及至少5个PEP8规范。对于想要检验自己学习成果的读者,这些题目将是一个不错的选择。请注意,答案在视频中,本文不提供答案。 ... [详细]
  • 本文介绍了2015年九月八日的js学习总结及相关知识点,包括参考书《javaScript Dom编程的艺术》、js简史、Dom、DHTML、解释型程序设计和编译型程序设计等内容。同时还提到了最佳实践是将标签放到HTML文档的最后,并且对语句和注释的使用进行了说明。 ... [详细]
  • 使用C++编写程序实现增加或删除桌面的右键列表项
    本文介绍了使用C++编写程序实现增加或删除桌面的右键列表项的方法。首先通过操作注册表来实现增加或删除右键列表项的目的,然后使用管理注册表的函数来编写程序。文章详细介绍了使用的五种函数:RegCreateKey、RegSetValueEx、RegOpenKeyEx、RegDeleteKey和RegCloseKey,并给出了增加一项的函数写法。通过本文的方法,可以方便地自定义桌面的右键列表项。 ... [详细]
  • 深入理解计算机系统之链接(一)
    程序是怎样运行的写好的c程序怎样运行的呢?答案是一个写好的程序要先经过语言预处理器,编译器,汇编器和链接器生成最后的可执行文件,然后加载器将可执行文件加载到内存中才能运行。这里以一 ... [详细]
  • 一,关于C语言的问卷调查【作业3】1.你对自己的未来有什么规划?做了哪些准备?没有明确的规划,在学习教材知识的同时准备了解其他知识。2.你认为什么是学 ... [详细]
author-avatar
手机用户2502885835
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有