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 ...
随机推荐
- C++ //多态 //静态多态:函数重载 和 运算符重载 属于静态多态 ,复用函数名 //动态多态:派生类和虚函数实现运行时多态
1 //多态 2 //静态多态:函数重载 和 运算符重载 属于静态多态 ,复用函数名 3 //动态多态:派生类和虚函数实现运行时多态 4 5 //静态多态和动态多态的区别 6 //静态多态的函数地址早 ...
- Salesforce Integration 概览(五) Remote Call-In(远程操作 外部->salesforce)
本篇参考:https://resources.docs.salesforce.com/sfdc/pdf/integration_patterns_and_practices.pdf 本篇博客介绍 Re ...
- Android面试6家一线大厂,这个问题是必问!
年后面了六家大厂,每家都会问的一个问题就是Android的消息机制!可见Android的消息机制是多么重要! 消息机制之所以这么重要是因为Android应用程序是通过消息来驱动的,Android某种意 ...
- pfx格式密钥库修改密码
1.pfx格式的密钥库不能直接用keytool修改私钥密码,需要先转成keystore keytool -importkeystore -srckeystore D:/ssl/test.pfx -sr ...
- Vue系列-04-项目1
路飞学城项目 项目搭建 创建项目目录 # cd 项目目录 # vue init webpack luffy 效果 根据上面的提示,我们已经把vue项目构建好了,接下来我们可以在vscode编辑器中把项 ...
- 解密优酷智能生产技术,看 AI 赋能内容数字化
2021 年,随着社会节奏的加快,用户碎片化消费时间不断增加,当前短视频的消费用户规模已超 7.73 亿人,短视频的市场规模超过 2000 亿元.短视频行业发展迅速,但也存在低质内容泛滥,精品内容稀缺 ...
- 深入解析多态和方法调用在JVM中的实现
深入解析多态和方法调用在JVM中的实现 1. 什么是多态 多态(polymorphism)是面向对象编程的三大特性之一,它建立在继承的基础之上.在<Java核心技术卷>中这样定义: 一个对 ...
- 题解 big
传送门 题面里那个式子 考场上我推了半天那个式子代表什么意思,但就是没想到位运算 \(\lfloor \frac{2x}{2x^n} \rfloor \iff x\gg(n-1)\), 即将x的第n位 ...
- [1.1W字] 复习: CSS 9个背景属性&6种渐变函数, 学会可以手写实现AI中强大的"任意渐变"! #Archives009
Title/ CSS Background&Gradient完全指南 #Archives009 序: 关于 background 属性, 了解点CSS的人总会知道个大概. 但是你肯定多半还有点 ...
- 谷歌浏览器崩溃、电脑版微信,vscode打不开网页
家里的电脑使用64位win7,谷歌浏览器直接打开页面都会提示页面崩溃,电脑版微信打开页面链接为空白,vscode打开发行说明或插件说明显示空白,这一系列的问题好像都跟浏览器器有关,之前找了很多文章,都 ...