目录
一、前导程序
// 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)好处:常量名比数字表达的信息更多;多处使用一个常量时,修改起来方便。
- 创建符号常量:
- 声明一个变量,然后将该变量设置为所需的常量。程序可能无意间改变其值。
- 利用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()函数使用指向变量的指针。两条简单的规则:
- 如果用scanf()读取基本变量类型的值,在变量名前加上一个&;
- 如果用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
另一方面,如果要在文字中嵌入一个数字,通常指定一个小于或等于该数字宽度的字段会比较方便。这样,输出数字的宽度正合适,没有不必要的空白。