0
点赞
收藏
分享

微信扫一扫

第五节(信息读写基础)

你创建的大部分程序都需要在屏幕上显示信息或接收用户从键盘输入的信息。

许多程序都完成了这些任务,但是你可能还不甚了解。

本次将介绍以下内容:

●C语言的输入和输出语句基础

●如何使用printf()和puts() 库函数在屏幕上显示信息

●如何格式化在屏幕上显示的信息

●如何使用scanf() 库函数从键盘读取用户输入的数据

一.在屏幕上显示信息:

大多数程序都要在屏幕上显示信息,最常用的两种方法是:

使用C语言的库函数printf()和puts() 。

1.1 printf()函数:

printf()函数是C标准库的一部分,也是ANSI标准的组成部分。

这也许是程序在屏幕上显示数据最常用的方式。

前面的许多笔记中程序示例都使用了printf(),下面来详细介绍printf()函数。

在屏幕上打印文本消息很简单。只需调用printf()函数,将待显示的信息用双引号括起来,并传递给该函数即可。

例如,要在屏幕上显示How Now Brown Cow! ,可以这样写:

printf("How Now Brown Cow!");

然而,除了文本消息外,还需要经常显示程序变量的值。这比显示消息略为复杂。

例如,你想在屏幕上另起一行显示数值变量myNumber的值和一些相关文本消息,可以这样使用printf() :

printf ("\nThe value of myNumber is %d", myNumber) ;

假设myNumber的值是12,那么屏幕上最终显示的是:

The value of myNumber is 12

在该例中,给printf()传递了两个实参。

第1个实参称为格式字符串,置于双引号中。

第2个实参是包含待打印值的变量名(myNumber)

1.2 printf()的格式字符串:

printf()的格式字符串指定了输出的格式。

格式字符串可由3部分组成。

●字面量文本,在格式字符串中精确地显示输入。在上面的示例中,字符串从 (The )开始到名(不包括%),组成了字面量文本。

●转义序列,提供特殊的格式控制。转义序列由反斜杠(\)和一个单独的字符组成。在上面的示例中,\n (称为换行符)是一个转义序列,它的意思是“移至下一行开始”。在上一节的程序清单中使用了\t来打印制表符,以格式化表格。另外,转义序列也可用于打印某些字符。常用的转义序列在表中列出。

●转换说明,由百分号(% )和一个转换字符组成。转换说明告诉printf()函数如何解译待打印的变量。在上面的示例中,转换说明是%d。%d告诉printf()将myNumber变量解译成有符号十进制整数。

\a

响铃

\b

后退一格

\f

换页

\n

换行

\r

回车

\t

水平制表符

\v

垂直制表符

\\

反斜杠

\?

问号

\'

单引号

\"

双引号

(1) printf()转义序列:

转义序列通过移动屏幕光标来控制输出的位置。

除此之外,转义序列还可用于打印一些对于printf()有特殊含义的字符。

例如,打印一个反斜杠字符,需要在格式字符串中写两个反斜杠(\\)。

第1个反斜杠告诉printf()应将第2个反斜杠解译为字面量字符,而非转义序列的开始。

一般而言,反斜杠告诉printf()以特殊的方式解译下一个字符。下面是一些示例:

转义序列

含义

n

字符n

\n

换行

\"

双引号字符

"

字符串的开头或结尾

表列出了C语言最常用的一些转义序列。

下面程序清单中演示了一些转义序列的用法。

输入:

// 常用的转义序列使用示例。

#include <stdio.h>

#define QUIT 3

int get_menu_choice(void);
void print_report(void);

int main(void)
{
int choice = 0;

printf("\"We\'d like to welcome you to the menu program\"\n");
printf("Are you ready to make a choice\?\n");
while (choice != QUIT )
{
choice = get_menu_choice();

if (choice == 1)
printf("nBeeping the computer\a\a\a");
else
{
if (choice == 2)
print_report();
}
}
printf("You chose to quit!\n");

return 0;
}

int get_menu_choice(void)
{
int selection = 0;

do
{
printf("\n");
printf("\n1 - Beep Computer");
printf("\n2 - Display Report");
printf("\n3 - Quit");
printf("\n");
printf("\nEnter a selection:");

scanf("%d", &selection);

} while (selection < 1 || selection > 3);

return selection;
}

void print_report(void)
{
printf("\nSAMPLE REPORT");
printf("\n\nSequence\tMeaning");
printf("\n=========\t=======");
printf("\n\\a\t\tabell (alert)");
printf("\n\\b\t\tbackspace");
printf("\n...\t\t...");
}

输出:

第五节(信息读写基础)_反斜杠

解析:

程序清单中比前面介绍的程序清单长,其中有一些需要注意的地方。
第3行是stdio.h头文件,因为程序清单中要使用printf(),所以必须包含该头文件。
第5行,通过#define指令定义了一个名为QUIT的符号常量。根据第3节中学过的知识,在程序中使用QUIT相当于使用值3。
第7行和第8行是函数原型。
除main()函数外,该程序还有两个函数: get_ menu_ choice() 和print_ report()
get _menu_ choice() 函数的定义在第33 51行,
第39行和第43行调用的printf()函数打印换行转义序列。
第40、41、 42和44行都使用了换行转义序列来打印文本。
可以删除第39行,并修改第40行。如下所示:

printf( "\n\n1 - Beep Computer" );

尽管如此,保留第39行可提高代码的可读性。
在main()函数中,第14行和第15行的printf()中演示了如何通过转义序列打印问号、单引号和双引号。
你可能不会经常用到这些标点符号,如果在使用时忘记这些转义序列,编译器不会报错,但是会导致和预期不符的输出。
第16行是while 循环的开头,只要choice不等于QUIT,程序将不断重复执行while循环体中的语句。
QUIT是一个符号常量,如果用3替换它,程序就不如现在这样清楚明了。
第18行获得choice变量,然后在if语句中的第20~26行用到它。
如果用户选择1,将打印换行符、一条消息,然后响铃3次(第21行)
如果用户选择2,将调用printf_ report() 函数(第25行)

提示:

第16~27行的while循环控制菜单的顶部,至少要运行一次。

以该例的情况看,使用do...while 循环会更合适。
你可以考虑将程序清单改用do.. .while循环来实现。
第53~61行是printf_ report() 函数的定义。
该函数中只使用了printf()函数,以及为了在屏幕上格式化信息的转义序列。
你对于换行符已经很熟悉了,第56~ 60行还使用了制表符转义序列\t。
上一节的程序示例中,使用了制表符垂直对齐表格的数据。
也许不太理解第58行和第59行。
从左往右仔细看,第58行打印一个换行(\n)、一个反斜杠(\)、一个字符a,以及一些描述性文本(bell (alert) )
第59行和第58行的格式相同。该程序打印表的表头标题和前两行。

(2) printf ()转换说明

在格式字符串中,必须包含所有待打印的变量对应的转换说明。

然后,printf()函数根据每个变量对应的转换说明来显示每个变量。

就现在而言,只需记住要为待打印的变量类型使用相应的转换说明。

例如,如果要打印一个有符号十进制整型(int 和long类型)变量,就要使用%d转换说明;

对于无符号十进制整型(unsigned int 和unsigned long )变量,要使用%u转换说明;

对于浮点型(float 和double类型)变量,则使用%f转换说明。

下列表列出了最常用的转换说明。

转换说明

含义

类型转换

%c

单个字符

char   

%d

有符号十进制整型

int  、 short

%1d

有符号十进制长整型

long

%f

十进制浮点型

float  、 double

%s

字符串

char    数组

%u

无符号十进制整型

unsigned  int  、  unsigned  short

%1u

无符号十进制长整型

unsigned   long

注意:

使用printf()的程序都必须包含stdio.h头文件。

在格式字符串中,除转义序列和转换说明以外的内容都是字面量文本。

printf()函数会原样打印字面量文本(包括其中所有的空格)。

如何打印多个变量的值?

一个printf()语句可以打印任意数量的变量,但是格式字符串必须包含所有待打印变量相应的转换说明。

转换说明与变量都按照从左至右的顺序成对出现。如下面的代码所示:

printf ("Rate = %f, amount = %d", rate, amount);

rate变量与%f对应,amount 变量与%d对应。

格式字符串中转换说明的位置决定了输出的位置。

如果传递给printf()函数的变量比转换说明多,那么未匹配的变量将无法打印出来。

如果转换说明比变量多,那么未匹配的转换说明将打印出“垃圾值”。

C语言并未规定printf()只能打印变量的值,它的实参可以是任意有效的C表达式。

例如,要打印x和y的和,可以这样写:

total = x + y;
printf("%d", total);

也可以这样写

printf("%d", x+ y);

程序清单演示了printf()的用法。

输入:

// 使用printf()函数显示数值的示例。

#include <stdio.h>

int a = 2, b = 10, c = 50;
float f = 1.05, g = 25.5, h = -0.1;

int main(void)
{
printf("\nDecimal values without tabs: %d %d %d", a, b, c);
printf("\nDecimal values with tabs: \t%d \t%d \t%d", a, b, c);

printf("\nThree floats on 1 line: \t%f\t%f\t%f", f, g, h);
printf("\nThree floats on 3 lines: \n\t%f\n\t%f\n\t%f", f, g, h);

printf("\nThe rate is %f%%", f);
printf("\nThe rate to 2 decimal places is %.2f%%", f);
printf("\nThe rate to 1 decimal place is %.1f%%", f);
printf("\nThe result of %f/%f = %f\n", g, f, g / f);

return 0;
}

输出:

第五节(信息读写基础)_字符串_02

解析:

程序中使用了8个printf()函数打印消息(第10~19行)
第10行和第11行,每个printf()都打印3个十进制数: a、b和c。
第10行的printf() 中,每个数前面使用了空格,并未使用制表符;
第11行在每个数前面使用了制表符。
第13行和第14行,每个printf()都打印3个float类型的变量: f、g和h。
第13行将3个变量打印成一行;
第14行将3个数分别打印成3行。
第16行打印一个float类型的变量f和一个百分号。因为百分号通常意味着要打印一个变量,因此必须连续写两个百分号才能打印出百分号,这类似于反斜杠转义字符。
第17行和第18行包含一个新的概念。
在默认情况下,C编译器会将浮点型变量打印成6位小数。
即使你将变量定义为1位小数(如5.5),当C编译器使用%f转换说明打印它时,仍将其打印为5. 500000
这通常不如你所愿,因此,C语言提供一个简单的方法减少打印的小数位数。
如第17行和第18行所示,在名和转换字符f之间添加一个点(. )和一个数字,命令编译器打印指定的位数。
但是,这里要注意-:如果设置打印的小数位数比实际变量的位数小,C编译器会截断数字,而非四舍五入。如第19行所示,1.05 变成了1.0,而不是1.1
另外,使用转换说明打印值时,除了变量还可以使用表达式(如,g/f),甚至可以使用常量。

打印多行信息时,要在printf() 语句中使用换行转义字符。
不要在一条printf()语句中放入多行文本。
大多数情况下,用多条ptintf() 语句打印多行比在一条printf() 语句中使用多个换行转义字符清楚得多。
不要写错stdio.h。
许多情况下都经常误写为studio.h。正确的写法中间没有u。stdio.h 代表标准输入/输出。

语法:printf()函数

#include <stdio.h>

printf( 格式字符串[,参数,...1]);

printf()函数接受一系列的参数。每个参数都在格式字符串中有相应的转换说明。

printf() 将格式化的信息打印在标准输出设备上(通常是显示屏)。

使用printf()函数时,必须包含标准输入/输出头文件stdio.h。

在printf()函数中,格式字符串必不可少,而参数是可选的。每个参数都必须有相应的转换说明。

上述表中列出了最常用的转换说明。

格式字符串中可以包含转义序列。上述表中列出了最常用的转义序列。

下面是调用printf()函数的示例和输出:

示例1:

#include <stdio.h>

int main(void)

{

printf("This is an example of something printed!");

return 0;

}

输出:

第五节(信息读写基础)_字符串_03

示例2:

printf("This prints a charater, %c\na number, %d\na floating \
point, %f", 'z', 123, 456.789 );

输出:

第五节(信息读写基础)_字符串_04

你可能注意到了,在上面的示例2中,printf() 函数中的字符串占了两行。

第1行末尾的反斜杠(\ )表明,该字符串将延续至下一行。

因此,编译器会将这两行视为一行。

1.3 使用puts()显示消息:

puts()也可用于在屏幕上显示文本消息,但是它不能显示数值变量。

puts() 函数只需要一个字符串作为参数,在该字符串末尾自动地添加换行符,并将其显示在屏幕上。

例如,下面的语句:

puts ("Hello, world.") ;

与下面语句等效:

printf ("Hello, world.\n");

可以将包含转义序列(包括\n )的字符串传递给puts(),其效果与使用printf()函数相同

与使用printf()函数类似,任何使用puts()函数的程序都要.包含头文件stdio.h。

注意:一个程序只能包含一次stdio.h。

如果只打印文本,不用打印任何变量,请使用puts()函数,而不是printf()函数。

不要在puts()函数中使用转换说明。

语法:puts()函数

#include <stdio.h>

puts ( 字符串 );

puts()函数将字符串拷贝至标准输出设备(通常是显示屏)。

如果要使用puts(),必须在程序中包含标准输入/输出头文件(stdio.h )。

puts()函数会在待打印的字符串末尾添加一个换行符。

格式字符串中可包含转义序列,上面表列出了最常用的转义序列。

下面是调用puts()函数的示例和输出:

示例1:

puts("This is printed with the puts() function!");

输出:

第五节(信息读写基础)_字符串_05

示例2:

puts("This prints on the fist line. \nThis prints on the second line.");

puts("This prints on the third line.");

puts("If these were printf()s, all four lines would be on two lines!");

输出:

第五节(信息读写基础)_字符串_06

二.使用scanf()输入数值数据:

大部分程序需要在屏幕上显示数据,同样,它们也需要用户从键盘输入数据。

用scanf()库函数读取从键盘输入的数值数据是最灵活的方式。

scanf()函数以指定的格式从键盘读取数据,并将输入的数据赋值给程序中的一个或多个变量。

printf() 和scanf() 都使用格式字符串描述输入的格式。

scanf()函数的格式字符串使用的转换说明与printf()函数的相同。

例如  语句:

scanf("%d" &x) ;

读取用户从键盘输入的一个十进制整型数,并将其赋值给整型变量x。

同样地,下面的语句读取用户从键盘输入一个浮点型值,并将其赋值给浮点型变量rate :

scanf("%f", &rate);

变量名前面的&是什么? &是C语言的取址运算符

目前,你只需记住,在scanf()函数的参数列表中,每个数值变量名前都必须包含&

如果在格式字符串中包含多个转换说明和变量名(再次提醒,参数列表中的每个变量名前必须有& ),一个scanf()函数便可打印多个值。下面的语句输入一个整型值和一个浮点型值,并将它们分别赋值给变量x和rate :

scanf ("&d %f", &X,&rate);

输入多个变量时,scanf() 使用空白将输入分隔成多个字段。

空白可以是空格、制表符或换行符。

格式字符串中的每.个转换说明都与一个输入字段匹配,scanf() 函数以空白来识别输入字段的末尾。

这给用户输入带来了极大的灵活性。以上面的scanf()为例,用户可以输入

10  12.45

也可以这样

10       12.45

更可以这样

10
12.45

只要输入的值之间有空白,scanf()便能将每个值分别赋给相应的变量。

警告:使用scanf()要小心。

如果要读取一个字符串而用户却输入了一个数字,或者要读取个数字而用户却输入了一个字符,那么程序输出的结果将出乎意料。

使用scanf() 的程序必须包含stdio.h头文件。

下面的程序中演示了如何使用scanf()。

输入:

//使用scanf()函数的示例

#include <stdio.h>

#define QUIT 4

int get_menu_choice(void);

int main(void)
{
int choice = 0;
int int_var = 0;
float float_var = 0;
unsigned unsigned_var = 0;

while (choice != QUIT)
{
choice = get_menu_choice();

if (choice == 1)
{
puts("\nEnter a signed decimal integer (i.e. -123)");
scanf("%d", &int_var);
}
if (choice == 2)
{
puts("\nEnter a decimal floating-point number\
(e.g. 1.23)");
scanf("%f", &float_var);
}
if (choice == 3)
{
puts("\nEnter an unsigned decimal integer \
(e.g. 123)");
scanf("%u", &unsigned_var);
}
}
printf("\nYour values are: int: %d float: %f unsigned: %u \n",
int_var, float_var, unsigned_var);

return 0;
}

int get_menu_choice(void)
{
int selection = 0;

do
{
puts("\n1 - Get a signed decimal integer");
puts("2 - Get a decimal floating-point number");
puts("3 - Get an unsigned decimal integer");
puts("4 - Quit");
puts("\nEnter a selection:");

scanf("%d", &selection);

} while (selection < 1 || selection > 4);

return selection;
}

输出:

第五节(信息读写基础)_转义序列_07

​解析:

程序使用的菜单大体上与上个程序清单相同。
但是,本例中的get_menu_choice() 函数较小,还需要注意几点。
其一,本例用puts()函数代替printf() 函数。
由于不需要打印变量,就没必要使用printf()
正是因为使用了puts(),第51行至第53行不用写换行转义字符。
其二,第58行将值的范围改为1至4,因为本例的菜单中有4个选项。
注意,第56行没有改动,scanf() 仍获取十进制值,并将其赋给变量selection。
第60行,get_menu_choice() 函数将selection返回主调程序。
main()结构。一个if语句测试get_menu_choice() 函数的返回值choice。
根据choice的值,程序打印一条消息,提示用户输入一个数字,并使用scanf()读取用户输入的值。
请注意第23行、第29行和第35行,每个scanf ()函数都获取不同类型的变量。
第12行至第14行声明(并初始化)了程序中要用到的变量。

如果用户选择退出,程序将打印用户输入的3个值。
如果用户没有输入,则打印0,因为第12、13和14行分别初始化了3个变量。
最后要注意的是,第20行至第36行。
这样使用3个if语句的结构并不好。有一种新的控制语句switch,本例的这种情况使用switch语句更好。可以自己去查看一下

scanf()要和printf()或puts() 一起使用。用打印雨数显示提示消息,指明scanf() 需要获取的数据。
不要忘记在scanf()的变量前添加取址运算符(&)

语法:scanf()函数

#include <stido.h>

scanf(格式字符串[,参数,...]);

scanf()函数在给定的格式字符串中使用转换说明,将值放入变量参数中。

参数必须是变量的地址,而非变量本身。对于数值变量,可以通过在变量名前添加取址符(&)来传递地址。

必须包含stdio.h 头文件才能使用scanf()。

scanf()从标准输入流中读取输入字段( inputfield ),并将读取的每个字段都放进一个参数中。

该函数在放置信息时,会将信息转换成格式字符串中相应转换说明的格式。

示例1:

int x, y, z;

scanf( "%d %d %d", &x, &y, &z);

示例2:

#include<stdio.h>

int main(void)
{
float y;
int x;
puts("Enter a float, then an int");
scanf("%f %d", &y, &x);
printf("\nYou entered %f and %d ", y, x);
return 0;
}

第五节(信息读写基础)_转义序列_08

三.  三字符序列:

现在你已经学完了使用诸如printf()和scanf() 这样的函数来读写信息的基本知识。
接下来,还要了解一下三字符序列。三字符序列是在源代码中被编译器解译成其他内容的特殊字符序列。

注意:你可能不会用到三字符序列。这里提到它是为了让你了解一下, 万一无意间在代码中使用了三字符序列,它们会被自动转换成本节表中所列的等价字符。

三字符序列与前面介绍过的转义序列类似。它们之间最大的区别是,编译器在查看源代码时解译三字符序列。源文件中出现三字符序列的地方,都将被转换。

三字符序列以两个问号(? )开始。

表列出了ANSI标准中规定的三字符序列。根据该标准,不存在其他的三字符序列。

代码

等价字符

??=

#

??(

[

??/

\

??(

]

??'

^

??<

{

??!

|

??>

}

??-

~

如果三字符序列代码(表中的代码一栏的任意一项)出现在源文件中,它将被更改为相应的等价字符。

即使三字符序列是字符串的一部分,也不例外,例如:

printf("?? (WOW??)");

将会被更改为:

printf ("[WOW]");

如果包含了更多问号,其余的问号不会被更改,例如:

printf("???-");

将会被更改为:

printf ("?~");

四.小结:

结合printf()、puts()、scanf()函数和前面学过的程序设计控制语句,完全可以编写出简单的程序。

printf()和puts() 函数用于在屏幕上显示信息。puts()函数只能显示文本消息,printf() 函数可以显示文本消息和变量。

这两个函数都使用转义序列来控制打印和表示特殊的字符。

scanf()函数获取用户从键盘输入的一个或多个数值,并根据相应的转换说明解译每个数值。

每个值都会被赋给程序中相应的变量。

最后,本次还介绍了三字符序列。三字符序列是特殊的代码,会被转换为相应的等价字符。

问答题

1:既然printf()函数的功能比puts()函数强,为何还要使用puts()函数?

正是由于printf()的功能更强大,因此它存在额外的开销。如果要编写一个小型、高效的程序,或者程序较大、资源很宝贵,那么考虑使用开销较小的puts () 。一般而言,应该尽量使用最简单的可用资源。

2:为什么在使用printf() 、puts ()或scanf()时,要在程序中包含stdio.h头文件?

stdio.h包含标准输入/输出函数的原型。printf()、puts ()和scanf()都是标准输入/输出函数。运行使用这些函数却没有stdio.h头文件的程序,编译器将生成错误和警告。

3:如果去掉scanf()函数中变量名前的的取址符( & ),会发生什么情况?

很容易犯这个错误。如果这样做会导致出乎意料的结果。目前只需记住,如果遗漏了取址运算符,scanf()就会把输入的信息放到内存中的其他地方,而不是变量中。这将导致计算机被锁死,你必须重启计算机。

4:put()和printf()的区别是什么?

​有两点printf()可以打印变量形参

put()在待打印字符末尾自动添加换行符​

5:使用printf()时,要包含什么头文件?

应包含stdio.h文件

6:下面的转义序列分别是做什么?

\\          代表打印反斜杠

\ b        代表退格

\n         代表换行

\t          代表打印制表符

\a         代表振铃

7:要打印下面的内容,应分别使用什么转换说明?

字符串     %s打印反斜杠

有符号十进制整数     %d退格

十进制浮点数        %f换行

8:在put()函数的字面量文本中使用以下的内容,它们之间的区别是?

    打印字符b

\b     退格

   转义字符

\\    打印一个反斜杠

实操题


1.分别用printf()和puts()编写一条换行的语句。

printf( "\n" );
puts( "" );

以上表示puts()会自动添加换行符而printf()不会

2.编写一条scanf()语句,可以获取一个字符、一个无符号十进制整型数和另一个字符。

char c1, c2;
int d1;
scanf("%c %u %c", &c1, &d1, &c2 );

3.编写能获取并打印一个整型值的语句。

#include<stdio.h>
int x;
int main(void)
{
puts("Enter an integer value");
scanf("%d", &x);
printf("\nThe value entered is %d\n", x);
return 0;
}

4.排错:找出下面语句中的错误:

printf( "Jack said,"Peter Piper picked a peck of pickledpeppers." ";

不能在引号中包含引号。要打印引号,必须使用转义字符\"

printf( "Jack said,\"Peter Piper picked a peck of pickledpeppers.\" ";

5.排错:找出下面程序中的错误:

int get_1_or_2( void )
{
int answer = 0;
while (answer <1 || answer > 2)
{
printf (Enter 1 for Yes, 2 for No);
scanf( "%f",answer );
}
return answer;
}

该程序3个错误:

第一个错误是,printf()语句中没有用双引号。

第二个错误是,在scanf()中answer变量前面没有取址运算符。

第三个错误是,scanf()语句中应该使用%d,而不是%f。因为answer是int类型,不是float类型。

正确的代码为:

int get_1_or_2( void )
{
int answer = 0;
while (answer <1 || answer > 2)
{
printf ("Enter 1 for Yes, 2 for No");
scanf( "%d", &answer );
}
return answer;
}


举报

相关推荐

0 条评论