第三章——字符串的格式化输入输出

.前导程序:

/*
	2020年5月27日11:15:32
	目的:了解字符串的格式化输入输出 
	
*/ 


#include <stdio.h>
#include <string.h> //提供strlen()函数
#define DENSITY 62.4     //人体密度

int main()
{
	float weight, volum;
	int size, letters;
	char name[40];    // name 是一个可以容纳40个字符的数组
	
	printf("海,你的姓名是\n");
	scanf("%s", name);
	printf("%s,你有多重呢?\n", name);
	scanf("%f", &weight);
	
	letters = strlen(name);      //计算字符数。 
	printf("你的名字有%d个字", letters);
	 
	
	
	
	return 0;
} 

字符串简介:

  • 一个或多个字符的序列。 如: “好好学习,加油” ------- 注:双引号告知编译器这是字符串

  • C语言没有专门用于存储字符串的变量类型,字符串都被存储在char类型的数组中。

char 类型数组和null字符
在这里插入图片描述
C语言使用— \0----来标记字符串的结束。不是表示数字 0 这是非打印字符,其ASCII 的值为 0。

  • 注:数组的容量至少比待存字符串中字符数多 1 ,用来存放 \0

如何使用字符串:

/*
	2020年5月27日11:33:36
	目的:使用字符串。 

*/
#include <stdio.h>
#define PRAISE "You are an extraordinary being"

int main()
{
	char name[40];                          //定义一个字符数组
	
	printf("What's your name? \n");
	scanf("%s", name);                        //从键盘指定输入字符串,scanf()函数会自动将 \0 读入末尾。
	printf("Hello, %s.%s\n", name, PRAISE);
	
	
	return 0;
} 

字符串和字符:
在这里插入图片描述
strlen()函数:

  • sizeof 运算符,它是以字节为单位给出对象大小。strlen()函数给出字符串字符串中的字符长度。
  • 程序实例:
/*
	2020年5月27日11:52:37	 
	目的:在计算字符串长度中-----测试sizeof 运算符 与 strlen()函数 的差别。 
*/
#include <stdio.h>
#include <string.h>
#define PRAISE "You are an extraordinary being."

int main()
{
	char name[40];
	
	printf("What's your name? \n");
	scanf("%s", name);
	printf("Hello, %s.%s\n", name, PRAISE);
	printf("sizeof_name = %zd, strlen_name = %zd\n", sizeof name, strlen(name));
	printf("sizeof_PRAISE = %zd, strlen_PRAISE = %zd\n", sizeof PRAISE, strlen(PRAISE));
	
	
	return 0;
} 

总结:

  • sizeof 计算name 数组时,是计算name数组占用的内存的字节数,而 strlen是计算数组中的字符数
  • 在这里插入图片描述
  • 对于上述字符串 PRAISE 来说:strlen 得出的也是字符串的字符数(包括空格与标点)。不包括 \0
  • 然而 sizeof 运算符给出的数更大,因为它把字符串末尾不可见 的空字符也计算在内。

注意:对于类型,应写 成sizeof(char)或sizeof(float);对于特定量,可写成sizeof name或sizeof 6.28。建议所有情况下都使用圆括号,如sizeof(6.28)。

常量和C预处理器

如何创建一个符号常量:
例:

#define TAXRATE 0.015
  • 编译程序时,程序中所有的TAXRATE都会被替换成0.015。这一过程被 称为编译时替换(compile-time substitution)。
  • 定义的常量也称为明示常量 (manifest constant)

格式:#define NAME value

  • 符号常量名和合适的值来替换NAME和value。
  • 末尾不用加分号
  • 符号常量的命名规则与变量相同。可以使用大小写字母、数字和下划线 字符,首字符不能为数字。
  • #define指令还可定义字符和字符串常量。前者使用单引号,后者使用双 引号。

程序示例:

/*
	2020年5月27日13:05:52 
	目的: 测试 define 定义符号常量 
*/ 
#include <stdio.h>
#define PI 3.14159

int main()
{
	float area, circum, radius;
	
	printf("What is the radius of your pizza?\n");
	scanf("%f", &radius);
	area = PI * radius * radius;
	circum = 2.0 * PI * radius;
	printf("area = %1.2f--------------circum = %1.2f\n", area, circum); //%1.2f表明,结果被四舍五入为两位小数输出。
 
	
	return 0;
} 

const 限定符:
C90标准新增了const关键字,用于限定一个变量为只读。

  • 声明如下:
    • const int MONTHS = 12; // MONTHS在程序中不可更改,值为12

4.3.2 明示常量:
C头文件limits.h和float.h分别提供了与整数类型和浮点类型大小限制相 关的详细信息。每个头文件都定义了一系列供实现使用的明示常量。

  • ---------------------- limits.h中的一些明示常量
    在这里插入图片描述
  • ---------------------- float.h中的一些明示常量`中的一些明示常量
  • 在这里插入图片描述

程序示例:

/*
	2020年5月27日13:27:30 
	目的:测试 整数类型与浮点数类型大小相关限制相关信息
*/

#include <stdio.h>
#include <limits.h>
#include <float.h> 

int main()
{
	printf("整数类型与浮点数类型大小相关限制相关信息\n");
	printf("Biggest int = %d\n", INT_MAX);
	printf("Smallest long long = %lld\n", LLONG_MIN);
	printf("One byte = %d\n",CHAR_BIT);
	printf("Largest double: %e\n", DBL_MAX);
	printf("Smallest normal float = %e\n", FLT_MIN);
	printf("float precision = %d\n", FLT_DIG);
	printf("float epsilon = %e\n", FLT_EPSILON); 
	
	return 0;
}

printf()和scanf() 函数:

printf()函数:

请求printf()函数打印数据的指令要与待打印数据的类型相匹配

  • 例如, 打印整数时使用%d,打印字符时使用%c。这些符号被称为转换说明

------------------------------- 转换说明及其打印的输出结果
在这里插入图片描述
程序示例:

/*
	2020年5月27日13:39:44 
	目的:测试printf 转换说明 
*/ 

#include <stdio.h>
#define PI 3.141593

int main()
{
	int number = 7;
	float pies = 12.75;
	int cost = 7800;
	
	printf("number = %d-----pies = %f\n", number, pies);
	printf("PI = %f\n", PI);
	printf("%c%d",'&', 2*cost);
		
	
	return 0; 
} 

printf()函数的格式:

  • printf( 格式字符串, 待打印项1, 待打印项2,…);
    • 待打印项1、待打印项2等都是要打印的项。它们可以是变量、常量,甚 至是在打印之前先要计算的表达式
    • 格式字符串应包含每个 待打印项对应的转换说明。
    • 格式字符串中的转换说明一定要与后面的每个项相匹配。

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

  • 在%和转换字符之间插入修饰符可修饰基本的转换说明。下面列出可作为修饰符的合法字符。如果要插入多个字符,其书写顺序应该与下表 中列出的顺序相同。不是所有的组合都可行
  • 表中有些字符是C99新增 的,如果编译器不支持C99,则可能不支持表中的所有项。

在这里插入图片描述
在这里插入图片描述
printf()中的标记:
在这里插入图片描述
程序示例:

/*
	2020年5月27日14:07:51 
	目的:字段宽度测试 
*/ 

#include <stdio.h> 
#define PAGES 959

int main()
{
	printf("*%d*\n", PAGES);
	printf("*%2d*\n", PAGES);
	printf("*%10d*\n", PAGES);
	printf("*%-10d*\n",PAGES);
	
	
	return 0;
}
/*
输出结果:
*959*
*959*
*       959*
*959       *
 
*/

说明:

  • 第1个转换说明%d不带任何修饰符,其对应的输出结果与带整数字段宽 度的转换说明的输出结果相同。
  • 第2个转换说明是%2d,其对应的输出结果应该是 2 字段宽度。因为待打印的整数有 3 位数字,所以字段宽度自动扩大以符合整数的长度。
  • 第3个转换说明是%10d,其对应的输出结果有10个空格宽度,实际上在两个星号之间有7个空格和3位数字,并且数字位于字段的右侧。
  • 最后一个转换说明是%-10d,其对应的输出结果同样是 10 个空格宽度,-标记说明打印的数字位于字段的左侧
/*
	2020年5月27日14:23:09 
	目的: 测试浮点型修饰符的组合 
*/

#include <stdio.h>

int main()
{
	const double RENT = 3825.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;
} 
/*
输出结果: 
*3825.990000*
*3.825990e+003*
*3825.99*
*3826.0*
*  3825.990*
*3.826E+003*
*+3825.99*
*0003825.99*

*/ 

说明:

  • 第1个转换说明是%f。在这种情况下,字段宽度和小数点后面的位数均为系统默认设置,即字段宽度是容纳带打印数字所需的位数和小数后打印6位数字
  • 第2个转换说明是%e。默认情况下,编译器在小数点的左侧打印1个数 字,在小数点的右侧打印6个数字。这样打印的数字太多!解决方案是指定 小数点右侧显示的位数。
  • 第4个和第6个例子对输出结果进行了四舍五入
  • 第7个转换说明中包含了+标记,这使得打印的值前面多了一个代数符 号(+)。
  • 0标记使得打印的值前面以0填充以满足字段要求。
  • %010.2f的第1个0是标记,句点(.)之前、标记之后的数字(本例为10) 是指定的字段宽度。
/*
	2020年5月27日14:38:32
	目的:测试一些格式标记 
*/ 

#include <stdio.h>

int main()
{

	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** 

*/ 

说明:

  • 第1行输出中,1f是十六进制数,等于十进制数31。第1行printf()语句 中,根据%x打印出1f,%F打印出1F,%#x打印出0x1f。
  • 第 2 行输出演示了如何在转换说明中用空格在输出的正值前面生成前导空格负值前面不产生前导空格。这样的输出结果比较美观,因为打印出来 的正值和负值在相同字段宽度下的有效数字位数相同。
  • 第3行输出演示了如何在整型格式中使用精度(%5.3d)生成足够的前 导0以满足最小位数的要求(本例是3)。然而,使用0标记会使得编译器用 前导0填充满整个字段宽度。最后,如果0标记和精度一起出现,0标记会被 忽略。
/*
	2020年5月27日14:48:42
	目的:测试字符串格式 
*/ 
#include <stdio.h> 
#define BLURB "Authentic imitation!"

int main()
{
	
	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个转换说明是%2s,但是字段被扩大为可容纳字符串中 的所有字符。
  • 精度限制了待打印字符的个数。.5告诉printf()只打 印5个字符。另外,-标记使得文本左对齐输出.

printf()的返回值:
printf()函数也有一个返回值,它返回打印字符的个数。

/*
	2020年5月27日15:03:20
	目的:测试 printf() 函数返回值 
*/ 

#include <stdio.h>

int main()
{
	int a;
	
	a = printf("哈哈哈%d\n", 222);
	printf("%d\n",a);
	
	return 0;
	
} 
/*
输出结果:
哈哈哈222
10
*/ 

说明:

  • 返回值是,格式化字符串中的所有字符,包括 \n

注意:

printf("The printf() function printed %d characters.\n"
rv); 

该语句在逗号和 rv之间断行。为了让读者知道该行未完,示例缩rv。C编译器会忽略多余的空白。

但是,不能在双引号括起来的字符串中间断行。如果这样写:

printf("The printf() function pr
inted %d characters.\n", rv);
  • C编译器会报错:字符串常量中有非法字符。在字符串中,可以使用\n 来表示换行字符,但是不能通过按下Enter(或Return)键产生实际的换行 符

解决方法:这是为了解决字符串很长问题。
示例:

#include <stdio.h>

int main()
{
	printf("哈哈哈哈哈哈哈哈哈");   //方法一 
	printf("whs\n");
	
	printf("哈哈哈哈哈哈哈哈哈\    //方法二
whs\n"); 
	
	printf("哈哈哈哈哈哈哈哈哈"   //方法三
	"whs\n");
	
	
	return 0; 
		
} 
/*
输出结果: 
哈哈哈哈哈哈哈哈哈whs
哈哈哈哈哈哈哈哈哈whs
哈哈哈哈哈哈哈哈哈whs

*/

说明:

  • 方法1:使用多个printf()语句。因为第1个字符串没有以\n字符结束,所 以第2个字符串紧跟第1个字符串末尾输出。
  • 方法2:用反斜杠(\)和Enter(或Return)键组合来断行。这使得光标 移至下一行,而且字符串中不会包含换行符。其效果是在下一行继续输出。 但是,下一行代码必须和程序清单中的代码一样从最左边开始。如果缩进该 行,比如缩进5个空格,那么这5个空格就会成为字符串的一部分
  • ANSI C引入的字符串连接。在两个用双引号括起来的字符串之 间用空白隔开,C编译器会把多个字符串看作是一个字符串。

scanf()函数:

  • scanf()是最通用的一个,因为它可以读取不同格式的数据。当 然,从键盘输入的都是文本,因为键盘只能生成文本字符:字母、数字和标 点符号。如果要输入整数 2014,就要键入字符 2、0、1、4。如果要将其储 存为数值而不是字符串,程序就必须把字符依次转换成数值,这就是scanf() 要做的。
  • scanf()把输入的字符串转换成整数、浮点数、字符或字符串,而 printf()正好与它相反,把整数、浮点数、字符和字符串转换成显示在屏幕上 的文本
  • scanf()和 printf()类似,也使用格式字符串和参数列表。
  • 两个函数主要的区别在参数列表 中。printf()函数使用变量、常量和表达式,而scanf()函数使用指向变量的指 针。

程序示例:

#include <stdio.h>

int main()
{
	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;
} 

说明:

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

scanf()中的转换说明:
在这里插入图片描述

  • scanf()函数所用的转换说明与printf()函数几乎相同。主要的区别是,对 于float类型和double类型,printf()都使用%f、%e、%E、%g和%G转换说 明。而scanf()只把它们用于float类型,对于double类型时要使用 l (不是数字1)修饰符

scanf()中转换说明的修饰符:
(百分号和转换字符之间)使用修饰 符。
在这里插入图片描述
在这里插入图片描述
scanf()总结

  • scanf()函数每次读取一个字符,跳过所有的 空白字符,直至遇到第1个非空白字符才开始读取。(除了%c,其他转换说明都会自动跳过待输入值前面所有的空白)
  • scanf()函数每次读取一个字符,跳过所有的 空白字符,直至遇到第1个非空白字符才开始读取
  • scanf()函数允许把普通字符放在格式字符串中。除空格字符外的普通字 符必须与输入字符串严格匹配。
    scanf("%d,%d", &n, &m)------------scanf()函数将其解释成:用户将输入一个数字、一个逗号,然后再输入一个数字。
    scanf()函数返回成功读取的项数。如果没有读取任何项,且需要读取一 个数字而用户却输入一个非数值字符串,scanf()便返回0。当scanf()检测 到“文件结尾”时,会返回EOF(EOF是stdio.h中定义的特殊值,通常用 #define指令把EOF定义为-1)。

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

  • printf()函数:
    • 如果你不想预先指定字段宽度,希望通过程序来指定,那么可以用*修 饰符代替字段宽度。但还是要用一个参数告诉函数,字段宽度应该是多少。 也就是说,如果转换说明是%d,那么参数列表中应包含和 d对应的值。这 个技巧也可用于浮点值指定精度和字段宽度。

程序示例:

#include <stdio.h>

int main()
{
	double weight = 242.5;
	
	printf("Weight = %0*.*f\n", 10, 3, weight);
	
	return 0;
} 
  • scanf()函数:
    • 把*放在%和转换字符之间时,会使得 scanf()跳过相应的输出项

程序示例:

#include <stdio.h>

int main()
{
	int n; 
	scanf("%*d %*d %d", &n); 
	printf("%d\n", n);
} 
/*
输入样例: 
1 2 3

输出结果:
3 
*/

猜你喜欢

转载自blog.csdn.net/qq_44923545/article/details/106377548