函数
一、定义函数
定义一个函数我们需要确定三部分内容:
1.函数的返回值类型
2.函数的名称
3.函数的参数
确定了以上内容后就可以定义一个特有功能的函数了:
int fun(int a,int b)
{
return a+b;
}
上面的的代码就定义了一个返回值类型为int类型的函数,其函数名为fun
,小括号里的内容为函数的参数,这个函数有两个传入参数 int a,int b。在函数体,直接使用return 返回a+b的和,如果a=1,b=1,那么返回值就是2了。
如果我们想定义一个没有返回值类型的函数则需要设计其返回值类型为void,同样,如果我们想定义一个没有参数的函数可以将其参数定义为void,通常如果一个函数没有参数可以在函数名后的小括号里什么都不写,例如:
void fun1(void)
{
}
void func2()
{
}
二、函数的调用与声明
#include <stdio.h>
int jia(int a ,int b);//函数声明“;”不要落下
main()
{
int a=1,b=2;
int c;
c=jia( a,b);
printf("%d + %d = %d",a,b,c);
return 0;
}
int jia(int a,int b)
{
a=a+2;
b=b+1
return a+b;
}
如果函数的定义是在调用函数的后面(下面)则需要在调用之前声明函数的定义,否则不需要事先声明。声明的意思是告诉编译器,这个函数的返回值类型、函数名和参数。
我们在调用一个函数时,需要向这个函数传其需要的参数,例如a和b这两个变量,并可以指定另一个变量用于接收这个函数执行后的返回值,比如变量c就接收了函数jia
的返回值,结果为3。但是我们看到程序的运行结果是 1 + 2= 6,也就是说,执行了函数jia()
后,我们虽然对函数内的参数变量分别加2,1,但主函数main中的a和b的值并没有发生变化。
三、实参与形参
当我们调用函数时,对其传入的参数和函数体内接收到的参数其实并不是同一个变量。调用函数时向函数传入的参数称作实际参数,简称实参,而函数体内部用于接收外部调用时传入的参数的参数称为形式参数,简称形参。
例如上面例子中,在main函数中定义的变量int a和int b,在调用jia(a, b);时这两变量是实参,也就是将这两个变量的值1和2传入到函数内部。而在函数jia()的函数体内,用于接收这两个参数时的int a和int b则是形参,这是函数体内部额外的两个变量,用于接收2和3这两个值,这两个变量并不是main函数中定义的a和b 。
在jia()函数体内,对形参做a = a + 2;和b = b + 1;操作,其实只影响到了函数体内部的这两个变量,而并未影响到main函数中的变量a和b的值。所以,在jia()函数体内的a和b的值为3和3,函数运行结果的返回值为7,而在main函数中的a和b两变量的值仍然是1和2,所以printf()函数显示出的结果则是 1 + 2 = 6
四、输出与输入函数
printf函数
灵魂拷问:你真的会print
f吗???
对于 printf
函数,相信大家并不陌生。之所以称它为格式化输出函数,关键就是该函数可以按用户指定的格式,把指定的数据显示到显示器屏幕上。该函数原型的一般格式如下:
int printf(const char * format, ... );
printf
函数是一个“可变参数函数”(即函数参数的个数是可变的)。确切地说,是其输出参数的个数是可变的,且每一个输出参数的输出格式都有对应的格式说明符与之对应,从格式串的左端第 1 个格式说明符对应第 1 个输出参数,第 2 个格式说明符对应第 2 个输出参数,第 3 个格式说明符对应第 3 个输出参数,以此类推。
%[flags][width][.prec][length] type_char
/*用中文标识如下:*/
%[标志符][宽度][精度][长度]类型符
1) 类型符(type_char)
它用以表示输出数据的类型,如表 1 所示。
符 号 | 类 型 | 说 明 | 示 例 | 结 果 |
---|---|---|---|---|
% | 无 | 输出字符“%”本身 | pnntf("%%"); | % |
d、i | int | 以整型输出 | printf("%i,%d", 100,100); | 100,100 |
u | unsigned int | 以无符号整型输出 | printf( “%u,%u”,100u,100); | 100,100 |
o | unsigned int | 以八进制无符号整S输出 | printf( "%o”,100); | 144 |
x | unsigned int | 以十六进制小写输出 | printf("%x",11); | b |
X | unsigned int | 以十六制大写输出 | printf("%X",11); | B |
2) 标志符(flags)
它用于规定输出格式,如表 2 所示。
符号 | 说 明 |
---|---|
(空白) | 右对齐,左边填充 0 和空格 |
(空格) | 输出值为正时加上空格,为负时加上负号 |
- | 输出结果为左对齐(默认为右对齐),边填空格(如果存在表格最后一行介绍的0,那么将忽略0) |
+ | 在数字前增加符号“+”(正号)或“-”(负号) |
# | 类塑符是o、x、X吋,增加前缀0、0x、0X;类型符是e、E、f、F、g、G时,一定要使用小数点;类型符是g、G时,尾部的 0 保留 |
0 | 参数的前面用0填充,直到占满指定列宽为止(如果同时存在“-”,将被“-”覆盖,导致 0 被忽略 |
3) 宽度(width)
它用于控制显示数值的宽度,如表 3 所示。
符号 | 说 明 |
---|---|
n | 至少输出 n 个字符(n 是一个正整数)。如果输出少于 n 个字符,则用空格填满余下的位置(如果标识符为“-”,则在右侧填,否则在左端填) |
0n | 至少输出 n 个字符(n 是一个正整数)。如果输出值少于 n 个字符,则在左侧填满 0 |
* | 输出字符个数由下一个输出参数指定(其必须为一个整形量) |
4) 精度(.prec)
它用于控制显示数值的精度。如果输出的是数字,则表示小数的位数;如果输出的是字符,则表示输出字符的个数;若实际位数大于所定义的精度数,则截去超过的部分。如表 4 所示。
表 4 精度及其说明符号说 明无系统默认精度.
符号 | 说明 |
---|---|
无 | 系统默认值 |
.0 | 对于 d、i、o、u、x、X等整形类型符,采用系统默认精度;对于f、F、e、E等浮点类型符,不输出小数部分. |
.n | 1)对于d、i、o、u、x、X类型符,至少输出 n 位数字,且:如果对应的输出参数少于 n 位数字,则在其左端用零(0)填充如果对应的输出参数多于 n 位数字,则输出时不对其进行截断2) 对于f、F、e、E类型符,输出结果保留 n 位小数。如果小数部分多于 n 位,则对其四舍五入 3) 对于 g 和 G 类型符,最多输出 n 位有效数字 4) 对于 s 类型符,如果对应的输出串的长度不超过 n 个字符,则将其原样输出,否则输出其头 n 个宁符*输出精度由下一个输出参数指定(其必须为一个整型量) |
5) 长度(length)
它用于控制显示数值的长度,如表 5 所示。
符号 | 说 明 |
---|---|
hh | 与d、i 一起使用,表示一个signed char 类型的值;与o、u、x、X—起使用,表示一个unsigned char 类型的值;与 n 一起使用,表示相应的变元是指向 signed char 型变量的指针(c99 ) |
h | 与d、i、o、u、x、X 或 n 一起使用,表示一个short int 或 unsigned short int 类型的值 |
l | 与d、i、o、u、x、X 或 n 一起使用,表示一个 long int 或者 unsigned long int 类型的值 |
ll | 与 d、i、o、u、x、X 或 n —起使用,表示相应的变元是 long long int 或 unsigned long long int 类型的值(c99 ) |
j | 与 d、i、o、u、x、X 或 n —起使用,表示匹配的变元是 intmax_t 或 uintmax_t 类型,这些类型在“stdint. h”中声明(c99 ) |
z | 与 d、i、o、u、x、X 或 n —起使用,表示匹配的变元是指向 size_t 类型对象的指针,该类型在“stddef. h”中声明(c99 ) |
t | 与d、i、o、u、x、X 或 n —起使用,表示匹配的变元是指向 ptrdiff_t 类型对象的指针,该类型在“stddef. h”中声明(c99 ) |
L | 和a、A、e、E、f、F、g、G—起使用,表示一个long double类型的值 |
scanf 函数
相对于 printf 函数,scanf 函数就简单得多。scanf 函数的功能与 printf 函数正好相反,执行格式化输入功能。即 scanf 函数从格式串的最左端开始,每遇到一个字符便将其与下一个输入字符进行“匹配”,如果二者匹配(相同)则继续,否则结束对后面输入的处理。而每遇到一个格式说明符,便按该格式说明符所描述的格式对其后的输入值进行转换,然后将其存于与其对应的输入地址中。以此类推,直到格式串结束为止。该函数原型的一般格式如下:
int scanf (const char *format, ...);
从函数原型可以看出,同 printf 函数相似,scanf 函数也是一个“可变参数函数”。同时,scanf 函数的第一个参数 format 也必须是一个格式化串。除此格式化串之外,scanf 函数还可以有若干个输入地址,且对于每一个输入地址,在格式串中都必须有一个格式说明符与之一一对应。即从格式串的左端第 1 个格式说明符对应第 1 个输入地址,第 2 个格式说明符对应第 2 个输入地址,第 3 个格式说明符对应第 3 个输入地址,以此类推。
也就是说,除第 1 个格式化串参数之外,其他参数的个数是可变的,且每一个输入地址必须指向一个合法的存储空间,以便能正确地接受相应的输入值。每个输入值的转换格式都由格式说明符决定。格式说明符的一般形式如下(方括号 [] 中的项为可选项):
%[][width][length] type_char
/用中文标识如下:/
%[][宽度][长度]类型符
在使用 scanf 函数的时候,需要特别注意的就是缓冲区问题。对 scanf 函数来说,估计最容易出错、最令人捉摸不透的问题应该是缓冲区问题了。