字符串简介

字符串是一个或多个字符的序列。

  1. char类型数组和null字符
    字符串都被存储在char类型的数组中,数组末尾位置有一个字符\0,这是空(null)字符,C语言用它标记字符串的结束。C中的字符串一定是以空字符结束的,这意味着数组的容量必至少比待存储字符串中的字符多1。
  2. 使用字符串

    • printf():使用%s打印一个字符串。
    • scanf():使用%s读取一个字符串,你不用亲自把空字符放入字符串末尾,scanf()在读取输入时就已经完成这项工作,字符串常量同样。注意,scanf()的%s遇到第一个空白(空格、制表符或换行符)时就不再读取输入
    • 字符串和字符:字符串常量"x"和字符常量'x'不同。区别在于:

      1. 'x'是基本类型(char),而"x"是派生类型(char数组);
      2. "x"实际上由两个字符组成:'x'和空字符\0
  3. strlen()函数

    sizeof运算符以字节为单位给出对象大小,strlen()函数给出字符串中的字符长度。

虽然一字节存储一个字符,但sizeof和strlen()得出的结果并不相同,它们的主要区别是:
sizeof侧重该字符串所占用的存储空间,即即使字符串并没有占用满该char数组的空间,sizeof也给出所有空间大小;
strlen()则侧重字符串的实际长度,即字符串没有占用满char数组的空间,只给出实际字符串的长度。

常量和C预处理器

#define(宏定义):符号常量(明示常量)。C预处理器会替换所有符号常量为其定义的实际值,这叫编译时替换。预处理器只做替换,不做任何计算,所以不用把定义符号常量当成变量定义,比如不用加赋值符号,不用分号结尾,实际上只是做一个对应关系即可。另外,符号常量通常采用全大写字母命名。

  1. const(C90标准):只读变量。用于限定一个变量为只读。与#define最大区别是,const是变量,会真实的把值存在内存里,处于程序运行时;而#define只是一个符号对应定义,不存在内存,只完成替换,处于编译时替换。
  2. 明示常量:C提供了一些定义好明示常量的头文件。如 limits.hfloat.h,分别提供了与整型类型和浮点类型大小限制相关的详细信息。

    • limits.h中的一些明示常量:
    明示常量含义
    CHAR_BITchar 类型的位数
    CHAR_MAXchar 类型的最大值
    CHAR_MINchar 类型的最小值
    SCHAR_MAXsigned char 类型的最大值
    SCHAR_MINsigned char 类型的最小值
    UCHAR_MAXunsigned char 类型的最大值
    SHRT_MAXshort 类型的最大值
    SHRT_MINshort 类型的最小值
    USHRT_MAXunsigned short 类型的最大值
    INT_MAXint 类型的最大值
    INT_MINint 类型的最小值
    UINT_MAXunsigned int 类型的最大值
    LONG_MAXlong 类型的最大值
    LONG_MINlong 类型的最小值
    ULONG_MAXunsigned long 类型的最大值
    LLONG_MAXlong long 类型的最大值
    LLONG_MINlong long 类型的最小值
    ULLONG_MAXunsigned long long 类型的最大值
    • float.h中的一些明示常量:
    明示常量含义
    FLT_MANT_DIGfloat 类型的尾数位数
    FLT_DIGfloat 类型的最少有效数字位数(十进制)
    FLT_MIN_10_EXP带全部有效数字的float 类型的最小负指数(以10为底)
    FLT_MAX_10_EXPfloat 类型的最大正指数(以10为底)
    FLT_MIN保留全部精度的float类型最小正数
    FLT_MAXfloat 类型的最大正数
    FLT_EPSILON1.00和比1.00大的最小float类型值之间的差值

printf()和scanf()

printf()函数和scanf()函数能让用户可以与程序交流,它们是输入/输出函数,或简称I/O函数

printf()函数

请求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
%%打印一个百分号

使用printf()

printf()函数的格式:printf(格式字符串, 待打印项1, 待打印项2, ...);
格式字符串中的转换说明一定要与后面的每个项相匹配,若忘记这个基本要求会导致严重后果。

printf()的转换说明修饰符

修饰符含义
标记有5种标记(-、+、空格、#和0),可以不使用标记或使用多个标记(参见下表)
数字最小字段宽度。如果该字段不能容纳待打印的数字或字符串,系统会使用更宽的字段
.数字精度。对于%e%E%f转换,表示小数点右边数字的位数;对于%g%G转换,表示有效数字最大位数;对于%s转换,表示待打印字符的最大数量;对于整型转换,表示待打印数字的最小位数;如有必要,使用前导0来达到这个位数;只使用.表示其后跟随一个0,所以%.f%.0f相同
h和整型转换说明一起使用,表示 short int 或 unsigned short int 类型的值
hh和整型转换说明一起使用,表示 signed char 或 unsigned char 类型的值
j和整型转换说明一起使用,表示 intmax_t 或 uintmax_t 类型的值。这些类型定义在 stdint.h 中
l和整型转换说明一起使用,表示 long int 或 unsigned long int 类型的值
ll和整型转换说明一起使用,表示 long long int 或 unsigned long long int 类型的值(C99)
L和浮点转换说明一起使用,表示 long double 类型的值
t和整型转换说明一起使用,表示 ptrdiff_t 类型的值。ptrdiff_t是两个指针差值的类型(C99)
z和整型转换说明一起使用,表示 size_t 类型的值。size_t 是 sizeof 返回类型(C99)
  • printf()中的标记:
标记含义
-待打印项左对齐
+有符号值若为正,则在值前面显示加号;若为负,则在值前面显示减号
空格有符号值若为正,则在值前面显示前导空格;若为负,则在值前面显示减号;+标记覆盖一个空格
#把结果转换为另外一种形式
0对于数值格式,用前导0代替空格填充字段宽度。对于整数格式,如果出现-标记或指定精度,则忽略该标记

转换说明的意义

转换说明把以二进制格式存储在计算机中的值转换成一系列字符(字符串)以便显示。转换说明是翻译说明

  1. 转换不匹配
    转换说明应该与待打印值的类型相匹配。因为参数传递:函数传参,程序把传入的值放入被称为的内存区域,计算机根据变量类型(不是根据转换说明)把这些值放入栈中;printf()函数根据转换说明(不是根据变量类型)从栈中读取值,根据转换说明读取相应的字节数。
  2. printf()的返回值
    返回打印字符的个数。如果有输出错误,则返回一个负值。
  3. 打印较长的字符串
    参数间(逗号)可以断行,但不能在双引号括起来的字符串中间断行(按下Enter或Return键),应使用\n表示换行字符。

使用scanf()

scanf()把输入的字符串转换成整数、浮点数、字符或字符串,而printf()正好相反,把整数、浮点数、字符和字符串转成显示在屏幕上的文本;两个函数的主要区别在于参数列表中,printf()函数使用变量、常量和表达式,而scanf()函数使用指向变量的指针。

scanf()函数使用空白(换行符、制表符和空格)把输入分成多个字段。再依次把转换说明和字段匹配时跳过空白;唯一例外的是%c转换说明。根据%c,scanf()会读取每个字符,包括空白。

  • ANSI C中的scanf()的转换说明:
转换说明含义
%c把输入解释成字符
%d把输入解释成有符号十进制整数
%e、%f、%g、%a把输入解释成浮点数(C99标准新增了%a)
%E、%F、%G、%A把输入解释成浮点数(C99标准新增了%A)
%i把输入解释成有符号十进制整数
%o把输入解释成有符号八进制整数
%p把输入解释成指针(地址)
%s把输入解释成字符串。从第一个空白字符开始,到下一个空白字符之前的所有字符都是输入
%u把输入解释成无符号十进制整数
%x、%X把输入解释成有符号十六进制整数
  • scanf()转换说明中的修饰符:
转换说明含义
*抑制赋值
数字最大字段宽度。输入达到最大字段宽度处,或第一次遇到空白字符时停止
hh把整数作为 signed char 或 unsigned char 类型读取
ll把整数作为 long long 或 unsigned long long 类型读取(C99)
h、l或L"%hd"和"%hi"表明把对应的值存储为short int类型; "%ho"、"%hx"和"%hu"表明把对应的值存储为unsigned short int类型; "%ld"和"%li"表明把对应的值存储为long类型; "%lo"、"%lx"和"%lu"表明把对应的值存储为unsigned long类型; "%le"、"%lf"和"%lg"表明把对应的值存储为double类型; 在e、f和g前面使用L而不是l,表明把对应的值被存储为long double类型。如果没有修饰符,d、i、o和x表明对应的值被存储为int类型,f和g表明把对应的值存储为float类型
j在整型转换说明后面时,表明使用 intmax_t 或 uintmax_t 类型(C99)
z在整型转换说明后面时,表明使用 sizeof 的返回类型(C99)
t在整型转换说明后面时,表明使用表示两个指针差值的类型(C99)
  • 从 scanf() 角度看输入

    • scanf()函数每次读取一个字符,跳过所有的空白字符,直至遇到第一个非空白字符(除了%c转换说明)才开始读取。
    • 遇到第一个空白字符(或其他不满足转换说明的不同类型数据)即读到了末尾,然后scanf()把剩下的字符放回输入。这意味着下次读取输入是从上一次丢弃的字符开始读取。
    • 如果使用字段宽度,scanf()会在字段结尾或第一个空白字符停止读取(满足两个条件之一便停止)。
    • 如果一直读取不了(转换说明不匹配)某个字符,scanf()就一直无法越过该字符读下一个字符。另外,如果使用带多个转换说明的scanf(),C规定在第一个出错处停止读取输入。
  1. 格式字符串中的普通字符
    scanf()函数允许把普通字符放在格式字符串中。除空格字符外的普通字符必须与输入字符串严格匹配。
  2. scanf()的返回值
    返回成功读取的项数。如没有读取到任何项,则返回0。当scanf()检测到文件结尾时,会返回EOF

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

如果你不想预先指定字段宽度,希望通过程序来指定,那么可以使用*修饰符代替字段宽度。但还是需要一个参数告诉函数,字段宽度应是多少。
scanf()中的*的用法有所不同。把*放在%和转换字符之间时,会使得scanf()跳过相应的输出项。

标签: C/C++, C-Primer-Plus

添加新评论