linux基础01|格式化的输入输出
格式化输入输出
printf 大伙太熟了这里就不细讲,给个表格自行查阅吧
符号 | 输出 |
---|---|
%d | int 十进制 |
%u | unsinged 十进制 |
%l | long |
%lld | long long |
%f | float |
%e | double 以指数形式 |
%s | char* |
%g | 较短的输出小数。 |
p | 指针 |
x | 十六进制 |
o | 八进制 |
str print format
sprintf()
1 | int sprintf(char *str, const char *format, ...); |
这玩意好用指出在于将数据整和,拼接到特定变量中, 或文件中(fprintf/fdprintf)。
为了安全起见防止数据溢出,建议使用snprintf() ,除非你很有把握
1 | int snprintf(char *str, size_t size, const char *format, ...); |
by the way :
今天发现了一个坑,发现在赋值的时候当需要赋值超出类型限制的值时,需要进行强制转化,否则就会报错。编译器为了内存安全死活不让你通过。
1 | int a{0xFFFFFFFF};//error |
格式化输出
需要头文件
include
简单的使用凡事
1 | void test(const char* format, ...) { |
va_start 宏用来处理后续参数,出现段错误的原因也在这:
段错误:一半是对内存进行了非法的访问产生。了解这一点我们思路就可以逐渐打开了。
va_list 表示的是参数列表, 而format 这是第一个参数的值
va_start 的作用就是根据format 作为 锚点,通过指针偏移,取出后续参数。本质上,是拿着第一个参数的压栈的地址,偏移。va_start(ap,v);执行ap = (va_list)&v + _INTSIZEOF(v)。
ap+= sizeof(t类型),让ap指向下一个参数的地址。然后返回ap-sizeof(t类型)的t类型指针,这正是第一个可变参数在堆栈里的地址。
vprintf()执行一次就会调用ap偏移指针,取出参数。
可以发现va_list 中记录了四个参数
每执行依次vprintf 参数都会发生改变,也就是偏移,偏着偏着就偏过头了。。
解决就是再调用之前初始化ap va_start(ap, format);
格式化输入
老生常谈scanf
不过需要注意其中还有一些默认的隐藏的东西行为
空格是默认的分隔符,当然输入的时候遇到“%d,%s,%f”时,输入的时候就必须使用逗号分隔!
不部分数据格式是可以自动正确分隔的。
比如说%c%d,反过来%d%c,也没问题…吗?测试一下
int ret = scanf("%d%c", &a, &c); printf("ret = %d %d %c\n", ret, a, c); if (isblank(c)) std::cout << "yes!blank\n"; if (iscntrl(c)) std::cout << "yes!cntrl (int)c = " << (int)c << char(10);
1324 ret = 2 1324 yes!cntrl (int)c = 101
2
3
输出结果嘛,就是将最后的确认 作为转义字符\n 传入c中了
格式化输入也有跟格式化输出相对应的几个函数
比如
格式化字符串输入
sscanf();
格式化字符串赋值
vsscanf()
vsnscanf()
格式化文件输入
vfscanf()