C语言基础 6. 数据类型
文章目录
6.1. 基础数据类型
-
C语言的变量:
- 必须在使用前定义, 并且确定类型
-
C以后的语言向两个方向发展:
-
C++和Java, 它们更强调类型, 对类型的检查更严格, C语言有时候允许在不同的类型之间使用一些过渡的事情(自动类型转换)
-
JavaScript,Python,PHP不看重类型,甚至不需要事先定义
-
-
类型安全:
-
工业界有两种不同的观点
- 支持明确类型的观点认为它有助于今早发现程序中的简单错误
- 反对它的认为过于强调类型迫使程序员面对底层实现而非事务逻辑
-
总的来说,早期语言和面向底层的语言强调类型,而越面向应用的语言越离底层远的语言,它会忽视类型
-
而对于C语言来说,它需要类型,但是对类型的安全检查并不足够,它并不是表现为一个非常强的强类型语言
-
-
C语言的类型:
-
四大类, 但是为啥会有五种呢, 我们这里把逻辑归类到整数当中, 等讲到逻辑的时候再来说
- 整数: char, short, int, long, long long
- 浮点数: float, double, long double
- 逻辑: bool
- 指针
- 自定义类型
-
-
类型有何不同:
- 类型名称: int long double
- 输入输出时的格式化: %d %ld %lf
- 所表达的数的范围: char<short<int<float<double
- 内存中所占的大小: 1字节到16字节
- 内存中的表达形式: 二进制数(补码)(是对于整数),编码(是对于浮点数)
-
sizeof
-
是一个运算符, 给出某个类型或变量在内存中所占据的字节数
int i; sizeof(int) == 4 sizeof(i) == 4
- 4个字节(byte),1byte == 8比特位(bit), 4byte==32bit
-
是一个静态运算符,它的结果在编译时刻就决定了,所以不要在sizeof的括号中做运算,这些运算是不会做的
int a = 0; printf("%ld", sizeof(++a)); -> 4 printf("%ld", a); -> 0
-
-
计算机中的单位
单位 | 描述 |
---|---|
bit (比特位) | 1bit表示一个1或0, 计算机是将接收到的信息转化成能识别的二进制码 |
byte (字节) | 1byte=8bit |
KB | 1KB=1024byte |
MB | 1MB=1024KB |
GB | 1GB=1024MB |
TB | 1TB=1024GB |
- 程序中的错误:
a = 0; 错误信息: 未定义标识符 "a" 错误原因: 变量a未定义 解决办法: 先定义并确定类型再使用
- 代码:
#include <stdio.h>
int main() {
int a;
a = 0;
printf("sizeof(int) = %ld\n", sizeof(int)); //%ld是长整型,更精确
printf("sizeof(a) = %ld\n", sizeof(a));
printf("%d\n", sizeof(5.0));
printf("%d\n", a);
return 0;
}
6.2. 除了Int外的数据类型
-
除了int,还有多少整数类型
-
sizeof(long) -> 4 在32位的操作系统上
-
sizeof(long) -> 8 在64位的操作系统上
-
int和long所占的字节数与所在的计算机有关,也与所用的编译器有关
-
int是要表达计算机的字长,也就是寄存器的大小
char 1
short 2
int 4
long 4或8
long long 8
-
-
字长:
- 计算机中有个东西叫做CPU,还会有另一个东西叫做内存RAM,在CPU和RAM中间有一个东西连接着它们两个, 叫做总线, 在CPU中外有一个东西叫做寄存器,让我们在说一个计算机的字长时,我们指的是计算机的寄存器是有多宽, 也就是寄存器是多少bit,当寄存器是32bit, 寄存器可以表达32bit的数据,同时我们在CPU和RAM之间传递数据时, 每一次传递32bit. 当我要去RAM中取数据到CPU里面时, 每一次会取32bit的数据,寄存器会表达32bit,这里的32就叫做字长.
- 计算机中有个东西叫做CPU,还会有另一个东西叫做内存RAM,在CPU和RAM中间有一个东西连接着它们两个, 叫做总线, 在CPU中外有一个东西叫做寄存器,让我们在说一个计算机的字长时,我们指的是计算机的寄存器是有多宽, 也就是寄存器是多少bit,当寄存器是32bit, 寄存器可以表达32bit的数据,同时我们在CPU和RAM之间传递数据时, 每一次传递32bit. 当我要去RAM中取数据到CPU里面时, 每一次会取32bit的数据,寄存器会表达32bit,这里的32就叫做字长.
-
代码:
#include <stdio.h>
int main() {
printf("sizeof(char) = %ld\n", sizeof(char)); //1
printf("sizeof(short) = %ld\n", sizeof(short)); //2
printf("sizeof(int) = %d\n", sizeof(int)); //4
printf("sizeof(long) = %ld\n", sizeof(long)); //4
printf("sizeof(long long) = %ld\n", sizeof(long long)); //8
return 0;
}
6.3. Int的内部表达
-
疑问:
- 这一节还不是太懂
-
整数的内部表达:
-
我们现在知道一个int表达的是一个寄存器的大小,那么整数在计算机的内部是如何表达的呢
-
计算机内部一切都是二进制,不管是整数还是浮点数(虽然是编码,但是计算机可以通过一定的方式)最终都是二进制,只是我们以什么样的方式来看待它,这是很重要的,而不是表明它在内部是如何表达的
- 比如:
18 -> 00010010 18是用00010010这样的一个二进制来表达的
0 -> 00000000
-18 -> ?
- 比如:
-
-
如何表示负数:
-
十进制用"-"表示负数
-
做运算时:
12+(-18)=12-18
12-(-18)=12+18
12*(-18)=-(12*18)
12/(-18)=-(12/18)- 做运算时,总是把这个负号抛掉,把它当作一个正数来做运算,然后在运算的结果上面再去设法处理这个
-
负号的问题,这是十进制,那么二进制怎么做呢?
-
二进制负数
-
1byte可以表达的数: 00000000-11111111(0-255)
-
补码:
-
考虑-1,让-1+1=0,怎么做?
0 -> 00000000
1 -> 00000001
11111111 + 00000001 -> 100000000//计算机内部,如果这个数是8bit,那么多出来的那一位就会被丢掉,所以这个结果正好是000000000 -
因为0-1 -> -1,所以-1 -> 11111111
(1)00000000 - 00000001 -> 11111111
11111111被当作纯二进制看待时,是255,被当作补码看待时是-1 -
同理, 对于-a, 其补码就是0-a, 实际是2^n-a, n是这种类型的位数
-
补码的意义就是拿补码和原码可以加出一个溢出的"0", 所以为什么要在计算机中使用补码呢, 如果你有一个补码, 你用补码来表示这个-1, 那么当你在做加法时, 你不需要根据条件去变换, 把加变成减, 你直接拿它去做普通的二进制加法, 你就会得到你想要的结果
-
-
计算机在底层存储数据时, 一律存储的是二进制的补码形式( 补码形式效率最高 ), 打印的是原码
-
二进制有 : 原码, 反码, 补码
-
对于一个正数来说 : 二进制原码, 反码, 补码都相同
-
对于一个负数来说 :
- char b = -1;
- 对应的原码 : 10000001
- 反码 : 11111110 ( 符号位不变, 其他位取反 )
- 补码 : 11111111 ( 反码+1 )
-
-
6.4. Int的范围
-
疑问:
- 这一节还不是太懂
-
数的范围:
-
对于一个字节(8位)(也就是整数当中的char)来说,可以表达的是:
00000000-11111111- 其中:
-
00000000 -> 0
11111111~10000000 ->-1
~-128
00000001~01111111 -> 1~127 -
11111111
- 把它看作是一个二进制数,它就是原码形式对应的十进制255
- 把它看作是一个整数,它就是补码形式对应的十进制-1
-
所以以什么样的方式来看待它,这是很重要的
-
但是这只是针对的一个字节的整数,也就是char,如果换成别的类型的整数呢,它就不是-1了
-
char c = 255; 11111111
-
int i = 255; 00000000 00000000 00000000 11111111他前面还有很多位可以填充为1,所以是正数
-
printf(“c = %d, i = %d”, c, i);//c = -1, i = 255
-
- 其中:
char: 1byte: -128~127 short: 2byte: -32768~32767 int: 4或8byte,取决于CPU : -2^(32-1)~2^(32-1)-1 long: 4或8byte,取决于CPU long long: 8byte -2^(n-1)~2^(n-1)-1,n为类型位数
-
-
unsigned:
-
如果我们想要将一个数当作纯二进制数,也就是说这个数不以补码的形式来表示负数,这个数没有负数部分,那么我们需要在那个类型的前面再加上一个关键字unsigned,但是有一个副作用就是这个类型所能表达的数在正数部分会扩大,相当于是原来正数部分的两倍
-
unsigned char a = 255U; 可以在后面加u或U表示自己是unsigned
-
如果想表示自己是long,可以在后面加上l或L
-
初衷:
- 它的设计并非扩展数能表达的范围,而是为了做纯二进制运算,主要是为了移位.
-
-
整数越界:
- 整数是以纯二进制方式进行计算的
11111111 + 1 -> 100000000 -> 0
01111111 + 1 -> 10000000 -> -128
10000000 - 1 -> 01111111 -> 127
char b = 127; b += 1; printf("%d\n", b);//-128 char d = -128; d -= 1; printf("%d\n", d);//127 unsigned char e = 127; e += 1; printf("%d\n", e);//128 unsigned char f = 255; f += 1; printf("%d\n", f);//0
- 整数是以纯二进制方式进行计算的
-
代码:
#include <stdio.h>
int main() {
char c = 255;
int i = 255;
printf("c = %d, i = %d\n", c, i);//c = -1, i = 255
unsigned char a = 255;
printf("a = %d\n", a);
char b = 127;
b += 1;
printf("%d\n", b);//-128
char d = -128;
d -= 1;
printf("%d\n", d);//127
unsigned char e = 127;
e += 1;
printf("%d\n", e);//128
unsigned char f = 255;
f += 1;
printf("%d\n", f);//0
return 0;
}
6.5. Int的格式化
-
疑问:
- 这一节还不是太懂
-
整数的输入输出:
-
只有两种形式: int和long long, 也就是说char和short也可以采用int的方式输入输出
%d: int
%u: unsigned
%ld: long long
%lu: unsigned long long -
char c = -1;
int i = -1;
printf(“c = %u, i = %u\n”, c, i);//c = 4294967295, i = 4294967295- 这个数是unsigned int所能表达的最大的数,因为-1表示全1,为什么这个不是一个字节呢,当我们把所有小于int的变量传给printf时,编译器会把这些变量转换为int传进去,因为是有符号的,所以传进去的时候,当然这个东西也被扩展到所有的位都是1,最后作为unsigned的结果就是这个结果
- 还是那句话,这和它在计算机内部是什么没有关系,这取决于你用正确的方式把它格式化,也就是这里的%u
-
-
八进制和十六进制:
- 以0开始的数字是八进制
- 以0x开始的数字是十六进制
- 无论是八进制还是十六进制,编译器都会将其转成二进制是得计算机能够理解
- %o: 八进制
- %x: 十六进制
- 八进制和十六进制只是如何把数字表达为字符串,与内部如何表达数字无关
- 十六进制很适合表达二进制数据,因为4位二进制正好是一个十六进制位
- 八进制的一位数字正好表达3位二进制, 因为早期计算机的字长是12的倍数, 而非8
-
进制转换
- 二, 八, 十六进制 转 十进制 :
- 十进制 转 二, 八, 十六进制 :
- 二, 八, 十六进制 转 十进制 :
-
代码:
#include <stdio.h>
int main() {
char c = 012;
int i = 0x12;
printf("c = %d, i = %d\n", c, i);//c = 10, i = 18
return 0;
}
6.6. 选择Int
- 选择整数类型:
- C语言有那么多复杂的事情, 是因为早期的语言需要准确的表达计算机里头的东西, 比如, 内存, 寄存器,接口
- 没有特殊需要, 就选择int
- 现在的CPU的字长普遍是32位或64位, 一次内存读写就是一个int, 一次计算也是一个int, 选择更短的类型不会更快, 甚至可能更慢
- 现代的编译器一般会设计内存对齐, 所以更短的类型实际在内存中有可能也占据一个int的大小(虽然sizeof告诉你更小)
- unsigned与否只是输出的不同, 内部计算是一样的
6.7. 浮点类型
-
浮点类型:
类型 字长 范围 有效数字 float 32 大概10^38 7 double 64 大概10^308 15
-
输入输出:
类型 scanf printf float %f %f, %e double %lf %f, %e(以科学计数法输出)
-
科学计数法:
-5.67E+16
-
可选的+或-
-
小数点也是可选的
-
可以用e或E
-
符号可以是-或+也可以省略(表+)
-
整个词不能有空格
-
假如值很大, 比如0.000000001有非常多的小数, 使用科学计数法就可以帮你直接帮你计算多少位小数
-
-
输出精度:
-
在%和f之间加上.n可以指定输出小数点后几位, 这样的输出是做四舍五入的
printf(“%.3f\n”, -0.0049);// -0.005
printf(“%.30f\n”, -0.0049);// -0.004899999999999999841793218991 这个结果是离散在0.0049附近的
printf(“%.3f\n”, -0.00049); //-0.000
-
-
代码:
#include <stdio.h>
int main() {
/*double d;
float f;
scanf("%lf %f", &d, &f);
printf("%e %f\n", d, f);*/
printf("%.3f\n", -0.0049);// -0.005
printf("%.30f\n", -0.0049);// -0.004899999999999999841793218991
printf("%.3f\n", -0.00049); //-0.000
//printf("sizeof(float) = %ld\n", sizeof(float)); //4
//printf("sizeof(double) = %ld\n", sizeof(double)); //8
//printf("sizeof(long double) = %ld\n", sizeof(long double)); //8
return 0;
}
6.8. 浮点类型的范围
-
超过范围的浮点数:
- printf输出inf表示超过范围的浮点数: ±∞
- printf输出nan表示不存在的浮点数
double zero = 0.0; printf("%f\n", 12.0 /zero ); //inf printf("%f\n", -12.0 / zero);//- inf printf("%f\n", 0.0 / zero);//- nan(ind)
- 无穷大可以用浮点数表达, 但是不能用整数来表达
-
浮点运算的精度:
- 浮点运算是没有精度的, 所以两个浮点数直接判断是否相等可能会失败
f1==f2可能失败
float a, b, c; a = 1.345f; //带小数点的字面量是double而非float, float需要用f或F后缀来表明身份 b = 1.123f; c = a + b; if (c == 2.468) { printf("相等\n"); } else { printf("不相等! c=%.10f, 或%f\n", c, c);//不相等! c=2.4679999352, 或2.468000 }
- 浮点运算是没有精度的, 所以两个浮点数直接判断是否相等可能会失败
-
浮点数的内部表达:
- 浮点数的内部是一种编码形式, 浮点数在计算时是由专用的硬件部件实现的, 计算double和float的部件是一样的
-
选择浮点类型:
- 如果没有特殊需要, 只是用double
- 现代CPU能直接对double做硬件运算, 性能不会比float差, 在64位的机器上, 数据存储的速度也不比float慢
-
程序中的错误:
printf("%f\n", 12.0 / 0.0 ); 错误信息: 被零除或对零求模 错误原因: 对零进行除法运算 解决办法: 把零赋值给一个变量, 让这个变量代替零做运算
-
代码:
#include <stdio.h>
int main() {
//double zero = 0.0;
//printf("%f\n", 12.0 /zero ); //inf
//printf("%f\n", -12.0 / zero);//- inf
//printf("%f\n", 0.0 / zero);//- nan(ind)
//int ling = 0;
//printf("%d", 12 / ling);//错误
float a, b, c;
a = 1.345f; //带小数点的字面量是double而非float, float需要用f或F后缀来表明身份
b = 1.123f;
c = a + b;
if (c == 2.468) {
printf("相等\n");
}
else
{
printf("不相等! c=%.10f, 或%f\n", c, c);//不相等! c=2.4679999352, 或2.468000
}
return 0;
}
6.9. 字符类型
-
字符(character)类型:
- char是一种整数, 也是一种特殊的类型: 字符, 这是因为:
- 用单引号表示的字符字面量: ‘a’, ‘1’
- ''也是一个字符
- printf和scanf里面用%c来输入输出字符
- char是一种整数, 也是一种特殊的类型: 字符, 这是因为:
-
字符的输入输出:
- 如何输入’1’这个字符给char c?
char c; scanf("%c", &c); // 1 printf("c = %d\n", c);// 49 printf("c = '%c'\n", c); // '1' int i; char c; scanf("%d", &i);//读进去的是一个整数 c = i; //整数赋给了c printf("c = %d\n", c);//c作为整数形式输出为49 printf("c = '%c'\n", c);//c作为字符形式输出为'1'
- ‘1’的ASCII编码是49, 所以当c==49时, 它代表’1’
if (49 == ‘1’) {
printf(“相等\n”);//相等
}
- 如何输入’1’这个字符给char c?
-
混合输入:
int i; char c; scanf("%d %c", &i, &c);//%d要把整数以及后面的空格都读掉, 后面的给%c scanf("%d%c", &i, &c);//%d只读到整数结束为止, 后面的给%c printf("i = %d, c = %d, c = '%c'\n", i, c, c);
-
字符计算:
-
一个字符加一个数字得到ASCII码表中那个数之后的字符
char c = ‘A’;
c++;
printf(“%c\n”, c);//B -
两个字符的减, 得到它们在表中的距离
int i = ‘Z’ - ‘A’;
printf(“%d\n”, i);//25
-
-
大小写转换:
-
字母在ASCII码表中是顺序排列的, ‘a’到’z’, ‘A’到’Z’
-
大写字母和小写字母是分开排列的, 并不在一起
-
‘a’-'A’可以得到两段之间的距离
-
大小写字母转换:
printf(“%d\n”, ‘a’ - ‘A’);//32
printf(“%d\n”, ‘A’ - ‘a’);//-32
printf(“%c\n”, ‘B’ + ‘a’ - ‘A’);//b
printf(“%c\n”, ‘b’ + ‘A’ - ‘a’);//B
-
-
代码:
#include <stdio.h>
int main() {
//char c;
//char d;
//c = 1;
//d = '1';
//if (c == d) {
// printf("相等\n");
//}
//else {
// printf("不相等\n"); //不相等
//}
//printf("c = %d\n", c);//c=1
//printf("d = %d\n", d);//d=49
//int i;
//char c;
//scanf("%d", &i);//读进去的是一个整数
//c = i; //整数赋给了c
//printf("c = %d\n", c);//c作为整数形式输出为49
//printf("c = '%c'\n", c);//c作为字符形式输出为'1'
/*if (49 == '1') {
printf("相等\n");
}*/
//int i;
//char c;
scanf("%d %c", &i, &c);
//scanf("%d%c", &i, &c);
//printf("i = %d, c = %d, c = '%c'\n", i, c, c);
//char c = 'A';
//c++;
//printf("%c\n", c);//B
//int i = 'Z' - 'A';
//printf("%d\n", i);//25
printf("%d\n", 'a' - 'A');//32
printf("%d\n", 'A' - 'a');//-32
printf("%c\n", 'B' + 'a' - 'A');//b
printf("%c\n", 'b' + 'A' - 'a');//B
return 0;
}
6.10. 逃逸字符
- 逃逸字符:
- 也叫做转义字符, 用来表达无法打印出来的控制字符或特殊字符, 他由一个反斜杠""开头, 后面跟上另一个字符, 这个两个字符合起来, 组成了一个字符.
字符 意义 \b 回退一格, 如果\b后面有东西, 则把后面要覆盖前面一格, 如果\b后面没有东西了, 那么不覆盖 \t 制表符tab \n 换行, 在早期的打字机上面回车和换行是两个动作, 但是在此shell当中\n就代替了这两个动作 \r 回车 \" 双引号 \' 单引号 \\ 反斜杠本身
- 调试控制台:
-
它是一个程序, 叫做shell, 它在程序员和计算机之间做了一个桥梁的作用, 相当于一个翻译官的角色, 程序员通过键盘输入代码, shell来执行我们的代码, 来传递给计算机底层, 计算机接收到之后, 会将结果给shell, shell对这个结果加工处理, 最终变成了程序员能看懂的东西.
-
也就是说, 不同的编译器有不同的shell, 不同的shell执行同一段代码会有不同的结果, 这个是毋庸置疑的, 比如说\b在不同的shell当中呈现出的结果是不一样的
-
printf(“123\b\n456\n”);
- 123
456 - 这是当前的shell的运行结果, 而在另一个shell中, 123后面还有个看不懂是什么玩意儿的东西
- 123
-
- 代码:
#include <stdio.h>
int main() {
printf("123\b\n456\n");//123换行456
printf("123\bA\n456\n");//12A换行456
return 0;
}
6.11. 类型转换
-
自动类型转换:
-
当运算符的两边出现不一致的类型时, 会自动转换成较大(也就是表达的数的范围更大)的类型
- char -> short -> int -> long -> long long
- int -> float -> double
-
对于printf, 任何小于int的类型会被转换成int, float会被转换成double, 但是scanf不会, 要输入short, 需要%hd
-
-
强制类型转换:
-
要把一个类型强制转换成另一个类型(通常是较小的类型)
-
格式: (类型)值
-
比如:
- (int)10.2
- (short)32
-
注意这时候的安全性, 小的变量不总能表达大的量
- (short)32768
- printf(“%d\n”, (short)32768);//-32768 因为short的能表示的最大整数为32767, 现在已经超出了所能承受的范围
-
它只是从那个变量计算出一个新的类型的值, 它并不改变那个变量, 无论是值还是类型都不改变
- int i = 32768;
- short s = (short)i;
- printf(“%d\n”, i); //32768
-
-
优先级:
- 强制类型转换的优先级是高于四则运算的
double a = 1.0; double b = 2.0; int i = (int)(a / b);//要想先算四则运算, 可以加上() printf("%d", i);
- 强制类型转换的优先级是高于四则运算的
-
代码:
#include <stdio.h>
int main() {
//int i = 32768;
//short s = (short)i;
//printf("%d\n", (int)10.2);//10
//printf("%d\n", i);//32768
//printf("%d\n", s);//-32768
double a = 1.0;
double b = 2.0;
int i = (int)(a / b);
printf("%d", i);
return 0;
}
6.12. 逻辑类型
-
bool:
-
布尔类型
-
#include <stdbool.h>, 才能使用bool和true, false
-
-
代码:
#include <stdio.h>
#include <stdbool.h>
int main() {
bool b = 6 > 5;
bool t = true;
printf("%d\n", b);//1
printf("%d\n", t);//1
return 0;
}
6.13. 逻辑计算
-
逻辑运算:
-
逻辑运算是对逻辑量进行的运算, 结果只有0或1
-
逻辑量是关系运算或逻辑运算的结果
运算符 描述 实例 结果 ! 逻辑非 !a 如果a是true(false), 结果就是false(true) && 逻辑与 a && b 如果a和b都是true, 结果就是true, 否则就是false || 逻辑或 a || b 如果a和b有一个是true, 结果就是true, 两个都是false, 结果才为false
-
-
区间:
-
如果要表达数学中的区间, 比如: x∈(4,6)或x∈[4,6], 应该如何写C的表达式
- 开区间: x > 4 && x < 6
- 闭区间: x >= 4 && x <= 6
-
如何判断一个字符c是否为大写字母?
- c >= ‘A’ && c <= ‘Z’
-
-
理解一下:
- age > 20 && age <30 : age∈(20,30)
- index < 0 || index > 99 : index∈(-∞,0]∪[99,+∞)
- !age < 20 : age∈[20,+∞)
- 虽然逻辑运算符的优先级低于比较运算符, 但是还有一条规则是, 单目运算符的优先级要高于双目运算符,而逻辑非就是单目运算符, 所以应该先算!age, 再算< 20
-
优先级:
- ! > && > ||
- !done && (count > MAX)
优先级 运算符 结合性 1 () 从左往右 2 ! + - ++ -- 从右向左(单目的+和-) 3 * / % 从左向右 4 + - 从左向右 5 < <= > >= 从左向右 6 == != 从左向右 7 && 从左向右 8 || 从左向右 9 = += -= *= /= %=从右向左
- 赋值运算是最低的, 逻辑运算比比较运算低, 往上是四则运算, 再往上是单目运算符, 最高的是()
- ! > && > ||
-
短路:
-
逻辑运算是自左向右进行的, 如果左边的结果已经能够决定结果了, 就不会做右边的计算了
-
比如:
-
a==6 && b++
-
a==6 && b++
// 当a!=6时, b++就不会执行, 即短路 -
对于&&, 左边是false时就不做右边了; 对于||, 左边是true时就不做右边了
-
不要把赋值, 包括复合赋值组合进逻辑运算表达式
-
-
-
代码:
#include <stdio.h>
int main() {
if ('C' >= 'A' && 'C' <= 'Z') {
printf("是");
}
//int i, j, k;
//if (i != j) {
// if (i != k) {
// if (j != k) {
// //第一种
// }
// }
//}
//if (i != j && i != k && j != k) {
// //第二种
//}
// 有了逻辑运算符之后, 我们就可以将第一种写成第二种形式, 看起来更简洁
int a = 5;
int b = 1;
if (a > 6 && b++) { //b++会短路
printf("ok");
}
printf("%d %d", a, b);//5 1
return 0;
}
6.14. 条件和逗号计算
-
条件运算符:
count = (count > 20) ? count - 10 : count + 10; 条件 ? 条件满足时的值 : 条件不满足时的值
- 相当于:
if(count > 20){ count -= 10; }else { count += 10; }
- 相当于:
-
优先级:
- 条件运算符的优先级高于赋值运算符, 但是低于其他运算符
-
嵌套条件表达式:
-
count = (count > 20) ? (count < 50) ? count - 10 : count + 10;
-
不建议使用嵌套的条件表达式, 太过于复杂, 可读性差
-
-
逗号表达式:
-
逗号用来连接两个表达式, 并以其右边的表达式的值作为它的结果
-
优先级: 逗号的优先级是所有的运算符中最低的, 比赋值运算符还低
int i; i = 3 + 4, 5 + 6; printf("i = %d", i);//i = 7 i = (3 + 4, 5 + 6);//i = 11
-
在for中使用:
for(i = 0, j = 10; i < j; i++, j–)
目前来说, 逗号表达式就只有这一个用处, 就是在for当中使用
-
-
代码:
#include <stdio.h>
int main() {
/*int count = 40;
count = (count > 20) ? count - 10 : count + 10;
printf("%d", count);*/
/*int i;
i = 3 + 4, 5 + 6;
printf("i = %d", i);*/
int i, j;
for (i = 0, j = 10; i < j; i++, j--) {
printf("i = %d, j = %d\n", i, j);
}
printf("i = %d, j = %d\n", i, j);
return 0;
}
6.15. PAT
-
06-0. 混合类型数据格式化输入(5)
-
本题要求编写程序,顺序读入浮点数1、整数、字符、浮点数2,再按照字符、整数、浮点数1、浮点数2的顺序输出。
-
输入格式:
输入在一行中顺序给出浮点数1、整数、字符、浮点数2,其间以1个空格分隔。 -
输出格式:
在一行中按照字符、整数、浮点数1、浮点数2的顺序输出,其中浮点数保留小数点后2位。 -
输入样例:
2.12 88 c 4.7 -
输出样例:
c 88 2.12 4.70 -
分析:
- 1.输入
- 2.输出并保留两位小数
#include <stdio.h> int main() { //输入 double num1, num2; int i; char c; scanf("%lf %d %c %lf", &num1, &i, &c, &num2); //输出 printf("%c %d %.2f %.2f", c, i, num1, num2); return 0; }
-
-
06-1. 简单计算器(20)
-
疑问:
-
如何接收这些不固定的四则运算符, 这一题不会
-
已解决, 刷两遍错题就行了
-
-
模拟简单运算器的工作。假设计算器只能进行加减乘除运算,运算数和结果都是整数,4种运算符的优先级相同,按从左到右的顺序计算。
-
输入格式:
输入在一行中给出一个四则运算算式,没有空格,且至少有一个操作数。遇等号”=”说明输入结束。 -
输出格式:
在一行中输出算式的运算结果,或者如果除法分母为0或有非法运算符,则输出错误信息“ERROR”。 -
输入样例:
1+2*10-10/2= -
输出样例:
10
#include <stdio.h> int main() { char c = 'a'; int flag = 1; int ret; scanf("%d", &ret); while (c != '=') { scanf("%c", &c); if (c == '=') { break; } int i; scanf("%d", &i); if (c == '+') { ret += i; } else if (c == '-') { ret -= i; } else if (c == '*') { ret *= i; } else if (c == '/') { if (i != 0) { ret /= i; } else { flag = 0; } } else { flag = 0; } } if (flag == 0) { printf("ERROR\n"); } else { printf("%d", ret); } return 0; }
-
-
06-2. 字符串字母大小写转换(10)
-
输入一个以#结束的字符串,本题要求将小写字母全部转换成大写字母,把大写字母全部转换成小写字母,其它字符不变。
-
输入格式:
输入在一行中给出一个长度不超过40的、以#结束的非空字符串。 -
输出格式:
在一行中按照要求输出转换后的字符串。 -
输入样例:
Hello World! 123# -
输出样例:
hELLO wORLD! 123 -
分析:
- 1.循环,每次接收一个字符
- 2.判断条件!=‘#’
- 3.判断小写字母并转大写
- 4.判断大写字母并转小写
- 5.其他的不用管,直接输出
#include <stdio.h> int main() { //字符变量 char c = 'a'; //循环每次接收一个字符 //判断条件 while (c != '#') { scanf("%c", &c); //判断小写 if (c >= 'a' && c <= 'z') { //小写转换大写 c += 'A' - 'a'; } //判断大写 else if (c >= 'A' && c <= 'Z') { //大写转换小写 c += 'a' - 'A'; } //转换完成之后, 其他的不用动, 输出 printf("%c", c); } return 0; }
-
-
06-3. 单词长度(15)
-
你的程序要读入一行文本,其中以空格分隔为若干个单词,以‘.’结束。你要输出每个单词的长度。这里的单词与语言无关,可以包括各种符号,比如“it’s”算一个单词,长度为4。注意,行中可能出现连续的空格;最后的‘.’不计算在内。
-
输入格式:
输入在一行中给出一行文本,以‘.’结束。 -
提示:用scanf(“%c”,…);来读入一个字符,直到读到‘.’为止。
-
输出格式:
在一行中输出这行文本对应的单词的长度,每个长度之间以空格隔开,行末没有最后的空格。 -
输入样例:
It’s great to see you here. -
输出样例:
4 5 2 3 3 4 -
分析:
- 1.循环读入每个字符
- 2.判断条件!=‘.’
- 3.每次循环count++,遇到空格,把count输出
#include <stdio.h> int main() { //字符变量 char c = 'a'; //计数变量 int count = 0; //循环读入每个字符 //判断条件 while (c != '.') { //It's great to see you here. scanf("%c", &c); //It's great to see you here if (c == ' ') { //12340123450120123012301234 printf("%d ", count); count = -1; } count++; } printf("%d", count - 1); return 0; }
-