一、学习内容
-
三种输入输出函数
-
putchar()/getchar() 单字符
-
putchar()
-
头文件:#include <stdio.h>
-
函数原型:int putchar(int c); //参数 int c; 说明可以接收整型/单字符型
-
功能:输出一个字符
-
-
getchar()
-
功能:获取一个字符
-
头文件:#include <stdio.h>
-
函数原型:int getchar(void); //参数是void 说明没有参数
-
-
-
puts()/gets() 字符串
-
puts()
-
功能:输出字符串,自带换行
-
头文件:#include <stdio.h>
-
函数原型:int puts(const char *s); //参数const char *s;——字符串的首地址
-
-
gets()
-
功能:获取一个字符串
-
头文件:#include <stdio.h>
-
函数原型:char *gets(char *s);
-
-
-
printf()/scanf() 格式化
-
printf()
-
功能:格式化输出内容
-
头文件:#include <stdio.h>
-
函数原型:int printf(const char *format, ...); //参数... 表示不定项
-
printf("原样输出内容+格式控制符" , 参数1 , 参数2 , 参数3 , ……);
-
-
scanf()
-
功能:输入,回车表示结束
-
头文件:#include <stdio.h>
-
函数原型:int scanf(const char *format, ...);
-
scanf("原样输入内容+格式控制符" , 地址1 , 地址2 , 地址3 ……);
-
注意:格式控制符只能是类型:%d %i %c %s %f
-
-
-
-
选择结构
-
三大结构
-
顺序结构——按照书写顺序依次执行,不允许跳过任何一条语句
-
选择结构——根据条件判断是否成立,执行不同的语句段【if语句 switch语句】
-
循环结构——重复结构,反复的执行某一部分代码
-
-
if语句
-
结构:
-
注意事项
-
①if(表达式) 表达式可以是任意合法表达式 eg:if(1) if(0) if(1+2) if(3.5) if('A') if(-1) if(a>b) if(a&&b) 结果只有两种,真【非0值】 和 假【0】
-
②if(表达式){} 若执行语句只有一条,{}可以省略;若有多条,不可以省略。建议不省略 eg: if(score>=670) printf("欢迎入学北大\n");
-
③else 先有if才有else,else和它前面的未被匹配的if进行配对 eg: if(1) printf("ok"); else printf("no"); //正确,输出ok if(1); printf("ok"); else printf("no"); //错误,输出ok
-
④ if(n=8) 和 if(n==8) 这两条语句不一样,一个=表示赋值,两个=表示判断相等 因为这两个语句C程序无法检测到错误,所以再进行判断两数相等的时候,我们强烈建议这样写 if(8 == n)
-
-
-
switch语句
-
switch(表达式)
{ case 常量表达式: 执行语句; break; case 常量表达式: 执行语句; break; case 常量表达式: 执行语句; break; case 常量表达式: 执行语句; break; …… default: 执行语句; break; } -
注意事项
-
switch(表达式),表达式可以是任意合法表达式,但是结果只能是整型或单字符型
-
case 常量表达式:【两个符号 一个空格 一个:】 case后的表达式必须是一个常量,而且还得是整型或单字符型 eg: case 3: case 1+2: case 'A': case 'A'+3: case 3.5:[X] case a>1&&a<3:[X] int a=10; case a:[X] case "hqyj":[X]
-
break表示中断结束,在switch语句表示跳出switch语句 可加可不加,不加继续往下执行,知道遇见break或者switch结束为止
-
default表示缺省值,可有可无,建议加上,保证程序的健壮性——对于非法数据做出合适的处理 不符合所有case的情况,执行default
-
case 和 default的顺序可以任意调换【电梯按键任意排列】
-
case后的常量表达式不能有重复值 case 3: 和 case 1+2: 不能在同一个switch语句中
-
多个case可以执行同一条语句
-
-
-
-
脑图
二、作业
1.下面的一段程序的输出结果为( ) (鲁科安全)
#include <stdio.h>
int main()
{
if(-1)
printf("1");
else
printf("2");
if(0)
printf("3");
else
printf("4");
return 0;
}
A. 23 B. 24 C. 13 D. 14
解析:
if(-1)中的-1代表的意思是括号里为真,所以执行printf(“1”),if(0)则表示为假,所以执行printf(“4”),最终为14
解答:
D
2.设int s = 100,要输出字符串"s的值是100"应使用下列哪个语句?(山东精电电气)
A. printf("s 的值是%d", s); B. printf("s 的值是%s", s)
C. printf("s 的值是%x", s): D. printf("s 的值是%i", s)
解析:
A选项:
d
是格式说明符,用于输出整数类型的值(如int
)。在这条语句中,s
的值100
会被插入到格式说明符%d
的位置,最终输出"s 的值是100"
B选项:%s
是格式说明符,用于输出字符串(即字符数组)。但是s
是一个整数,而不是字符串。因此,这种用法是错误的,可能会导致未定义的行为或输出不正确的结果。C选项:
%x
是格式说明符,用于输出整数的十六进制表示。如果使用这个语句,100
会被转换为其对应的十六进制数64
,最终输出"s 的值是64"
,这与题目要求不符。D选项:
%i
和%d
都是用于输出整数的格式说明符,实际上它们在处理整数时是等效的。在这个语句中,s
的值100
会被插入到格式说明符%i
的位置,最终输出"s 的值是100",但少了一个分号所以错误
解答:
A
3.if(n==8)和if(8== n)两种判断方式,哪一种更好,为什么?(泰华智)
解析:
两种方式判断都是正确的,但第二个较好,可以防止错误赋值,当我们在编程是,如若少打一个'='时,第一种会直接进行赋值,不会报错,不太好检查问题,而第二种则会进行报错,及时知道编程出现错误。
解答:
第二种
4.if-elseif-else结构和switch-case结构,哪个效率高,为什么?(泰华智慧)
解析:
`if-elseif-else` 结构:
这个结构从上到下逐步检查每个条件。每个条件都需要单独计算,直到找到匹配的条件或到达 `else` 分支。这意味着在最坏的情况下,可能需要检查所有条件,特别是当条件数量较多时,效率较低。每个条件判断可以是任意复杂的表达式,这使得 `if-elseif-else` 结构的效率依赖于条件的复杂度和数量。
switch-case` 结构
`switch-case` 结构在编译时,通常会生成一个跳转表(jump table)或二分查找表(binary search tree),特别是在 `case` 标签是连续或接近连续的整数时。通过这种方式,可以直接跳转到相应的 `case` 标签,从而在常数时间内完成判断。对于不连续或非常复杂的 `case` 标签,编译器可能会将 `switch-case` 转换为与 `if-elseif-else` 类似的结构,但在大多数情况下,`switch-case` 仍然能提供更好的性能。
解答:
’switch-case‘结构
5.结构化程序设计所规定的三种基本控制结构是:( ) (易购软件)
A. 输入、处理、输出 B. 形、网形、环形
C. 顺序、选择、循环 D. 主程序、子程序、函数
解析:
A选项:是一个典型的程序执行流程,而不是控制结构。
B选项:不是结构化程序设计中的控制结构,而是与数据结构或流程相关的术语。
C选项:是三种基本控制结构
D选项:是程序的模块化结构,与基本控制结构无关。
解答:
C
6.C语言中的标识符只能由字母,数字和下划线三种字符组成,且第一个字符:__________ (智洋)
A. 必须为字母 B. 必须为下划线
C. 必须为字母或下划线 D. 可以是字母,数字和下划线中任一字符
解析:
标识符只能由 字母(大小写)、数字 和 下划线(_) 组成。标识符的第一个字符 不能是数字,但可以是字母或下划线。
解答:
C
7.若执行下面的程序时,从键盘上输入 5,则输出是 ( ) (智洋创新)
int main(int argc, char **argv)
{
int x;
scanf("%d", &x);
if(x++ > 5)
printf("%d\n", x);
else
printf("%d\n", x--);
return 0;
}
A. 7 B. 4 C. 6 D. 5
解析:
键盘输入5,进入代码,则x=5,然后5++>5为假,所以进入else分支,此时x从5变成了6,进入else分支执行语句,因为‘--’在x后面,所以先打印后自减,打印x自减之前的值
解答:
C
8.以下语句中,能够判断uiNum(unsigned int)可以被16整除的有()(H3C)
A. if (((uiNum / 16) * 16) == uiNum)
B. if ((uiNum % 16) == 0)
C. if ((uiNum & 0x0F) == 0)
D. if (((uiNum >> 4) << 4) == uiNum)
解析:
A选项:这段代码通过先将
uiNum
除以 16,得到商后再乘以 16。如果uiNum
可以被 16 整除,那么乘回去的结果应该等于原始的uiNum
。这种方法是可行的。B选项:直接通过求余运算
%
来判断uiNum
是否能被 16 整除。如果uiNum % 16
为 0,则说明uiNum
可以被 16 整除。这个方法是直接、有效的。C选项:使用按位与操作检查
uiNum
的低四位是否为 0。如果uiNum
能被 16 整除,那么它的二进制表示的低四位应该为 0。这种方法是非常高效的。D选项:通过右移 4 位然后再左移 4 位,来判断
uiNum
的低四位是否为 0。如果uiNum
能被 16 整除,右移再左移后应该等于原始的uiNum
。这个方法也是可行的。
解答:
ABCD
9.编写一个程序。实现输入一个小写字母,程序输出它对应的大写字母。(提示:小写字母的ASCII码值比大写宇母大32) (中科四平)
解答:
#include <stdio.h>
int main() {
char a, b;
// 输入一个小写字母
printf("请输入一个小写字母: ");
scanf("%c", &a);
// 将小写字母转换为大写字母
if (a >= 'a' && b <= 'z') {
b = a - 32;
printf("对应的大写字母是: %c\n", b);
} else {
printf("输入的不是一个小写字母。\n");
}
return 0;
}
10.已知学生成绩(100分为满分)与等级的对应关系为: (中科四平)
成绩(grade)
等级
90<=grade<=100
A
80<=grade<90
B
70<=grade<80
C
60<=grade<70
D
grade<60
E
请你编写一个程序,要求:输入学生成绩,输出学生成绩对应的等级。(提示:使用switch....case 语句)
解答:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, const char *argv[])
{
int score=0;
printf("请输入学生的成绩:\n");
scanf("%d",&score);
//判断输入的成绩是否符合格式
if(score>=0 || score<=100 ){
//进行分类
switch(score/10){
case 10://简洁代码,使用case击穿
case 9:
printf("A\n");
break;
case 8:
printf("B\n");
break;
case 7:
printf("C\n");
break;
case 6:
printf("D\n");
break;
default:
printf("E\n");
break;
}
}else{
printf("输入错误\n");
}
return 0;
}
11.编写一个程序。a=3,b=5,对a和b的值进行交换。 (北京君正集成电路)
解答:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, const char *argv[])
{
int a=3;
int b=5;
int temp=0;
//方法1
//三杯水交换法
temp = a;
a=b;
b=temp;
printf("%d %d\n",a,b);
//方法2
//三次异或实现两个变量的交换
a=3;
b=5;
a=a^b;
b=a^b;
a=a^b;
printf("%d %d\n",a,b);
//方法3
//这种方法不安全,可能会出现数据越界
a=3;
b=5;
a=a+b;
b=a-b;
a=a-b;
printf("%d %d\n",a,b);
return 0;
}
12.编写一个程序。实现输入一个三位数,判断是否是水仙花数。
水仙花数——各个位立方之和等于本身。
eg: 1*1*1 + 5*5*5 + 3*3*3 = 153,所以153是水仙花数
153由1个100 5个10 3个1
个位 = num%10
十位 = num/10%10
百位 = num/100%10
解答:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, const char *argv[])
{
int num=0;
printf("请输入一个数\n");
//获取数字
scanf("%d",&num);
int g=0;
int s=0;
int b=0;
//计算个位、十位、百位
g=num%10;
s=num%100/10;
b=num/100;
//判断是否是水仙花数
if(g*g*g + s*s*s + b*b*b == num){
printf("%d 是水仙花数\n",num);
}else{
printf("%d 不是水仙花数\n",num);
}
return 0;
}
13.编写一个程序。实现输入一个年份,判断是不是闰年。
解答:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, const char *argv[])
{
int year=0;
printf("请输入一个年份:");
//获取年份
scanf("%d",&year);
//按照要求进行判断
if(year%4==0 && year%100!=0){
printf("这是闰年\n");
}else if(year%400==0){
printf("这是闰年\n");
}else{
printf("这是平年");
}
return 0;
}
14.编写一个程序。请实现以下功能:(威海精讯畅通)
15.输入三个数,分别为年、月、日,输出此日是该年的第几天。
输入:
XXX XXX XXX
输出:
此日是该年的第XXX 天
示例:
输入 2020 2 20
程序输出 此日是该年的第51 天
解答:
#include <stdio.h>
//输入一个日期,输出当前日期是这一年的第几天
#define MONTH_1 31
#define MONTH_2 28
#define MONTH_3 31
#define MONTH_4 30
#define MONTH_5 31
#define MONTH_6 30
#define MONTH_7 31
#define MONTH_8 31
#define MONTH_9 30
#define MONTH_10 31
#define MONTH_11 30
#define MONTH_12 31
int main()
{
int year, month, day;
printf("请输入要查询的日期(年/月/日):");
scanf("%d/%d/%d", &year, &month, &day);
//闰年的增量 也是闰年的标志位 0 平年 1 闰年
int leap = 0;
//printf("%d/%d/%d\n", year, month, day);
//判断输入的日期是否有误
//判断年是闰年还是平年
if(((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0)){
leap = 1;
}
//判断月份输入的是否有误
if(month < 1 || month > 12){
printf("您输入的月份有误,请重新输入\n");
//在main函数里面使用return,结束整个程序
return -1;
}
//判断日是否有误
//月份:1 3 5 7 8 10 12 最多31天
if(month==1 || month==3 || month==5 || month==7 || month==8 || month==10 || month==12){
if(day < 1 || day > 31){
printf("您输入的日期有误,请重新输入\n");
return -1;
}
}
//月份:4 6 9 11 最多30天
if(month==4 || month==6 || month==9 || month==11){
if(day < 1 || day > 30){
printf("您输入的日期有误,请重新输入\n");
return -1;
}
}
//月份:2 闰年最多29天 平年最多28天
if(month == 2){
if(leap == 1){ //闰年
if(day < 1 || day > 29){
printf("您输入的日期有误,请重新输入\n");
return -1;
}
}else if(leap == 0){ //平年
if(day < 1 || day > 28){
printf("您输入的日期有误,请重新输入\n");
return -1;
}
}
}
int days = 0;
switch(month){
case 12:
days += MONTH_11;
case 11:
days += MONTH_10;
case 10:
days += MONTH_9;
case 9:
days += MONTH_8;
case 8:
days += MONTH_7;
case 7:
days += MONTH_6;
case 6:
days += MONTH_5;
case 5:
days += MONTH_4;
case 4:
days += MONTH_3;
case 3:
days += MONTH_2 + leap;
case 2:
days += MONTH_1;
case 1:
days += day;
break;
}
printf("%d年%d月%d日%d年的第%d天\n", year, month, day, year, days);
return 0;
}
16.编写一个程序。输入三角形的 三个边长 判断能否构成三角形,如果能,输出能构成三角形,再输出是什么三角形
等边 [a==b && a==c && b==c]
等腰 [a==b || a==c || b==c]
直角(勾股定理)[a*a+b*b==c*c || a*a+c*c==b*b || b*b+c*c==a*a]
普通
如果不能
输出不能构成三角形
解答:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, const char *argv[])
{
int a=0;
int b=0;
int c=0;
printf("请输入三角形的三边长:\n");
scanf("%d%d%d",&a , &b ,&c);
//判断能否构成三角形
if(a+b>c && b+c>a && a+c>b){
//判断是否是等边三角形
if(a==b && b==c && c==a){
printf("这是一个等边三角形\n");
//判断是否是等腰三角形
}else if(a==b || b==c || c==a){
printf("这是一个等腰三角\n");
//判断是否是直角三角形
}else if(a*a+b*b==c*c ||c*c+b*b==a*a ||a*a+c*c==b*c){
printf("这是一个直角三角形\n");
}else{
printf("这是一个普通三角形\n");
}
}else{
printf("不能构成三角形\n");
}
return 0;
}
17.编写一个程序。有 4 个变量 a,b,c,d,我们提前并不知道他们的值,请用你的方式将他们从大到小排序。算法任意。(山东丁一)
解答:
#include <stdio.h>
int main() {
int a, b, c, d;
// 输入四个变量的值
printf("请输入四个整数 (a, b, c, d): ");
scanf("%d %d %d %d", &a, &b, &c, &d);
// 使用冒泡排序将四个变量从大到小排序
if (a < b) { int temp = a; a = b; b = temp; }
if (a < c) { int temp = a; a = c; c = temp; }
if (a < d) { int temp = a; a = d; d = temp; }
if (b < c) { int temp = b; b = c; c = temp; }
if (b < d) { int temp = b; b = d; d = temp; }
if (c < d) { int temp = c; c = d; d = temp; }
// 输出排序后的结果
printf("从大到小排序结果: %d %d %d %d\n", a, b, c, d);
-------------------------------------------------------------------------
int a, b, c, d;
// 输入四个变量的值
printf("请输入四个整数 (a, b, c, d): ");
scanf("%d %d %d %d", &a, &b, &c, &d);
int arr[4] = {a, b, c, d};
// 插入排序,从大到小
for (int i = 1; i < 4; i++) {
int key = arr[i];
int j = i - 1;
while (j >= 0 && arr[j] < key) {
arr[j + 1] = arr[j];
j = j - 1;
}
arr[j + 1] = key;
}
// 输出排序后的结果
printf("从大到小排序结果: %d %d %d %d\n", arr[0], arr[1], arr[2], arr[3]);
return 0;
}
三、总结
在实际编程中,需要仔细选择合适的输入输出函数。例如,在处理单字符输入时,getchar()
较为简单高效;而在处理字符串输入时,尽量避免使用gets()
,而采用更安全的fgets()
。
在使用printf()
和scanf()
时,需要特别注意格式控制符与数据类型的匹配,否则可能导致输出错误或读取失败。同时,对于scanf()
,需要考虑到用户输入可能不符合预期格式的情况,并做好相应的错误处理。
针对输入函数,处理多字符或字符串时,应考虑输入缓冲区的清理问题,避免残留字符影响后续输入。
在使用if-else
结构时,需要注意表达式的逻辑正确性和代码的可读性。特别是在复杂条件下,可能需要将逻辑拆分成多个if
语句来提高可读性。
对于switch-case
结构,需要特别注意break
语句的使用,以防止意外的“贯穿”执行。同时,尽量使用default
分支来处理所有未匹配的情况,以提高代码的健壮性。
选择if-else
或switch-case
时,应根据具体情况选择最适合的结构。if-else
更灵活,适用于复杂的条件判断,而switch-case
在处理简单多分支时更为简洁。
注意事项:
继续深入理解输入输出函数的各种边界情况和可能引发的问题,例如缓冲区溢出、输入缓冲区残留等。在使用选择结构时,关注代码的可读性和效率,特别是在复杂条件下,确保逻辑的正确性。加强对格式化输入输出的练习,尤其是对复杂格式字符串的掌握,确保能够灵活运用printf
和scanf
处理各种数据类型和格式。在学习和实践中,多关注C语言中的标准库函数,理解它们的优缺点,并养成使用安全、高效函数的良好编程习惯。