深圳市华胄科技有限公司 >> MCU专题 >> 单片机编程


单片机c语言,10小时学会C 语言 (四)



提交者 电子007  在  2008-3-17 12:34:14 

上一篇 下一篇
单片机c语言,10小时学会C 语言 (四)
第四章 基本输出入函式


这一章将介绍一些基本输出入的函式,使用者经由这些函式可以与计算机沟通,让程序读取使用者的输入部分。程序依使用者不同的要求,做不同的事,再将结果输出给使用者。


◎ 输出指令:printf()


在第二章中,曾经谈过 printf 指令,现在来详细的探讨它。
printf是一种格式化的输出指令,换句话说,你可以用它来编排你所要的输出格式。printf 的一般型式如下:
┌─────────────────────────────────────────────────────┐
│ printf("控制字符串" , 表达式1 , 表达式2 , ... ); │
└─────────────────────────────────────────────────────┘


控制字符串是你打算要秀出的讯息,其中利用 % 与 \ 这两个字符,来控制数值的 输出格式。


控制字符串中每一个 % 符号,表示在后面有一个表达式与它对应,表达式的值会代入这个 % 的位置。在 % 后的字符表示代入数的型别,常用的句柄如下表:
┌────────────────┬──────────────────┐
│printf 的句柄 │ 代表代入的数值型别 │
├────────────────┼──────────────────┤
│%c │ 字符 │
│%d │ 十进制之整数 │
│%ld │ 十进制之长整数 │
│%f │ 浮点数 │
│%lf │ 倍精浮点数 │
│%Lf │ 长倍精浮点数 │
│%s │ 字符串 │
└────────────────┴──────────────────┘


表达式的型别必须跟句柄所代表的型别相符,否则会秀出不可预期的资料。另一个控制符号 \ ,其实只是定义字符而已。在上一章已经介绍了字符的各种表示法,如:'\x41' 表示 A 字符。在 C 语言中,将一些特殊的控制字符另外定义,这些控制字符大部份跟光标的控制有关,如下表:
┌────────┬────┬────┬──────────────────────────┐
│控制字符 │Dec │Hex │功能 │
├────────┼────┼────┼──────────────────────────┤
│\n │ 10 │0x0A│换列,也就是将光标移到下一列 │
│\t │ 9 │0x09│将光标移到下一个定位(1+8n) │
│\b │ 8 │0x08│退一格,类似按下左键 │
│\a │ 7 │0x07│喇叭叫一声 │
│\r │ 13 │0x0D│回到列首 │
│\f │ 12 │0x0C│跳页,在列表时控制列表机跳页 │
│\\ │ 92 │0x5C│印出 \ 字符 │
│\' │ 39 │0x27│印出 ' 字符 │
│\" │ 34 │0x22│印出 " 字符 │
│\xHH │ │0xHH│印出 0xHH 所表示的字符 │
*│%% │ 37 │0x25│印出 % 字符 │
└────────┴────┴────┴───────────────────────────┘


其中,% 字符的定义与在控制字符串中的表示法不同,其余的字符在定义上与在控制字符串中的表示法都相同。printf 在做输出时,你也可以指定保留多少位置给对应的表达式放结果。指定的方式是在 % 之后加一个数值,如 %5d:表示保留 5 个字符空间给一个十进制整数;


%12ld:表示保留 12 个字符空间给一个十进制长整数。如果要输出数据的长度比你指定的保留空间还要大时,printf 就不理会你的设定,把要输出的数据完整的输出,所以,你在设定保留空间时,应该注意输出数据的范围及长度,保留够大的空间,确保输出格式的整齐。在浮点数方面,你除了可以指定保留的空间外,还可以指定小数点后要取几位。如 %8.3f :表示保留 8 个字符空间给一个浮点数,小数部分则是占 3 个字符空间,由于小数点本身占一个字符,所以整数部分占 8 - ( 3 + 1 ) = 4 个字符空间。


printf 在输出数据时,如果你指定保留的空间比要秀的数据长度还要大时,那printf 先秀一些空白,再秀出数据,使总长度等于你所指定的宽度,这样等于是让输出的数据向右对齐。如果你想要让数据是向左对齐的话,可以在指定宽度时使用负数,如 %-5d:表示保留 5 个字符空间给一个十进制整数,若数据长度不足5 ,则在秀出资料后补空白。


○ 整数(int)及长整数(long)
┌─────────────────────────────────────────────────────────┐
│ % - + w d → int │
│ % - + w ld → long │
│ ↑ ↑ ↑ │
│ │ │ └─── 若有指定,则保留 w 个字符 │
│ │ │ 若无指定,秀出长度将由数据决定 │
│ │ └───── 若有指定,则一定会秀出正负号 │
│ │ 若无指定,则只有负数会秀出负号 │
│ └────── 若有指定,则向左对齐 │
│ 若无指定,则向右对齐 │
└─────────────────────────────────────────────────────────┘


○ 浮点数(float)、倍精浮点数(double)及长倍精浮点数(long double)
┌─────────────────────────────────────────────────────────┐
│ % - + w . p f → float │
│ % - + w . p lf → double │
│ % - + w . p Lf → long double │
│ ↑ ↑ ↑ ↑ │
│ │ │ │ └─ 若有指定,则保留 p 个字符给小数 │
│ │ │ │ 若无指定,内定是保留 6 个字符给小数 │
│ │ │ └─── 若有指定,则保留 w 个字符含小数及小数点 │
│ │ │ 若无指定,秀出长度将由数据决定 │
│ │ └───── 若有指定,则一定会秀出正负号 │
│ │ 若无指定,则只有负数会秀出负号 │
│ └────── 若有指定,则向左对齐 │
│ 若无指定,则向右对齐 │
└─────────────────────────────────────────────────────────┘


说了这么多,只有自己试试看才知道!以下是个简单的例子:
┌──────────────────────────────────────────────────────────────────┐
│print.c │
├──────────────────────────────────────────────────────────────────┤
1│#include
2│void main(void) │
3│{ │
4│ printf("|%ld|\n", 123456 ); │
5│ printf("|%5ld|\n", 123456 ); │
6│ printf("|%d|\n", 123 ); │
7│ printf("|%5d|\n", 123 ); │
8│ printf("|%-5d|\n", 123 ); │
9│ printf("|%f|\n", 12.345 ); │
10│ printf("|%9f|\n", 12.345 ); │
11│ printf("|%9.2f|\n", 12.345 ); │
12│ printf("|%-9.2f|\n",12.345 ); │
13│} │
├──────────────────────────────────────────────────────────────────┤
│|123456| ← 123456 大于 32767 要长整数才能表示,所以用 %ld │
│|123456| ← 所保留的 5 个字符不够使用,所以 TC 视同你没设 │
│|123| │
│| 123| ← 保留 5 个字符,只使用 3 个字,向右靠齐 │
│|123 | ← 保留 5 个字符,只使用 3 个字,向左靠齐 │
│|12.345000| ← 小数没有指定,所以 TC 使用内定的 6 个小数。 │
│|12.345000| ← 保留 9 个字符,小数部分仍使用内定值 │
│| 12.35| ← 保留 9 个字符,小数 2 个字符,向右靠齐 │
│|12.35 | ← 保留 9 个字符,小数 2 个字符,向左靠齐 │
└──────────────────────────────────────────────────────────────────┘


◎ 输入指令:scanf()


C 语言使用 scanf 指令来读取keyboard输入的数据。scanf 的一般型式如下:
┌──────────────────────────────────────────────────────┐
│ scanf("控制字符串" , &变量1 , &变量2 , ... ); │
└──────────────────────────────────────────────────────┘


scanf 与 printf 可以说是相对的,一个用来做输入,一个用来做输出。scanf 的控制字符串与 printf 几乎是一样。
┌────────────────┬──────────────────┐
│scanf 的句柄 │ 代表输入的数值型别 │
├────────────────┼──────────────────┤
│%c │ 字符 │
│%d │ 十进制之整数 │
│%ld │ 十进制之长整数 │
*│%D │ 十进制之长整数 │
│%f │ 浮点数 │
│%lf │ 倍精浮点数 │
│%Lf │ 长倍精浮点数 │
│%s │ 字符串 │
└────────────────┴──────────────────┘
★ 注意:没有 %F 这种句柄,课本有误!
%D 的句柄只能用在 scanf() ,在 printf() 中无法使用。


在用 scanf 时还有一点要注意,在控制字符串后的变量,使用的是指针(pointer)。


什么是指标?指针就是指向内存的一个地址,在那个地址存放着数据。例如:一个整数变量 i ,它是存在内存的某一个地址,那个地址在 C 语言中,是以 &i 来表示,我们通常称 &i 是 i 的地址,也称为 i 的指标。


以下是常用的变量及其指针(因为它的地址固定不会改变,也称为指标常数):
┌───────────────────────────────────────────────────────────────────┐
│char c; /* 字符 */ /* c 的指针是 &c */ │
│int i; /* 整数 */ /* i 的指标是 &i */ │
│long l; /* 长整数 */ /* l 的指标是 &l */ │
│float f; /* 浮点数 */ /* f 的指标是 &f */ │
│double d; /* 倍精浮点数 */ /* d 的指标是 &d */ │
│long double ld; /* 长倍精浮点数 */ /* ld 的指标是 &ld */ │
│ │
│char str[80]; /* 字符数组(字符串) */ /* str[80] 的指标是 str */ │
│int a[100]; /* 整数数组 */ /* a[100] 的指标是 a */ │
│long b[100]; /* 长整数数组 */ /* b[100] 的指标是 b */ │
│float c[100]; /* 浮点数数组 */ /* c[100] 的指标是 c */ │
└───────────────────────────────────────────────────────────────────┘


以下的范例,将第三章的范例var.c 变量改由 scanf 输入:
┌────────────────────────────────────────────────────────────────┐
│io.c │
├────────────────────────────────────────────────────────────────┤
1│#include
2│void main(void) │
3│{ │
4│ int i,j; │
5│ │
6│ printf("Enter 2 integers:"); │
7│ scanf("%d %d", &i, &j ); /* 用 i 与 j 的指标 &i,&j */ │
8│ printf("Now, I find that ...\n"); │
9│ printf("%d + %d = %d\n", i , j , i+j ); │
10│ printf("%d - %d = %d\n", i , j , i-j ); │
11│ printf("%d * %d = %d\n", i , j , i*j ); │
12│ printf("%d / %d = %d\n", i , j , i/j ); │
13│} │
├────────────────────────────────────────────────────────────────┤
│Enter 2 integers:20 4 ← 相当于 i = 20 , j = 4 │
│Now, I find that ... │
│20 + 4 = 24 │
│20 - 4 = 16 │
│20 * 4 = 80 │
│20 / 4 = 5 │
└────────────────────────────────────────────────────────────────┘


scanf 在读取多笔数据时,是把调位字符(如:空白、定位(tab)及换列字符)当作数据的分隔的记号,也就是利用 scanf 输入多笔数据时,必须用调位字符分隔输入的数据。如本例中,输入的 i 值与 j 值,可以用空白区隔,也可以用换列或定位来区隔。在结束输入时则要用换列字符,也就是说要按 Enter 。


进阶的程序设计师通常不会用 scanf 作为数据的输入,因为只要输入的格式有一点点错误, scanf 所得到的结果就无法预期。大部分的程序设计师会用gets() 这个函式读入字符串,gets 是以换列字符作为结束记号,所以,利用gets 可以读入包含空白及定位的字符串。读入的字符串可以用 atoi() 转成整数、用 atol() 转成长整数、用 atof() 转成浮点数。更进阶的程序设计师则是自行设计输入函式,并加入一些设定防止输入错误发生,例如,在输入整数的函式中,使用者只有按下数字键才有反应,若按下非数字键,则不会反应。也可以限定使用者输入的数据长度,防止输入的数值过大,等等。


以下的范例,将华氏温度(℉)换算成摄氏温度(℃)
┌────────────────────────────────────────────────────────────────┐
│f2c.c │
├────────────────────────────────────────────────────────────────┤
1│#include
2│void main(void) │
3│{ │
4│ int f,c; │
5│ │
6│ printf("Enter the temperature in F : "); │
7│ scanf("%d", &f ); /* 用 f 的指标 &f */ │
8│ c = ( f - 32 ) * 5 / 9 ; /* 换算公式 */ │
9│ printf("%d degrees in F is %d degrees in C.", f, c); │
10│} │
├────────────────────────────────────────────────────────────────┤
│Enter the temperature in F : 100 │
│100 degrees in F is 37 degrees in C. │
└────────────────────────────────────────────────────────────────┘


华氏温度(℉)与摄氏温度(℃)的互换公式如下:
C = ( F - 32 ) * 5 / 9
F = C * 9 / 5 + 32


以下是课本的范例,将年纪改用"日"来估算:
┌────────────────────────────────────────────────────────────────┐
│age.c │
├────────────────────────────────────────────────────────────────┤
1│#include
2│void main(void) │
3│{ │
4│ float years, days; │
5│ │
6│ printf("Enter the age of you : "); │
7│ scanf("%f", &years ); /* 用 years 的指标 &years */ │
8│ days = years * 365.25 ; /* 换算公式 */ │
9│ printf("You are %f days old.", days ); │
10│} │
├────────────────────────────────────────────────────────────────┤
│Enter the age of you : 28.5 │
│You are 10409.625000 days old. │
└────────────────────────────────────────────────────────────────┘


◎ 输入指令:getche()


使用 scanf() 读取字符时,必须再按下 Enter 键,该字符才会被读取。在某些场合中,我们希望每按一个键,程序就会读取,不用再按下 Enter 键,例如:在计算机游戏中,每按下方向键,所控制的人物就依所按的方向移动。利用 getche() 可以达到这个目的。 getche 的一般型式如下:
┌────────────────────────────────────────────────────────┐
│ ch = getche(); │
└────────────────────────────────────────────────────────┘


将 getche() 所读到的字符传给 ch 。此外,getche() 会将读到的字符先秀在屏幕上。


以下的范例,将所按的键秀出其 ASCII 码:
┌────────────────────────────────────────────────────────────────┐
│code.c │
├────────────────────────────────────────────────────────────────┤
1│#include /* 宣告 printf() 的原型 */ │
2│#include /* 宣告 getche() 的原型 */ │
3│void main(void) │
4│{ │
5│ char ch; │
6│ │
7│ ch = getche(); /* getche() 会传回你所按下键的字符 */ │
8│ printf(" -- You typed %c.\n", ch ); │
9│ printf("Character %c has ASCII code %d.\n", ch, ch ); │
10│} │
├────────────────────────────────────────────────────────────────┤
│A -- You typed A. │
│Character A has ASCII code 65. │
└────────────────────────────────────────────────────────────────┘
这个范例主要是用来查询一般字符的 ASCII 码,请勿输入方向键,否则它的结果可能会让你失望。因为方向键及功能键等特殊按键会产生两个码,必须读两次才能得到正确的结果。


第 9 行,用 %c 的控制字符,表示要秀出 ch 所代表的字符;用 %d 的控制字符,表示要秀出 ch 所代表的数值。


☆★☆★☆★☆★ 练习 ☆★☆★☆★☆★


实作课本习题第 10 题,看看你所得到的结果与课本所列的的结果一不一样?


☆★☆★☆★☆★ 作业 ☆★☆★☆★☆★


■ Help参考数据:
┌──────────────── Help ──────────────────────────┐
│ printf: formatted output to stdout │格式化输出至 stdout
│ │
│ int printf(const char *format, ...); │printf 的语法
│ │
│ Prototype in stdio.h │必须 #include
│ │
│ Print formats a variable number of arguments │不同的格式须要不同的
│ according to the format, and sends the output │参数,这些数据会送到
│ to stdout. Returns the number of bytes output. │stdout。传回值是输出
│ In the event of error, it returns EOF. │的byte数,若发生错误
│ │则传回 EOF
│ See also ecvt fprintf putc │
│ puts scanf vprintf │相关指令
└────────────────────────────────────────────────┘
┌─────────────────── Help ───────────────────────┐
│ Format Specifiers │format 的格式
│ │
│ % [flags] [width] [.prec] [F|N|h|l] type │[ ] 表示不一定要用
│ │
│ type Format of Output │格式化输出的型别:
│ d signed decimal int │d 带正负号十进制整数
│ i signed decimal int │i 带正负号十进制整数
│ o unsigned octal int │o 不带正负号八进位整数
│ u unsigned decimal int │u 不带正负号十进制整数
│ x in printf = unsigned hexdecimal int │x 不带正负号16进位整数(小写)
│ lowercase; in scanf = hexadecimal int │ 在 scanf 为16进位整数
│ X in printf = unsigned hexdecimal int │X 不带正负号16进位整数(小写)
│ uppercase; in scanf = hexadecimal long │ 在 scanf 为16进位长整数
│ f floating point [-]dddd.ddd │f 浮点数 例: 314.159
│ e floating point [-]d.ddd e [+/-]ddd │e 浮点数 例: 3.14159e2
│ g format e or f based on precision │g 由精度决定用 f 或 e 的格式
│ E same as e except E for exponent │E 同 e 只是以 E 表示指数符号
│ G same as g except E for exponent │G 同 g 只是以 E 表示指数符号
│ c single character │c 单一字符
│ s print characters till '\0' or [.prec] │s 打印字符直到 '\0' 或指定长度
│ % the % character │% 打印 % 这个字符
│ p pointer: near - YYYY; far - XXXX:YYYY │p 指标:近 YYYY 远 XXXX:YYYY
│ n stores count of characters written so │n 将目前已经打印出的字符数值
│ far in the location pointed to by │ 传给输入的参数。在此,
│ input argument │ 输入的参数必须是整数指标。
│ │
│ [flag] What it Specifies │[旗标]
│ │
│ none right-justify, pad 0 or blank to left │无 靠右对齐不足在左边补空白或0
│ - left-justify, pad spaces to right │- 靠左对齐不足在右边补空白
│ + always begin with + or - │+ 正负号一定会秀出
│ blank print sign for negative values only │空白 只有负数才会秀出负号
│ # convert using alternate form: │# 转换格式
│ c,s,d,i,u no effect │对 c,s,d,i,u 没有影响
│ o 0 prepended to nonzero arg │o 如果数据不是 0 就会先秀 0
│ x or X 0x or 0X prepended to arg │x,X 在资料前加秀 0x 或 0X
│ e, E, f always use decimal point │e,E,f 会秀出小数点
│ g or G same as above but no │g,G 会秀出小数点,但是不补 0
│ trailing zeros │
│ │
│ [width] Effect on Output │[宽度]
│ │
│ n at least n characters, blank-padded │n 指定输出的宽度,不足补空白
│ 0n at least n characters, 0 left fill │0n 指定输出的宽度,不足在左补0
│ * next argument from list is width │* 由下一个参数决定宽度
│ │
│ [.prec] Effect on Output │[.精度]
│ │
│ none default precision │无 内定的精度
│ .0 d,i,o,u,x default precision │.0 d,i,o,u,x 是内定的格式
│ e, E, f no decimal point │ e,E,f 表示没有小数
│ .n at most n characters │.n 指定 n 个字符长度
│ * next argument from list is precision │.* 由下一个参数决定精度
│ │
│ Modifier How arg is Interpreted │输入大小修饰词
│ │
│ F arg is far pointer │F 远指标
│ N arg is near pointer │N 近指标
│ h d,i,o,u,x,X arg is short int │h 短整数
│ l d,i,o,u,x,X arg is long int │l 长整数
│ l e, E, f, g, G arg is double │l 倍精数(只有在 scanf)
│ (scanf only) │
│ L e,E,f,g,G arg is long double │L 长倍精数
└────────────────────────────────────────────────┘
┌─────────────────── Help ───────────────────────┐
│ scanf: performs formatted input from stdin │由 stdin 读入格式化的数据
│ │
│ int scanf(const char *format, ...); │scanf 的语法
│ │
│ Prototype in stdio.h │必须 #include
│ │
│ Returns the number of input fields processed │传回成功读取的字段数。
│ successfully. It processes input according to │输入的数据会依照指定格式
│ the format and places the results in the │储存,并将它们放到参数所
│ memory locations pointed to by the arguments. │指到的内存。
│ │
│ See also atof cscanf fscanf │相关指令
│ getc printf sscanf │
│ vfscanf vscanf vsscanf │
└────────────────────────────────────────────────┘
┌───────────────────── Help ─────────────────────┐
│ getch: gets character from console, no echoing │由控制台读入字符,不响应
│ getche: gets character from the console and │由控制台读入字符,并
│ echoes to screen │响应到屏幕
│ │
│ int getch(void); │getch 的语法
│ int getche(void); │getche 的语法
│ │
│ Prototype in conio.h │必须 #include
│ │
│ Both functions return the character read. │getch 及 getche 两者都会
│ Characters are available immediately - no │回传所读到的字符。由于没
│ buffering of whole lines. │有缓冲区,所传回的字符
│ │立即可用。
│ Special keys such as function keys and arrow │功能键或方向键等这些特殊
│ keys are represented by a two character │按键,会产生连续的两个字
│ sequence: a zero character followed by the │元:第一个字符是 0,第二
│ scan code for the key pressed. │个是所按下键的扫描码。
│ │
│ See also getpass cgets cscanf │相关指令
│ kbhit ungetch putch │
│ getchar getc │
└────────────────────────────────────────────────┘



单片机教程,五系列(55讲)电子书全集下载

论坛精选:
■ 单片机c语言,10小时学会C 语言 (一)
第一章 C 语言简介与Turbo C 的使用
■ 单片机c语言,10小时学会C 语言 (二)
第二章 C 程序的结构
■ 单片机c语言,10小时学会C 语言 (三)
第三章 常数与变数
■ 单片机c语言,10小时学会C 语言 (四)
第四章 基本输出入函式
■ 单片机c语言,10小时学会C 语言 (五)
第五章 流程图与抉择指令
■ 单片机c语言,10小时学会C 语言 (六)
第六章 循环与自动重复
■ 单片机c语言,10小时学会C 语言 (七)
第七章 数组与指针
■ 单片机c语言,10小时学会C 语言 (八)
第八章 函数与呼叫
■ 单片机c语言,10小时学会C 语言 (九)
第九章 档案存取

1 楼  提交者:陈春 在 2008-3-18 11:39:07
艰苦的撒
2 楼  提交者:king 在 2008-3-18 15:52:08
ok
3 楼  提交者:浪人 在 2008-3-18 20:52:00
ni hao a 
4 楼  提交者:卫立 在 2008-3-18 22:48:54
5 楼  提交者:清风 在 2008-3-19 9:46:32
付出代价
6 楼  提交者:木木林 在 2008-3-19 10:16:51
7 楼  提交者:Guest 在 2008-3-19 11:22:32
可以不可以不用回復
8 楼  提交者:han2002asd 在 2008-3-19 11:55:07
bv
9 楼  提交者:郭总 在 2008-3-19 13:43:02
10 楼  提交者:anny2008 在 2008-3-19 16:24:24
11 楼  提交者:Guest 在 2008-3-19 16:39:43
付出代价
12 楼  提交者:中山盈亮 在 2008-3-20 11:20:12
不错
13 楼  提交者:Guest 在 2008-3-20 18:25:27
What is chip select
14 楼  提交者:goldskin 在 2008-3-20 21:47:43
gan
15 楼  提交者:梦蝶秋 在 2008-3-21 11:41:53
16 楼  提交者:youminbuluo 在 2008-3-21 20:52:40
我看看
谢谢
17 楼  提交者:Guest 在 2008-3-21 21:59:48
hlijkjllljjlk
18 楼  提交者:高臣 在 2008-3-22 13:16:27
学习
19 楼  提交者:luxs 在 2008-3-22 13:56:51
可以不可以不用回復 累
20 楼  提交者:liuyiqiangqq 在 2008-3-22 21:50:02
21 楼  提交者:有点意思 在 2008-3-22 23:42:29
good hao
22 楼  提交者:Guest 在 2008-3-23 0:23:09
23 楼  提交者:Guest 在 2008-3-23 13:35:26
看在眼里看看在眼里看看看在眼里
24 楼  提交者:hanozi 在 2008-3-25 11:55:02
kankan
25 楼  提交者:shw0320 在 2008-3-25 12:01:23
uyiou
26 楼  提交者:Guest 在 2008-3-25 16:21:00
print
27 楼  提交者:有点意思 在 2008-3-26 16:58:50
hao~
28 楼  提交者:cqhj 在 2008-3-27 15:27:51
继续
29 楼  提交者:Guest 在 2008-3-27 17:28:43
30 楼  提交者:悠悠 在 2008-3-27 23:25:39
上一篇 下一篇
当前第〖1〗页 共有20页 转到第 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20