C语言学习笔记---3.字符串格式化输入输出
1.C语言字符串
字符串(character string)是一个或多个字符的序列,例如:"Zing went the strings of my heart!"
C语言没有专门用于储存字符串的变量类型,字符串都被储存在char类型的数组中。数组由连续的存储单元组成,字符串中的字符被储存在相邻的存储单元中,每个单元储存一个字符。如下图:

注意图4.1中数组末尾位置的字符\0。这是空字符(null character),C语言用它标记字符串的结束。空字符不是数字0,它是非打印字符,其ASCII码值是(或等价于)0。C中的字符串一定以空字符结束,这意味着数组的容量必须至少比待存储字符串中的字符数多1。一个40个储存单元的字符串,只能储存39个字符,剩下一个字节留给空字符。
字符和字符串
字符串常量"x"和字符常量'x'不同。区别之一在于'x'是基本类型(char),而"x"是派生类型(char数组);区别之二是"x"实际上由两个字符组成:'x'和空字符\0
2.C语言格式化输入输出
2.1 printf函数
请求printf()函数打印数据的指令要与待打印数据的类型相匹配。例如,打印整数时使用%d,打印字符时使用%c。这些符号被称为转换说明,们指定了如何把数据转换成可显示的形式。
下表列出了一些转换说明和各自对应的输出类型。

printf()的转换说明修饰符
在%和转换字符之间插入修饰符可修饰基本的转换说明。
如果要插入多个字符,其书写顺序应该与下表相同


1.使用修饰符和标记的示例
#include <stdio.h>
#define PAGES 959
int main(void)
{
printf("*%d*\n", PAGES);
printf("*%2d*\n", PAGES);
printf("*%10d*\n", PAGES);
return 0;
printf("*%-10d*\n", PAGES);
}
结果:
*959*
*959*
* 959*
*959 *
第一个与默认情况相同;第二个转换说明是%2d输出结果应该是两个字段,因为待打印的整数有3位数字,字段宽度自动扩大为3位;
第三个转换说明是%10d,对于输出宽度为10位,即在输出的3位数字前加7个空格;
第四个转换说明为%-10d,输出结果也是10个空格,-标记数字位于字段左侧。
浮点型修饰符示例
示例1:
#include <stdio.h>
int main(void)
{
const double RENT = 3852.99; // const变量
printf("*%f*\n", RENT);
printf("*%e*\n", RENT);
printf("*%4.2f*\n", RENT);
printf("*%3.1f*\n", RENT);
printf("*%10.3f*\n", RENT);
printf("*%10.3E*\n", RENT);
printf("*%+4.2f*\n", RENT);
printf("*%010.2f*\n", RENT);
return 0;
}
结果:
*3852.990000*
*3.852990e+03*
*3852.99*
*3853.0*
* 3852.990*
* 3.853E+03*
*+3852.99*
*0003852.99*
示例2:
#include <stdio.h>
int main(void)
{
printf("%x %X %#x\n", 31, 31, 31);
printf("**%d**% d**% d**\n", 42, 42, -42);
printf("**%5d**%5.3d**%05d**%05.3d**\n", 6, 6, 6, 6);
return 0;
}
输出
1f 1F 0x1f
**42** 42**-42**
** 6** 006**00006** 006**
示例3:
#include <stdio.h>
#define BLURB "Authentic imitation!"
int main(void)
{
printf("[%2s]\n", BLURB);
printf("[%24s]\n", BLURB);
printf("[%24.5s]\n", BLURB);
printf("[%-24.5s]\n", BLURB);
return 0;
}
结果:
[Authentic imitation!]
[ Authentic imitation!]
[ Authe]
[Authe ]
示例1:
第1个转换说明是%f。在这种情况下,字段宽度和小数点后面的位数均为系统默认设置,即字段宽度是容纳带打印数字所需的位数和小数点后打印6位数字。
第2个转换说明是%e。默认情况下,编译器在小数点的左侧打印1个数字,在小数点的右侧打印6个数字。这样打印的数字太多!解决方案是指定小数点右侧显示的位数,程序中接下来的 4 个例子就是这样做的。请注意,第4个和第6个例子对输出结果进行了四舍五入。另外,第6个例子用E代替了e。
第7个转换说明中包含了+标记,这使得打印的值前面多了一个代数符号(+)。0标记使得打印的值前面以0填充以满足字段要求。注意,转换说明%010.2f的第1个0是标记,句点(.)之前、标记之后的数字(本例为10)是指定的字段宽度。
示例2:
第1行输出中,1f是十六进制数,等于十进制数31。第1行printf()语句中,根据%x打印出1f,%F打印出1F,%#x打印出0x1f。
第 2 行输出演示了如何在转换说明中用空格在输出的正值前面生成前导空格,负值前面不产生前导空格。这样的输出结果比较美观,因为打印出来的正值和负值在相同字段宽度下的有效数字位数相同。
第3行输出演示了如何在整型格式中使用精度(%5.3d)生成足够的前导0以满足最小位数的要求(本例是3)。然而,使用0标记会使得编译器用前导0填充满整个字段宽度。最后,如果0标记和精度一起出现,0标记会被忽略。
示例3:
注意,虽然第1个转换说明是%2s,但是字段被扩大为可容纳字符串中的所有字符。还需注意,精度限制了待打印字符的个数。.5告诉printf()只打印5个字符。另外,-标记使得文本左对齐输出。
printf()函数返回值
printf()函数也有一个返回值,它返回打印字符的个数。如果有输出错误,printf()则返回一个负值。
打印较长的字符串
在字符串中,可以使用\n来表示换行字符,但是不能通过按下Enter(或Return)键产生实际的换行符。
给字符串断行有3种方法
方法1:
使用多个printf()语句。因为第1个字符串没有以\n字符结束,所以第2个字符串紧跟第1个字符串末尾输出。
方法2:
用反斜杠(\)和Enter(或Return)键组合来断行。
方法3:
ANSI C引入的字符串连接。
示例:
#include <stdio.h>
int main(void)
{
printf("Here's one way to print a ");
printf("long string.\n");
printf("Here's another way to print a \
long string.\n");
printf("Here's the newest way to print a "
"long string.\n"); /* ANSI C */
return 0;
}
输出:
Here's one way to print a long string.
Here's another way to print a long string.
Here's the newest way to print a long string.
2.2 scanf函数
scanf()把输入的字符串转换成整数、浮点数、字符或字符串,使用指向变量的指针作为参数列表
如果用scanf()读取基本变量类型的值,在变量名前加上一个&;如果用scanf()把字符串读入字符数组中,不要使用&。
示例:
#include <stdio.h>
int main(void)
{
int age; // 变量
float assets; // 变量
char pet[30]; // 字符数组,用于储存字符串
printf("Enter your age, assets, and favorite pet.\n");
scanf("%d %f", &age, &assets); // 这里要使用&
scanf("%s", pet); // 字符数组不使用&
printf("%d $%.2f %s\n", age, assets, pet);
return 0;
}
交互结果:
Enter your age, assets, and favorite pet.
38
92360.88 llama
38 $92360.88 llama
scanf()函数使用空白(换行符、制表符和空格)把输入分成多个字段。在依次把转换说明和字段匹配时跳过空白。
scanf转换说明如下表:

scanf()函数修饰符:


示例:
#include <stdio.h>
#define PRAISE "You are an extraordinary being."
int main(void)
{
char name[40];
printf("What's your name? ");
scanf("%s", name);
printf("Hello, %s.%s\n", name, PRAISE);
return 0;
}
输出:
What's your name? Angela Plains
Hello, Angela.You are an extraordinary being.
在上述示例中scanf()只读取了Angela Plains中的Angela,它在遇到第1个空白(空格、制表符或换行符)时就不再读取输入。一般而言,根据%s转换说明,scanf()只会读取字符串中的一个单词,而不是一整句。
如果使用带多个转换说明的scanf(),C规定在第1个出错处停止读取输入。
格式字符串中的普通字符
scanf()函数允许把普通字符放在格式字符串中。除空格字符外的普通字符必须与输入字符串严格匹配。例如,假设在两个转换说明中添加一个逗号:
scanf("%d,%d", &n, &m);
用户必须像下面这样进行输入两个整数:
88,121
除了%c,其他转换说明都会自动跳过待输入值前面所有的空白。因此,scanf("%d%d", &n, &m)与scanf("%d %d", &n, &m)的行为相同。
对于%c,在格式字符串中添加一个空格字符会有所不同。例如,如果把%c放在格式字符串中的空格前面,scanf()便会跳过空格,从第1个非空白字符开始读取。也就是说,scanf("%c", &ch)从输入中的第1个字符开始读取,而
scanf(" %c", &ch)则从第1个非空白字符开始读取。
scanf()的返回值
scanf()函数返回成功读取的项数。如果没有读取任何项,且需要读取一个数字而用户却输入一个非数值字符串,scanf()便返回0。当scanf()检测到“文件结尾”时,会返回EOF
printf()和scanf()的*修饰符
printf()和scanf()都可以使用*修饰符来修改转换说明的含义
printf()的*修饰符:
如果你不想预先指定字段宽度,希望通过程序来指定,那么可以用*修饰符代替字段宽度。但还是要用一个参数告诉函数,字段宽度应该是多少。也就是说,如果转换说明是%*d,那么参数列表中应包含*和 d对应的值
示例:
#include <stdio.h>
int main(void)
{
unsigned width, precision;
int number = 256;
double weight = 242.5;
printf("Enter a field width:\n");
scanf("%d", &width);
printf("The number is :%*d:\n", width, number);
printf("Now enter a width and a precision:\n");
scanf("%d %d", &width, &precision);
printf("Weight = %*.*f\n", width, precision, weight);
printf("Done!\n");
return 0;
}
输出:
Enter a field width:
6
The number is : 256:
Now enter a width and a precision:
8 3
Weight = 242.500
Done!
scanf()函数*修饰符
把*放在%和转换字符之间时,会使得scanf()跳过相应的输出项.
2.3 strlen()函数
strlen()函数给出字符串中的字符长度
strlen()和sizeof 区别:
示例:
#include <stdio.h>
#include <string.h> /* 提供strlen()函数的原型 */
181
#define PRAISE "You are an extraordinary being."
int main(void)
{
char name[40];
printf("What's your name? ");
scanf("%s", name);
printf("Hello, %s.%s\n", name, PRAISE);
printf("Your name of %zd letters occupies %zd memory cells.\n",
strlen(name), sizeof name);
printf("The phrase of praise has %zd letters ",
strlen(PRAISE));
printf("and occupies %zd memory cells.\n", sizeof PRAISE);
return 0;
}
结果:
What's your name? Serendipity Chance
Hello, Serendipity.You are an extraordinary being.
Your name of 11 letters occupies 40 memory cells.
The phrase of praise has 31 letters and occupies 32 memory cells.
sizeof运算符报告,name数组有40个存储单元。但是,只有前11个单元用来储存Serendipity,所以strlen()得出的结果是11。name数组的第12个单元储存空字符,strlen()并未将其计入。图4.4演示了这个概念。
对于 PRAISE,用 strlen()得出的也是字符串中的字符数(包括空格和标点符号)。然而,sizeof运算符给出的数更大,因为它把字符串末尾不可见的空字符也计算在内。该程序并未明确告诉计算机要给字符串预留多少空间,所以它必须计算双引号内的字符数。
%zd转换说明对strlen()和sizeof都适用。
sizeof使用对象是类型时必须加括号,是特点量时可以加括号也可以不加
例如:
sizeof name;
sizeof 6.28;
sizeof(char);
sizeof(int);
3.常量和预处理
C语言预处理格式:
#define NAME value
用大写表示符号常量是 C 语言一贯的传统。这样,在程序中看到全大写的名称就立刻明白这是一个符号常量,而非变量。大写常量只是为了提高程序的可读性
#define指令还可定义字符和字符串常量。前者使用单引号,后者使用双引号。如下所示:
#define BEEP '\a'
#define TEE 'T'
#define ESC '\033'
#define OOPS "Now you have done it!"
const限定符:
C90标准新增了const关键字,用于限定一个变量为只读。
const int MONTHS = 12;
明示常量:
C头文件limits.h和float.h分别提供了与整数类型和浮点类型大小限制相关的详细信息。每个头文件都定义了一系列供实现使用的明示常量。
limits.h中的明示常量:

float.h中的一些明示常量:

C语言学习笔记---3.字符串格式化输入输出的更多相关文章
- R语言学习笔记:字符串处理
想在R语言中生成一个图形文件的文件名,前缀是fitbit,后面跟上月份,再加上".jpg",先不百度,试了试其它语言的类似语法,没一个可行的: C#中:"fitbit&q ...
- python学习笔记:字符串格式化
% 格式化方法 "我的名字是 %s, 我的年龄是 %d" % (name, age) 常用格式:%[(name)][flags][width].[precision]typecod ...
- 【C语言学习笔记】字符串拼接的3种方法 .
昨天晚上和@buptpatriot讨论函数返回指针(malloc生成的)的问题,提到字符串拼接,做个总结. #include<stdio.h> #include<stdlib.h&g ...
- c语言学习笔记(3)——输入输出
一.基本的输入和输出函数的用法 printf() //屏幕输出 用法: (1)printf("字符串\n"); (2)printf("输出控制符", 输出参数 ...
- C语言学习笔记之字符串拼接的2种方法——strcat、sprintf
本文为原创文章,转载请标明出处 1. 使用strcat进行字符串拼接 #include <stdio.h> #include <stdlib.h> #include <s ...
- Go语言学习笔记六: 循环语句
Go语言学习笔记六: 循环语句 今天学了一个格式化代码的命令:gofmt -w chapter6.go for循环 for循环有3种形式: for init; condition; increment ...
- 2017-05-4-C语言学习笔记
C语言学习笔记... ------------------------------------ Hello C语言:什么是程序:程序是指:完成某件事的既定方式和过程.计算机中的程序是指:为了让计算机执 ...
- GO语言学习笔记(一)
GO语言学习笔记 1.数组切片slice:可动态增长的数组 2.错误处理流程关键字:defer panic recover 3.变量的初始化:以下效果一样 `var a int = 10` `var ...
- Haskell语言学习笔记(88)语言扩展(1)
ExistentialQuantification {-# LANGUAGE ExistentialQuantification #-} 存在类型专用的语言扩展 Haskell语言学习笔记(73)Ex ...
随机推荐
- linux copy_id
ssh-keygen 产生公钥与私钥对. ssh-copy-id 将本机的公钥复制到远程机器的authorized_keys文件中,ssh-copy-id也能让你有到远程机器的home, ~./ssh ...
- Distribute SSH Pubkey to Multiple Hosts with Fabric
Generate ssh keys on source host with ssh-keygen; Disable known_hosts prompt(optional): add "St ...
- 关于stm32 HardFault_Handler 异常的处理 死机
在系统开发的时候,出现了HardFault_Handler硬件异常,也就是死机,尤其是对于调用了os的一系统,程序量大,检测堆栈溢出,以及数组溢出等,找了半天发现什么都没有的情况下,估计想死的心都有了 ...
- Apache虚拟web主机构建
目录 一.构建虚拟web主机 1.1.虚拟web主机概述 二.搭建虚拟web主机步骤 2.1.基于域名搭建虚拟主机 ①为虚拟主机提供域名解析 ②为虚拟主机准备网页文档 ③添加虚拟主机配置 ④设置访问路 ...
- Linux中的账号权限管理
一.用户账号和组账号概述 Linux基于用户身份对资源访问进行控制 1.1.用户账号 超级用户:root 用户是 Linux 操作系统中默认的超级用户账号,对本主机拥有最高的权限.系统中超级用户是唯一 ...
- Linux统计文本中某个字符串出现的次数
常用的有如下两种方式: 1.VIM 用vim打开文件,然后输入: :%s/hello//gn 如下图: 图中的例子就是统计文本中"hello"字符串出现的次数 说明: %s/pat ...
- NOIP 模拟 $26\; \rm 幻魔皇$
题解 \(by\;zj\varphi\) 观察可发现一个点向它的子树走能到的白点,黑点数是一个斐波那契数列. 对于白色点对,可以分成两种情况: 两个白点的 \(lca\) 是其中一个白点 两个白点的 ...
- C#多线程---Semaphore实现线程同步
一.简介 Semaphore类限制可同时访问某一资源或资源池的线程数.线程通过调用 WaitOne方法将信号量减1,并通过调用 Release方法把信号量加1. 构造函数:public Semapho ...
- C# 文件的读取与另存为(WPF)
刚学习时,随便记录的一个小程序.因为有不少人看(应该都是学生),稍作修改,方便阅读. xaml:样式 <!--绑定事件--> <Window.CommandBindings> ...
- css - 样式 - 可见性
visibility 可见性 取值:visible(可见) | hidden(隐藏.保留占位) 设置给:块.行内块.行内元素 作用:设置元素在文档上的可见性 此属性只是隐藏元素,但会为元素保留占位. ...