目录
1.什么是语句
2.分支语句
2.1 if 语句
2.2 switch 语句
2.2.1 break
2.2.2 default子句
3.循环语句
3.1 while 循环
3.1.1 原本这是一个死循环
3.1.2 后来加入了条件
3.1.3 随着break的加入
3.1.4 伴随着continue的出场
3.1.5 getchar() 和 putchar()
分支语句
- if
- switch
循环语句
- while
- for
- do while
1.什么是语句goto语句
C语句可分为以下五类
1.表达式语句
2.函数调用语句
3.控制语句
4.复合语句
5.空语句
以上的语句都是控制语句
控制语句用于控制程序的执行流程,以实现程序的各种结构方式,它们由特定的语句定义符组成,C语言有九种控制语句。
可分为以下三类:
1.条件判断语句也叫分支语句:if语句、switch语句;
2.循环执行语句:do while语句、while语句、for语句;
3.转向语句:break语句、goto语句、continue语句、return语句。
语法结构:
//单分支
if(表达式)
语句1;
//双分支
if (表达式)
语句1;
else
语句2;
//多分支
if (表达式1)
语句1;
else if (表达式2)
语句2;
else
语句3;
小栗子:
#define _CRT_SECURE_NO_WARNINGS
#include
int main()
{
// 如果条件为真打印haha,否则不打印
if (3 == 5)
printf("haha");
if (3 == 3)
printf("\nhaha");
//这里不再是判断而是赋值,条件会一直满足
int a = 0;
if (a = 1)
printf("\nhaha\n");
//进一步的,给if语句赋予一定的意义
int age = 0;
scanf("%d", &age);
if (age < 16)
printf("未成年");
else if (age >= 16 && age < 30)
printf("成年");
else if (age >= 30 && age < 40)
printf("中年");
else if (age >= 40 && age < 60)
printf("壮年");
else if (age >= 60 && age < 90)
printf("寿星");
else
printf("仙人");
//if后跟一条语句不用{},如果跟多条语句需要{},else后的语句也是同样的道理
int time = 0;
scanf("%d", &time);
if (time < 6)
{
printf("\n清晨");
printf("早起背词");
}
// 这个栗子中"工作"不在if-else语句中,不论条件如何变化,都会一直打印
// 要想使"工作"满足一定条件再打印只需模仿这里if的写法即可
// 一个大括号括起来的就是代码块
int age2 = 0;
if (age < 16)
{
printf("\n未成年");
printf("自我提升");
}
else
printf("\n成年");
printf("\n认真学习");
return 0;
}
有趣的栗子:
结果会打印什么呢?
答案是:
#define _CRT_SECURE_NO_WARNINGS
#include
int main()
{
int a = 0;
int b = 2;
if (a == 1)
if (b == 2)
printf("嗯哼");
else
printf("哪个呢");
return 0;
}
神马都不打印;
因为 if-else语句 算作一条语句,所以如果 "a == 1" 不满足的话就什么都不打印,当然也不用{ }哦
相同的栗子,else语句 和最近的 if语句 匹配,就比如这样,尽管else和第一个if对齐,但实际上是和第二个if匹配,一般编译器会自动匹配,但是如果编译器没有自动匹配,那自己就要在这里注意了,养成良好的代码书写风格大有裨益
#define _CRT_SECURE_NO_WARNINGS
#include
int main()
{
int a = 0;
int b = 2;
if (a == 1)
if (b == 2)
printf("嗯哼");
else
printf("哪个呢");
return 0;
}
还有一个令我迷惑的代码:
#define _CRT_SECURE_NO_WARNINGS
#include
//通过函数来测试
test()
{
int a = 3;
if (a == 3)
return 1;
return 0;
}
int main()
{
int r = test();
// 用r接收test的返回值
printf("%d", r);
return 0;
}
这个结果是1,如果给a赋值为5呢;
#define _CRT_SECURE_NO_WARNINGS
#include
//通过函数来测试
test()
{
int a = 5;
if (a == 3)
return 1;
return 0;
}
int main()
{
int r = test();
// 用r接收test的返回值
printf("%d", r);
return 0;
}
这个结果就是0;
所以这个代码的逻辑仍然是条件满足返回1,不满足返回0,为什么没有else就可以返回return 0呢?我目前不知道啊,得到这个结论是通过一步步地调试观察调试过程中如果满足条件代码会跳过那个部分不执行,以及r的值来确定的。
我的结论是:不要写这种风格的代码,代码写出来的目的是给人看的,要做到简单易懂,一目了然,而且评价代码的好坏是不能拿代码的长度来衡量滴;
如果这样写感觉就好多了:
#define _CRT_SECURE_NO_WARNINGS
#include
//通过函数来测试
test()
{
int a = 3;
if (a == 3)
return 1;
else
return 0;
}
int main()
{
int r = test();
// 用r接收test的返回值
printf("%d", r);
return 0;
}
这里还有补充一个写代码的小技巧
这里x君可能经常会少写一个=,于是代码变成了
代码的含义都变了,即使编译过去没用了啊,如果我们把常量放在左侧变量放在右侧,当写成赋值语句时(就是上面这个),就会报错,写成判断语句时才会编译通过,让编译器提醒你,妙哉妙哉
先到这里吧 ~ 4.13
2.2 switch 语句switch语句也是一种分支语句,通常用于多分支的情况
如果我们要这样输出
输入1 输出星期一
输入2 输出星期二
输入3 输出星期三
输入4 输出星期四
输入5 输出星期五
……
如果用 if-else 语句编写就太过复杂,这时我们就要使用 switch 语句;
语法结构:
switch(整型表达式)
{
语句项;
}
这里的语句项是:
case 整型常量表达式:
语句;
注意:switch后跟整型表达式
case后跟整型常量表达式
我们可以测试一下浮点型
在这里程序报错了 ,所以说switch后跟整型表达式
再测试一下如果在case后跟变量或浮点型时的情况
跟变量时会报错变量
跟浮点型时会报错
所以说case后跟整型常量表达式
来看看
正常滴:
#define _CRT_SECURE_NO_WARNINGS
#include
int main()
{
int day = 0;
scanf("%d", &day);
switch (day)
{
case 1:
printf("星期一\n");
case 2:
printf("星期二\n");
case 3:
printf("星期三\n");
case 4:
printf("星期四\n");
case 5:
printf("星期五\n");
case 6:
printf("星期六\n");
case 7:
printf("星期日\n");
}
return 0;
}
从代码的运行结果来看switch的工作原理
switch通过后面的整型表达式,判断从哪个case语句进去,然后一路执(直)行下去
case只是入口,并没有告诉我们从哪里出去
2.2.1 break假设我们不希望switch在执行完case 1后再执行其他语句,这时就要用到break
#define _CRT_SECURE_NO_WARNINGS
#include
int main()
{
int day = 0;
scanf("%d", &day);
switch (day)
{
case 1:
printf("星期一\n");
break;
case 2:
printf("星期二\n");
break;
case 3:
printf("星期三\n");
break;
case 4:
printf("星期四\n");
break;
case 5:
printf("星期五\n");
break;
case 6:
printf("星期六\n");
break;
case 7:
printf("星期日\n");
break;
}
return 0;
}
这时每个case在处理完自己的任务就会走出来
更进一步地
我们要求1.输入1~5,输出weekday
2.输入6~7,输出weekend
可能会改成
#define _CRT_SECURE_NO_WARNINGS
#include
int main()
{
int day = 0;
scanf("%d", &day);
switch (day)
{
case 1:
printf("weekday\n");
break;
case 2:
printf("weekday\n");
break;
case 3:
printf("weekday\n");
break;
case 4:
printf("weekday\n");
break;
case 5:
printf("weekday\n");
break;
case 6:
printf("weekend\n");
break;
case 7:
printf("weekend\n");
break;
}
return 0;
}
但是利用case的特点,我们还可以这样写
#define _CRT_SECURE_NO_WARNINGS
#include
int main()
{
int day = 0;
scanf("%d", &day);
switch (day)
{
case 1:
case 2:
case 3:
case 4:
case 5:
printf("weekday\n");
break;
case 6:
case 7:
printf("weekend\n");
break;
}
return 0;
}
在这里输入1~5程序会根据case的入口一路向下执行,直到输出weekday
同样的道理,输入6~7,程序会向下执行,直到输出weekend
2.2.2 default子句当switch表达式的值并不匹配所有case标签的值时,default子句后面的语句就会执行,所以每个switch语句中只能出现一条default语句
就以上面的例子来说,如果我们并没有输入1~7,而是输入一个随机值,这时就要提示重新输入,
随机值不确定呀,你总不能case一个吧,在这种情况下就用到了default
#define _CRT_SECURE_NO_WARNINGS
#include
int main()
{
int day = 0;
scanf("%d", &day);
switch (day)
{
case 1:
case 2:
case 3:
case 4:
case 5:
printf("weekday\n");
break;
case 6:
case 7:
printf("weekend\n");
break;
default:
printf("请重新输入:");
break;
}
return 0;
}
再补充一点
可以有这样的表达吗
case (day < 6) :
当然可以,只不过如果day输入的是1~5,判断结果为真
case ( day < 6) :
就应该理解为
case 1:
若day输入的是1~5以外的数字,判断结果为假,代码就应理解为
case 0:
好习惯:
在每个switch语句后都放一条default子句,再加一个break
3.循环语句- while
- for
- do while
语法结构:
while(表达式)
循环语句;
// 表达式为真,执行循环语句,为假,跳出循环
栗子:
3.1.1 原本这是一个死循环#define _CRT_SECURE_NO_WARNINGS
#include
int main()
{
while (1)
{
printf("hehe\n");
}
return 0;
}
会一直打印hehe,死循环
3.1.2 后来加入了条件打印1~10
#define _CRT_SECURE_NO_WARNINGS
#include
int main()
{
int i = 0;
while (i < 10)
{
i++;
printf("%d\t", i);
}
return 0;
}
3.1.3 随着break的加入
会打印1~5,因为当 i==4时,会输出5,之后会跳出循环,程序结束
#define _CRT_SECURE_NO_WARNINGS
#include
int main()
{
int i = 0;
while (i < 10)
{
if (5 == i)
break;
i++;
printf("%d\t", i);
}
return 0;
}
break的作用:break直接作用于while循环,只要遇到break,循环整体就会被终止
3.1.4 伴随着continue的出场会打印1~5,此时,代码是死循环状态,程序并没有结束,因为代码满足执行continue的条件,一直跳过continue后面的代码,循环continue前面的代码
#define _CRT_SECURE_NO_WARNINGS
#include
int main()
{
int i = 0;
while (i < 10)
{
if (5 == i)
continue;
i++;
printf("%d\t", i);
}
return 0;
}
稍作修改,会打印除了5以外,1~10的其他数字
#define _CRT_SECURE_NO_WARNINGS
#include
int main()
{
int i = 0;
while (i < 10)
{
i++;
if (5 == i)
continue;
printf("%d\t", i);
}
return 0;
}
continue的作用:continue会跳过本次循环中continue后面的代码,直接去判断部分,判断要不要执行下一次循环
继续展开
3.1.5 getchar() 和 putchar()引入 getchar() 和 putchar()
栗子1:
#define _CRT_SECURE_NO_WARNINGS
#include
int main()
{
// getchar()可从键盘获取一个字符,把获取的字符的ASCII码值放到ch里
int ch = getchar();
// 为什么getchar从键盘获取的是一个字符却要赋给int型的ch,为什么不是char型呢
// 从MSDN可以知道getchar()是从键盘获取一个字符,返回值返回的是该字符的ASCII码值,所以返回的是整型
// 当输入错误或遇到文件末尾会返回EOF,EOF是#define定义的-1,综上所述,getchar()的返回值应该是整型
// 方法一
// 把ch以字符的形式打印出来
printf("%c\n", ch);
// 方法二
// 利用putchar()获取ch
putchar(ch);
return 0;
}
思考:
为什么getchar从键盘获取的是一个字符却要赋给int型的ch,为什么不是char型呢?
从MSDN可以知道getchar()是从键盘获取一个字符,返回值返回的是该字符的ASCII码值,所以返回的是整型;
当输入错误或遇到文件末尾会返回EOF,EOF是#define定义的-1,综上所述,getchar()的返回值应该是整型;
栗子2:
#define _CRT_SECURE_NO_WARNINGS
#include
int main()
{
int ch = 0;
// 当ch返回的字符不是EOF时,也就是说,当ch返回的字符正常时
while ((ch = getchar()) != EOF)
{
putchar(ch);
}
return 0;
}
// 按Ctrl+z代码就返回EOF,停下来
为什么 putchar() 那里没有换行符 \n 代码却自动换行了呢?
getchar() 并不是直接从从键盘获取一个字符,而是通过输入缓冲区来获取字符的,每次只能获取一个字符,当我们键入一个字符a,按下回车,会在输入缓冲区生成a以及换行字符\n,接着a满足循环条件,输出a,继续判断,\n也满足循环条件,执行换行
这个代码常用在清空输入缓冲区
栗子:
#define _CRT_SECURE_NO_WARNINGS
#include
int main()
{
// 假设密码是一个字符串
char password[20] = { 0 };
printf("请输入密码:>");
scanf("%s", password);
printf("请确认密码(Y/N):>");
int ret = getchar();
if ('Y' == ret)
{
printf("密码正确\n");
}
else
{
printf("重新输入");
}
return 0;
}
这个代码运行的结果是
我们没有输入Y或者其他字符,结果就自动生成为“重新输入”,why?
这当然又和输入缓冲区有关,scanf 和 getchar() 都是一类型的函数,都需要从输入缓冲区读取字符,键入一串字符,按下回车,输入缓冲区会生成键入的字符串以及 \n ,而scanf仅仅会拿走字符串,留下\n ,当代码执行到 “请确认密码” 时,getchar() 发现输入缓冲区有字符,于是就把 \n 放到ret,经过 if 判断,打印“重新输入”;
如果想让代码在完成输入后停下来,可以改进代码
#define _CRT_SECURE_NO_WARNINGS
#include
int main()
{
// 假设密码是一个字符串
char password[20] = { 0 };
printf("请输入密码:>");
scanf("%s", password);
getchar();// 读取了\n
printf("请确认密码(Y/N):>");
int ret = getchar();
if ('Y' == ret)
{
printf("密码正确\n");
}
else
{
printf("重新输入");
}
return 0;
}
可以额外加一个 getchar() 读取多余的 \n,清空输入缓冲区
但是
如果这样输入(在字符串间加一个空格),没错,又输出了错误的结果
why?
这又和scanf的特性有关,当scanf读到空格时,scanf只会把空格前的内容拿走,留下其余部分,这时getchar()只会拿走空格,留下其余部分赋给ret,然后进入if判断,结果打印“重新输入”,我们发现清理字符时往往不是一个字符,而是一堆字符
这时我们需要改进刚才的代码,让getchar()循环执行,清理一堆字符
#define _CRT_SECURE_NO_WARNINGS
#include
int main()
{
// 假设密码是一个字符串
char password[20] = { 0 };
printf("请输入密码:>");
scanf("%s", password);
int ch = 0;
// getchar()获取字符,然后赋给ch,当ch读到\n时,条件为假,跳出循环
while ((ch = getchar()) != '\n')
// 读取一个字符清空一个字符
{
;
}
printf("请确认密码(Y/N):>");
int ret = getchar();
if ('Y' == ret)
{
printf("密码正确\n");
}
else
{
printf("重新输入");
}
return 0;
}
最后一个栗子:
只打印字符 ‘0’ ~ ‘9’
#define _CRT_SECURE_NO_WARNINGS
#include
int main()
{
// 初始化
char ch = '\0';
// 获取字符,并确保输入的字符正确
while ((ch = getchar()) != EOF)
{
if (ch < '0' || ch > '9')
continue;
putchar(ch);
}
return 0;
}
附一张ASCII码表,便于理解代码
结果是这样滴
不打印其余字符,只打印数字字符
今天就到这里4.14
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)