为了让计算机执行某些操作或解决某个问题而编写的一系列有序指令的合集。
1)C程序源文件以“c”为扩展名。
2)C程序的执行入口时main()函数。
3)C语言严格区分大小写。
4)C程序由一条条语句构成,每个语句以“;”结束。
\t:一个制表位,实现对齐功能
\n:换行符
\\:\
\":"
\':'
\r:一个回车
//:单行注释文字
/* */:块注释。多行注释。
变量相当于内存中一个数据存储空间的表示,你可以把变量看做是一个房间的门牌号,通过门牌号我们可以找到房间,而通过变量名可以访问到变量(值)。
声明变量:int num;
赋值:num = 60;
使用:printf("num = %d",num);
一步到位:int num2 = 99;
基本类型:数值类型:整型(短整型short2、整型int2、长整型long4)、浮点型(单精度float4、双精度double8)、字符型char1
构造类型:数组、结构体struct、共用体union、枚举类型enum
指针类型
空类型void
1)默认传递值的类型:基本数据类型(整型类型、小数类型,字符类型),结构体,共用体。
值传递:将变量指向的存储内容,在传递赋值时,拷贝一份给接收变量。
1)常量是固定值,在期间不能改变。这些固定的值,又叫做字面量。
2)常量可以是任何的基本数据类型,比如整数常量、浮点常量、字符常量,或字符串字面值,也有枚举常量。
3)常量的值在定义后不能进行修改。
整数、浮点、字符、字符串常量
1)使用#define预处理器,#define 常量名 常量值
2)使用const关键字,const 数据类型 常量名=常量值;//即就是一个语句
1)const定义的常量时,带类型,define不带类型
2)const是在编译、运行的时候起作用,而define是在编译的预处理阶段起作用
3)define只是简单的替换,没有类型检查。简单的字符串替换会导致边界效应
4)const常量可以进行调试的,define是不能进行调试的,主要是预编译阶段就已经替换掉了,调试的时候就没它了
5)const 不能重定义,不可以定义两个一样的,而define通过undef取消某个符号的定义,再重新定义
6)define可以配合#ifdef、#ifindef、 #endif来使用,可以让代码更加灵活,比如我们可以通过#define 来启动或者关闭调试信息
+-*/%
%:7%5=2;a%b=a-a/b*b
==、!=、>、<、<=、>=
1)关系运算符的结果要么是真(非0表示),要么是假(0表示)
2)关系表达式经常用在if结构的条件中或循环结构的条件中
与&&、或||、非!
用于连接多个条件(一般来讲就是关系表达式),最终的结果要么是真(非0表示),要么是假(0表示)
=、+=、-=、*=、/=、%=、<<=、>>=、&&=、|=
运算顺序从右往左。
作用于位,并逐位执行操作。
条件表达式?表达式1:表达式2;
条件表达式为非0(真),运算后的结果是表达式1;
条件表达式为0(假),运算后的结果是表达式2;
1)C语言对各种变量、函数等命名时使用的字符序列称为标识符
2)凡是自己可以起名字的地方都叫标识符
关键字中所有字母都为小写。
1)include <stdio.h>
2)使用scanf函数
3)使用适当的格式参数接收输入
二进制
十进制
八进制:以数字0开头表示。
十六进制:以0X或0x开头表示。
1)
2)分支控制
3)
程序从上到下逐行执行,中间没有任何判断和跳转。
1)单分支
2)双分支
3)多分支
if(条件表达式){
执行代码块;
}
if(条件表达式){
执行代码块1;
}else{
执行代码块2;
}
if(条件表达式1){
执行代码块1;
}else if(条件表达式2){
执行代码块2;
}
.......
else{
执行代码块n;
}
在一个分支结构中又完整的嵌套了另一个分支结构,里面的分支的结构称为内层分支外面的分支结构称为外层分支。嵌套分支不适合过多,最多不要超过3层。
if(条件表达式){
if(条件表达式){//被包含的可以是单分支、双分支、多分支
}
}else{
执行代码块2;
}
break语句用于终止某个语句块的执行,一般使用在switch或者循环[三大循环]中。
continue语句用于结束本次循环,继续执行下一次循环。
return使用在函数,表示跳出所在的函数,在讲解函数的时候会详细的介绍,这里我们简单的提一下。
1)枚举是C语言中的一种构造,它可以让数据更加简洁,更易读,对于只有几个有限的特定数据,可以使用枚举
2)枚举对应英文(enumeration,简写enum)
3)枚举是一组常量的集合,包含一组有限的特定的数据
4)枚举语法定义格式为
enum 枚举名 {枚举元素1,枚举元素2,.....}
enum DAY{ NON=1,TUE=2,WED=3,THU=4,FRI=5,SAT=6,SUN=7 };
#include <stdio.h>
#include <stdbool.h>
enum SEASONS{
SPRING=1,SUMMER,AUTUMN,WINTER
} season;
void main(){
printf("请输入你喜欢的季节:(1.spring,2.summer,3.autumn,4.winter):");
scanf("%d",&season);
switch (season) {
case SPRING:
printf("春天");
break;
case SUMMER:
printf("夏天");
break;
case AUTUMN:
printf("秋天");
break;
case WINTER:
printf("冬天");
break;
default:
printf("没有");
}
getchar();
getchar();
}
1)第一个枚举成员的默认值为整型的0,后续枚举成员的值在前一个成员上加1。例如:第一个枚举成员的值定义为1,第二个就是为2,以此类推。
2)在定义枚举类型时改变枚举元素的值
enum DAY{
MON,TUE,WED,THU=9,FRI,SAT,SUN//如果没有给赋值,就会按照顺序赋值
}day;//表示定义了一个枚举类型enum Day,同时定义了一个变量day(类型是enum DAY)
//说明 FRI,SAT,SUN 就是10,11,12
3)枚举变量的定义的形式1–先定义枚举类型,在定义枚举变量
enum SEASONS{
SPRING=1,SUMMER,AUTUMN,WINTER
};
enum SEASONS season;
4)枚举变量的定义的形式2-定义枚举类型的同时定义枚举变量
enum SEASONS{
SPRING=1,SUMMER,AUTUMN,WINTER
}season;
5)枚举变量的定义的形式3-省略枚举名称,直接定义枚举变量
enum{
SPRING=1,SUMMER,AUTUMN,WINTER
}season;//这样使用枚举,该枚举类型只能使用一次
6)可以将整数转换为对应的枚举值
不能直接将一个整数,赋给枚举变量,但是可以将整数,转成枚举类型,再赋给枚举变量.
#include <stdio.h>
#include <stdbool.h>
void main(){
enum SEASONS{
SPRING=1,SUMMER,AUTUMN,WINTER
}season;
int n=4;
season=(enum SEASONS)n;
printf("season=:%d",season);
getchar();
}
为完成某一功能的程序指令(语句)的集合,称为函数。在C语言中,函数分为:自定义函数、系统函数.
返回类型 函数名(形参列表){
执行语句...;//函数体
return 返回值; //可选
}
1)形参列表:表示函数的输入
2)函数中的语句:表示为了实现某一功能代码块
3)函数可以有返回值,也可以没有,如果没有返回值,返回类型声明为 void 。
1)头文件是扩展名为.h的文件,包含了C函数声明和宏定义,被多个源文件中引用共享。有两种类型的头文件:程序员编写的头文件和C标准库自带的头文件
2)在程序中要使用头文件,需要使用C预处理指令#include来引用它。前面我们已经看过 stdio.h头文件,它是C标准库自带的头文件
3)#include叫做文件包含命令,用来引入对应的头文件(.h文件)。#include也是C语言预处理命令的一种。#include的处理过程很简单,就是将头文件的内容插入到该命令所在的位置,从而把头文件和当前源文件连接成一个源文件,这与复制粘贴的效果相同。但是我们不会直接在源文件中复制头文件的内容,因为这么做很容易出错,特别在程序是由多个源文件组成的时候。
4)建议把所有的常量、宏、系统全局变量和函数原型写在头文件中,在需要的时候随时引用这些头文件
1)引用头文件相当于复制头文件的内容
2)源文件的名字可以不和头文件一样,但是为了好管理,一般头文件名和源文件名一样
3)C语言中include <>与include ""的区别
4)函数调用规则
1、当调用(执行)一个函数时,就会开辟一个独立的空间(栈)
2、每个栈空间是相互独立
3、当函数执行完毕后,会返回到调用函数位置,继续执行
4、如果函数有返回值,则,将返回值赋给接收的变量
5、当一个函数返回后,该函数对应的栈空间也就销毁
一个函数在函数体内又调用了本身,我们称为递归调用
8.8.3 函数递归需要遵守的重要原则:
1)执行一个函数时,就创建一个新的受保护的独立空间(新函数栈)
2)函数的局部变量是独立的,不会相互影响
3)递归必须向退出递归的条件逼近,否则就是无限递归,死龟了:)
4)当一个函数执行完毕,或者遇到return,就会返回,遵守谁调用,就将结果返回给谁
所谓变量作用域(Scope),就是指变量的有效范围
1)函数内部声明/定义的局部变量,作用域仅限于函数内部
2)函数的参数,形式参数,被当做该函数内的局部变量,如果与全局变量同名它们会优先使用局部变量(编译器使用就近原则)
3)在一个代码块,比如for / if中的局部变量,那么这个变量的的作用域就在该代码块
4)在所有函数外部定义的变量叫全局变量,作用域在整个程序有效
1)局部变量,系统不会对其默认初始化,必须对局部变量初始化后才能使用,否则,程序运行后可能会异常退出.
2)全局变量,系统会自动对其初始化,如下所示
1)全局变量(Global Variable)保存在内存的全局存储区中,占用静态的存储单元,它的作用域默认是整个程序,也就是所有的代码文件,包括源文件(.c文件)和头文件(.h文件)。
2)局部变量(Local Variable)保存在栈中,函数被调用时才动态地为变量分配存储单元,它的作用域仅限于函数内部。【内存布局分析】
3)C语言规定,只能从小的作用域向大的作用域中去寻找变量,而不能反过来,使用更小的作用域中的变量
4)在同一个作用域,变量名不能重复,在不同的作用域,变量名可以重复,使用时编译器采用就近原则.
5)由{}包围的代码块也拥有独立的作用域
8.12.1 基本介绍
static关键字在c语言中比较常用,使用恰当能够大大提高程序的模块化特性,有利于扩展和维护。
8.12.2 局部变量使用static修饰
1)局部变量被static修饰后,我们称为静态局部变量
2)对应静态局部变量在声明时未赋初值,编译器也会把它初始化为0
3)静态局部变量存储于进程的静态存储区(全局性质),只会被初始一次,即使函数返回,它的值也会保持不变
8.12.3 全局变量使用static修饰
1)普通全局变量对整个工程可见,其他文件可以使用extern外部声明后直接使用。也就是说其他文件不能再定义一个与其相同名字的变量了(否则编译器会认为它们是同一个变量),静态全局变量仅对当前文件可见,其他文件不可访问,其他文件可以定义与其同名的变量,两者互不影响
2)定义不需要与其他文件共享的全局变量时,加上 static关键字能够有效地降低程序模块之间的耦合,避免不同文件同名变量的冲突,且不会误使用
8.12.4 函数使用static修饰
1)函数的使用方式与全局变量类似,在函数的返回类型前加上static,就是静态函数
2)非静态函数可以在另一个文件中通过extern引用
3)静态函数只能在声明它的文件中可见,其他文件不能引用该函数
4)不同的文件可以使用相同名字的静态函数,互不影响
头文件<string.h>
1)得到字符串的长度 size_strlen(const char *str)计算字符串 t 的长度,直到空结束字符,但不包括空结束字符
2) 拷贝字符串char *strcpy(char *dest, const char *src)把 src 所指向的字符串复制到 dest。
3) 连接宁符串char *strcat(char *dest, const char *src)把 src 所指向的字符串追加到 dest 所指向的字符串的结尾。
1) 获取当前时间char *ctime(const time t *timer)返回一个表示当地时间的字符串,当地时间是基于参数 timer。
2) 编写一段代码来统计 函数 test 执行的时间double difftime(time t timel, time t time2)
返回 timel 和 time2 之间相差的秒数(timel-time2)
mah.h 头文件定义了各种数学函数和一个宏。在这个库中所有可用的功能都带有一个 double 类型的参数,且都返回 double 类型的结果
举例说明:
1) double exp(double x)返回 e 的 x 次幂的值。
2)double log(double x)返回 x 的自然对数(基数为 e 的对数)
3)double pow(double x, double y)返回 x 的 y 次幂。
4)double sqrt(double x)返回 x 的平方根。
4)double fabs(double x)返回 x 的绝对值。
1)sprintf和平时我们常用的 printf函数的功能很相似。sprintf函数打印到字符串中,而printf函数打印输出到屏幕上。sprintf 函数在我们完成其他数据类型转换成字符串类型的操作中应用广泛
2)该函数包含在 stdio.h的头文件中
#include <stdio.h>
int main(){
char str1[20];
char str2[20];
char str3[20];
int a=20984,b=48090;
double d=14.309948;
//说明
//1.sprintf是一个系统函数,可以将结果存放到字符串中
//2.格式化的结果,会存放到str1中
sprintf(str1, "%d %d",a,b);
sprintf(str2,"%.2f",d);
//%8.2f含义是格式化后,一共有8位,小数点后占用2位,不够用空格占位
sprintf(str3,"%8.2f",d);
printf("str1=%s,str2=%s,str3=%s",str1,str2,str3);
getchar();
}
语法:通过<stdlib.h>的函数调用atoi atof即可
#include <stdio.h>
#include <stdlib.h>
void main(){
//字符数组
char str[10]="123456";
char str2[10]="12.67423";
char str3[3]="ab";
char str4[4]="111";
//说明
//1. atoi(str)将str转成整数
int num1=atoi(str);
short s1=atoi(str4);
//说明
//1. atof(str2) 将str2转成小数
double d=atof(str2);
//说明
//1.str3[0] 表示获取到str3这个字符串(数组)的第一个元素 'a'
char c=str3[0];
printf("num1=%d d=%f c=%c s1=%d",num1,d,c,s1);
getchar();
}
1)在将char数组类型转成基本数据类型时,要确保能够转成有效的数据,比如 我们可以把"123",转成一个整数,但是不能把"hello"转成一个整数
2)如果格式不正确,会默认转成0 或者0.0
1)使用库函数之前,应该用#include引入对应的头文件。这种以#号开头的命令称为预处理命令。
2)这些在编译之前对源文件进行简单加工的过程,就称为预处理(即预先处理、提前处理)
3)预处理主要是处理以#开头的命令,例如#include<stdio.h>等。预处理命令要放在所有函数之外,而且一般都放在源文件的前面
4)预处理是C语言的一个重要功能,由预处理程序完成。当对一个源文件进行编译时,系统将自动调用预处理程序对源程序中的预处理部分作处理,处理完毕自动进入对源程序的编译
5)C语言提供了多种预处理功能,如宏定义、文件包含、条件编译等,合理地使用它们会使编写的程序便于阅读、修改、移植和调试,也有利于模块化程序设计
1) #define叫做宏定义命令,它也是C语言预处理命令的一种。所谓宏定义,就是用一个标识符来表示一个字符串,如果在后面的代码中出现了该标识符,那么就全部替换成指定的字符串
1)#表示这是一条预处理命令,所有的预处理命令都以#开头。宏名是标识符的一种,命名规则和变量相同。字符串可以是数字、表达式、if语句、函数等
2)这里所说的字符串是一般意义上的字符序列,不要和C语言中的字符串等同,它不需要双引号
3)程序中反复使用的表达式就可以使用宏定义
#define N 100
#define M (n*n+3*n)
1)宏定义是用宏名来表示一个字符串,在宏展开时又以该字符串取代宏名,这只是一种简单的替换。字符串中可以含任何字符,它可以是常数、表达式、if 语句、函数等,预处理程序对它不作任何检查,如有错误,只能在编译已被宏展开后的源程序时发现。
2)宏定义不是说明或语句,在行末不必加分号,如加上分号则连分号也一起替换
3)宏定义必须写在函数之外,其作用域为宏定义命令起到源程序结束。如要终止其作用域可使用#undef 命令
4)代码中的宏名如果被引号包围,那么预处理程序不对其作宏代替
5)宏定义允许嵌套,在宏定义的字符串中可以使用已经定义的宏名,在宏展开时由预处理程序层层代换
#define PI 3.1415926
#define S PI*y*y
printf("%f",S);
//在宏替换后变为:
printf("%f",3.1415926*y*y);
6)习惯上宏名用大写字母表示,以便于与变量区别。但也允许用小写字母
7)可用宏定义表示数据类型,使书写方便
8)宏定义表示数据类型和用 typedef定义数据说明符的区别:宏定义只是简单的字符串替换,由来处理;而typedef 是在编译阶段由编译器处理的,它并不是简单的字符串替换,而给原有的数据类型起一个新的名字,将它作为一种新的数据类型。
1)C语言允许宏带有参数。在宏定义中的参数称为“形式参数”,在宏调用中的参数称为“实际参数”,这点和函数有些类似
2)对带参数的宏,在展开过程中不仅要进行字符串替换,还要用实参去替换形参
3)带参宏调用的一般形式为:宏名(实参列表);
#include <stdio.h>
//说明
//1.MAX就是带参数的宏
//2.(a,b)就是形参
//3.(a>b) ? a : b是带参数的宏对应字符串,该字符串中可以使用形参
#define MAX(a,b) (a>b)?a:b
int main(){
int x,y,max;
printf("input two numbers:");
scanf("%d %d",&x,&y);
//说明
//1.MAX(x, y);调用带参数宏定义
//2.在宏替换时(预处理,由预处理器),会进行字符串的替换,同时会使用实参,去替换形参
//3.即MAX(x, y)宏替换后(x>y) ? x : y
max=MAX(x, y);
printf("max=%d\n",max);
getchar();
getchar();
return 0;
}
1)带参宏定义中,形参之间可以出现空格,但是宏名和形参列表之间不能有空格出现
2)在带参宏定义中,不会为形式参数分配内存,因此不必指明数据类型。而在宏调用中,实参包含了具体的数据,要用它们去替换形参,因此实参必须要指明数据类型
3)在宏定义中,字符串内的形参通常要用括号括起来以避免出错。
#include <stdio.h>
#include <stdlib.h>
#define SQ(y) (y)*(y) //带参宏定义,字符串内的形参通常要用括号括起来以避免出错
int main(){
int a,sq;
printf("input a number");
scanf("%d",&a);
sq=SQ(a+1);//宏替换 (a+1)*(a+1)
printf("sq=%d\n",sq);
system("pause");
return 0;
}
1)宏展开仅仅是字符串的替换,不会对表达式进行计算;宏在编译之前就被处理掉了,它没有机会参与编译,也不会占用内存。
2)函数是一段可以重复使用的代码,会被编译,会给它分配内存,每次调用函数,就是执行这块内存中的代码
预处理指令是以#号开头的代码行,#号必须是该行除了任何空白字符外的第一个字符。#后是指令关键字,在关键字和#号之间允许存在任意个数的空白字符,整行语句构成了一条预处理指令,该指令将在编译器进行编译之前对源代码做某些转换
1)预处理功能是C语言特有的功能,它是在对源程序正式编译前由预处理程序完成的,程序员在程序中用预处理命令来调用这些功能。
2)为了避免宏代换时发生错误,宏定义中的字符串应加括号,字符串中出现的形式参数两边也应加括号。
3)文件包含是预处理的一个重要功能,它可用来把多个源文件连接成一个源文件进行编译,结果将生成一个目标文件。
4)条件编译允许只编译源程序中满足条件的程序段,使生成的目标程序较短,从而减少了内存的开销并提高了程序的效率。
5)使用预处理功能便于程序的修改、阅读、移植和调试,也便于实现模块化程序设计
数据类型 数组名 【数组大小】;
int a[5]; 赋初值 a[0]=1;a[1]=30;...
字符数组实际上是一系列字符的集合,也就是字符串(Suing)。在C语言中,没有专门的字符串变量,没有string 类型,通常就用一个字符数组来存放一个字符串
在 C 语言中,字符串实际上是使用 null字符(\0)终止的一维字符数组。因此,一个以 null结尾的字符串,包含了组成字符串的字符。
"\0'是 ASCI 码表中的第0个字符,用 NUL表示,称为空字符。该字符既不能显示,也不是控制字符,输出该字符不会有任何效果,它在C语言中仅作为字符串的结束标志。
如果在给某个字符数组赋值时,(1)赋给的元素的个数小于该数组的长度,则会自动在后面加"\0,表示字符串结束,(2)赋给的元素的个数等于该数组的长度,则不会自动添加"\0'。
2) printf("%s\n",str);可以输出 str 指向的字符串
3)对字符指针变量,采用下面方法赋值,是可以的
语法:类型 数组名[大小][大小];
比如:int a[2][3];
int a[4][6];//没有初始化,则是分配的内存垃圾值
int i,j;
//全部初始化为0
for (i=0;i<4; i++) {
for(j=0;j<6;j++){
a[i][j]=0;
}
}
1)可以只对部分元素赋值,未赋值的元素自动取“零”值
2)如果对全部元素赋值,那么第一维的长度可以不给出。比如:
比如: int *ptr = # ptr就是指向 int类型的指针变量,即 ptr是 int*类型。
5)获取指针类型所指向的值,使用: * (取值符号),比如: int * ptr,使用*ptr获取 ptr指向的值
指针可以用关系运算符进行比较,如==、<<=和>>=。如果pl和 p2指向两个变量,比如同一个数组中的不同元素,则可对pl 和 p2进行大小比较,
数据类型 *指针数组名[大小];
1)比如:int *ptr[3];
2)ptr声明为一个指针数组
3)由3个整数指针组成。因此,ptr中的每个元素,都是一个指向int值的指针
1)一个指向指针的指针变量必须如下声明,即在变量名前放置两个星号。例如,下面声明了一个指向 int类型指针的指针:
int **ptr;//ptr的类型是int **
2)当一个目标值被一个指针间接指向到另一个指针时,访问这个值需要使用两个星号运算符,比如 **ptr
#include <stdio.h>
#include <string.h>
void test2(int *p);//函数声明,接受int *
int main(){
int num=90;
int *p=#
test2(&num);//传地址
printf("\nmain()中的num=%d",num);
test2(p);//传指针
printf("\nmain()中的num=%d",num);
getchar();
return 0;
}
void test2(int *p){
*p+=1;
}
#include <stdio.h>
#include <string.h>
double getAverage(int *arr,int size);
double getAverage2(int *arr,int size);
int main(){
int balance[5]={1000,2,3,17,50};
double avg;
avg=getAverage(balance, 5);
printf("Average value is :%f\n",avg);
avg=getAverage2(balance, 5);
printf("Average value is :%f\n",avg);
getchar();
return 0;
}
double getAverage(int *arr,int size){
int i,sum=0;
double avg;
for(i=0;i<size;++i){
sum+=arr[i];
printf("\narr存放的地址=%p",arr);
}
avg=(double)sum/size;
return avg;
}
double getAverage2(int *arr,int size){
int i,sum=0;
double avg;
for(i=0;i<size;++i){
sum+=*arr;
printf("\narr存放的地址=%p",arr);
arr++;//指针的++运算,会对arr存放的地址做修改
}
avg=(double)sum/size;
return avg;
}
如果在getAverage()函数中,通过指针修改了数组的值,那么main函数的balance数组的值是否会相应改变?会的,因为getAverage()函数中的指针,指向的就是main函数的数组。
请编写一个函数strlong(),返回两个字符串中较长的一个
#include <stdio.h>
#include <string.h>
char* strlong(char *str1,char *str2){
printf("\nstr1的长度%d str2的长度%d",strlen(str1),strlen(str2));
if(strlen(str1)>=strlen(str2)){
return str1;
}else {
return str2;
}
}
int main(){
char str1[30]="abc";
char str2[30]="dddddd";
printf("\nLonger string:%s\n",strlong(str1,str2));
getchar();
return 0;
}
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int* f1(){
static int arr[10];
int i=0;
for(i=0;i<10;i++){
arr[i]=rand();
}
return arr;
}
void main(){
int *p;
int i;
p=f1();//p指向是在f1生成的数组的首地址(即第一个元素的地址)
for(i=0;i<10;i++){
printf("\n%d",*(p+i));
}
getchar();
}
用函数指针来实现对函数的调用,返回两个整数中的最大值.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int max(int a,int b){
return a>b?a:b;
}
void main(){
int x,y,maxVal;
//说明 函数指针
//1. 函数指针的名字 pmax
//2. int 表示 该函数指针指向的函数是返回int类型
//3. (int,int) 表示 该函数指针指向的函数形参是接受两个int
//4. 在定义函数指针时,也可以写上形参名 int (*pmax)(int x,int y)=max;
int (*pmax)(int,int)=max;
printf("Input two numbers:");
scanf("%d %d",&x,&y);
maxVal=(*pmax)(x,y);
printf("Max value:%d pmax=%p pmax本身的地址=%p\n",maxVal,pmax,&pmax);
getchar();
}
1)函数指针变量可以作为某个函数的参数来使用的,回调函数就是一个通过函数指针调用的函数
2)简单的讲:回调函数是由别人的函数执行时调用你传入的函数(通过函数指针完成)
使用回调函数的方式,给一个整型数组 int arr[10]赋10个随机数
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
//回调函数
//1.int (*f)(void)
//2.f就是函数指针,它可以接收的函数是(返回int,没有形参的函数)
//3.f在这里被initArray调用,充当了回调函数的角色
void initArray(int *array,int arraySize,int (*f)(void)){
int i;
for(i=0;i<arraySize;i++){
array[i]=f();
}
}
int getNextRandomValue(void){
return rand();
}
void main(){
int myarray[10],i;
initArray(myarray, 10,&getNextRandomValue);
for(i=0;i<10;i++){
printf("%d ",myarray[i]);
}
getchar();
}
1)全局变量--内存中的静态存储区
2)非静态的局部变量--内存中的动态存储区--stack 栈
3) 临时使用的数据…建立动态内存分配区域,需要时随时开辟,不需要时及时释放--heap 堆
4)根据需要向系统中请所需大小的空间,由于未在声明部分定义其为变量或者数组,不能通过变量名或者数组名来引用这些数据,只能通过指针来引用)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void main(){
/*
张老太养了两只猫猫:一只名字叫小白,今年3岁,白色。还有一只叫小花,今年100岁,花色。
请编写一个程序,当用户输入小猫的名字时,就显示该猫的名字,年龄,颜色。如果用户输入的小猫名错误,
则显示张老太没有这只猫猫。
分析:
1.猫猫有三个成员(变量)组成
2.使用结构体解决
*/
//创建结构体Cat【是数据类型】
struct Cat{//结构体名Cat, Cat就是我们自己构造的一个数据类型
char* name;//名字
int age;//年龄
char* color;//颜色
};
//使用Cat结构体,创建变量
struct Cat cat1;
struct Cat cat2;
//给cat1、cat2的各个成员赋值
cat1.name="小白";
cat1.age=3;
cat1.color="白色";
cat2.name="小花";
cat2.age=100;
cat2.color="花色";
//输出两只猫的信息
printf("\n 第1只猫 name=%s age=%d color=%s", cat2.name, cat1.age, cat1.color);
printf("\n 第2只猫 name=%s age=%d color=%s", cat2.name, cat2.age, cat2.color);
getchar();
}
景区门票案例
1)一个景区根据游人的年龄收取不同价格的门票
2)请编写游人结构体(Visitor),根据年龄段决定能够购买的门票价格并输出
3)规则:年龄>18,门票为20元,其他情况免费
4)可以循环从控制台输入名字和年龄,打印门票收费情况,如果名字输入 n ,则退出程序
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct Visitor{
char name[10];
int age;
double pay;//应付票价
};
/*
编写函数处理业务
说明:因为结构体默认是值传递,会拷贝一份完整数据,效率较低
因此,为了提高效率,我们直接接收地址(指针)
*/
void ticket(struct Visitor* visitor){
if(visitor->age>18){
//(*visitor).pay=20;
visitor->pay=20;
}else{
//(*visitor).pay=0;
visitor->pay=0;
}
}
void main(){
struct Visitor visitor;
while(1){
printf("\n 请输入游客名字");
scanf("%s",visitor.name);
if(!strcmp("n",visitor.name)){
break;
}
printf("\n 请输入游客年龄");
scanf("%d",&visitor.age);
ticket(&visitor);
printf("\n 该游客应付票价=%.2f",visitor.pay);
}
}
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
/*
data就是一个共用体(内存布局),包含三个成员,共享数据空间,
该空间的大小以占用最大的成员为准
*/
union data{
int n;
char ch;
short m;
};
void main(){
union data a;
printf("%d,%d\n",sizeof(a),sizeof(union data));
a.n=0x40;
printf("%d,%c,%d\n",a.n,a.ch,a.m);
a.ch='9';
printf("%d,%c,%d\n",a.n,a.ch,a.m);
a.m=0x2059;
printf("%d,%c,%d\n",a.n,a.ch,a.m);
a.n=0x3E25AD54;
printf("%d,%c,%d\n",a.n,a.ch,a.m);
getchar();
}
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define TOTAL 2//人员总数
struct Person{
char name[20];
int num;//编号
char sex;//性别 f=>女 m=>男
char profession;//职员 s=>学生 t=>老师
union{
float score;
char course[20];
}sc;//sc是一个共用体变量
};
void main(){
int i;
struct Person persons[TOTAL];//定义了一个结构体数组
//输入人员信息
for (i=0; i<TOTAL; i++) {
printf("Input info:");
scanf("%s %d %c %c",persons[i].name,&(persons[i].num),&(persons[i].sex),&(persons[i].profession));
if(persons[i].profession=='s'){
printf("请输入该学生成绩:");
scanf("%f",&persons[i].sc.score);
}else{
printf("请输入该老师课程:");
scanf("%s",persons[i].sc.course);
}
fflush(stdin);//刷新
}
//输出人员信息
printf("\nName\t\tNumtSex\tProfession\tScore/Course\n");
for(i=0; i<TOTAL; i++){
if(persons[i].profession == 's'){//如果是学生
printf("%s\t%d\t%c\t%c\t%f\n",persons[i].name,persons[i].num,persons[i].sex,persons[i].profession,persons[i].sc.score);
}else{//如果是老师
printf("%s\t%d\t%c\t%c\t%s\n",persons[i].name,persons[i].num,persons[i].sex,persons[i].profession,persons[i].sc.course);
}
}
getchar();
}
C标准库-stdio.h该头文件定义了三个变量类型、一些宏和各种函数来执行输入和输出,在开发过程中,可以来查询
1)当我们提到输入时,这意味着要向程序写入一些数据。输入可以是以文件的形式或从命令行中进行。C语言提供了一些列内置的函数来读取给定的输入,并根据需要写入到程序中
2)当我们提到输出时,这意味着要在屏幕、打印机上或任意文件中显示一些数据。C语言提供了一系列内置的函数来输出数据到计算机屏幕上和保存数据到文本本间或二进制文件中
1)C语言把所有的设备都当做文件。所以设备(比如显示器)被处理的方式与文件相同。以下三个文件会在程序执行时自动打开,以便访问键盘和屏幕
2)文件指针是访问文件的方式,我们会讲解如何从屏幕读取值以及如何把结果输出到屏幕上
3)C语言中的I/O(输入/输出)通常使用printf()和scanf()两个函数。scanf()函数用于从标准输入(键盘)读取并格式化,printf()函数发送格式化输出到标准输出(屏幕)
4)案例演示,将内容输出到屏幕
#include <stdio.h>
int main(){
printf("hello");
return 0;
}
1)int getchar(void)函数从屏幕读取下一个可用的字符,并把它返回为一个整数。这个函数在同一个时间内只会读取一个单一的字符。您可以在循环内使用这个方法,以便从屏幕上读取多个字符。
2)int putchar(int c)函数把字符输出到屏幕上,并返回相同的字符。这个函数在同一个时间只会输出一个单一的字符。您可以在循环内使用这个方法,以便在屏幕上输出多个字符
3)应用实例:程序会读取一个单一的字符
#include <stdio.h>
int main(){
int c;
printf("Enter a value");
c=getchar();
printf("\n You entered");
putchar(c);
printf("\n");
return 0;
}
1)char *gets(char *s)函数从stdin读取一行到s所指向的缓冲区,直到一个终止符或EOF
2)int puts(const char *s)函数把字符串s和一个尾随的换行符写入到stdout
3)应用实例:程序读取一整行直到该行结束
#include <stdio.h>
int main(){
char str[100];
printif("Enter a value:");
gets(str);
printf("\nYou entered");
puts(str);
return 0;
}
#include <stdio.h>
int main(){
char str[100];
int i;
printf("Enter a value");
scanf("%s %d",str,&i);
printf("\nYou entered:%s %d",str,i);
printf("\n");
return 0;
}
#include <bits/types/FILE.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void main(){
//创建一个文件指针
FILE* fp=NULL;
//打开该文件
fp=fopen("d:/test/100.txt", "w+");//w+ 模式是 文件会被截断尾零长度
//fp=fopen("d:/test/100.txt", "a+");//w+ 模式是 文件会被截断尾零长度
//将内容写入到文件中
/*
fprintf(fp, "你好 北京\n");
fputc("你好,上海\n", fp);*/
//关闭文件
fclose(fp);
printf("创建,写入信息完成");
getchar();
}
#include <bits/types/FILE.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void main(){
//创建一个文件指针
FILE* fp=NULL;
//定义一个缓冲区
char buff[1024];
//打开文件
fp=fopen("d:/test200.txt","r");
//方法1
//fscanf(fp, "%s",buff);
//输出
//printf("%s\n",buff);
//方法2 读取整个文件
//说明,循环读取fp指向的文件内容,如果读到NULL,就结束
while (fgets(buff,1024,fp)!=NULL) {
printf("%s",buff);
}
//关闭文件
fclose(fp);
getchar();
}
因篇幅问题不能全部显示,请点此查看更多更全内容