一、类型转换
(一)强制类型转换
在C语言中,如果需要进行不同类型间成员赋值,则需要使用强制类型转换
(类型) 表达式;
或者
(类型) (表达式);
(二)隐式类型转换
1. 赋值转换
若等号两边的数值类型不同,会把右边表达式的类型转换为左边变量的类型,可能导致数据失真(精度降低)。
2. 运算转换
①向数据长度增加的方向进行(确保精度不会降低)
②unsigned和signed类型参与运算会转换成unsigned
③整型提升:只要char类型和short类型参与运算就会提升为int类型
char 类型和short 类型参与运算时,整型提升为int类型。
char类型和char类型参与运算时,整型提升为int类型。
short 类型和short 类型参与运算时,整型提升为int类型。
- 注:int类型和int类型参与运算,还是int类型
④float类型只要参与运算,就会提升为double类型。
二、浮点数判断相等问题
判断某一浮点类型的变量是否和另外一个变量相等的时候,应该使用区间的方式判断。因为浮点数具有精度问题不能单纯判断值是否相等。
一般默认保留小数点后六位。
eg:
|pi - 3.14|<0.000001 如果成立则相等
注意:浮点数在赋值的时候也会存在精度问题,所以判断浮点数时不要太极限
#include <stdio.h>
#include <stdlib.h>
int main(int argc, const char *argv[])
{
double i=0.0000001;//精度
double a=3.140001,b=3.140000;
//注意:浮点数在赋值的时候也会存在精度问题,所以判断时不要太极限
if(a-b<i)
{
printf("a == b\n");
}
else if(a-b>=i)
{
printf("a != b\n");
}
return 0;
}
三、输入输出
C语言中的输入输出是指向程序中输入数据或者程序向终端输出结果的过程。
(一)printf函数
可以向终端输出字符,字符串,整数,整数,实型数,字符串,地址等。
1、使用格式
printf(“控制格式”,变量1,变量2,…)
2、控制格式
类型 | 控制格式 | 使用方法 | 注 |
---|---|---|---|
char | %c,%d | printf(“%c”,a) | 以字符形式输出 |
short | %d | printf(“%d”,a) | 以十进制形式输出 |
int | %d | printf(“%d”,a) | |
%nd(n为数字) | printf(“%4d”,a) | 以4位输出,不足4位补空;超出4位,不会截取,正常显示 | |
%0nd(n为数字) | printf(“%04d”,a) | 以4位输出,不足4位补0 | |
%-nd | printf(“%-4d”,a) | -代表左对齐,默认是右对齐 | |
%#o | printf(“%#o”,a) | 打印八进制数,#代表补充前缀0 | |
%#x | printf(“%#x”,a) | 打印十六进制,#代表补充前缀0x | |
unsigned int | %u | printf(“%u”,a) | 打印无符号整型 |
long | %#ld | printf(“%#ld”,a) | 以十进制打印long类型 |
%#lo | printf(“%lo”,a) | 以八进制打印long类型 | |
%#lx | printf(“%lx”,a) | 以十六进制形式打印long类型 | |
long long | %#lld | printf(“%#lld”,a) | 以十进制打印long long类型 |
%#llo | printf(“%llo”,a) | 以八进制打印long long类型 | |
%#llx | printf(“%llx”,a) | 以十六进制形式打印long long类型 | |
float | %f | printf(“%f”,a) | 打印浮点数,默认显示小数点后六位 |
%.2f | printf(“%.2f”,a) | 打印浮点数,显示小数点后两位 | |
%e | printf(“%e”,a) | 使用科学计数法的的方式显示 | |
%g | printf(“%g”,a) | 打印小数点后的有效位,一共可以显示6位(包括整数位) | |
double | %lf | printf(“%lf”,a) | 打印double类型,默认显示小数点后六位 |
%e | printf(“%e”,a) | 使用科学计数法的的方式显示 | |
%g | printf(“%g”,a) | 打印小数点后的有效位,一共可以显示6位(包括整数位) | |
int * 地址 | %p | printf(“%p”,&a) | 在64位系统是八字节;32位系统是四字节 |
char a[n] | %s | printf(“%s”,a); | 将a字符数组中的内容打印到终端上,遇到\0停 |
%10s | printf(“%10s”,a); | 打印字符串占10位,不足左侧补空 | |
%-10s | printf(“%-10s”,a); | 打印字符串占10位,左对齐,不足右侧补空 |
3. 使用实例
#include <stdio.h>
int main(int argc, const char *argv[])
{
double a = 123.123456789;
char b[20]="12345";
printf("%g\n",a); //只显示六位,包含整数位
printf("%10s\n",b);//打印十位字符串,默认右对齐,左侧补空
printf("%-10s\n",b); //打印十位字符串,左对齐,右侧补空
return 0;
}
输出结果:
- 补充:关于sprintf函数
#include <stdio.h>
int sprintf(char *str, const char *format, ...);
//将格式化字符串输出到str指向的字符串中
向字符串中输入整型数据,也会将其转化成字符,即如果输入整型数字’1’,在字符串中就占1个字节,如果输入’11’,在字符串中就占2个字节
示例:
#include <stdio.h>
#include <string.h>
int main(int argc, char const *argv[])
{
char buff[128]={0};
sprintf(buff,"%d",11);
printf("size:%ld\n",strlen(buff));
return 0;
}
输出结果:
(二)scanf
1. 使用格式
scanf(“%d”,&变量);
2. 控制格式
类型 | 控制格式 | ||
---|---|---|---|
char | %c | scanf(“%c”,&a) | 向变量a中输入一个字符 |
int | %d | scanf(“%d”,&a) | 向变量a输入一个整数;%d遇到空格,换行和tab键会自动跳过 |
unsigned int | %u | scanf(“%u”,&a) | 向变量a中输入一个无符号整型 |
float | %f | scanf(“%f”,&a) | 输入一个单精度浮点数 |
double | %lf | scanf(“%lf”,&a) | 输入一个双精度浮点数 |
char a[20] | %s | scanf(“%s”,a); | 向a数组中输入字符串,a是数组名,他就是数组的首地址。(%s遇到空格,Tab,换行都会结束,所以输入字符串时不能输入这些字符);不会对数组越界进行检查 |
%[^\n] | scanf(“%[^\n]”,a); | 表示除了回车"\n"之外的所有字符都可以输入到数组中;不会对数组越界进行检查 | |
3. 混合输入(垃圾字符问题)
①问题:
#include <stdio.h>
/****此代码是为了体现垃圾字符的问题*****/
int main(int argc, const char *argv[])
{
char name[20];
char sex;
int age;
printf("input name:");
scanf("%s",name);
//sanf遇到空格、tab键、换行符后会停止读入,但是并不会将换行符读走
//换行符仍保留在输入缓冲区中
printf("input sex:");
scanf("%c",&sex);
//此时继续读入,首先会读入上次输入遗留的换行符
printf("input age:");
scanf("%d",&age);
printf("输出读入的数据--name:%s;sex:%c;age:%d\n",name,sex,age);
return 0;
}
现象:
可以看到此时sex中存储的是一个换行符。
②总结
- 控制格式为%c时,前有空格,tab,换行会被读取
- 控制格式为%d时,前有空格,tab或者换行,没有影响
- 控制格式为%s时,前有空格,tab,换行可以被跳过;输入后,遇到换行,空格,Tab就会结束
- 控制格式为[^\n]时,回车不能跳过,需要使用%*c处理垃圾字符,空格和tab可以跳过
③解决方法:
方法一: 在控制格式中使用“%*c”吃掉一个字符
scanf(“%*c%c”,&sex);
输出结果(正常):
(2)注意控制格式后不要加入空格,tab和回车
控制格式前加空格,tab,回车,对输入无影响。
控制格式后加入空格,tab,回车,会无法结束,需要再输入一个字符才能结束。
4. 注意点
scanf
不会将在终端输入结束时的’\n
’读走
5. 练习
(1)向程序中输入一个字符,如果是A-Z,打印出“这是大写字母”;如果是a-z,打印“这是小写字母”
#include <stdio.h>
int main(int argc, const char *argv[])
{
char a;
printf("input(char):");
//一句话写多行们可以使用单左斜杠,作为续航符,续航符后不能加空格
((a>='a'&& a<='z')||(a>='A' && a<='Z'))?\
((a>='A'&&a<='Z')?printf("这是大写字母\n"):printf("这是小写字母\n"))\
:printf("这既不是大写也不是小写字母\n");
/* (a>='A' && a<='Z')?printf("这是大写字母\n"):\
((a>='a'&&a<='z')?printf("这是小写字母\n"):\
printf("这既不是小写字母也不是大写字母\n"));
*/
return 0;
}
(三)getchar
1. 使用格式
变量 = getchar(void);
从终端读取一个字符,赋值给变量
2. 使用实例
一般用于做垃圾字符的处理
#include <stdio.h>
int main(int argc, const char *argv[])
{
int a;
char b;
printf("input(int):");
scanf("%d",&a);
getchar();
printf("input(char):");
scanf("%c",&b);
printf("a=%d;b=%c\n",a,b);
return 0;
}
(四)putchar
1. 使用格式
putchar(字符或字符变量);
向终端输出一个字符;
2. 使用实例
#include <stdio.h>
int main(int argc, const char *argv[])
{
putchar('H');
putchar('e');
putchar('l');
putchar('l');
putchar('o');
putchar('\n');
return 0;
}
~
输出结果:
(五)gets
1. 使用格式
gets(字符数组名);
从终端上向程序读取字符串,存到字符数组中。
该函数没有越界检查,编译时会出现危险警告。如下:
- 注:
- 该函数只有遇到’\0’才会停止读入数据,遇到空格或者tab不会停止
- 该函数会将输入的"\n"读走,然后将其替换为\0。
2. 使用实例
#include <stdio.h>
int main(int argc, const char *argv[])
{
char a[20];
printf("input string >");
gets(a);
printf("%s\n",a);
return 0;
}
输出结果:
(六)puts
1.使用格式
puts(字符数组名或字符串);
将字符串输出到终端上。
遇到\0会将它替换为\n,因此会自动换行。
2.使用实例
#include <stdio.h>
int main(int argc, const char *argv[])
{
puts("hello world!");
return 0;
}
输出结果:
可见,程序中并未加入换行符,但是已经自动换行。