目录
前言
C 语句(statement)的作用是向计算机系统发出操作指令,要求执行相应的操作。本文则详细讲解 C 语句的另一大知识点,即 C 语句的分类,C 语句可以分为以下的 5 类。
一、表达式语句
表达式语句由表达式加上分号 ";" 组成。执行表达式语句就是计算表达式的值。
表达式(expression)是由操作符(运算符)和操作数组合构成的,其中操作数是操作符操作的对象。最简单的表达式即一个单独的操作数。
常见的表达式有:算术表达式、关系表达式、逻辑表达式、赋值表达式、逗号表达式等
#include <stdio.h>
int main()
{
int a = 0;
int b = 0;
a = b = 10;
printf("%d %d\n", a, b); // 10 10
return 0;
}
b = 10 是一个赋值表达式,表达式的结果即赋给 b 的值。
a = b = 10 也是一个赋值表达式,即 a = (b = 10),
整个表达式的结果是赋给 a 的子表达式(subexpression)的结果。
二、函数调用语句
函数调用语句由函数名、实际参数加上分号 ";" 组成,其一般形式为:函数名(实际参数表);。
执行函数调用语句就是调用函数体并把实际参数赋予函数定义中的形式参数,然后执行被调函数体中的语句,求取函数值。
#include <stdio.h>
int get_max(int x, int y)
{
return x > y ? x : y;
}
int main()
{
printf("hello world!\n");
// 调用库函数 printf,打印字符串 hello world!
int num1 = 10;
int num2 = 20;
int max = get_max(num1, num2);
printf("max = %d\n", max); // max = 20
// 调用自定义函数 max,求两个数中的较大值
return 0;
}
三、控制语句
控制语句即用来实现对程序流程的选择、循环、转向和返回等进行控制,它们由特定的语句定义符组成,C 语言中共有 9 中控制语句。可分成以下三类:
-
条件判断语句(分支语句):if 语句、switch 语句;
-
循环执行语句:do while 语句、while 语句、for 语句;
-
转向语句:break 语句、continue 语句、return 语句、goto 语句(此语句尽量少用,因为这不利于结构化程序设计,滥用它会使程序流程无规律,可读性差)。
四、复合语句
复合语句简称为语句块(代码块),它用大括号 {} 将多条语句组合在一起,形成单条语句,特别地,如果大括号里什么内容都没有,相当于只有一个分号的空语句。
复合语句有以下三个主要特点:
-
大括号中虽然可能有多条语句,但是算作一个复合语句。因此当出现语法上某处需要一条语句,但程序却需要执行多条语句时,就可以用到复合语句,这经常会发生在使用分支和循环语句的时候。
-
复合语句有自己的作用域,因此在离开复合语句以后,其中定义的变量会被销毁。
-
从语句的角度来说,分号是语句的结束标志,但是复合语句的结束不需要分号。
#include <stdio.h>
int main()
{
// 输入两个整数,将两个整数按从大到小的顺序输出
int a = 0;
int b = 0;
scanf("%d%d", &a, &b);
if (a < b)
{
int tmp = a;
a = b;
b = tmp;
}
// if 语句后面跟的就是复合语句,它用大括号将多条语句组合在了一起
printf("%d %d\n", a, b);
return 0;
}
五、空语句
只由分号 ";" 组成的语句称为空语句。空语句是什么也不执行的语句。
实例 - 输入密码:
#include <stdio.h>
int main()
{
char passwd[20] = { 0 };
printf("请输入密码:>");
scanf("%s", passwd);
printf("请确认密码(Y/N):>");
char ch = getchar();
// getchar 是从标准输入(stdin)中读取字符的函数,
// 在读取失败或遇到 end-of-file 的情况下,会返回 EOF。
if (ch == 'Y')
printf("确认成功~");
else
printf("确认失败!");
return 0;
}
问题一:
当我们输入完密码,例如:123456 ,理应会根据我们再输入的 Y 或 N,打印"确认成功~"或"确认失败!",但实际情况是这样吗?
实际情况是:程序还未等我们输入 Y 或 N,就已经打印了"确认失败!"。
原因是:scanf 和 getchar 函数不是直接从键盘上读取数据的,而是从输入缓冲区中读取数据,如果输入缓冲区中有数据,就直接"拿"走了,而不需要从键盘输入数据,如果缓冲区中没有数据,则需要从键盘输入数据。当我们将密码 123456 从键盘上输入时,还敲了一个回车(\n),所以输入缓冲区里的数据是 "123456\n"。scanf 读取的是 \n 之前的内容,即 123456,因此 getchar 函数就直接"拿"走了输入缓冲区中的数据 '\n',最终就出现程序还未等我们输入 Y 或 N,就已经打印了"确认失败!"。
解决措施一:
#include <stdio.h>
int main()
{
char passwd[20] = { 0 };
printf("请输入密码:>");
scanf("%s", passwd);
getchar(); // 清理输入缓冲区中的 '\n'
printf("请确认密码(Y/N):>");
char ch = getchar();
// getchar 是从标准输入(stdin)中读取字符的函数,
// 在读取失败或遇到 end-of-file 的情况下,会返回 EOF。
if (ch == 'Y')
printf("确认成功~");
else
printf("确认失败!");
return 0;
}
问题二:
运行上面的改进代码,当我们输入完密码,例如:123 456,即密码中间有空格时,是否会根据我们输入的 Y 或 N,打印"确认成功~"或"确认失败!"?
实际情况是:程序还未等我们输入 Y 或 N,就已经打印了"确认失败!"。
原因是:输入缓冲区里的数据是 "123 456\n"。scanf 读取的是空格之前的内容,即 123,因此 getchar 函数就直接"拿"走了输入缓冲区中的空格数据,最终就出现程序还未等我们输入 Y 或 N,就已经打印了"确认失败!"。
解决措施二:
#include <stdio.h>
int main()
{
char passwd[20] = { 0 };
printf("请输入密码:>");
scanf("%s", passwd);
while (getchar() != '\n');
// 清理输入缓冲区中的所有内容,其中空语句用作循环体
printf("请确认密码(Y/N):>");
char ch = getchar();
// getchar 是从标准输入(stdin)中读取字符的函数,
// 在读取失败或遇到 end-of-file 的情况下,会返回 EOF。
if (ch == 'Y')
printf("确认成功~");
else
printf("确认失败!");
return 0;
}
根据这段改进代码,就可以彻底实现我们的要求了。