2.6 优先级与结合性
优先级与结合性
运算符的优先级与结合性的知识点,在前面的课程中记录过……
notes
简述
优先级与结合性:2.2 的笔记中记录的内容,涵盖了大部分 2.6 中老师在视频中介绍的点。
了解一下运算符分级原则
理解自动类型转换和强制类型转换
作业 | x = 3 + 5 * 2 / (4 - 1)
根据运算符的优先级与结合性,分析计算的详细步骤
=
优先级最低,最后计算=
是右结合的,先计算=
右边表达式的值3 + 5 * 2 / (4 - 1)
()
优先级最高,最先计算3 + 5 * 2 / 3
*
/
优先级高,先计算;由于5 * 2 / 3
中的*
和/
是同级的,此时它们的执行顺序得看结合性,它们都是左结合的,即左边先计算3 + 10 / 3
3 + 3
- 执行加法运算
6
- 经过计算,得到表达式右边的结果为 6,最后执行赋值语句
x = 6
运算符的优先级与结合性
引用:有关 C 语言中的运算符优先级和结合性的部分知识点在这篇文档(2.2 C 语言的符号)中。
运算符的分级原则
自动类型转换
#include <stdio.h>
int main() {
int a = 10;
float b = 3.14;
// 整型和浮点型进行运算,会自动将整型转为浮点型
float c = a + b;
printf("c = %f\n", c); // 输出结果
return 0;
}
/* 运行结果:
c = 13.140000
*/
在这个示例代码中,我们定义了一个 int 类型的变量 a 和一个 float 类型的变量 b。接着我们将 a 和 b 相加并将结果赋值给一个 float 类型的变量 c。在这个计算过程中,由于 整型和浮点型进行运算,编译器会自动将 a 转换为浮点型,然后再进行计算,最后将结果赋给 c。
#include <stdio.h>
int main() {
int a = 5;
float b = 73.2;
char c = 'a';
// 将 a 赋值给 b,自动进行类型转换
b = a;
// 将 b 赋值给 a,自动进行类型转换
a = b;
// 将 c 赋值给 a,自动进行类型转换
a = c;
printf("a 的值为:%d\n", a);
printf("b 的值为:%.2f\n", b);
printf("c 的值为:%c\n", c);
return 0;
}
/* 运行结果:
a 的值为:97
b 的值为:5.00
c 的值为:a
*/
- 将 a 赋值给 b,由于 b 是浮点型变量,因此 a 会自动转换成浮点型再赋值给 b。
- 将 b 赋值给 a,由于 a 是整型变量,因此 b 会自动转换成整型再赋值给 a。(精度丢失)
- 将 c 赋值给 a,由于 a 是整型变量,因此 c 会自动转换成整型再赋值给 a。
在自动类型转换中,C 语言会按照一定的规则进行类型转换,如 将小类型自动转换成大类型,或将无符号类型转换成有符号类型。在这个过程中,我们不需要手动进行强制类型转换,C 语言会 自动完成。
#include <stdio.h>
int main() {
double a = 3.14;
int b;
// double 类型转为 int 类型
b = a;
printf("b 的值为:%d\n", b); // 输出 b 的值
return 0;
}
/* 运行结果:
b 的值为:3
*/
因为 double 变量 a 的值是 3.14,自动转换为 int 类型时只保留了整数部分 3,因此变量 b 的值为 3。自动类型转换可能会导致数据 精度的损失,从而影响程序的正确性,因此在编写程序时应谨慎使用自动类型转换。
- 自动类型转换是指:有些运算符在操作不同类型的数据时会自动进行类型转换
- 自动类型转换也称:隐式类型转换
- 自动类型转换会根据 C 语言中的一定规则进行
自动类型转换的常见规则:
- 如果两个操作数的类型不同,C 语言会将它们都转换为同一种类型,然后再进行运算。类型转换的顺序一般为
char -> short -> int -> unsigned int -> long -> unsigned long -> float -> double -> long double
- 如果将浮点数赋值给整型变量,C 语言会将浮点数的小数部分截断,只保留整数部分,然后再进行赋值操作。
- 如果将整型值赋值给浮点型变量,C 语言会自动将整型值转换为浮点型。
- 如果将 char 类型的值赋值给整型变量,C 语言会自动将 char 类型的值转换为整型。
- 如果将浮点数和整型数进行运算,C 语言会自动将整型数转换为浮点数。
- 如果将两个不同类型的指针相减,C 语言会将两个指针转换为相同的整型数,然后再进行相减操作。
注意:
- 类型范围:在自动类型转换时,需要确保转换后的类型可以容纳转换前的类型,否则可能会导致数据精度丢失或者溢出的情况。
- 安全:取值范围 小 的赋值给取值范围 大 的
- 不安全:取值范围 大 的赋值给取值范围 小 的
- 若大类型的值在小类型能容纳的范围之内,则平安无事
- 但是浮点数转为整数,会丢弃小数部分,而非四舍五入
- 精度问题:在将 float 或 double 类型自动转换为 int 类型时,可能会出现精度丢失的问题,因此需要进行舍入操作。在进行浮点数和整数的混合运算时,也需要注意类型转换的问题,否则也可能会出现精度丢失的情况。
- 语法规范:在进行自动类型转换时,需要遵循 C 语言的语法规范,否则会出现编译错误。例如,不能将字符类型自动转换为指针类型。
强制类型转换
#include <stdio.h>
int main() {
int a = 10;
float b = 3.14;
int c = (int)(a / b); // 强制将 a / b 的结果转换为整型
float d = a / b;
printf("(int)(a / b) 的结果为:%d\n", c);
printf("a / b 的结果为:%.2f\n", d);
return 0;
}
/* 运行结果:
(int)(a / b) 的结果为:3
a / b 的结果为:3.18
*/
在上述代码中,使用了强制类型转换 (int) 将浮点数除以整数得到的结果转换为整型,并将结果存储在变量 c 中。
注意:
- 在进行强制类型转换时,可能会出现精度丢失的情况。
- 在使用强制类型转换时,应该尽量避免精度丢失的情况,并在必要的情况下对结果进行四舍五入或其他处理。
#include <stdio.h>
int main() {
int x = 10;
float y;
double z;
y = float(x);
z = double(x);
printf("x:%d sizeof(x):%lu\n", x, sizeof(x));
printf("y:%.2f sizeof(y):%lu\n", y, sizeof(y));
printf("z:%.2f sizeof(z):%lu\n", z, sizeof(z));
return 0;
}
/* 运行结果:
x:10 sizeof(x):4
y:10.00 sizeof(y):4
z:10.00 sizeof(z):8
*/
2.7 输入与输出
输入与输出
输入与输出例子
notes
简述
- 2.7.1:输入输出这一部分,细节比较多,不过在本节视频的结尾,有提到一个小 demo,先将 demo 掌握好再说。具体的知识点细节,暂且先不要刻意去记。
- 2.7.2:本节介绍了一个小 demo —— 如何输出二进制的数据。打印二进制数据,在 2.5.4 扫地机器人 中有类似的 demo,可以结合在一起对比着看。
- 掌握 4 个输入、输出函数 printf、putchar、scanf、getchar
数据的输入与输出
在 C 语言中,可以使用标准输入输出库中的函数来实现数据的输入和输出:
- 输入函数包括 scanf() 和 getchar()
- 输出函数包括 printf() 和 putchar()
printf
- printf 是 C 语言中一个非常常用的函数
- 函数原型:
int printf(const char *format, ...);
- 作用:将格式化的数据输出到标准输出或指定文件中
- 参数:
- 第一个参数 format 是格式化字符串,用于指定输出的格式
- 后面的参数为可选参数,用于填充格式化字符串中的占位符
- 返回值:除了格式化字符串和可选参数,printf 函数还有一个返回值,表示输出的字符数。如果出现错误,则返回负数。
- 格式化字符串:以 % 开头的字符表示占位符,具体形式:
%[flags][width][.precision][length]specifier
flags、width、.precision、length 和 specifier 都是格式化参数,用于指定输出格式 - 常用的格式化参数:
- %d、%i:用于输出十进制整数。
- %f:用于输出浮点数。
- %s:用于输出字符串。
- %c:用于输出字符。
- %p:用于输出指针的地址。
- %u:用于输出无符号整数。
- %o:用于输出八进制整数。
- %x、%X:用于输出十六进制整数。
- %e、%E:用于输出科学计数法表示的浮点数。
- %g、%G:用于输出浮点数,具体格式取决于数值的大小。
- 在占位符中,各个格式化参数之间可以用
.
-
+
#
0
等字符作为标志,用于进一步指定输出格式。
#include <stdio.h>
int main() {
// 1. 字段宽度
int i = 123;
printf("[%6d]\n", i); // => [ 123]
printf("[%06d]\n", i); // => [000123]
// 2. 负号
float x = 1234.567;
printf("[%9.3f]\n", x); // => [ 1234.567]
printf("[%-9.3f]\n", x); // => [1234.567 ]
// 3. 字符*
printf("[%*d]\n", 5, i); // => [ 123]
int w = 6;
printf("[%*d]\n", w, i); // => [ 123]
printf("[%-*.*f]\n", 7, 2, x); // => [1234.57]
return 0;
}
#include <stdio.h>
int main() {
// 使用转义字符控制输出格式
int m = 3, n = 12;
printf("num1 = %d \t num2 = %d\n", m, n); // => num1 = 3 num2 = 12
// 打印百分号
printf("%f%%\n", 95.6); // => 95.600000%
return 0;
}
putchar
- putchar 是 C 标准库中的一个输出函数
- 其定义在 stdio.h 头文件中
- 函数原型:
int putchar(int c);
- 参数:c 表示要输出的字符
- 作用:向标准输出流(通常是屏幕)输出一个字符
- 返回值:输出的字符的 ASCII 码值
- putchar 只能输出一个字符,如果需要输出字符串,需要使用其他函数,例如 puts 和 printf 等
Q:为什么参数是 int 类型?
因为 char 可能被编译器默认为 signed char 或 unsigned char,当输出一些比较大的字符时可能会发生截断
#include <stdio.h>
int main() {
putchar('A');
putchar(97);
putchar(65);
char c = '!';
putchar(c);
return 0;
}
// AaA!
scanf
- scanf() 是 C 语言中的一个输入函数,用于从标准输入(键盘)或文件中读取数据,并将读取到的数据按照指定的格式保存到指定的变量中。
- scanf 函数原型:
int scanf(const char *format, ...);
- 作用:scanf() 函数会按照指定的格式从标准输入中读取数据,并将其保存到对应的变量中。
- 参数:
- 第一个参数 format 表示读取数据的格式,是一个字符串,其可以包含转换说明符(%d、%f 等)
- 从第二个参数开始,依次是要保存读取到的数据的变量名
- 返回值:
- 如果读取成功,scanf() 函数会返回成功读取的数据个数
- 如果发生错误,scanf() 函数会返回 EOF(-1)
- 读取数据时,需要输入与指定格式相符的数据,否则会发生错误。
- scanf() 函数在读取数据时会自动忽略空格、换行符等空白字符,但在格式字符串中使用空白字符时会强制要求输入中出现空白字符,否则会读取失败。
- scanf() 函数不能读取超过指定长度的字符串,否则会发生缓冲区溢出。
- scanf() 函数读取的数据类型必须与指定格式相符,否则会发生数据类型不匹配的错误。
- scanf() 函数读取数据时遇到非法字符会停止读取,并将其放回输入流中,需要使用 getchar() 函数将其读取并丢弃。
#include <stdio.h>
int main() {
int i, j;
scanf("%d%d", &i, &j);
printf("i = %d\tj = %d\n", i, j);
scanf("%*d%d", &i, &j); // => warning: data argument not used by format string [-Wformat-extra-args]
// scanf("%*d%d", &i);
printf("i = %d\tj = %d\n", i, j);
return 0;
}
警告分析:warning: data argument not used by format string [-Wformat-extra-args]
scanf("%*d%d", &i, &j);
等效写法 scanf("%*d%d", &i);
这个警告就是在提示我们,我们写得 &j
多余了,在输入时会跳过它
#include <stdio.h>
int main() {
int i, j;
char ch;
scanf("%d%d%c", &i, &j, &ch);
printf("i = %d\tj = %d\tch = %c\n", i, j, ch);
return 0;
}
#include <stdio.h>
int main() {
int i, j;
char ch;
scanf("%d%d %c", &i, &j, &ch);
printf("i = %d\tj = %d\tch = %c\n", i, j, ch);
return 0;
}
#include <stdio.h>
int main() {
int i, j;
char ch;
scanf("%d,%d,%c", &i, &j, &ch);
printf("i = %d\tj = %d\tch = %c\n", i, j, ch);
return 0;
}
getchar
- getchar 是 C 语言中的一个输入函数
- 原型:
int getchar(void);
- 作用:从标准输入(通常是键盘)读取一个字符并返回
- 返回值:getchar 函数读取用户在标准输入设备上输入的字符,然后将字符转换为整数形式返回,即返回其 ASCII 码值(int 类型)
- getchar 函数会将输入的字符缓存起来,如果程序中有多次使用 getchar 函数,缓存中的字符将依次被读取
- 如果读取的字符是回车符 \n,那么表示一行的输入结束,getchar 函数将读取并返回回车符
- 如果读取的字符是文件结束符 EOF(End Of File,即 Ctrl+Z 或 Ctrl+D),那么表示输入结束,getchar 函数将返回 EOF,该值是一个负整数
#include <stdio.h>
int main() {
char c;
c = getchar();
putchar(c);
c = 007;
putchar(c);
putchar(007);
return 0;
}
#include <stdio.h>
int main() {
char c;
int c1, c2;
c = getchar();
c1 = c - 1; c2 = c + 1;
printf("%c\t%c\t%c\n", c1, c, c2);
printf("%d\t%d\t%d\n", c1, c, c2);
return 0;
}
/* 运行结果:
B
A B C
65 66 67 */
将整数以二进制形式输出
#include <stdio.h>
/**
* @brief 将 unsigned char 类型的数据以二进制形式输出
* @param c 待输出的 unsigned char 类型的数据
*/
void print_bin(unsigned char c) {
printf("c: %d\n", c); // 输出待输出数据的十进制表示
printf("对应的二进制: ");
for (int i = 7; i >= 0; i--) {
printf("%d", (c >> i) & 1); // 输出待输出数据的二进制表示
}
}
int main() {
char x = 0b01101111; // 定义一个二进制数值
// 调用打印二进制函数,将 x 的二进制表示输出到控制台
print_bin(x);
return 0;
}
/* 运行结果:
c: 111
对应的二进制: 01101111 */
解释:
上述代码定义了一个名为 print_bin 的函数,该函数将传入的 unsigned char 类型的数据以二进制形式输出到控制台。该函数使用了一个 for 循环,从二进制表示的最高位开始逐位输出,每次输出一个二进制位。
在 main 函数中,定义了一个 char 类型的变量 x,使用二进制表示的方式初始化为 0b01101111。然后调用 print_bin 函数,将 x 的二进制表示输出到控制台。
输入一个十进制数,输出这个数的八进制、十六进制、二进制
#include <stdio.h>
int main() {
int num;
printf("请输入一个十进制整数(小于 256):");
scanf("%d", &num);
printf("%d 转换成二进制是 ", num);
// 将十进制数转换为二进制并打印
for (int i = 7; i >= 0; i--) {
int bit = (num >> i) & 1;
putchar(bit + '0');
}
printf("\n");
printf("%d 转换成八进制是 0%o\n", num, num); // 打印八进制数
printf("%d 转换成十六进制是 0x%x\n", num, num); // 打印十六进制数
return 0;
}
/* 运行结果:
请输入一个十进制整数(小于 256):195
195 转换成二进制是 11000011
195 转换成八进制是 0303
195 转换成十六进制是 0xc3*/
putchar(bit + '0');
参数 bit + ‘0’ 表示将二进制数位 0 或 1 转换成对应的字符 ‘0’ 或 ‘1’,然后使用 putchar() 输出这个字符。由于字符 ‘0’ 的 ASCII 码值为 48,因此加上 0 就能得到对应的字符。例如,当 bit 等于 1 时,表达式 bit + ‘0’ 的值就是 49(即字符 ‘1’ 的 ASCII 码值)。putchar() 函数将其输出到屏幕上,即输出 ‘1’。
2.8 编程实战
温度转换
廉租房
输入与输出
notes
简述
- 2.8.1:独立完成“温度转换”的小 demo
- 2.8.2:独立完成“廉租房”的小 demo
- 2.8.3:通过写一个两整数求和的小 demo,思考 4 个问题,理解输入、输出。
温度转换
#include <stdio.h>
int main() {
float fahrenheit, celsius;
printf("请输入华氏温度:");
scanf("%f", &fahrenheit);
// 利用公式将华氏温度转换为摄氏温度
celsius = (fahrenheit - 32) * 5 / 9;
printf("对应的摄氏温度为:%.2f\n", celsius);
return 0;
}
/* 运行结果:
请输入华氏温度:100
对应的摄氏温度为:37.78 */
廉租房
#include <stdio.h>
int main() {
float father_income, mother_income, ming_income, total_income;
float normal_rent, cheap_rent;
float normal_rent_yearly, cheap_rent_yearly;
float yearly_saving;
// 输入爸爸、妈妈和小明的年收入
printf("请输入爸爸的年收入:");
scanf("%f", &father_income);
printf("请输入妈妈的年收入:");
scanf("%f", &mother_income);
printf("请输入小明的年收入:");
scanf("%f", &ming_income);
// 计算小明家庭总年收入
total_income = father_income + mother_income + ming_income;
// 判断小明家庭年收入是否少于6万
if (total_income < 60000) {
printf("小明家庭年收入为 %.2f 元,符合廉租房要求\n", total_income);
} else {
printf("小明家庭年收入为 %.2f 元,不符合廉租房要求\n", total_income);
}
// 输入普通房租和廉租房租金
printf("请输入普通房租每月的租金:");
scanf("%f", &normal_rent);
printf("请输入廉租房每月的租金:");
scanf("%f", &cheap_rent);
// 计算普通房和廉租房每年的租金
normal_rent_yearly = normal_rent * 12;
cheap_rent_yearly = cheap_rent * 12;
// 计算小明家庭每年除房租外还剩余的钱
yearly_saving = total_income - cheap_rent_yearly;
// 输出小明家庭每年除房租外还剩余的钱
printf("小明家庭每年除房租外还剩余 %.2f 元\n", yearly_saving);
return 0;
}
/* 运行结果:
请输入爸爸的年收入:35000
请输入妈妈的年收入:15000
请输入小明的年收入:0
小明家庭年收入为 50000.00 元,符合廉租房要求
请输入普通房租每月的租金:1000
请输入廉租房每月的租金:300
小明家庭每年除房租外还剩余 46400.00 元 */
输入与输出
#include <stdio.h>
int main() {
int x, y, sum;
printf("请输入两个整数:\n");
scanf("%d%d", &x, &y);
sum = x + y;
printf("x + y = %d\n", sum);
return 0;
}
/* 运行结果:
请输入两个整数:
3 5
x + y = 8 */
问题 1:测试实际运行过程中,用空格,回车符号,逗号分隔输入的 2 个整数分别输出什么?
问题 2:如果要求用回车分隔输入的 2 个数据,scanf(“%d\n%d\n” ,&x,&y); 这种格式正确吗?为什么? 不正确
原因:
在格式控制字符串 "%d\n%d\n"
中
- 第一个
%d
可以读取输入流中的一个整数,但紧跟其后的\n
将导致 scanf 函数在读取第一个整数后就停止读取,并将剩余的回车符留在输入流中。 - 第二个
%d
将无法读取正确的输入值,而是读取了上一个输入行中留下的回车符。因此,程序的输出结果会异常。
修改:
如果要使用回车符作为输入值之间的分隔符,可以使用格式控制字符串:scanf("%d\n%d", &x, &y);
- 第一个
%d
会读取一个整数,并在读取完整数后立即舍弃掉之前输入流中的所有空格和回车符 - 接着的
\n
可以保证 scanf 函数正确识别输入值之间的回车符,并将其从输入流中清除 - 最后的
%d
将读取第二个整数,输入值之间不需要额外的空格或回车符
问题 3:如果要求输入符号 +,也就是输入 3 + 5,输出 3 + 5 = 8,怎么写程序?
#include <stdio.h>
int main() {
int x, y, sum;
char op;
printf("请输入两个整数和一个符号(如3+5):\n");
scanf("%d%c%d", &x, &op, &y);
if (op == '+') {
sum = x + y;
printf("%d%c%d=%d\n", x, op, y, sum);
} else {
printf("输入有误!\n");
}
return 0;
}
问题 4:scanf_s 对字符类型数据有没有什么特殊要求? scanf_s 对字符类型数据的输入没有特殊要求,可以像输入其他类型数据一样使用。
但是为了避免安全漏洞,建议使用带有长度限制的格式字符串。
例如:对于输入字符类型的数据,可以使用 %s 指定格式字符串,同时在后面指定字符串长度,如 %7s,表示最多读取 7 个字符。
这样可以防止输入字符长度超过了所分配的空间大小,导致缓冲区溢出,从而引发安全问题。
2.9 小结
小结
notes
简述
视频中主要提及了 12 个问题,作为本章节的自测题,如果都能够理解,那么本章的知识点掌握得就 OK 了。
PPT | 自测题列表
回答以下 12 个问题:
问题 1:字符型数据的最大值和最小值分别是多少?
#include <stdio.h>
#include <limits.h>
void print_binary(unsigned char c) {
for (int i = 7; i >= 0; i--) {
printf("%d", (c >> i) & 1);
if (i % 4 == 0) printf(" ");
}
}
int main() {
printf("有符号字符型的最小值是:%d,二进制形式为:", SCHAR_MIN);
print_binary(SCHAR_MIN);
printf("\n有符号字符型的最大值是:%d,二进制形式为:", SCHAR_MAX);
print_binary(SCHAR_MAX);
printf("\n无符号字符型的最小值是:%d,二进制形式为:", 0);
print_binary(0);
printf("\n无符号字符型的最大值是:%d,二进制形式为:", UCHAR_MAX);
print_binary(UCHAR_MAX);
printf("\n");
return 0;
}
/* 运行结果:
有符号字符型的最小值是:-128,二进制形式为:1000 0000
有符号字符型的最大值是:127,二进制形式为:0111 1111
无符号字符型的最小值是:0,二进制形式为:0000 0000
无符号字符型的最大值是:255,二进制形式为:1111 1111
*/
有符号的二进制 1000 0000
转为 10 进制:
有符号的二进制数 1000 0000 在补码表示法下表示的是 -128,因为符号位为1表示负数,其余位取反加1得到其对应的十进制值为:1000 0000 => - 0111 1111 + 1 => - 1000 0000
有符号的二进制 0111 1111
转为 10 进制:
根据最高位为 0 表示正数,最高位为 1 表示负数的规则,该二进制数为正数,因此直接将二进制数转换为十进制数即可。
问题 2:2 字节的无符号整数的最大值是多少?
二进制表示:1111 1111 1111 1111
公式:
因为无符号整数的范围是从 0
开始,所以最终还需要 -1
补充:<limits.h>
中的 USHRT_MAX
存放的就是 2 字节的无符号整数的最大值。
#include <stdio.h>
#include <limits.h>
int main() {
unsigned short max = USHRT_MAX;
printf("2字节无符号整数的最大值是:%hu\n", max);
return 0;
}
/* 运行结果:
2字节无符号整数的最大值是:65535
*/
问题 3:'X'
和 "X"
的区别?
‘X’ 和 “X” 的区别在于:’X’ 是一个字符类型,而 “X” 是一个字符串类型
'X'
是一个 字符常量,只包含一个字符'X'
"X"
是一个 字符串常量,实际上是由两个字符'X'
和'\0'
(字符串结束符)组成的 字符数组
注意:
- 单引号 括起来的是 字符常量
- 双引号 括起来的是 字符串常量
问题 4:'0'
和 '\0'
相等吗?
不相等
原因分析:
'0'
表示数字 0 的 ASCII 码值48
'\0'
表示 字符串的结束符,其值为0
,所以 ‘\0’ 在字符串中非常重要
#include <stdio.h>
int main() {
printf("'0':%d\n", '0');
printf("'\\0':%d\n", '\0');
printf("NULL:%ld\n", NULL);
return 0;
}
/* 运行结果:
'0':48
'\0':0
NULL:0
*/
注意:
- 字符串以
NULL
或者'\0'
结尾
问题 5:SIZEOF(“COMPUTER”) 的值为多少?
SIZEOF("COMPUTER")
的值为 9
- 其中包括 8 个字符和一个字符串结束符
'\0'
- 当我们计算字符串长度的时候,需要将结尾的
NULL
或者'\0'
符给减掉
#include <stdio.h>
#include <string.h>
int main() {
char str[] = "COMPUTER";
printf("1. 使用 strlen 获取到字符串 \"COMPUTER\" 的长度是:%lu\n", strlen(str));
printf("2. 使用 sizeof 计算字符串 \"COMPUTER\" 的长度是:%lu\n", sizeof(str) / sizeof(char) - 1);
return 0;
}
/* 运行结果:
1. 使用 strlen 获取到字符串 "COMPUTER" 的长度是:8
2. 使用 sizeof 计算字符串 "COMPUTER" 的长度是:8
*/
strlen
函数返回字符串的实际长度,不包括 字符串末尾的NULL
字符sizeof
函数返回字符串占用的空间大小,包括 字符串末尾的NULL
字符,因此计算结果sizeof(str) / sizeof(char)
还需要- 1
问题 6:INT I = 33 / 4;
请问 I 的值为多少?
I 的值为 8
公式:
因为 33 除以 4 等于 8 余 1,而在 C 语言中 整数除法会向下取整,所以 I 的值为 8
问题 7:==
和 =
的区别?
==
是比较运算符,用于比较两个值是否相等;=
是赋值运算符,用于将右边的值赋给左边的变量;
问题 8:&&
和 &
的区别?||
和 |
的区别?
逻辑运算、位运算
&&
和||
是 逻辑运算符,它们用于将多个逻辑表达式组合在一起,得出一个新的逻辑值。&
和|
是 位运算符,它们用于将多个二进制位组合在一起,得出一个新的二进制值。
逻辑运算:
&&
表示逻辑与,当且仅当所有逻辑表达式都为真时,结果为真||
表示逻辑或,当且仅当至少有一个逻辑表达式为真时,结果为真- 存在短路现象:当某个逻辑表达式已经能够决定最终结果时,后面的表达式就不再执行。
位运算:
&
表示按位与,对应位都为 1 时,结果为 1|
表示按位或,对应位都为 0 时,结果为 0- 无短路现象:它们会对所有的位进行运算,不会像逻辑运算符那样出现短路现象。
问题 9:位运算能对浮点型和双精度型变量操作吗?
不能
位运算只适用于整型数据类型,不能对浮点型和双精度型变量进行位运算操作。
因为浮点型和双精度型变量是按照 IEEE 754 标准存储的,其中包含符号位、指数和尾数等部分,而不是简单的二进制表示。
问题 10:数据类型转换,能否改变变量的数据类型和值?
这个问题的描述是有些许问题的,意思应该是在问: 如果在程序运行过程中,发生了类型转换(自动类型转换、强制类型转换),那么变量的类型和变量的值是否会发生变化。
变量类型转换 不会 改变变量的数据类型和变量的值。
变量的数据类型不可能变:
C 语言是一门强类型的语言,强类型意味着在 C 语言中,变量的类型是严格定义的,一旦定义就不能更改。每个变量都有其特定的数据类型,而且只能存储相应类型的数据。
变量没有被重新赋值,所以变量的值也没有变化。
虽然从结果来看,变量的值“貌似”变化了,但是这是在程序执行过程中做的处理,相当于已经把数据从那块地址(空间)中拿出来了,然后改变了数据的值,这过程中并没有直接修改那块地址中存放的内容。
浮点强制转整型,精度丢失,变量的数据变了吗? 精度丢失是指在进行数据类型转换时,一些信息的丢失,从而导致转换后的值不再和原值相等,但这并 不意味着变量的值被改变了。
例如,当将一个 float 类型的变量赋值给一个 int 类型的变量时,由于 int 类型的变量无法保存 float 类型的小数部分,所以小数部分将被截断丢失,转换后的值会变成一个整数,但原来的 float 类型变量的值并没有被改变,只是赋值给了一个不同类型的变量,所以数据类型转换只是改变变量的数据类型,而不是改变变量的值。
#include <stdio.h>
int main() {
float x = 3.14159;
int y = (int) x; // 将 x 转换为 int 类型,并将结果存储在 y 中
printf("x = %f\n", x);
printf("y = %d\n", y);
return 0;
}
/* 运行结果:
x = 3.141590
y = 3
*/
在一些特殊的情况下,如对 float 或 double 类型的变量进行简单的四则运算时,由于浮点数在计算机内部的存储方式和十进制表示方式有所不同,可能会出现一些意料之外的结果,但这并不意味着变量的值被改变了,而只是计算的结果不够准确。
建议 11:多用 ()
运算符
对于那些我们想要让它优先运算的部分,使用 ()
小括号将它们给括起来即可。
#include <stdio.h>
int main() {
int a = 2, b = 3, c = 4;
int result1 = a + b * c;
int result2 = (a + b) * c;
printf("result1 = %d\n", result1);
printf("result2 = %d\n", result2);
return 0;
}
/* 运行结果:
result1 = 14
result2 = 20
*/
a + b * c;
默认先乘除、后加减,所以默认会先计算 b * c,然后再加上 a
(a + b) * c;
如果我们想要让 a + b 先运算,只要加上小括号即可,这样就是先运算 a + b,然后再乘 c
问题 12:找出下述程序中的错误
#include <stdio.h>
int main() {
int idata1;
const char cdata1 = '0';
unsigned char idata1;
scanf("%d%c%f", idata1, &cdata1); // ,值是不可变的,
return 0;
}
int idata1;``unsigned char idata1;
重复声明同名变量 idata1scanf("%d%c%f", idata1, &cdata1);
idata1 前边少了一个取地址符&
const char cdata1 = '0';
、scanf("%d%c%f", idata1, &cdata1);
cdata1 是一个常量,常量在程序运行过程中是不可修改的,所以无法直接将 scanf 读入的数据重新赋值给一个常量。
#include <stdio.h>
int main() {
int idata1;
const char cdata1 = '0';
unsigned char idata2;
scanf("%d%c", &idata1, &idata2);
printf("idata1 = %d\n", idata1);
printf("cdata1 = %c\n", cdata1);
printf("idata2 = %d\n", idata2);
return 0;
}
/* 运行结果:
1A
idata1 = 1
cdata1 = 0
idata2 = 65
*/
2.10 华为 cloudIDE 开发编程
- 题目:温度转换(前面学习过程中已写过)
- 介绍华为 CloudIDE 的使用(先直接跳过)
本章有一个温度转换的 demo 练手。不过这东西在之前就已经练过了,快速过一遍就好。
#include <stdio.h>
int main() {
int celsius, fahrenheit;
printf("请输入摄氏温度:");
scanf("%d", &celsius);
fahrenheit = 9 * celsius / 5 + 32;
printf("华氏温度为:%d\n", fahrenheit);
return 0;
}
/* 运行结果:
用例 1:
请输入摄氏温度:10
华氏温度为:50
用例 2:
请输入摄氏温度:100
华氏温度为:212
用例 3:
请输入摄氏温度:-10
华氏温度为:14
用例 4:
请输入摄氏温度:-50
华氏温度为:-58
用例 5:
请输入摄氏温度:-100
华氏温度为:-148
*/
可以将温度定义为实数,以获取更好的精度。
#include <stdio.h>
int main() {
float celsius, fahrenheit;
printf("请输入摄氏温度:");
scanf("%f", &celsius);
fahrenheit = celsius * 9.0 / 5.0 + 32.0;
printf("摄氏温度 %.2f 对应的华氏温度是:%.2f\n", celsius, fahrenheit);
return 0;
}