1.标准输出:
屏幕、终端 就是我们所说的标准输出设备,把数据输出到屏幕\终端被称为=标准输出。
相关函数:
printf(); // 格式化输出函数
printf("s:%s\n", "HelloEven" ); // %s输出一个字符串
printf("d:%d\n", 199 ); // 输出一个整型数
printf("c:%c\n", 0121 ); // 0121 八进制 输出一个字符
printf("f:%f\n", 199.234 ); // 输出一个浮点数
格式控制符:
-
- %d %md %ld %u %lu 十进制整型输出 %md m 表示需要多少个字符空位 如果比实际的小则按实际输出 ,如果比实际大则用空格填补。
- %o 八进制整型输出
- %x %X %#x %#X 十六进制
- %c 字符
- %s 字符串
- %f %mf %m.nf 单精度浮点数输出 m--》控制需要多少个字符位置 n --》 小数点后保留的个数(四舍五入)
- %lf 双精度浮点数
- %Lf 长双精度浮点数
- %p 地址
代码规范:
缩进:凡是有代码块的地方都应该缩进,一对大括号成为一个代码块 { }
空格:标点符号前后一般添加空格
空行:一般不同逻辑的段落,一般添加一到两行空行
符号命名:尽可能短+尽可能表达你的意思,顾名思义,避免使用无意义的字符
#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
#include <errno.h>
#include <string.h>
#define DIR_PATH "./"
int main(int argc, char const *argv[])
{
//打开
DIR * fd_dir = opendir(DIR_PATH);
if (NULL == fd_dir )
{
perror("open dir error");
return -1 ;
}
//读取
struct dirent * dir_info = NULL ;
while(1)
{
dir_info = readdir(fd_dir);
if (NULL == dir_info)
{
perror("read dir error");
break;
}
// 输出
printf("fileName : %s \n" , dir_info->d_name);
}
return 0;
}
2.整型
用来表达、存放一个整形数据的类型成为整型 (非小数的数字)
int a = 123 ;
- 先开辟一片内存 名字叫 a
- 根据具体的类型来分配内存大小 4字节
- 把 数据 123 转换成 二进制 存放到该内存中
注意:
取值范围 2,147,483,647 ----- -2,147,483,648
32位的数据中 第 31位位符号位, 如果31·位为 1 表示负数 否则表示正数
整形的修饰符:
short 短整形,用来修改整型使之取值范围缩小,减小内存的开支
long 长整形 , 用来修改整型使之取值范围增大,增加内存的开支(64位系统8字节)
long long 长长整整, 用来修改整型使之取值范围增大,增加内存的开支(64位系统8字节)
unsigned 无符号 , 用来修改整型使之取值范围不涉及负数,取值范围4,294,967,295 --- 0
short int b ;
short a ; // short 与 short int 是一样的没有区别
printf("int:%ld\n" , sizeof(int) );
printf("long:%ld\n" , sizeof(long) );
printf("long long:%ld\n" , sizeof(long long) );
2.1符号位:
32位的数据中 第 31位位符号位, 如果31·位为 1 表示负数 否则表示正数
2.2编码形式:
源码:如果是正整数 ,就使用二进制码来存储 , 比如 100 -->0000 0000 ....... 0110 0100
补码:如果是负整数, 就使用补码来存储
补码 = 源码取反 + 1
源码: 1000 0000 0000 0000 0000 0000 0110 0100
取反: 1111 1111 1111 1111 1111 1111 1001 1011
加一: 1111 1111 1111 1111 1111 1111 1001 1100
注意负数的补码在取反加一时符号位不动。
2.3溢出:
当我们整形数超出最大值后,会变成相邻的最小值。
2.4进制:
十六进制: 0xFA39
十进制: 1024
八进制: 01024
二进制: 0110 0010
3.浮点:
用来表达一个实数的数据类型。
3.1分类:
单精度 float 占用4字节 (64位)
双精度 double 占用8字节 (64位)
长双进度 long double 占用16字节 (64位)
占用内存越多精度越高。
float f ; //单精度
double d ; //双精度
long double ld ; //长双进度
float 10的-37次方 --- 10的38次方
double 10的-307次方 --- 10的308次方
long double 10的-4931次方 --- 10的4932次方
3.2存储方式:
4.字符
char ch1 = 'a' ; // '字符' "字符串" 'a' "a" -->系统自动送一个结束符
char ch2 = '\0' ; // \0 \n \t 结束符属于不可见字符
字符如何存储? 计算机不管存储的什么东西都是0和1 而已。每一个字符都有一个对应的编号
因此有个对照表 成为 ascii 码对照表。
如何查询:
man ascii
字符类型本质上是一个单字节的整型,支持所有整型的运算
char ch = 'a';
char ch2 = 10 ;
char ch3 = ch + ch2 ;
printf("ch3:%c\n" , ch3); // 使用字符形式输出得到 'k'
printf("ch3:%d\n" , ch3); // 使用整型输出 得到 107
5.字符串
定义: 分为两种方式 指针 、 数组
char * s1 = "Hello Even" ; // 使用指针来指向一个字符串 只读 不可修改
char s2[] = "Hello xxxxxx" ; // 使用数组来存放一个字符串 可读写, 可以任意修改
注意:
- 在内存中实际上是多个单独的字符组合而成。
- 每一个字符串后面都会有一个结束符 '\0'
- 用指针的形式来表示字符串需要注意该指针指向的内存是否可读(一般如s1所表示的字符串是不接受修改)
6.布尔类型
布尔类型只能用来表达 真、假 。 逻辑判断中 《非零则真》
bool a = 199 ; //非零 则真 true
bool b = 0 ; // false
注意:
- 在逻辑判断中非零则真
- bool类型的大小是 1 字节 , 但是他的值 true / false 都是4字节
- 使用bool 类型需要添加头文件
7.常量与变量
不可以被修改的数据(内存)成为常量 , 可以被修改的数据(内存)称为变量。
int a = 100 ; // a 是变量 100是常量
float f = 123.456 // f 是变量 123.456 是常量
char s[] = "Hello XX" ; // s 是变量 , "Hello XX"是常量
常量类型:
100 整型常量
100L 长整型常量
100LL 长长整型常量
100UL 无符号的长整形常量
3.14 双精度浮点常量
3.14L 长双精度浮点常量
‘a’ 字符型常量
“abc” 字符指针型的常量
8.标准输入:
键盘就是系统提供的标准输入设备, 从键盘中读取数据就称为标准输入。
相关函数:
scanf () ; // 格式化输入函数
头文件:
#include <stdio.h>
函数原型:
int scanf(const char *format, ...);
参数分析:
format --> 格式化控制字符串
返回值:
成功 返回输入成功的次数
失败 0
fgets() ; //字符串输入函数 从标准输入文件中读取字符串
头文件:
#include <stdio.h>
函数原型:
char *fgets(char *s, int size, FILE *stream);
参数分析:
s --> 用于存放获取到的数据
size --> 期望获取多少字节的数据
stream --> 文件的指针流 每一个程序运行都有自动打开(以下三个文件流指针是系统赠送)
stdin --> 标准输入
stdout --> 标准输出
stderr --> 标准出错
返回值:
成功 返回 指针 s
失败 返回NULL
int num; // 没有初始化的话是随机值
printf("num : %d \n" , num );
// & --》 取址符 取得变量的地址
int ret_val = scanf("%d" , &num ); // scanf 会造成阻塞,程序在这里等待不动
printf("ret_val : %d \n" , ret_val );
printf("num : %d \n" , num );
注意:
- scanf 非常矫情, 如果代码中是%d 那么用户必须输入一个整型,否自该数据将会永远留在缓冲区中。
- 格式控制符 format 在用户输入参数中时必须严重代码中的格式来输入(空格似乎不用在意?)
//建议scanf 与getchar 套餐使用
int ret_val = scanf("%d" , &num ); // scanf 会造成阻塞,程序在这里等待不动
while(getchar() != '\n') ; //把scanf 所留在缓冲区的内容给一个一个字符的读取出来直到遇到换行符(回车)
char buf [32] ;
fgets( buf , 32 , stdin ); // 使用 fgets 函数从 stdin(标准输入文件)
//读取 最多 32 字节的信息到 buf 所指向的内存空间中
printf("你输入的内容为:%s \n" , buf );
9.数据类型的转换:
互相兼容但是又不同的数据类型之间可以在同一个表达式中进行类型转换
隐式转换: 系统会按照隐式转换规则帮你转换 。
强制转换: 用户主动要求转换
隐式规则:从类型的精度低到高的转换,目的是保证数据的精度在运算过程中不会丢失。
char --> short --> int --> long --> long long --> float --> double --> long double
低精度 ----------------------------------------------------------------------------> 高精度
9.1隐式转换:
int a = 100 ;
char b = 99 ;
float f = 3.998 ; // 浮点数在存入内存中是通过计算
// 浮点数从内存取出也需要通过计算
// 所以浮点数存进去再取出来数值不能确保完全不变
float x = a + b + f ; // 在当前表达式中所有类型都会被隐式转换为 float
printf("x:%f\n" , x );
9.2强制转换
由用户强制性求去转换(注意精度可能会丢失)
int a = 100 ;
char b = 99 ;
float f = 3.998 ;
float x = a + (int)b + (int)f ;
//当前使用的是强制类型转换
// 注意浮点 f 强转的过程中精度丢失 , f 本身是不受影响,
// 转换只是表达式运算中临时转换
printf("x:%f\n" , x );
printf("f:%d\n" , (int)f );
注意:不管是强转还是隐式转换 都只发生在表达式中临时被转换,并不会影响变量本身。
10.数据类型的本质
各种数据类型只是用户与系统之间约定好如何去分析一片内存。
类型转换只是临时对该约定进行打破。
理论上所有类型都可以互相转换,但是从逻辑上看转后的数据不一定都有意义。