C | 字符串和格式化输入/输出

目录

一、前导程序

二、字符串简介

2.1 char类型数组和null字符

2.2 使用字符串

2.3 strlen()函数

三、常量和C预处理器

3.1 const限定符

3.2 明示常量

四、printf()和scanf()

4.1 printf()函数

4.2 使用printf()

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

4.4 转换说明的意义

1.转换不匹配

2、printf()的返回值

3、打印较长的字符串

4.5 使用scanf()

1、从scanf()角度看输入

2、格式字符串中的普通字符

3、scanf()的返回值

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

4.7 printf()的用法提示


一、前导程序

// talkback.c -- 演示与用户交互
#include <stdio.h>
#include <string.h> // 提供strlen()函数的原型
#define DENSITY 62.4 // 人体密度(单位:磅/立方英尺)
int main()
{
	float weight, volume;
	int size, letters;
	char name[40]; // name是一个可容纳40个字符的数组
	printf("Hi! What's your first name?\n");
	scanf("%s", name);
	printf("%s, what's your weight in pounds?\n", name);
	scanf("%f", &weight);
	size = sizeof name;
	letters = strlen(name);
	volume = weight / DENSITY;
	printf("Well, %s, your volume is %2.2f cubic feet.\n",
		name, volume);
	printf("Also, your first name has %d letters,\n",
		letters);
	printf("and we have %d bytes to store it.\n", size);
	getchar();
	getchar();
	getchar();
	return 0;
}

运行结果:

Hi! What's your first name?
James
James, what's your weight in pounds?
25
Well, James, your volume is 0.40 cubic feet.
Also, your first name has 5 letters,
and we have 40 bytes to store it.

  • 数组(array)储存字符串(character string)。用户输入的名被储存在数组中,该数组占用内存中40个连续的字节,每个字节储存一个字符值。
  • %s转换说明来处理字符串的输入和输出。name没有&前缀。
  • C预处理器把字符常量DENSITY定义为62.4。
  • 函数strlen() 获取字符串的长度。
     

二、字符串简介


字符串(character string)是一个或多个字符的序列,用双引号括起来。双引号不是字符串的一部分,仅告知编译器它括起来的是字符串。

如:"Zing went the strings of my heart!"

2.1 char类型数组和null字符

  • 字符串都被储存在char类型的数组中。数组由连续的存储单元组成,字符串中的字符被储存在相邻的存储单元中,每个单元储存一个字符。

     

  • 空字符( null character):C语言用空字符标记字符串的结束。空字符为非打印字符,ASCII码值是(或等价于)0。
  • C中的字符串一定以空字符结束,这意味着数组的容量必须至少比待存储字符串中的字符数多1。
  • 数组是同类型数据元素的有序序列。

由此,字符串必须先创建一个数组,把字符串中的字符逐个放入数组,还要记得在末尾加上一个\0。这由计算机自动处理。

2.2 使用字符串

/* praise1.c -- 使用不同类型的字符串 */
#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);
	system("pause");
	//getchar();
	//getchar();
	return 0;
}

运行结果:

What's your name? James HD
Hello, James.You are an extraordinary being.

  •  scanf()在读取输入时已经把空字符放入字符串末尾;对于PRAISE后面用双引号括起来的字符串,编译器会在末尾加上空字符。
  • 根据%s转换说明,scanf() 只会读取字符串中的一个单词,而不是一整句。它在遇到第1个空白(空格、制表符或换行符)时就不再读取输入。C语言还有其他的输入函数(如,fgets()),用于读取一般字符串。
  • 字符与字符串

2.3 strlen()函数

/* praise2.c */
// 如果编译器不识别%zd,尝试换成%u或%lu。
#include <stdio.h>
#include <string.h> /* 提供strlen()函数的原型 */
#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);
	system("pause");
	return 0;
}

运行结果:

What's your name? James HD
Hello, James.You are an extraordinary being.
Your name of 5 letters occupies 40 memory cells.
The phrase of praise has 31 letters and occupies 32 memory cells. 

  • 处理很长的printf()语句:第1种方法是将printf() 语句分为两行(可以在参数之间断为两行,但是不要在双引号中的字符串中间断开);第 2 种方法是使用两个printf() 语句打印一行内容,只在第2条printf()语句中使用换行符(\n)。
  • name数组有40个储存单元,只有前5个用来储存James;第6个储存空字符,strlen() 并未将其计入。sizeof 运算符,它以字节为单位给出对象的大小,得到的是name的总空间大小。
  •  对于 PRAISE,该程序并未明确告诉计算机要给字符串预留多少空间,所以它必须计算双引号内的字符数,不计空字符
  • sizeof(),运算对象是类型时,圆括号必不可少,但是对于特定量,可有可无。

三、常量和C预处理器


符号常量(symbolic constant)好处:常量名比数字表达的信息更多;多处使用一个常量时,修改起来方便。

  • 创建符号常量:
  1. 声明一个变量,然后将该变量设置为所需的常量。程序可能无意间改变其值。
  2. 利用C预处理器。如,#define TAXRATE 0.015。编译程序时,程序中所有的TAXRATE都会被替换成0.015。这一过程被称为编译时替换(compile-time substitution)。在运行程序时,程序中所有的替换均已完成(见图 4.5)。通常,这样定义的常量也称为明示常量(manifest constant)格式:#define 符号常量名 符号常量的值
  • 大写表示符号常量是 C 语言一贯的传统。
  • 不常用的命名约定,即在名称前带c_或k_前缀来表示常量(如,c_level或k_line)。
  • 符号常量的命名规则与变量相同。可以使用大小写字母、数字和下划线字符,首字符不能为数字。
/* pizza.c -- 在比萨饼程序中使用已定义的常量 */
#include <stdio.h>
#define PI 3.14159
int main(void)
{
	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("Your basic pizza parameters are as follows:\n");
	printf("circumference = %1.2f, area = %1.2f\n", circum, area);
	getchar();
	getchar();
	return 0;
}

运行结果:

What is the radius of your pizza?
25
Your basic pizza parameters are as follows:
circumference = 157.08, area = 1963.49

注:#define指令还可定义字符和字符串常量。前者使用单引号,后者使用双引号。

3.1 const限定符


C90标准新增了const关键字,用于限定一个变量为只读,即可以使用、打印等,但不能更改。

3.2 明示常量


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

注:符号常量的概念在K&R合著的《C语言程序设计》中介绍过。但是,在历年的C标准中(包括最新的C11),并没有符号常量的概念,只提到过#define最简单的用法是定义一个“明示常量”。

limits.h中能找到的一些明示常量。

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

把明示常量名中的FLT分别替换成DBL和LDBL,即可分别表示double和long double类型对
应的明示常量。
 

// defines.c -- 使用limit.h和float头文件中定义的明示常量
#include <stdio.h>
#include <limits.h> // 整型限制
#include <float.h> // 浮点型限制
int main(void)
{
	printf("Some number limits for this system:\n");
	printf("Biggest int: %d\n", INT_MAX);
	printf("Smallest long long: %lld\n", LLONG_MIN);
	printf("One byte = %d bits on this system.\n", CHAR_BIT);
	printf("Largest double: %e\n", DBL_MAX);
	printf("Smallest double: %e\n", DBL_MIN);
	printf("Largest normal float: %e\n", FLT_MAX);
	printf("Smallest normal float: %e\n", FLT_MIN);
	printf("double precision = %d digits\n", DBL_DIG);
	printf("float precision = %d digits\n", FLT_DIG);
	printf("double epsilon = %e\n", DBL_EPSILON);
	printf("float epsilon = %e\n", FLT_EPSILON);
	getchar();
	return 0;
}

 运行结果:

Some number limits for this system:
Biggest int: 2147483647
Smallest long long: -9223372036854775808
One byte = 8 bits on this system.
Largest double: 1.797693e+308
Smallest double: 2.225074e-308
Largest normal float: 3.402823e+38
Smallest normal float: 1.175494e-38
double precision = 15 digits
float precision = 6 digits
double epsilon = 2.220446e-16
float epsilon = 1.192093e-07


四、printf()和scanf()

printf()是输出函数,scanf()是输入函数,两个函数都使用格式字符串和参数列表。

4.1 printf()函数


转换说明(conversion specification):指定了如何把数据转换成可显示的形式

4.2 使用printf()

/* printout.c -- 使用转换说明 */
#include <stdio.h>
#define PI 3.141593
int main(void)
{
	int number = 7;
	float pies = 12.75;
	int cost = 7800;
	printf("The %d contestants ate %f berry pies.\n", number,
		pies);
	printf("The value of pi is %f.\n", PI);
	printf("Farewell! thou art too dear for my possessing,\n");
	printf("%c%d\n", '$', 2 * cost);
	getchar();
	return 0;
}

运行结果:

The 7 contestants ate 12.750000 berry pies.
The value of pi is 3.141593.
Farewell! thou art too dear for my possessing,
$15600

printf()函数的格式:
printf( 格式字符串, 待打印项1, 待打印项2,...);

  • 待打印项1、待打印项2等都是要打印的项。它们可以是变量、常量,甚至是在打印之前先要计算的表达式。格式字符串应包含每个待打印项对应的转换说明。
  • 格式字符串中的转换说明一定要与后面的每个项相匹配,若忘记这个基本要求会导致严重的后果。
  • 如果单独使用一个%符号,编译器会认为漏掉了一个转换字符。解决方法:使用两个%符号表示%

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

在%和转换字符之间插入修饰符可修饰基本的转换说明。如果要插入多个字符,其书写顺
序应该与表中列出的顺序相同。不是所有的组合都可行。

表4.5 printf()中的标记

注意 类型可移植性
sizeof 运算符以字节为单位返回类型或值的大小。这应该是某种形式的整数,但是标准只规定了该值是无符号整数。stddef.h头文件(在包含stdio.h头文件时已包含其中)size_t定义成系统使用sizeof返回的类型,这被称为底层类型(underlying type)。C还定义了ptrdiff_t类型t修饰符来表示系统使用的两个地址差值的底层有符号整数类型。

注意 float参数的转换
对于浮点类型,有用于double和long double类型的转换说明,却没有float类型的。这是因为在K&R C中,表达式或参数中的float类型值会被自动转换成double类型
 

/* width.c -- 字段宽度 */
#include <stdio.h>
#define PAGES 959
int main(void)
{
	printf("*%d*\n", PAGES);
	printf("*%2d*\n", PAGES);
	printf("*%10d*\n", PAGES);
	printf("*%+10d*\n", PAGES);
	printf("*%-10d*\n", PAGES);
	printf("*% d*\n", PAGES);
	printf("*%0d*\n", PAGES);
	getchar();
	return 0;
}

运行结果:

*959*
*959*
*       959*
*      +959*
*959       *
* 959*
*959*

// floats.c -- 一些浮点型修饰符的组合
#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);
	getchar();
	return 0;
}

运行结果:

*3852.990000*
*3.852990e+03*
*3852.99*
*3853.0*
*  3852.990*
* 3.853E+03*
*+3852.99*
*0003852.99*

/* flags.c -- 演示一些格式标记 */
#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**%5.3d**%.3d**%0.3d**\n", 6, 6, 6, 6, 6, 6, 6);
	getchar();
	return 0;
}

运行结果:

1f 1F 0x1f
**42** 42**-42**
**    6**  006**00006**  006**  006**006**006**

  • 用空格在输出的正值前面生成前导空格,负值前面不产生前导空格。这样的输出结果比较美观,因为打印出来的正值和负值在相同字段宽度下的有效数字位数相同
  • 如果0标记和精度一起出现,0标记会被忽略。
     
/* stringf.c -- 字符串格式 */
#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);
	getchar();
	return 0;
}

运行结果:

[Authentic imitation!]
[    Authentic imitation!]
[                   Authe]
[Authe                   ]

  • 精度限制了待打印字符的个数。.5告诉printf()只打印5个字符。另外,-标记使得文本左对齐输出。
     

4.4 转换说明的意义

转换说明把以二进制格式储存在计算机中的值转换成一系列字符(字符串)以便于显示。转换说明是翻译说明,%d的意思是“把给定的值翻译成十进制整数文本并打印出来”。

1.转换不匹配

/* intconv.c -- 一些不匹配的整型转换 */
#include <stdio.h>
#define PAGES 336
#define WORDS 65618
int main(void)
{
	short num = PAGES;
	short mnum = -PAGES;
	printf("num as short and unsigned short: %hd %hu\n", num, num);
	printf("num as int and unsigned int: %d %u\n", num, num);
	printf("num as o and x: %o %x\n", num, num);
	printf("num as short and unsigned short: %hd %hu\n",mnum, mnum);
	printf("num as o and x: %o %x\n", mnum, mnum);
	printf("num as int and char: %d %c\n", num, num);
	printf("WORDS as int, short, and char: %d %hd %c\n",WORDS,WORDS, WORDS);
	getchar();
	return 0;
}

运行结果:

num as short and unsigned short: 336 336
num as int and unsigned int: 336 336
num as o and x: 520 150
num as short and unsigned short: -336 65200
num as o and x: 37777777260 fffffeb0
num as int and char: 336 P
WORDS as int, short, and char: 65618 82 R

  • 首先,short int的大小是2字节;其次,系统使用二进制补码来表示有符号整数。这种方法,数字0~32767代表它们本身,而数字32768~65535则表示负数。其中,65535表示-1,65534表示-2,以此类推。因此,-336表示为65200(即, 65536-336)。
  • 别期望用%u转换说明能把数字和符号分开。
  • 当printf()使用%c打印336时,它只会查看储存336的2字节中的后1字节。这种截断相当于用一个整数除以256,只保留其余数。

/* floatcnv.c -- 不匹配的浮点型转换 */
#include <stdio.h>
int main(void)
{
	float n1 = 3.0;
	double n2 = 3.0;
	long n3 = 2000000000;
	long n4 = 1234567890;
	printf("%.1e %.1e %.1e %.1e\n", n1, n2, n3, n4);
	printf("%ld %ld\n", n3, n4);
	printf("%ld %ld %ld %ld\n", n1, n2, n3, n4);
	getchar();
	return 0;
}

 运行结果:

3.0e+00 3.0e+00 3.1e+46 2.0e-305
2000000000 1234567890
0 1074266112 0 1074266112

  • 当printf()查看n3(本系统中是4字节的值)时,除了查看n3的4字节外,还会查看查看n3相邻的4字节,共8字节单元。最终得到的结果是无意义的值。
  • float类型的值作为printf()参数时会被转换成double类型。
  • 如果printf()语句有其他不匹配的地方,即使用对了转换说明也会生成虚假的结果。用%ld转换说明打印浮点数会失败,但是在这里,用%ld打印long类型的数竟然也失败了!问题出在C如何把信息传递给函数。

解释:程序把传入的值放入被称为栈(stack)的内存区域。计算机根据变量类型(不是根据转换说明)把这些值放入栈中。n1被储存在栈中,占8字节(float类型被转换成double类型)。同样,n2也在栈中占8字节,而n3和n4在栈中分别占4字节。
然后,控制转到printf()函数。该函数根据转换说明(不是根据变量类型)从栈中读取值。

2、printf()的返回值

 大部分C函数都有一个返回值,这是函数计算并返回给主调程序(calling program)的值。可以把返回值赋给变量,也可以用于计算,还可以作为参数传递。

printf()函数也有一个返回值,它返回打印字符的个数。如果有输出错误,printf()则返回一个负值(printf()的旧版本会返回不同的值)。

/* prntval.c -- printf()的返回值 */
#include <stdio.h>
int main(void)
{
	int bph2o = 212;
	int rv;
	rv = printf("%d F is water's boiling point.\n", bph2o);
	printf("The printf() function printed %d characters.\n",
		rv);
	getchar();
	return 0;
}

运行结果:

212 F is water's boiling point.
The printf() function printed 32 characters.

  • 第二个printf() 语句执行了两项任务:打印信息和给变量赋值注意计算针对所有字符数,包括空格和不可见的换行符(\n)

3、打印较长的字符串

printf() 不能在双引号括起来的字符串中间断行。在字符串中,可以使用\n来表示换行字符,但是不能通过按下Enter(或Return)键产生实际的换行符。
现提供三种方法

  • 方法1:使用多个printf()语句
  • 方法2:用反斜杠(\)和Enter(或Return)键组合来断行。下一行代码必须和程序清单中的代码一样从最左边开始。如果缩进该行,比如缩进5个空格,那么这5个空格就会成为字符串的一部分。
  • 方法3:ANSI C引入的字符串连接。
     
/* longstrg.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 */
	getchar();
	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.

4.5 使用scanf()

  • scanf()把输入的字符串转换成整数、浮点数、字符或字符串,而 printf()正好与它相反,把整数、浮点数、字符和字符串转换成显示在屏幕上的文本。
  • scanf()和 printf()类似,也使用格式字符串和参数列表,两个函数主要的区别在参数列表中。printf()函数使用变量、常量和表达式,而scanf()函数使用指向变量的指针。两条简单的规则:
  1. 如果用scanf()读取基本变量类型的值,在变量名前加上一个&;
  2. 如果用scanf()把字符串读入字符数组中,不要使用&
// input.c -- 何时使用&
#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);
	getchar();	
	getchar();
	return 0;
}

运行结果:

Enter your age, assets, and favorite pet.
28
25.25 cat
28 $25.25 cat

  • scanf()函数使用空白(换行符、制表符和空格)把输入分成多个字段。在依次把转换说明和字段匹配时跳过空白。只要在每个输入项之间输入至少一个换行符、空格或制表符即可,可以在一行或多行输入。唯一例外的是%c转换说明。根据%c,scanf()会读取每个字符,包括空白。
  • scanf()函数所用的转换说明与printf()函数几乎相同。主要的区别是,对于float类型和double类型,printf()都使用%f、%e、%E、%g和%G转换说明。而scanf()只把它们用于float类型,对于double类型时要使用l修饰符。

ANSI C中scanf()的转换说明

scanf()转换说明中的修饰符

 

 注:printf(),%o和%x中,分别表示无符号八进制整数和无符号十六进制整数,而在scanf(),%o和%x中,分别表示有符号八进制整数和有符号十六进制整数。

#include <stdio.h>
int main(void)
{
	int a, b, c;

	printf("Enter number: ");
	scanf("%x %x", &a, &b);
	c = a + b;
	printf("Answer = %x\n", c);

	while (getchar() != EOF)//ctrl+z,然后按Enter可结束循环
		getchar();
	return 0;
}

 运行结果:

Enter number: 5 -4
Answer = 1

Enter number: 5 -6
Answer = ffffffff

1、从scanf()角度看输入

  • 如果使用字段宽度,scanf()会在字段结尾或第1个空白字符处停止读取(满足两个条件之一便停止)。
  • 如果使用带多个转换说明的scanf(),C规定在第1个出错处停止读取输入。
  • 如果使用%s 转换说明,scanf()会读取除空白以外的所有字符。scanf()跳过空白开始读取第 1 个非空白字符,并保存非空白字符直到再次遇到空白。如果使用字段宽度,scanf()在字段末尾或第1个空白字符处停止读取。无法利用字段宽度让只有一个%s的scanf()读取多个单词。当scanf()把字符串放进指定数组中时,它会在字符序列的末尾加上'\0',让数组中的内容成为一个C字符串,试了一下,如果输入字符(包括自动加入的空字符)超过数组容量会报错,读者可自己运行下面的程序。
#include <stdio.h>
int main(void)
{
	char a[5];

	printf("Enter number: ");
	scanf("%s", &a);//输入字符超过5(包括5)会报错
	printf("%s\n", a);
	getchar();
	getchar();
	return 0;
}

C 语言还有其他的输入函数,如 getchar()和 fgets()。这两个函数更适合处理一些特殊情况,如读取单个字符或包含空格的字符串。


2、格式字符串中的普通字符

  • scanf()函数允许把普通字符放在格式字符串中。除空格字符外的普通字符必须与输入字符串严格匹配
  • 格式字符串中的空白意味着跳过下一个输入项前面的所有空白。
  • 除了%c,其他转换说明都会自动跳过待输入值前面所有的空白。因此,scanf("%d%d", &n, &m)与scanf("%d %d", &n, &m)的行为相同。对于%c,scanf("%c", &ch)从输入中的第1个字符开始读取,而scanf(" %c", &ch)则从第1个非空白字符开始读取。

3、scanf()的返回值

scanf()函数返回成功读取的项数。
如果没有读取任何项,且需要读取一个数字而用户却输入一个非数值字符串,scanf()便返回0。当
scanf()检测到“文件结尾”时,会返回EOF(EOF是stdio.h中定义的特殊值,通常用#define指令把EOF定义为-1)。
 

#include <stdio.h>
int main(void)
{
	int a,b,c,d,e,f,q1,q2,q3;

	printf("Enter number: ");
	q1=scanf("%d,%d", &a, &b);
	q2=scanf("%d%d", &c, &d);
	q3=scanf("%d %d", &e, &f);
	printf("%d%d\n", a, b);
	printf("%d%d\n", c, d);
	printf("%d%d\n", e, f);
	printf("%d %d\n", a, b);
	printf("%d %d %d\n", q1, q2, q3);
	
	system("pause");
	return 0;
}

运行结果:

Enter number: 3,4
5 6 7
8
34
56
78
3 4
2 2 2

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

printf()和scanf()都可以使用*修饰符来修改转换说明的含义

printf()的*修饰符

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

/* varwid.c -- 使用变宽输出字段 */
#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");
	getchar();
	getchar();
	return 0;
}

运行结果:

Enter a field width:
8 6 3
The number is :     256:
Now enter a width and a precision:
Weight = 242.500
Done!

scanf()中*的用法与此不同。把*放在%和转换字符之间时,会使得scanf()跳过相应的输出项。
 

/* skiptwo.c -- 跳过输入中的前两个整数 */#include <stdio.h>
int main(void)
{
	int n;
	printf("Please enter three integers:\n");
	scanf("%*d %*d %d", &n);
	printf("The last integer was %d\n", n);
	getchar();
	getchar();
	return 0;
}

运行结果:

Please enter three integers:
4 5
7
The last integer was 7

在程序需要读取文件中特定列的内容时,这项跳过功能很有用。

4.7 printf()的用法提示

想把数据打印成列,指定固定字段宽度很有用。如果同一列中打印的数字位数不同,打印出来的数字可能参差不齐。使用足够大的固定字段宽度可以让输出整齐美观。
 

//使用足够大的固定字段宽度可以让输出整齐美观
#include <stdio.h>
int main(void)
{
	int val1=123, val2=12345, val3=12345678;
	printf("%d %d %d\n", val1, val2, val3);
	val1 = 12 ;
	val2 = 1234;
	val3 = 1234567;
	printf("%d %d %d\n", val1, val2, val3);
	val1 = 1;
	val2 = 123;
	val3 = 123456;
	printf("%d %d %d\n", val1, val2, val3);

	val1 = 123;
	val2 = 12345;
	val3 = 12345678;
	printf("%-10d %-10d %-10d\n", val1, val2, val3);
	val1 = 12;
	val2 = 1234;
	val3 = 1234567;
	printf("%-10d %-10d %-10d\n", val1, val2, val3);
	val1 = 1;
	val2 = 123;
	val3 = 123456;
	printf("%-10d %-10d %-10d\n", val1, val2, val3);
	getchar();
	return 0;
}

运行结果:

123 12345 12345678
12 1234 1234567
1 123 123456
123        12345      12345678
12         1234       1234567
1          123        123456

另一方面,如果要在文字中嵌入一个数字,通常指定一个小于或等于该数字宽度的字段会比较方便。这样,输出数字的宽度正合适,没有不必要的空白。
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

HaGoq

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值