目录

  • 1. 字符串简介
    • 1.1 char类型数组和null字符
    • 1.2 使用字符串
      • 字符串和字符
    • 1.3 strlen()函数
  • 2. 常量和C预处理器
    • 2.1 const 限定符
    • 2.2 明示常量
  • 3. printf()和scanf()
    • 3.1 printf()函数
    • 3.2 使用printf()
    • 3.3 printf()的转换说明修饰符
      • 使用修饰符和标记的示例
    • 3.4 转换说明的意义
      • 3.4.1 转换不匹配
        • 参数传递
      • 3.4.2 printf()的返回值
      • 3.4.3 打印较长的字符串
    • 3.5 使用scanf()
      • 3.5.1 从scanf()角度看输入(坑)
      • 3.5.2 格式字符串中的普通字符(内存原理未知)
      • 3.5.3 scanf() 的返回值
    • 3.6 printf() 和 scanf() 的 * 修饰符
    • 3.7 printf()的用法提示

1. 字符串简介

1.1 char类型数组和null字符

  • C语言没有专门用于存储字符串的变量类型,字符串都被存储在 char 类型的数组中
  • 数组由连续的存储单元组成,字符串中的字符被存储在相邻的存储单元中,每个单元存储一个字符
a b c \0
每个储存单元1字节 空字符
  • \0:空字符(null character),C语言用它标记字符串的结束
  • 数组的容量必须比待存储字符串中的字符数多1
char c;
// 分配1个字节char c[5];
// 分配5个字节

1.2 使用字符串

  • C语言使用 %s 打印字符串
#include <stdio.h>int main() {char c[5] = "abc";printf("%s\n", c);
}

字符串和字符

字符(‘a’) 字符串(“a”)
基本类型(char) 派生类型(char 数组)
1个字符组成(‘a’) 2个字符组成(‘a’ 和 \0)

1.3 strlen()函数

  • strlen()函数:给出字符串中的字符长度
#include <stdio.h>
#include <string.h>
// 提供 strlen() 函数的原型int main() {char c[5] = "abc";printf("length of %s is %zd\n", c, strlen(c));// length of abc is 3
}
  • strlen() 函数知道在何处停止,不会将空字符计入

2. 常量和C预处理器

  • 使用符号常量(symbolic constant),只需更改符号常量的定义,不用在程序中查找使用常量的地方,然后逐一修改

  • 创建符号常量

    • 声明变量,并将其赋值

      int i = 1;
      
      • 问题:程序可能无意间改变变量的值
    • C预处理器

      #define i 1
      
      • 程序中所有的 i 都会被替换成 1,这一过程被称为编译时替换(compile-time substitution)
      • 在运行程序时,程序中所有的替换均已完成
      • 这样定义的常量也被称为明示常量(manifest constant)

2.1 const 限定符

  • C90新增 const 关键字,用于限定一个变量为只读
  • 只读:可以计算、打印,无法修改
const int i = 1;

2.2 明示常量

  • limits.h:提供与整数类型大小限制相关的详细信息
明示常量 含义
CHAR_BIT char 类型的位数
CHAR_MAX char 类型的最大值
CHAR_MIN char 类型的最小值
  • 可将以上的 CHAR 替换成其他常量名
明示常量 含义
CHAR char 类型
SCHAR signed char 类型
UCHAR unsigned char 类型
SHRT short 类型
USHRT unsigned char 类型
INT int 类型
UINT unsigned int 类型
LONG long 类型
ULONG unsigned long 类型
LLONG long long 类型
ULLONG unsigned long long 类型
  • float.h:提供与浮点数类型大小限制相关的详细信息
明示常量 含义
FLT_MANT_DLG float 类型的尾数位数
FLT_DIG float 类型的最少有效数字位数(十进制)
FLT_MIN_10_EXP 带全部有效数字的 float 类型的最小负指数(以10为底)
FLT_MAX_10_EXP float 类型的最大正指数(以10为底)
FLT_MIN 保留全部精度的 float 类型最小正数
FLT_MAX float 类型的最大正数
FLT_EPSILON 1.00和比1.00大的最小float类型值之间的差值
  • 可将以上的 FLT 替换成其他常量名
明示常量 含义
FLT float 类型
DBL double 类型
LDBL long double 类型

3. printf()和scanf()

  • I/O 函数

  • printf():输出函数

  • scanf():输入函数

3.1 printf()函数

转换说明 输出
%a 浮点数、十六进制数和 p 记数法(C99 / C11)
%A 浮点数、十六进制数和 p 记数法(C99 / C11)
%c 单个字符
%d 有符号十进制整数
%e 浮点数,e 记数法
%E 浮点数,E 记数法
%f 浮点数,十进制记数法
%g 根据值的不同,自动选择 %f 或 %e;%e 格式用于指数小于 -4 或者大于或等于精度
%G 根据值的不同,自动选择 %f 或 %E;%E 格式用于指数小于 -4 或者大于或等于精度
%i 有符号十进制整数(与 %d 相同)
%o 无符号八进制整数
%p 指针
%s 字符串
%u 无符号十进制整数
%x 无符号十六进制整数,使用十六进制数 0f
%X 无符号十六进制整数,使用十六进制数 0F
%% 打印一个百分号

3.2 使用printf()

#include <stdio.h>
#define i 10int main() {printf("%c %d %%\n", '$', 2 * i);// $ 20 %
}

3.3 printf()的转换说明修饰符

修饰符 含义 示例
标记 标记 “%-10d”
数字 最小字段宽度
如果该字段不能容纳待打印的数字或字符串,系统会使用更宽的字段
“%4d”
.数字 精度
对于 %e、%E 和 %f 转换,表示小数点右边数字的位数
对于 %g 和 %G 转换,表示有效数字最大位数
对于 %s 转换,表示待打印字符的最大数量
对于整型转换,表示待打印数字的最小位数
"%5.2f"打印一个浮点数
字段宽度为5字符,其中小数点后有2位数字
h 和整型转换说明一同使用,表示 short int 或 unsigned short int 类型的值 “%hu”,"%hx","%6.4hd"
hh 和整型转换说明一同使用,表示 signed char 或 unsigned char 类型的值 “%hhu”,"%hhx","%6.4hhd"
j 和整型转换说明一同使用,表示 intmax_t 或 uintmax_t 类型的值
这些类型定义在stdint.h中
“%jd”,"%8jx"
l 和整型转换说明一同使用,表示 long int 或 unsigned long int 类型的值 “%ld”,"%8lu"
ll 和整型转换说明一同使用,表示 long long int 或 unsigned long long int 类型的值(C99) “%lld”,"%8llu"
L 和浮点转换说明一同使用,表示 long double 类型的值 “%Lf”,"%10.4Le"
t 和整型转换说明一同使用,表示 ptrdiff_t 类型的值
ptrdiff_t 是2个指针差值的类型(C99)
“%td”,"%12ti"
z 和整型转换说明一同使用,表示 size_t 类型的值
size_t 是 sizeof 返回的类型
“%zd”,"%12zd"
标记 含义 示例
- 待打印项左对齐,即从字段的左侧开始打印该项 “%-20s”
+ 有符号值若为正,则在前面显示加号
有符号值若为负,则在前面显示减号
“%+6.2f”
空格 有符号值若为正,则在前面显示前导空格(不显示任何符号)
有符号值若为负,则在前面显示减号
“% 6.2f”
# 把结果转换为另一种形式
如果为 %o,则以 0 开始
如果为 %x 或 %X,则以 0x 或 0X 开始
对于所有的浮点格式,即使后面没有任何数字,也打印一个小数点字符
对于 %g 和 %G,防止结果后面的 0 被删除
“%#o”,"%#8.0f","%+#10.3e"
0 对于数值,用前导 0 代替空格填充字段宽度
对于整数格式,如果出现 - 标记或指定精度,则忽略该标记
“%010d”,"%08.3f"

使用修饰符和标记的示例

#include <stdio.h>int main() {int i = 123;printf("%d\n", i);// 123printf("%2d\n", i);// 123printf("%5d\n", i);//   123printf("%-5d\n", i);// 123
}
#include <stdio.h>int main() {double d = 1.234;printf("%f\n", d);// 1.234000printf("%e\n", d);// 1.234000e+00printf("%4.2f\n", d);// 1.23printf("%3.1f\n", d);// 1.2printf("%10.3f\n", d);//      1.234printf("%10.3E\n", d);//  1.234E+00printf("%+4.2f\n", d);// +1.23printf("%010.2f\n", d);// 0000001.23
}

3.4 转换说明的意义

3.4.1 转换不匹配

#include <stdio.h>int main() {int i = 336;int j = 65618;printf("short = %hd, unsigned short = %hu\n", i, i);// short = 336, unsigned short = 336printf("short = %hd, unsigned short = %hu\n", -i, -i);// short = -336, unsigned short = 65200printf("int = %d, char = %c\n", i, i);// int = 336, char = P// 336 = 256 + 80;80 = Pprintf("int = %d, short = %hd, char = %c\n", j, j, j);// int = 65618, short = 82, char = R// 65618 = 65536 + 82// 65618 = 256 * 256 + 82;82 = R}

参数传递

#include <stdio.h>int main() {float f = 1.0f;double d = 123456789.0;long l1 = 1, l2 = 1;printf("%ld %ld %ld %ld\n", f, d, l1, l2);// 0 1072693248 1409286144 1100836660
}
  • 第一个 %ld 获取 f 的前 4 个字节
  • 第二个 %ld 获取 f 的后 4 个字节
  • 第三个 %ld 获取 d 的后 4 个字节
  • 第四个 %ld 获取 d 的后 4 个字节

3.4.2 printf()的返回值

  • printf() 函数返回值为打印字符的个数

3.4.3 打印较长的字符串

#include <stdio.h>int main() {printf("abc ");printf("ABC\n");printf("abc \
ABC\n");printf("abc ""ABC\n");
}

3.5 使用scanf()

printf() scanf()
参数列表:变量、常量和表达式 指向变量的指针
  • 如果用 scanf() 读取基本变量类型的值,在变量名前加上 &
  • 如果用 scanf() 把字符串读入字符数组中,不要使用 &
#include <stdio.h>int main() {int i;float f;char c[10];printf("i, f = ");scanf("%d %f", &i, &f);printf("c[10] = ");scanf("%s", c);printf("%d %.2f %s\n", i, f, c);
}
转换说明 含义
%c 字符
%d 有符号十进制整数
%e、%f、%g、%a 浮点数(C99新增 %a)
%E、%F、%G、%A 浮点数(C99新增 %A)
%i 有符号十进制整数
%o 有符号八进制整数
%p 指针(地址)
%s 字符串
从第一个非空白字符开始,到下一个空白字符之前的所有字符
%u 无符号十进制整数
%x、%X 有符号十六进制整数
修饰符 含义 示例
* 抑制赋值 “%*d”
数字 最大字段宽度
输入达到最大字段宽度处,或第1次遇到空白字符停止
“%10s”
hh 把整数作为 signed char 或 unsigned char 类型读取 “%hhd”、"%hhu"
ll 把整数作为 long long 或 unsigned long long 类型读取(C99) “%lld”、"%llu"
h、l 或 L 把整数作为 short、long 类型读取 “%hd”、"%ld"
j 使用 intmax_t 或 uintmax_t 类型(C99) “%jd”、"%ju"
z 使用 sizeof 的返回值类型(C99) “%zd”、"%zo"
t 使用表示2个指针差值的类型(C99) “%td”、"%tx"

3.5.1 从scanf()角度看输入(坑)

  • scanf() 从缓冲区获取数据

  • scanf() 会将所有输入的数据全部送入缓冲区,在缓冲区中按照输入条件获取数据,并将获取的数据从缓冲区删除

  • 在输入获取之后,如有数据残留,保留该数据,当下次使用 scanf() 时从缓冲区获取,不再进行输入

  • 当缓冲区为空时才会让用户进行输入

  • scanf() 将字符串类型数据送入执行数组中时,会自动在字符序列的末尾添加 ‘\0’

#include <stdio.h>int main() {int i;char c[10];scanf("%d %s", &i, c);// 1.23 abcprintf("i = %d, c[10] = %s\n", i, c);// i = 1, c[10] = .23scanf("%s", c);printf("c[10] = %s\n", c);// c[10] = abc
}

3.5.2 格式字符串中的普通字符(内存原理未知)

  • 用户需要严格按照 scanf() 中格式字符串的格式进行输入
#include <stdio.h>int main() {int i;char c[10];scanf("%d, %s", &i, c);// 1,abcprintf("i = %d, c[10] = %s\n", i, c);// i = 1, c[10] = abc
}

3.5.3 scanf() 的返回值

  • scanf() 函数返回值为成功读取的项数

3.6 printf() 和 scanf() 的 * 修饰符

  • printf()
#include <stdio.h>int main() {int i = 6;int j = 8;int a = 1234;double d = 242.5;printf("%*d\n", i, a);//   1234printf("%*.*f\n", j, i, d);// 242.500000
}
  • scanf()
#include <stdio.h>int main() {int i = 0;scanf("%*d %*d %d", &i);// 1 2 3printf("%d\n", i);// 3
}

3.7 printf()的用法提示

  • 使用足够大的固定字段宽度让输出整齐美观
#include <stdio.h>int main() {printf("%d %d %d\n", 1, 123, 12345);printf("%d %d %d\n", 12345, 123, 1);// 1 123 12345// 12345 123 1printf("%7d %7d %7d\n", 1, 123, 12345);printf("%7d %7d %7d\n", 12345, 123, 1);//       1     123   12345//   12345     123       1
}
  • 在文字中嵌套数字,指定一个小于或等于该数字宽度的字段
#include <stdio.h>int main() {printf("ABC %10.2f abc\n", 1.234);// ABC       1.23 abcprintf("ABC %.2f abc\n", 1.234);// ABC 1.23 abc
}

C Primer Plus 第4章(字符串和格式化输入输出)相关推荐

  1. 第4章 字符串和格式化输入/输出

    学习笔记--<C Primer Plus> 第4章 字符串和格式化输入/输出 4.1 前导程序 4.2 字符串简介 4.2.1 char 类型数组和 null 字符 4.2.2 使用字符串 ...

  2. c语言字符型输入格式化,c语言之字符串和格式化输入输出

    字符串和格式化输入输出 #include #include #define DENSITY 62.4 int main(void) { float weight, volume; int size, ...

  3. java判断输入的格式化_Java的字符串及格式化输入输出

    Java的字符串及格式化输入输出 1.String的不可变 在浅析Java的jvm上的内存位置的分配里已经说明,String使用了常量池技术,所以在栈中的应用要么是指向常量池,要么是指向堆,Strin ...

  4. c++ 数组的输入遇到特定字符停止输入_C语言 第4章-字符串和格式化输入/输出

    #include 用数组name储存字符串,name数组有40个字节,每个字节储存一个字符值. 在scanf()函数中,输入字符串name没有&前缀. C预处理器把字符常量DENSITY定义为 ...

  5. C Primer Plus第三章总结

    C Primer Plus第三章总结 关于整数和浮点数 关于整数的常用的关键词有:char.int .long.longlong.unsigned-- 浮点数常用的关键词有:double.float ...

  6. 《C++ Primer》第14章 14.3节习题答案

    <C++ Primer>第14章 操作重载与类型转换 14.3节  算术和关系运算符  习题答案 练习14.13:你认为Sales_data类还应该支持哪些其他算术运算符(参见表4.1,第 ...

  7. 《C++ Primer》第9章 9.3节习题答案

    <C++ Primer>第9章 顺序容器 9.3节顺序容器操作习题答案 练习9.18:编写程序,从标准输入读取string序列,存入一个deque中.编写一个循环,用迭代器打印deque中 ...

  8. C++ Primer Plus 第七章编程题练习

    C++ Primer Plus 第七章编程题练习 第一题 题目描述 编写一个程序,不断要求用户输入两个数,直到其中的一个为0.对于每两个数,程序将使用一个 函数来计算它们的调和平均数,并将结果返回给m ...

  9. 《C++ Primer》第13章 13.5节习题答案

    <C++ Primer>第13章 拷贝控制 13.5节 动态内存管理类 习题答案 练习13.39:编写你自己版本的StrVec,包括自己版本的reserve.capacity(参见9.4节 ...

最新文章

  1. Windows 2008 r2域更名
  2. 从易于扩展扩展的角度来设计FizzBuzzWhizz
  3. BZOJ 1568 李超线段树
  4. jetson nano包安装
  5. 自动化机器学习(三)神经网络架构搜索综述(NAS)简述
  6. DCMTK:用于管理常见细分特定类型的类
  7. [转](传输层)UDP协议
  8. React 是怎样炼成的
  9. gis发布及应用服务器,超图云GIS应用服务器平台
  10. 易错点:C 语言 continue while for 循环
  11. 【转】Content-type的几种常见类型
  12. 交互式计算机图形学 第六版 pdf,1交互式计算机图形学系统.pdf
  13. 数字光电耦合器为汽车应用提供低功耗和高隔离
  14. SEM和SEO的区别?
  15. MCtalk对话尚德机构:与教研和大数据结合的AI,才是真功夫
  16. 同步和异步修改页面传来的时间类型
  17. 产品三维模型在线展示
  18. 利用python open-cv aimageio完成avi png mp4 gif间的转换
  19. D.E.Shaw拟以8000万美元收购SunEdison光伏电站股权
  20. Java找出字符串中第一个不重复的字符

热门文章

  1. 后端基础入门技术栈简单小结(非常简单)
  2. 新功能上线:JCJC错别字检测支持自定义词汇啦!
  3. Python:哔哩哔哩B站视频下载,我终于对小破站下手了
  4. 瞎说系列——Mysql update的执行过程
  5. 【DockerCE】Docker-CE 24.0.1正式版发布
  6. 记录一下HALCON基于可变形,利用CAD画dxf模板进行模板匹配(三)
  7. 如何使用ArcGIS计算道路中心线
  8. 项目如何简单的使用pass平台部署服务
  9. 人机对齐概述|10. AGI可能导致的生存性风险:早期的概念性探讨
  10. java实现图片固定长宽的缩放和裁剪