Linux和C语言(Day04)

一、学习内容

  1. 三种输入输出函数

    1. putchar()/getchar() 单字符

      1. putchar()
        1. 头文件:#include <stdio.h>

        2. 函数原型:int putchar(int c); //参数 int c; 说明可以接收整型/单字符型

        3. 功能:输出一个字符

      2. getchar()
        1. 功能:获取一个字符

        2. 头文件:#include <stdio.h>

        3. 函数原型:int getchar(void); //参数是void 说明没有参数

    2. puts()/gets() 字符串

      1. puts()
        1. 功能:输出字符串,自带换行

        2. 头文件:#include <stdio.h>

        3. 函数原型:int puts(const char *s); //参数const char *s;——字符串的首地址

      2. gets()
        1. 功能:获取一个字符串

        2. 头文件:#include <stdio.h>

        3. 函数原型:char *gets(char *s);

    3. printf()/scanf() 格式化

      1. printf()
        1. 功能:格式化输出内容

        2. 头文件:#include <stdio.h>

        3. 函数原型:int printf(const char *format, ...); //参数... 表示不定项

        4. printf("原样输出内容+格式控制符" , 参数1 , 参数2 , 参数3 , ……);

      2. scanf()
        1. 功能:输入,回车表示结束

        2. 头文件:#include <stdio.h>

        3. 函数原型:int scanf(const char *format, ...);

        4. scanf("原样输入内容+格式控制符" , 地址1 , 地址2 , 地址3 ……);

        5. 注意:格式控制符只能是类型:%d %i %c %s %f

  2. 选择结构

    1. 三大结构

      1. 顺序结构——按照书写顺序依次执行,不允许跳过任何一条语句

      2. 选择结构——根据条件判断是否成立,执行不同的语句段【if语句 switch语句】

      3. 循环结构——重复结构,反复的执行某一部分代码

    2. if语句

      1. 结构:
      2. 注意事项
        1. ①if(表达式) 表达式可以是任意合法表达式 eg:if(1) if(0) if(1+2) if(3.5) if('A') if(-1) if(a>b) if(a&&b) 结果只有两种,真【非0值】 和 假【0】

        2. ②if(表达式){} 若执行语句只有一条,{}可以省略;若有多条,不可以省略。建议不省略 eg: if(score>=670) printf("欢迎入学北大\n");

        3. ③else 先有if才有else,else和它前面的未被匹配的if进行配对 eg: if(1) printf("ok"); else printf("no"); //正确,输出ok if(1); printf("ok"); else printf("no"); //错误,输出ok

        4. ④ if(n=8) 和 if(n==8) 这两条语句不一样,一个=表示赋值,两个=表示判断相等 因为这两个语句C程序无法检测到错误,所以再进行判断两数相等的时候,我们强烈建议这样写 if(8 == n)

    3. switch语句

      1. switch(表达式)
        { case 常量表达式: 执行语句; break; case 常量表达式: 执行语句; break; case 常量表达式: 执行语句; break; case 常量表达式: 执行语句; break; …… default: 执行语句; break; }
      2. 注意事项
        1. switch(表达式),表达式可以是任意合法表达式,但是结果只能是整型或单字符型

        2. 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]

        3. break表示中断结束,在switch语句表示跳出switch语句 可加可不加,不加继续往下执行,知道遇见break或者switch结束为止

        4. default表示缺省值,可有可无,建议加上,保证程序的健壮性——对于非法数据做出合适的处理 不符合所有case的情况,执行default

        5. case 和 default的顺序可以任意调换【电梯按键任意排列】

        6. case后的常量表达式不能有重复值 case 3: 和 case 1+2: 不能在同一个switch语句中

        7. 多个case可以执行同一条语句

  3. 脑图

二、作业

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-elseswitch-case时,应根据具体情况选择最适合的结构。if-else更灵活,适用于复杂的条件判断,而switch-case在处理简单多分支时更为简洁。
 

注意事项:

继续深入理解输入输出函数的各种边界情况和可能引发的问题,例如缓冲区溢出、输入缓冲区残留等。在使用选择结构时,关注代码的可读性和效率,特别是在复杂条件下,确保逻辑的正确性。加强对格式化输入输出的练习,尤其是对复杂格式字符串的掌握,确保能够灵活运用printfscanf处理各种数据类型和格式。在学习和实践中,多关注C语言中的标准库函数,理解它们的优缺点,并养成使用安全、高效函数的良好编程习惯。

Linux中,`cal`是一个内建的命令行工具,用于显示日历。虽然它的核心是用C语言实现的,但作为系统的一部分,直接查看源码并不常见,因为这些通常由操作系统内核维护,且不公开。然而,如果你想了解如何编写一个简单的C语言日历程序,我可以给你提供一个基础的示例。 这是一个简单的C程序,使用了`ncurses`库(一个用于终端界面的库)来模拟一个基本的日历: ```c #include <stdio.h> #include <ncurses.h> #define MONTHS 12 #define DAY_OF_WEEK 7 void draw_month(int year, int month) { initscr(); // 初始化ncurses环境 cbreak(); // 使输入非阻塞 noecho(); // 隐藏用户输入 curs_set(0); // 关闭光标 int days_in_month[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; int current_day = 1; int row = 1; for (int i = 0; i < DAY_OF_WEEK; ++i) { mvprintw(row++, 0, "%2d ", i + 1); } int days_left = DAY_OF_WEEK - 1; for (int day = 1; day <= days_in_month[month-1]; ++day) { if (current_day == 1 && month == 2 && is_leap_year(year)) { days_in_month[month-1]++; } if (days_left > 0) { mvprintw(row++, 0, "%2d ", current_day++); --days_left; } else { for (int j = 0; j < DAY_OF_WEEK - 1; ++j) { mvprintw(row++, 1 + j * 3, " "); } mvprintw(row++, 1, "%2d ", current_day++); days_left = DAY_OF_WEEK - 1; } } getch(); // 等待用户按键 endwin(); } bool is_leap_year(int year) { return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0); } int main() { int year, month; printf("Enter year and month: "); scanf("%d %d", &year, &month); draw_month(year, month); return 0; }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值