当前位置: 首页 > news >正文

PTA C语言程序设计 第三章

Q3-2

if语句的简写

C中单行语句省略大括号:如果 if 条件后只有一条语句,可以省略 {}

if (a > b) printf("a is greater\n");

对比完整写法:

if (a > b) {
    printf("a is greater\n");
}

C中三元运算符替代简单 if-else:对于简单的条件赋值,可以使用 ?: 三元运算符

int max = (a > b) ? a : b;  //如果 a>b,则 max=a,否则 max=b

 对比完整写法:

int max;
if (a > b)
    max = a;
else
    max = b;

类似的,Python中提供了更简洁的条件表达式(类似C的三元运算符)

max = a if a > b else b  #等价于C的 (a > b) ? a : b

对比完整写法:

if a > b:
    max = a
else:
    max = b

注意:Python不像C那样用 {} 分隔代码块,而是靠缩进,因此单行 if 不推荐滥用。

for语句的简写

C中单行省略大括号(只能是单行情况下)

for (int i = 0; i < 5; i++) printf("%d\n", i);

对比完整写法:

for (int i = 0; i < 5; i++) {
    printf("%d\n", i);
}

初始化和增量合并:某些情况下可利用逗号运算符将多个初始化或增量合并。

for (int i = 0, j = 10; i < 5; i++, j--) printf("%d %d\n", i, j);
//这会同时操作 i 和 j。

类似的Python的for循环本身没有像C那样的三段式结构,但可通过列表推导式实现类似简写效果:

[print(i) for i in range(5)]

对比完整写法:

for i in range(5):
    print(i)

多变量循环(类似C的逗号运算符效果): 

[print(i, j) for i, j in zip(range(5), range(10, 5, -1))]

这里 zip函数将两个序列配对,达到类似C中 i++, j-- 的效果

区别两种if语句

if…if…if…(多个独立条件)

特点:每个 if语句是独立的,互不影响。程序会逐一检查所有条件,即使前一个条件为真,后续条件依然会被测试。
执行逻辑:可能有多个条件同时成立,导致多个代码块都被执行。

int a = 10;
if (a > 5) printf("a > 5\n");      // 执行
if (a > 0) printf("a > 0\n");      // 执行
if (a == 10) printf("a == 10\n");  // 执行

/*输出:
a > 5
a > 0
a == 10
*/

适用场景:当需要检查多个独立条件,且这些条件之间没有排斥关系时使用。

if…else if…else if…(条件分支)

特点:条件是互斥的,一旦某个条件成立,后续条件将不再检查。整个结构只执行一个分支。
执行逻辑:从上到下检查条件,找到第一个为真的条件后跳出,执行对应代码块。

int a = 10;
if (a > 15) printf("a > 15\n");         // 不执行
else if (a > 5) printf("a > 5\n");      // 执行,然后跳出
else if (a > 0) printf("a > 0\n");      // 不执行
else printf("a <= 0\n");                // 不执行

/*输出:
a > 5
*/

适用场景:当条件是互斥的,且只需要执行一个分支时使用
关键区别:

1.执行次数:
if…if…if…:可能执行多个代码块。
if…else if…else if…:只执行一个代码块。
2.逻辑关系:
if…if…if…:条件之间无依赖,各自独立。
if…else if…else if…:条件之间有先后顺序,后续条件只有在前面的条件不成立时才会被检查。
3.性能影响:
if…if…if…:所有条件都会被测试,可能更耗时。
if…else if…else if…:找到第一个成立的条件后跳出,效率更高。

类似的,Python中逻辑相同,只是用 elif 替代 else if:

a = 10
if a > 5: print("a > 5")      # 执行
if a > 0: print("a > 0")      # 执行
if a == 10: print("a == 10")  # 执行
a = 10
if a > 15: print("a > 15")
elif a > 5: print("a > 5")    # 执行,然后跳出
elif a > 0: print("a > 0")
else: print("a <= 0")

Q3-3

double和int类型转换

C语言中,当定义了double average、int sum 和 int N,然后执行 average = sum / N; 时,结果取决于 sum 和 N 的类型以及除法运算的行为。
1. sum / N的结果:
因为 sum 和 N 都是 int 类型,sum / N 会执行整数除法。整数除法会直接丢弃小数部分,只保留整数部分。
如果 sum = 5,N = 2,那么 sum / N 的结果是 2(而不是 2.5),因为小数部分被截断了。
如果 sum = 7,N = 3,结果是 2(而不是 2.333...)。
然后,这个整数结果(比如 2)被赋值给 average,由于 average 是 double 类型,它会自动转换为浮点数,变成 2.0,而不是精确的小数值(如 2.5 或 2.333...)。
2. 如何得到精确到小数点的数值?
为了让 average 得到带有小数部分的精确结果,需在除法运算中确保至少有一个操作数是浮点数类型(float 或 double)。C语言中,只有当操作数中有浮点数时,除法才会执行浮点除法,保留小数部分。
方法一:将其中一个数乘以 1.0,即 average = sum * 1.0 / N;
这里的 1.0 是 double 类型,sum * 1.0 的结果会自动转换为 double,然后再除以 N(N 会被隐式转换为 double),结果就是浮点数。
例如:sum = 5,N = 2,average = 5 * 1.0 / 2; 的结果是 2.5。
方法二:直接转换为 double,即 average = (double)sum / N;
通过强制类型转换 (double),sum 被转换为 double,除法变成浮点除法,结果也是精确的浮点数。
例如:sum = 7,N = 3,average = (double)sum / N; 的结果是 2.333...。
3. 什么情况下必须用 *1.0 或强制转换?
当需要保留小数部分的精确结果时,必须确保除法是浮点除法。如果两个操作数都是整数,C语言默认执行整数除法,小数部分会丢失。
4. 注意运算顺序
如果写成 average = sum / N * 1.0;,结果仍然是错的,因为 sum / N 先执行整数除法,得到整数后再乘以 1.0,小数部分已经丢失。
例如:sum = 5,N = 2,5 / 2 * 1.0 是 2 * 1.0 = 2.0,而不是 2.5。
正确的写法是 sum * 1.0 / N 或 (double)sum / N。

Python中的区别:Python的类型处理更动态和灵活。average = sum / N类似的操作在Python中的表现:

1.Python的除法:
/ 运算符默认执行浮点除法,无论操作数是整数还是浮点数,结果都会是浮点数(float 类型),保留小数部分。

sum = 5
N = 2
average = sum / N
print(average)  # 输出: 2.5

sum = 7
N = 3
average = sum / N
print(average)  # 输出: 2.3333333333333335

因此,Python中不需要像C语言那样手动乘以 1.0 或强制转换为浮点类型,/ 天然就会返回精确的浮点结果。 

2.Python中的整数除法:
如果想要像C语言那样的整数除法(丢弃小数部分),需要使用 // 运算符。// 返回的结果是整数(int 类型),小数部分被截断。

sum = 5
N = 2
average = sum // N
print(average)  # 输出: 2

总结:Python不需要类似 *1.0 的操作。Python的 / 已经默认处理为浮点除法。即使两个操作数都是整数,结果也会是 float 类型。如果明确想要浮点数结果,直接用 / 就行;如果想要整数结果,则用 //。

3.C 和 Python 的强制类型转换格式区别:
C语言的强制类型转换
格式:(目标类型)表达式
示例:(double)sum 将 sum 从 int 转换为 double。
机制:C是静态类型语言,变量的类型在声明时固定,强制类型转换是告诉编译器在运算时将某个值按指定类型处理。

int sum = 5;
int N = 2;
double average = (double)sum / N;  // 强制转换为 double,结果是 2.5

特点:显式转换,必须手动指定,适用于需要改变运算行为的情况(如整数除法转浮点除法)。

Python的强制类型转换
格式:目标类型(表达式)
示例:float(sum) 将 sum 转换为浮点数。
机制:Python 是动态类型语言,变量类型可以随时改变,强制类型转换是通过内置函数完成的,结果会生成一个新对象。

sum = 5
N = 2
average = float(sum) / N  # 结果是 2.5

特点:Python 不需要在除法中强制转换,因为 / 默认返回 float。类型转换通常用于其他场景,比如将字符串转为整数(int("123"))或将整数转为浮点数(float(5))。

特性C语言Python
语法(type)expressiontype(expression)
类型系统静态类型,需显式转换动态类型,灵活自动调整
除法行为/ 是整数除法(int/int)/ 是浮点除法,// 是整数除法
转换时机编译时处理类型运行时生成新对象
典型用途改变运算结果类型数据类型转换(如输入处理)

Q3-4

判断字符是否为数字或字母或空白字符的方法

方法一:C语言中,可以使用标准库 <ctype.h> 中的函数来判断字符的性质,类似于Python的 isdigit() 和 isalpha()等。以下是常用的函数:

判断是否为数字:isdigit(int c)
检查字符是否是数字('0' 到 '9')。
参数是字符的ASCII码(传入 int 类型),返回非零值(真)表示是数字,0(假)表示不是。

#include <ctype.h>
#include <stdio.h>

int main() {
    char ch = '5';
    if (isdigit(ch)) {
        printf("%c 是数字\n", ch);  // 输出: 5 是数字
    }
    return 0;
}

判断是否为字母:isalpha(int c)
检查字符是否是字母('a' 到 'z' 或 'A' 到 'Z')。
返回非零值(真)表示是字母,0(假)表示不是。

#include <ctype.h>
#include <stdio.h>

int main() {
    char ch = 'A';
    if (isalpha(ch)) {
        printf("%c 是字母\n", ch);  // 输出: A 是字母
    }
    return 0;
}

检查是否为空白字符:isspace(int c)
空白字符包括:空格 ' ', 制表符 '\t', 换行符 '\n', 回车符 '\r', 垂直制表符 '\v', 换页符 '\f'。
返回非零(真)表示是空白字符,0(假)表示不是。 

与Python的区别:

Python的 isdigit() 和 isalpha() 是字符串方法,直接作用于整个字符串对象(如 "123".isdigit()),要求其中所有字符都满足条件。返回 True(全满足)或 False(不满足或空字符串)

print("123".isdigit())   # True
print("12a3".isdigit())  # False
print("abc".isalpha())   # True
print("ab1c".isalpha())  # False
print("".isdigit())      # False

C的 isdigit() 和 isalpha() 是函数,作用于单个字符,输入参数是 int 类型,通常传入字符的 ASCII 值(通过 char 隐式转换),返回整数(非零或 0)。

如果想在C中模仿Python检查整个字符串,需要遍历字符串并对每个字符调用这些函数。

//检查字符串是否全为数字

#include <ctype.h>
#include <string.h>
#include <stdio.h>

int is_all_digits(const char *str) {
    if (str == NULL || *str == '\0') {  // 空字符串或空指针返回 0
        return 0;
    }
    while (*str) {
        if (!isdigit((unsigned char)*str)) {  // 如果有一个不是数字
            return 0;
        }
        str++;
    }
    return 1;  // 全是数字
}

int main() {
    printf("%d\n", is_all_digits("123"));   // 输出: 1
    printf("%d\n", is_all_digits("12a3"));  // 输出: 0
    printf("%d\n", is_all_digits(""));      // 输出: 0
    return 0;
}
//检查字符串是否全为字母

#include <ctype.h>
#include <string.h>
#include <stdio.h>

int is_all_alpha(const char *str) {
    if (str == NULL || *str == '\0') {  // 空字符串或空指针返回 0
        return 0;
    }
    while (*str) {
        if (!isalpha((unsigned char)*str)) {  // 如果有一个不是字母
            return 0;
        }
        str++;
    }
    return 1;  // 全是字母
}

int main() {
    printf("%d\n", is_all_alpha("abc"));   // 输出: 1
    printf("%d\n", is_all_alpha("ab1c"));  // 输出: 0
    printf("%d\n", is_all_alpha(""));      // 输出: 0
    return 0;
}
//判断字符串是否全为空白字符

#include <ctype.h>
#include <string.h>
#include <stdio.h>

int is_all_space(const char *str) {
    if (str == NULL || *str == '\0') {  // 空指针或空字符串返回 0
        return 0;
    }
    while (*str) {  // 遍历字符串
        if (!isspace((unsigned char)*str)) {  // 如果有一个字符不是空白
            return 0;
        }
        str++;
    }
    return 1;  // 所有字符都是空白,返回 1
}

int main() {
    printf("%d\n", is_all_space(" "));      // 输出: 1(全是空格)
    printf("%d\n", is_all_space("\t\n"));   // 输出: 1(制表符和换行)
    printf("%d\n", is_all_space("a"));      // 输出: 0(包含非空白)
    printf("%d\n", is_all_space(""));       // 输出: 0(空字符串)
    printf("%d\n", is_all_space("  a"));    // 输出: 0(包含非空白)
    return 0;
}

方法二:直接判断

int letter = 0, blank = 0, digit = 0, other = 0;
char ch;
for(i=0;i<=9;i++){
    ch=getchar();
    if((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z'))letter++;
    else if((ch==' ')||(ch=='\n'))blank++;
    else if(ch>='0'&&ch<='9')digit++;
}
printf("letter = %d, blank = %d, digit = %d,",letter,blank,digit);

getchar()函数

getchar(void):读取输入的字符,并返回它的ASCII值(类型为int)。失败时或到达文件末尾时(End Of File),返回 EOF(通常是 -1)

特点:读取的是仅单个字符,包括空白字符(如空格、换行符 \n、回车符 \r)。
类似scanf(),程序会暂停,等待用户输入并按回车键。
返回类型是 int 而不是 char,是为了区分正常字符和 EOF

#include <stdio.h>

int main() {
    int ch;
    printf("请输入一个字符: ");
    ch = getchar();  // 读取用户输入的字符
    printf("你输入了: %c\n", ch);  // 输出字符
    return 0;
}

/*运行:
输入:a 并按回车
输出:你输入了: a。
*/
getchar() 会读取回车键(\n),如果只想读取有效字符,需要额外处理换行符。
#include <stdio.h>

int main() {
    int ch;
    printf("请输入一个字符: ");
    ch = getchar();       // 读取字符
    while (getchar() != '\n');  // 清除输入缓冲区中的换行符
    printf("你输入了: %c\n", ch);
    return 0;
}

流程:

1.输入提示:
printf("请输入一个字符: "); 输出提示,等待用户输入。
2.用户输入:
比如输入了123 45 6,然后按下回车键(\n)。
输入的内容会被存储在标准输入缓冲区中。此时缓冲区内容是:

'1' '2' '3' ' ' '4' '5' ' ' '6' '\n'。
3.第一次 getchar():
ch = getchar(); 从缓冲区读取第一个字符 '1',并将其 ASCII 值(49)赋值给 ch。
此时缓冲区剩余:'2' '3' ' ' '4' '5' ' ' '6' '\n'。
4.循环 while (getchar() != '\n');:
这个循环的目的是清空输入缓冲区,直到遇到换行符 \n。
每次循环调用 getchar(),读取缓冲区中的下一个字符,并丢弃它(没有存储)。
对于 123 45 6:读取 '2'、'3'、' '、'4'、'5'、' '、'6',最后读取 \n,循环结束。
结果:缓冲区被清空,其他字符被“吃掉”但未使用。
5.输出:
printf("你输入了: %c\n", ch); 只打印 ch 的值,也就是第一次 getchar() 读取的 '1'。
所以输出是:你输入了: 1。
这个循环的设计初衷是清除输入缓冲区的换行符(\n),以防下一次再输入字符想让程序读取时,却读到的是上次的未清除的换行符(\n)。但它会把从第一个字符之后的所有内容都清掉,直到遇到 \n,因此一次输入有效的也仅有第一个字符。

如果想读取并输出所有输入的字符,可以有以下几种方法:

//方法1:逐个读取并输出

#include <stdio.h>

int main() {
    int ch;
    printf("请输入字符(按回车结束): ");
    while ((ch = getchar()) != '\n' && ch != EOF) {  // 读取直到换行或 EOF
        printf("你输入了: %c\n", ch);  // 每次读取一个字符就输出
    }
    return 0;
}

/*
输入:123 45 6 + 回车。
输出:
你输入了: 1
你输入了: 2
你输入了: 3
你输入了:  
你输入了: 4
你输入了: 5
你输入了:  
你输入了: 6
说明:每次读取一个字符并立即输出,直到遇到换行符。
*/
//方法2:保存到数组再输出

#include <stdio.h>

int main() {
    char buffer[100];  // 假设最多输入 100 个字符
    int i = 0;
    printf("请输入字符(按回车结束): ");
    int ch;
    while ((ch = getchar()) != '\n' && ch != EOF) {
        buffer[i++] = ch;  // 保存每个字符到数组
    }
    buffer[i] = '\0';  // 添加字符串结束符
    printf("你输入了: %s\n", buffer);  // 输出整个字符串
    return 0;
}

/*
输入:123 45 6 + 回车。
输出:你输入了: 123 45 6
说明:将输入存入字符数组,最后以字符串形式输出。
*/
//方法3:逐个回显(类似回显程序)

#include <stdio.h>

int main() {
    int ch;
    printf("请输入字符(按回车结束): ");
    while ((ch = getchar()) != '\n' && ch != EOF) {
        putchar(ch);  // 读取并立即输出
    }
    putchar('\n');  // 换行
    return 0;
}

/*
输入:123 45 6 + 回车。
输出:123 45 6(直接回显)。
说明:使用 putchar() 实时显示输入。
*/

Python中,如果用 input(),默认读取整行:

text = input("请输入字符: ")  # 输入 "123 45 6"
print(f"你输入了: {text}")    # 输出 "你输入了: 123 45 6"

Python的 input() 不像C的 getchar() 那样逐字符读取,而是直接获取整行字符串。

区别 getchar() 和 scanf():

getchar():
只读取一个字符,包括空白字符(如空格 ' '、换行符 \n、制表符 \t)。
不跳过任何输入,直接从缓冲区取下一个字符。

int ch1 = getchar();  // 输入 "a b",ch1 = 'a'
int ch2 = getchar();  // ch2 = ' '
int ch3 = getchar();  // ch3 = 'b'

scanf()根据格式说明符读取:
%c:读取一个字符(包括空白字符)。
%d、%f 等:读取数字,自动跳过前导空白字符(空格、换行等)。
%s:读取字符串,跳过前导空白,直到遇到空白字符停止。 

char ch;
scanf("%c", &ch);  // 输入 "a b",ch = 'a'
scanf("%c", &ch);  // ch = ' '(不会跳过空格)
int num;
scanf("%d", &num); // 输入 "  123",num = 123(跳过前导空白)

可见scanf()同样容易在缓冲区残留换行符或其他未读取的部分

char ch;
scanf("%c", &ch);  // 输入 "a\n",ch = 'a'
scanf("%c", &ch);  // ch = '\n'(残留的换行符,需手动清理)

putchar()函数

putchar(int c):将一个字符输出

参数:一个 int 类型的值,表示要输出的字符的 ASCII 码。
返回值:返回输出的字符(以 int 形式)。失败时返回 EOF(通常是 -1)。
特点:只输出单个字符。参数虽然是 int,但通常传入 char 类型的值(会自动转换为 int)。

#include <stdio.h>

int main() {
    putchar('A');  // 输出字符 A
    putchar('\n'); // 输出换行符
    return 0;
}

//运行:屏幕显示 A 并换行。
结合使用 getchar() 和 putchar()
#include <stdio.h>

int main() {
    int ch;
    printf("请输入字符(按 Ctrl+D 或 Ctrl+Z 结束):\n");
    while ((ch = getchar()) != EOF) {  // 读取直到 EOF
        putchar(ch);  // 回显输入的字符
    }
    return 0;
}

/*运行:
输入 hello 并按回车,屏幕显示 hello 并换行。
按 Ctrl+D(Unix)或 Ctrl+Z(Windows)结束输入。*/

 这个程序将输入的每个字符立即输出,类似于简单的回显功能。

字符类型

Python中的字符类型

Python没有单独的字符类型,字符是长度为 1 的字符串(str 类型)。
例如:'a' 是字符串,"a" 也是字符串,没有像 C 那样的 char 类型。
存储:Python使用 Unicode 编码,字符可以是任何语言的字符(如中文、表情符号),而不是仅限于 ASCII。

C中的字符类型

C有显式的字符类型 char,它实际上是一个整数类型,通常占 1 字节(8 位)。
char 的值范围通常是 -128 到 127(有符号)或 0 到 255(无符号,取决于编译器)。
字符(如 'a')在内存中存储为对应的 ASCII 码(例如 'a' 是 97)。
与整数的关系:因为 char 也是整数类型,可以直接与整数运算。

char ch = 'a';  // ASCII 值为 97
int num = ch;   // num = 97
ch = ch + 1;    // ch 变成 'b' (ASCII 98)

存储:C默认使用 ASCII 编码(1 字节),支持范围有限。

Python中转换为字符类型

目标:将变量转换为长度为 1 的字符串(即字符)。
方法:使用 chr() 函数,将整数(通常是 Unicode 码点)转换为字符。

# 整数转字符
num = 97
ch = chr(num)
print(ch)  # 输出: a

# 其他类型转字符(先转整数)
float_num = 65.0
ch = chr(int(float_num))
print(ch)  # 输出: A

特点:
Python不区分字符和字符串,chr() 返回的是字符串。
输入必须是整数(Unicode 码点),否则需要先转换(如 int())

C中转换为字符类型

目标:将变量转换为 char 类型。
方法:1.整数转字符:直接赋值或强制转换,整数会被截取为 1 字节。

int num = 97;
char ch = (char)num;  // ch = 'a' (ASCII 97)
printf("%c\n", ch);   // 输出: a

2.其他类型转字符:先转换为整数,再赋值给 char

double num = 65.7;
char ch = (char)num;  // 截取整数部分,ch = 'A' (ASCII 65)
printf("%c\n", ch);   // 输出: A

3.字符串转字符:取字符串中的某个字符(C 中字符串是 char 数组)

char str[] = "hello";
char ch = str[0];     // ch = 'h'
printf("%c\n", ch);   // 输出: h

特点:
C 中 char 是整数类型,转换时会截取低 8 位。
强制转换 (char) 是显式指定类型。

示例对比

整数转字符:
Python: ch = chr(97) → 'a'
C: char ch = (char)97; → 'a'
浮点数转字符:
Python: ch = chr(int(65.7)) → 'A'
C: char ch = (char)65.7; → 'A'

python中不区分字符和字符串,那str()和chr()有什么区别

Python没有像C那样的独立 char 类型。在C中,char 是一个单独的类型(1 字节整数),而字符串是 char 数组。
在Python中,无论是单个字符(如 'a')还是多个字符(如 "hello"),它们的类型都是 str(字符串类型)。Python 用统一的 str 类型表示所有字符序列。

ch = 'a'       # 单个字符
s = "hello"    # 多个字符
print(type(ch))  # 输出: <class 'str'>
print(type(s))   # 输出: <class 'str'>

从类型上看,'a' 和 "hello" 都是 str,区别仅在于长度(len('a') == 1,len("hello") == 5)。这与C 不同,C中 'a' 是 char,"hello" 是 char[]。

所以,Python 中没有“字符类型”这个独立概念,字符只是长度为 1 的字符串

尽管Python用 str 表示所有字符串(包括单个字符),str() 和 chr() 是两个不同的工具,它们的功能和用途完全不同:

str():通用类型转换为字符串

是什么:str() 是一个内置函数(也是 str 类的构造器),用于将任意对象转换为其字符串表示形式。对应C中的 (char)
输入:可以是任何类型(整数、浮点数、列表、对象等)。
输出:一个 str 类型的对象,内容是输入对象的“可读表示”(通常由对象的 __str__() 方法定义)。
特点:输出的字符串长度不固定,取决于输入

print(str(123))    # 输出: "123"(整数转为字符串)
print(str(3.14))   # 输出: "3.14"(浮点数转为字符串)
print(str([1, 2])) # 输出: "[1, 2]"(列表转为字符串)

chr():整数码点转为单个字符

是什么:chr() 是一个内置函数,专门将一个整数(Unicode 码点)转换为对应的单个字符。
输入:必须是一个整数(范围通常是 0 到 1114111,Unicode 的有效码点)。
输出:一个长度为 1 的 str 对象,表示该码点对应的字符。
特点:输出的字符串始终是单个字符

print(chr(97))     # 输出: "a"(Unicode 97 是字符 a)
print(chr(65))     # 输出: "A"(Unicode 65 是字符 A)
print(chr(20013))  # 输出: "中"(Unicode 20013 是汉字“中”)

总结: 

str() 把输入对象“描述”为字符串,结果可能是多字符。
chr() 把输入整数“映射”为单个字符,结果永远是长度为 1 的字符串。

num = 97
print(str(num))  # 输出: "97"(数字 97 的字符串表示)
print(chr(num))  # 输出: "a"(Unicode 97 对应的字符)
print(len(str(num)))  # 输出: 2("97" 有 2 个字符)
print(len(chr(num)))  # 输出: 1("a" 有 1 个字符)

Q3-7

switch case语句

switch (表达式) {
    case 值1:
        // 当表达式的值等于值1时执行的代码
        break;
    case 值2:
        // 当表达式的值等于值2时执行的代码
        break;
    case 值3:
        // 当表达式的值等于值3时执行的代码
        break;
    default:
        // 当表达式的值不匹配任何 case 时执行的代码
}

switch (表达式):表达式是一个需要判断的值,通常是整数、字符或枚举类型。
case 值:表示表达式的可能取值,后面跟冒号 :。
break:用于跳出 switch 语句,避免后续 case 继续执行(如果没有 break,会发生“贯穿”现象)。
default:可选的默认分支,当表达式不匹配任何 case 时执行,类似于 if-else 中的 else。

工作原理:

1.计算 switch 后面的表达式的值。
2.将该值与每个 case 后面的值进行比较。
3.如果匹配某个 case,则从该 case 开始执行代码,直到遇到 break 或 switch 语句结束。
4.如果没有匹配的 case,则执行 default 块(如果存在)。

//示例1:简单数字判断

#include <stdio.h>

int main() {
    int day = 3;
    switch (day) {
        case 1:
            printf("星期一\n");
            break;
        case 2:
            printf("星期二\n");
            break;
        case 3:
            printf("星期三\n");
            break;
        default:
            printf("无效的日期\n");
    }
    return 0;
}

//输出:星期三
//day 的值是 3,匹配 case 3,执行对应代码并因 break 跳出。

//示例3:没有break的情况

#include <stdio.h>

int main() {
    int num = 2;
    switch (num) {
        case 1:
            printf("这是 1\n");
        case 2:
            printf("这是 2\n");
        case 3:
            printf("这是 3\n");
        default:
            printf("默认\n");
    }
    return 0;
}

/*输出:
这是 2
这是 3
默认

因为没有 break,从 case 2 开始,后续所有代码都会执行,这种行为称为“贯穿”。*/

注意事项:

1.表达式的类型限制:
C/C++:只能是整数类型(int、char 等)或枚举类型。
Java:支持整数类型、枚举类型和字符串(String)。
JavaScript:支持几乎所有类型,包括字符串和对象(通过严格相等 === 判断)。
2.case 值必须是常量:case 后的值必须是编译时已知的常量表达式,不能是变量。
例如:case i:(i 是变量)是非法的。
3.break 的重要性:如果遗漏 break,会导致代码从匹配的 case 开始一直执行到 switch 结束,除非有意利用贯穿现象。
4.default 的位置:default 不一定放在最后,即使放在中间,也只有在没有匹配 case 时才会执行。但习惯上放在最后更清晰。

高级用法:

//多值匹配(贯穿应用)
//可以用多个 case 叠加来处理相同逻辑:

#include <stdio.h>

int main() {
    char ch = 'a';
    switch (ch) {
        case 'a':
        case 'e':
        case 'i':
        case 'o':
        case 'u':
            printf("这是一个元音\n");
            break;
        default:
            printf("这不是元音\n");
    }
    return 0;
}

//输出:这是一个元音

与 if-else 的比较:

优点:代码更简洁,尤其当条件是单一变量的多个值时。
缺点:只能处理离散值(等于某个值),不能处理范围或复杂条件(如 x > 5)。如果分支逻辑复杂,if-else 更灵活。

常见问题:

可以省略 default 吗?
可以,但建议保留,用于处理意外情况,提高代码健壮性。
case 值可以重复吗?
不可以,重复的 case 会导致编译错误。
switch 可以用在浮点数上吗?
在大多数语言(如 C/C++、Java)中不行,因为浮点数比较不精确。

E3-1

比较三数大小并排序

#include <stdio.h>

void swap(int *a, int *b) {
    int temp = *a;
    *a = *b;
    *b = temp;
}

int main() {
    int a = 5, b = 2, c = 8;

    // 三步排序
    if (a > b) swap(&a, &b); // 确保 a <= b
    if (b > c) swap(&b, &c); // 确保 b <= c
    if (a > b) swap(&a, &b); // 再次确保 a <= b

    printf("排序后的结果: %d %d %d\n", a, b, c);
    return 0;
}
//不用函数的写法

#include <stdio.h>

int main() {
    int a = 5, b = 2, c = 8;
    int temp;

    if (a > b) { temp = a; a = b; b = temp; }
    if (b > c) { temp = b; b = c; c = temp; }
    if (a > b) { temp = a; a = b; b = temp; }

    printf("排序后的结果: %d %d %d\n", a, b, c);
    return 0;
}

E3-3

输入输出中浮点数的占位符

printf 中:

float 的占位符:%f
默认情况下,%f 会显示浮点数的小数点后6位。

可以用 .n 指定小数点后的位数,例如 %.2f 表示保留2位小数

double 的占位符:%lf 或 %f
printf 中double 默认也可以使用 %f,因为 float 会被自动提升为 double。

scanf 中:

float 的占位符:%f
用于读取单精度浮点数。

double 的占位符:%lf
用于读取双精度浮点数。
总结:1.在 scanf 中,float 和 double 的占位符是严格区分的,必须正确使用 %f 和 %lf,否则可能导致读取错误。
2.在 printf 中,%f 对 float 和 double 都适用,但为了代码可读性,推荐对 double 使用 %lf。

输入输出中的小问题(对Q2-12补充)

在 printf 的格式化输出中,%.nf 表示将浮点数显示为指定的小数点后 n 位。具体的截断方式是四舍五入后再截断,而不是直接截断后面的小数。

#include <stdio.h>

int main() {
    float f1 = 3.14159;
    float f2 = 3.14659;
    printf("%.2f\n", f1);  // 输出: 3.14
    printf("%.2f\n", f2);  // 输出: 3.15
    return 0;
}

在 scanf 中,%nf(例如 %5f)的含义不是保留几位小数,而是指定输入字段的最大宽度,即最多读取 n 个字符(包括小数点和数字)。它表示从输入流中读取的浮点数的最大字符数,而不是控制小数点后的位数。

#include <stdio.h>

int main() {
    float f;
    scanf("%5f", &f);  // 最多读取 5 个字符
    printf("%f\n", f);
    return 0;
}

/*
输入:123.456
%5f 只读取前 5 个字符 123.4,结果 f = 123.4。
输入:12.34
%5f 读取完整输入 12.34,结果 f = 12.34。
输入:123456.78
%5f 只读取 12345,结果 f = 12345.0(因为超过 5 个字符,后面的被忽略)。
*/

注意:1.%nf 中的 n 是宽度限制,而不是小数位数限制。
2.如果输入的字符数少于 n,scanf 会读取整个数字,直到遇到非数字字符(如空格、换行)。
3.如果需要控制小数位数,scanf 本身无法直接做到,需要在读取后再通过代码处理。

相关文章:

  • linux Redhat9.5采用DNS主从实现跨网段解析
  • 批量删除 PPT 中的所有图片、某张指定图片或者所有二维码图片
  • 【Java】——方法的使用(从入门到进阶)
  • deepseek使用记录99——为何追问
  • nginx 配置ip黑白名单
  • Docker 内部通信(网络)
  • 基于MySQL的创建<resultMap>和查询条件<if test>
  • zookeepernacoskafka之间的联系
  • Linux系统上后门程序的原理细节,请仔细解释一下
  • 【GeeRPC】项目总结:使用 Golang 实现 RPC 框架
  • PostgreSQL:语言基础与数据库操作
  • Cloudlog系统接口 search_log未授权存在SQL注入漏洞代码审计(DVB-2025-8964)
  • 大数据 ETL 异常值缺失值处理完整方案
  • 美团-测开
  • git tag常用操作
  • gem rbenv介绍【前端扫盲】
  • 泰勒多项式
  • 星越L_第二排座椅/头枕使用讲解
  • ABAQUS球体颗粒重力堆积3D模型
  • Spring 中的 AOP 实现机制
  • 四姑娘山一游客疑因高反身亡,镇卫生院:送到时已很严重
  • 5.19中国旅游日,上海56家景区景点限时门票半价
  • 雷军:过去一个多月是创办小米以来最艰难的时间
  • 国博馆刊|北朝至唐初夏州酋豪李氏家族的发展与身份记忆
  • 读图|展现城市品格,上海城市影像走进南美
  • 教育部、国家发改委联合启动实施教师教育能力提升工程