C语言_05 函数, main函数, scanf, printf详解

 

概念

“函数”是从英文function翻译过来的,其实,function在英文中的意思即是“函数”,也是“功能”。从本质意义上来说,函数就是用来完成一定功能的。这样对函数的概念就很好理解了,所谓函数名就是给该功能起个名字,如果该功能是用来实现数学运算的,就是数学函数。

函数的写法

            返回类型 函数名(参数1, 参数2, ... 参数n)//参数可以不写
            {
                //函数体
                ....
                return 返回类型; //如果返回类型为void 可以没有return.
            }

main函数

每个C语言程序至少有一个函数,我们常常用main()函数, 也称之为主函数, 但是C语言的程序的主函数是不是一定叫main呢? 答案当然是否定的, 操作系统在执行main函数之前, 调用了其他代码, 这些代码就有初始化main函数所需的运行环境,而负责初始化main函数的这个函数就称之为入口函数/入口点.而入口函数规定的C程序的主函数就是main, 那么我们当然可以找到这个文件,修改主函数名.

main函数的返回值

main函数的返回值一般有两种写法
1.void main 2.int main但是这前者最好不要使用, 不仅仅是有些编译器不支持.还因为操作系统对于一个程序的正常或者执行异常都是整型,如果程序返回 0 表示程序正常执行, 如果返回其他整型,执行异常.那么可以说 void main就是一种不恰当的写法.int main的返回值为0或者不为0的程序的执行结果其实都一样,但为什么一定要返回0呢? 举个例子:
//test.c
    #include <stdio.h>

    int main(){
        printf("hello ");
        return 0;
    }
//test1.c
    #include <stdio.h>

    int main(){
        printf("world!\n");
        return 0;
    }
执行test 和 test1 &&运算符是指执行成功&&前面的便执行后面的, 如果执行前面失败,后面便不会执行.
panyiwen@god:~/temp$ ./test && ./test1
hello world!
如果我们将第一个test.c的返回值改为 return 1;执行结果:
panyiwen@god:~/temp$ ./test && ./test1
hello panyiwen@god:~/temp$
只输出hello , 没有world和换行.也就是第二个test1.c没有执行.原因便是第一个程序的返回值是1,系统认为该程序没有执行成功.所以不会执行第二个test1

main函数的三种写法(两种)

1.int main(void) //括号中的void可以不写
2.int main(int argc, char *argv[])
3.int main(int argc, char *argv[], char *envp[]) //不建议使用, 因为第三个参数只是类unix系统的拓展
其实也就是main函数中可以不写参数, 写两个参数, 写三个参数.因为是参数,所以名称可以自己取,也可以就用上述名称.
三个参数
  1. int argc 整型参数, argc = 1+输入的参数个数, 系统自动赋值, 无需我们写, 1 为程序的名称.
  2. char *argv[] 字符串数组, argv[0] 表示程序的名称, argv[1]~argv[argc-1]代表我们传入的参数.
  3. char *envp[] 字符串数组, 表示系统的环境变量
例子:
#include <stdio.h>
    int main(int argc, char *argv[], char *envp[]){
        int i;
        printf("%d\n\n", argc);
        for (i = 0; i &lt; argc; i++){
            printf("%s\n", argv[i]);
        }
        printf("\n");
        for (i = 0; envp[i] != NULL; i++){
            printf("%s\n", envp[i]);
        }
        return 0;
    }
我们执行这段程序, 并输入参数hello world, 部分输出结果, 因为系统环境变量太多.
panyiwen@god:~/temp$ ./test hello world
3

./test hello world

XDG_VTNR=7 XDG_SESSION_ID=c2 CLUTTER_IM_MODULE=xim XDG_GREETER_DATA_DIR=/var/lib/lightdm-data/panyiwen GPG_AGENT_INFO=/home/panyiwen/.gnupg/S.gpg-agent:0:1 SHELL=/bin/bash TERM=xterm-256color ...
我们可以看到, argc = 3 执行的程序名称+两个参数 argv = {"./test", "hello", "world"}; 而envp则全是系统环境变量key=value的字符串.那么我们知道系统环境变量有什么用? 我们可以得到环境变量配置的一些参数来完成我们需要的功能,但是不建议推荐使用第三个参数传入,因为拓展性不强, 我们可以通过C语言的 #include <stdlib.h>库中的函数来得到和设置删除系统环境变量.这样在不同系统上的使用方式就是一致的.

库函数

C语言库函数是把自定义函数放到库里,是别人把一些常用到的函数编完放到一个文件里,供程序员使用。程序员用的时候把它所在的文件名用#include<>加到里面就可以了(尖括号内填写文件名),例如 #include <math.h>
库函数也就是一些程序员大牛们,他们将一些我们常用的函数,写到文件里面供我们调用,每次计算机语言的更新,除了一些语法的更新外,很多也是加入一些别的优秀的代码文件加入库中.说到库函数,我们就不得不提 #include <stdio.h> 我们平常写的几乎所有的C程序的开头都会加上这么一句,标准输入输出.那么我们就来介绍以下stdio.h.

stdio.h

stdio 就是指 “standard input & output"(标准输入输出) 所以,源代码中如用到标准输入输出函数时,就要包含这个头文件!
引用方法: #include <stdio.h>

stdio.h所包含的函数:文件访问: fopen,freopen,fflush,fclose二进制输入/输出: fread, fwrite非格式化输入/输出: fgetc/getc, fputc/putc, ungetc, fgets ,fputs格式化输入/输出: scanf/fscanf/sscanf ,printf/fprintf/sprintf, perror文件定位: ftell, fseek, fgetpos ,fsetpos, rewind错误处理: feof, ferror文件操作: remove, rename, tmpfile
大名鼎鼎的EOF 也是宏定义在stdio.h中, 一般编译器定义是: #define EOF -1
我们常用的scanf, printf 函数都是写在stdio.h中.

scanf函数和printf函数:

用 法: int scanf(char *format[,argument,...]);用 法: int printf("<格式化字符串>", <参量表>);
我们知道scanf是格式化输入, 调用此函数,我们在计算机的键盘中输入的字符串会传化为相对应的格式,储存到变量中, 并返回一个整数,代表成功输入了多少个.printf是格式化输出, 输出内容到显示器(终端) 返回值是输出字符的个数,若出错,则返回负数。 .例子:
int num = scanf("%f %d", &a, &b);
printf("a=%f, b=%d, num = %d\n", a, b, num);
分析:上面的例子,如果我们正常输入 11.2 2,那么函数就会返回一个2表示我们输入成功输出 a=11.200000, b=2, num=2, 如果我们输入 11.2 a那么就会将11.2 赋值给 a, 但是'a'无法赋值给b, 输入就会失败, 输出 a=11.200000, b=517694128, num=1b被随机赋予了一个值, 成功输入一个.如果是 a 11那么返回值就是0了,a,b都会被随机赋值.小知识: 我们知道一个变量是要在内存中开辟一段内存的, 变量储存的值是储存在内存中, &为取地址符,我们要存值, 必须知道变量的地址. 我们平时用的a 其实是 *&a 先取出地址再得到内存中的值, 为了方便将*&省略.但是如果用的多的人就会发现scanf有一些很神奇的事情发生,举几个例子:
scanf("%d %lf", &a, &b);
scanf("%s", ch);
scanf("%d%c",&a, &c);
我们对其输出,第一个我们输入 11.234 12.3,结果: a=11 b=0.234000第二个我们输入 Hello World !!!, 结果: Hello第三个我们输入 16 c, 结果: a=16 c=' '我们其实明白scanf输入浮点型给整型会被强制转换, 字符串%s是不能接受空格的,如果我们没有规定分隔符是什么,一般默认是空格, 但是输入的空格会被%c接收,所以c='  '.等等很多有意思的点,那么我们就来看看这个理由吧.先引入点知识点:

stdin, stdout, stderr的简单介绍:

1.stdin, 标准输入流: 通常是键盘输入.2.stdout, 标准输出流: 输出到屏幕.3.stderr, 标准错误流: 无缓冲.输出到屏幕. 一般是错误信息.全缓冲: 直到文件结束或者手动清空缓存,才清空缓冲.行缓冲: 遇到回车或者换行, 或者文件结束, 清空缓冲
ISO C规定:当且仅当stdin和stdout不指向交互式设备时,他们才是全缓冲。 stderr决不会是全缓冲。Linux系统默认:stderr是不带缓冲的。 若流指向终端设备,则是行缓冲,否则为全缓冲。
所以在c语言中stdin和stdout是行缓冲, 我们的scanf和printf函数就是使用了stdin和stdout, 而stdin和stdout就是写在stdio中的.本质就是系统帮我们打开了两个文件句柄. 我们输入的数据就储存在stdin那个文件中, 输出的数据就存储在stdout文件中, 我们调用scanf和printf就是在文件中取数据, 进行输入和输出.第一个例子 scanf("%d %lf", &a, &b); 我们就是从缓冲区stdin 也就是字符串取出 11 赋值给a 取出 .234赋值给b. 所有有关这些奇特的现象就是和stdin和stdout有关. scanf 也就是 int fscanf(stdin, const char *format, [argument...]); 遇到换行或空格结束printf 也就是int fprintf( stdout, const char *format, [ argument ]...);其他的库函数也就是大同小异,主要是知道怎么用的就好.

自定义函数

在库函数不满足我们的需求的时候, 我们又不想把所有代码都写在主函数里面, 那样不仅丑,而且可读性,复用性都很差.那么我们就需要自定义函数,来满足我们的需要写法和main函数一样
返回值类型 函数名(参数1, 参数2 ...)//可不写
{
    //函数体
    ...
    return 返回值;
}
举个例子, 比大小, 返回最大值:(虽然库函数中有)
int max(int a, int b){
    return a > b ? a : b;   //三目运算符 等价与 if(a > b) {return a;} else{ return b;}
}

int main(){
    int a = 100, b = 120;
    int maxnum;
    maxnum = max(a, b); //调用max函数 返回两个数最大的那个
    return 0;
}
C语言中需要注意的是函数要么写在执行前面, 要么是需要声明(告诉计算机有这个函数), 要不然找不到.也就是掉个位置:
int main(){
    int a = 100, b = 120;
    int maxnum;
    int max(int, int);  //使用前需要声明有这个函数  只要使用前声明就好,也就是可以写在int main()的上面也可以.
    maxnum = max(a, b); //调用max函数 返回两个数最大的那个
    return 0;
}

int max(int a, int b){
    return a > b ? a : b;   //三目运算符 等价与 if(a > b) {return a;} else{ return b;}
}
声明也就是告诉计算机,如果在这之前没找到这个函数没关系,先别报错,我的函数在下面.

致谢: http://blog.csdn.net/Crazy_Tengt/article/details/72717144 http://blog.csdn.net/q565220/article/details/49951885

查看原文: http://www.welcom212.com/wordpress/?p=293
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值