提示:以下是本篇文章正文内容,下面案例可供参考
1.头文件
2.常用函数
2·常量
四,数据的运算处理
C语言学习笔记整理
一、C语言具体结构
二、C语言中的数学函数
1.头文件
2.常用函数
三,基本数据类型
1·变量
(1)变量的定义与赋值
(2)连续定义多个变量
(3)数据的长度
sizeof 操作符
2·常量
3·输出各种类型数据
不同整形的输出:
4·二进制数、八进制数和十六进制数的表示
(1)定义
(2)输出
四,数据的运算处理
五,程序的基本控制结构
1.顺序结构
编辑编辑编辑
2.选择结构
(1)if循环
(2)switch循环
3.循环结构与循环的镶嵌
(1)当型循环
(2)直到型循环
(3)计数型循环
(4)循环结构的镶嵌
4.四大跳转
(1)break——跳出本层循环
(2)continue———跳出本次循环,进入下一次循环
(3)goon———强制跳转到指定位置
(4)return——返回内容
六,同批次类型数据的组织and字符数据的组织——数组and字符串
(1)一维数组
1.数组的概念和定义
2.数组内存是连续的
3.数组的初始化
(2)二维数组
1.二维数组的定义
2.二维数组的初始化
(3)字符数组和字符串
1.定义与赋值
2.字符串的结束标志
3.字符串的长度
4.字符串的输出
5.字符串的输入
6.字符串复制
7.字符串的比较
8.字符串的 链接
9.字符串的大小转换
七,程序的组装单元——函数
(1)函数的定义与调用
(2)对被调函数的声明和函数原型
(3)函数的镶嵌调用
(4)函数的递归调用
(5)数组作为函数的参数
1.数组元素作为函数的实参
2.一维数组名作为函数参数
3.多维数组名作为函数参数
(6)局部变量与全局变量
1.局部变量
2.全局变量
(7)变量的储存方式与生存期
1·动态储存方式与静态储存方式
2·局部变量的储存类别
<1>自动变量(auto变量)
<2>静态局部变量(static变量)
<3>寄存器变量(register变量)
3·全局变量的储存类别
<1>在一个文件内拓展外部变量的作用域
<2>将外部变量的作用域拓展到其他文件
<3>将外部变量的作用域限制在本文件中
(8)变量的声明与定义
(9)内部函数与外部函数
八,变量的间接访问——指针
1.指针的定义,初始化和引用
2.通过指针引用数组
3.通过指针引用字符串
4.指向函数的指针与返回函数值得指针
5.指针数组与多重数组
6.动态内存分配与指向它的指针变量
九,自定义数据类型
十,文件操作
1.文件定义
(1)程序文件:
(2)数据文件:
2.文件名
3.文件指针
(1)定义:
(2)文件操作步骤:编辑
4.打开文件
总结
0 :32,A:65,a:97
C语言典型结构:
第一部分:预处理指令符号常量定义
全局变量定义
函数声明
第二部分:主函数
第三部分:函数定义
#include /*头文件*/
int main()/*主函数*/
{
printf("Hello world");
return 0;
}
math.h
#include
1,指数函数
pow(a,n)
//*a的n次方,a为底数,n为指数
2,开平方函数
sqrt(m)
//*开实数m的算术平方根
3,向上取整函数
ceil(m)
//*对实数m向上取整 eg:ceil(4.2)=5
4,向下取整函数
floor(m)
//*对实数m向下取整 eg:floor(4.8)=4
5,整数绝对值函数
abs(b)
//*返回整数b的绝对值 eg:abs(-5)=5
6,
关键字 | 格式化输出scanf | 格式化输出printf | |
1 | double | %lf(小数形式) %le(指数形式) |
%f %m.nf %-m.nf %e |
2 | float | %f(小数形式) %e(指数形式) |
同上 |
3 | char | %c(字符) %s(字符串) |
%c %mc %-mc %s %ms %-ms |
4 | int | %d(十进制) %x(十六进制) %o(八进制) %u(无符号十进制) |
%d %md %-md %ld(long int) %x %o %u %mu %-mu |
(2)m所占字符个数,n小数所占字符个数;
数据是放在内存中的,在内存中存取数据要明确三件事情:数据存储位置、数据的长度以及数据的处理方式。
变量名不仅是为数据起了一个好记的名字,还告诉我们数据存储位置,使用数据时,只要提供变量名即可;而数据类型则指明了数据的长度和处理方式。
标识符有其构成的规则,基本原则是:只能由字母、数字和下划线组成。数字不可以出现在第一个位置上,C语言的关键字不能作为标识符。
1,定义整数变量
int a;
(这个语句的意思)是:在内存中找一块区域,命名为 a,用它来存放整数.
int
(Integer 的简写)意思是整数。(a 是我们给这块区域起的名字)
2,赋值
赋值是指把数据放到内存的过程。
变量的初始化or赋初值:
int a=123;
或者
int a;
a=123;
整数的值可以改变,更改方式是再次赋值。(第二次赋值会覆盖第一次的数据)
连续定义的多个相同类型变量以逗号,
分隔;变量可以初始化,也可以不初始化
int a,b;
float m,n;
char p,q='@';
数据长度(Length),是指数据占用多少个字节。占用的字节越多,能存储的数据就越多,对于数字来说,值就会更大,反之能存储的数据就有限。多个数据在内存中是连续存储的,彼此之间没有明显的界限。
在定义变量时还要指明数据的长度。而这恰恰是数据类型的另外一个作用。数据类型除了指明数据的解释方式,还指明了数据的长度。因为在C语言中,每一种数据类型所占用的字节数都是固定的,知道了数据类型,也就知道了数据的长度。
sizeof 用来获取某个数据类型或变量所占用的字节数。
如果后面跟的是变量名称,那么可以省略( )
,如果跟的是数据类型,就必须带上( )
。
需要注意的是,sizeof 是C语言中的操作符,不是函数,所以可以不带( )
。
注:
区别于:strlen是计算给定数组长度,它从内存的某个位置(可以是字符串开头,中间某个位置,甚至是某个不确定的内存区域)开始扫描,直到碰到第一个字符串结束符'\0'为止,然后返回计数器值(长度不包含'\0')
#include
int main()
{
short a = 10;
int b = 100;
int short_length = sizeof a;
int int_length = sizeof(b);
int long_length = sizeof(long);
int char_length = sizeof(char);
printf("short=%d, int=%d, long=%d, char=%d\n", short_length, int_length, long_length, char_length);
return 0;
}
输出结果:
short=2, int=4, long=4, char=1
指数形式为:
aEn 或 aen
a 为尾数部分,是一个十进制数;n 为指数部分,是一个十进制整数;E
或e
是固定的字符,用于分割尾数部分和指数部分。整个表达式等价于 a×10n。
指数形式的小数举例:
在 ASCII 码表中,字符 'E'、'F'、'G'、'H' 对应的编号分别是 69、70、71、72。
a、b、c、d 实际上存储的都是整数:
#include
int main()
{
char a = 'E';
char b = 70;
int c = 71;
int d = 'H';
printf("a: %c, %d\n", a, a);
printf("b: %c, %d\n", b, b);
printf("c: %c, %d\n", c, c);
printf("d: %c, %d\n", d, d);
return 0;
}
转义字符 | 意义 | ASCII码值(十进制) |
---|---|---|
\a | 响铃(BEL) | 007 |
\b | 退格(BS) ,将当前位置移到前一列 | 008 |
\f | 换页(FF),将当前位置移到下页开头 | 012 |
\n | 换行(LF) ,将当前位置移到下一行开头 | 010 |
\r | 回车(CR) ,将当前位置移到本行开头 | 013 |
\t | 水平制表(HT) | 009 |
\v | 垂直制表(VT) | 011 |
\' | 单引号 | 039 |
\" | 双引号 | 034 |
\\ | 反斜杠 | 092 |
\n
和\t
是最常用的两个转义字符:
\n
用来换行,让文本从下一行的开头输出,前面的章节中已经多次使用;\t
用来占位,一般相当于四个空格,或者 tab 键的功能。(1)for ,(2)do ……while,(3)while循环
(4)break :跳出当前循环
(5)continue :结束当前循环,开始下一轮循环
(6)return :子程序返回语句(可以带参数,也看不带参数)
(7)if:条件语句
(8) else :条件语句否定分支(与 if 连用)
(9) goto :无条件跳转语句
(10) switch :用于开关语句
(11) case :开关语句分支
(12) default :开关语句中的“其他”分支
(1)auto :声明自动变量 一般不使用
(2) extern:声明变量是在其他文件正声明(也可以看做是引用变量)
(3) register :声明积存器变量
(4) static :声明静态变量
(1) const :声明只读变量
(2) sizeof :计算数据类型长度
(3) typedef :用以给数据类型取别名
(4) volatile :说明变量在程序执行中可被隐含地改变
a++;或者++a;这种写法叫做自加或自增,意思很明确,就是每次自身加 1。a--
和--a
,它们叫做自减,表示自身减 1。++
和--
分别称为自增运算符和自减运算符,
++ 在变量前面和后面是有区别的:
#include
int main()
{
int a = 10, b = 20, c = 30, d = 40;
int a1 = ++a, b1 = b++, c1 = --c, d1 = d--;
printf("a=%d, a1=%d\n", a, a1);
printf("b=%d, b1=%d\n", b, b1);
printf("c=%d, c1=%d\n", c, c1);
printf("d=%d, d1=%d\n", d, d1);
return 0;
}
输出结果:
a=11, a1=11
b=21, b1=20
c=29, c1=29
d=39, d1=40
无论是自动类型转换还是强制类型转换,都只是为了本次运算而进行的临时性转换,转换的结果也会保存到临时的内存空间,不会改变数据本来的类型或者值。
float) a; //将变量 a 转换为 float 类型 (int)(x+y); //把表达式 x+y 的结果转换为 int 整型 (float) 100; //将数值 100(默认为int类型)转换为 float 类型
注:
( )
的优先级高于/
,对于表达式(double) sum / count
,会先执行(double) sum
,将 sum 转换为 double 类型,然后再进行除法运算,这样运算结果也是 double 类型,能够保留小数部分。注意不要写作(double) (sum / count)
,这样写运算结果将是 3.000000,仍然不能保留小数部分。
注:puts ( output string ),只能用来输出字符串,不能输出整数、小数、字符等,我们需要用另外一个函数,那就是 printf。
printf 可以输出字符串,整数、小数、单个字符等,并且可以定义格式化输出:
- 以十进制、八进制、十六进制形式输出;
- 要求输出的数字占 n 个字符的位置;
- 控制小数的位数。
#include
int main()
{
int n = 100;
char c = '@'; //字符用单引号包围,字符串用双引号包围
float money = 93.96;
printf("n=%d, c=%c, money=%f\n", n, c, money);
return 0;
}
输出结果:
n=100, c=@, money=93.959999
也可以是
#include
int main()
{
float money = 93.96;
printf("n=%d, c=%c, money=%f\n", 100, '@', money);
return 0;
}
使用不同的格式控制符可以输出不同类型的整数,它们分别是:
%hd
用来输出 short int 类型,hd 是 short decimal 的简写;%d
用来输出 int 类型,d 是 decimal 的简写;%ld
用来输出 long int 类型,ld 是 long decimal 的简写。(当使用%d
输出 short,或者使用%ld
输出 short、int 时,不管值有多大,都不会发生错误,因为格式控制符足够容纳这些值。当使用%hd
输出 int、long,或者使用%d
输出 long 时,如果要输出的值比较小(就像上面的情况),一般也不会发生错误,如果要输出的值比较大,就很有可能发生错误,)
0b
或0B
(不区分大小写)开头。数字0
开头(注意是数字 0,不是字母 o)。0x
或0X
(不区分大小写)开头。 //合法的十六进制
int a = 0X2A; //换算成十进制为 42
int b = -0XA0; //换算成十进制为 -160
int c = 0xffff; //换算成十进制为 65535
//非法的十六进制
int m = 5A; //没有前缀 0X,是一个无效数字
int n = 0X3H; //H不是有效的十六进制数字//
//合法的八进制数
int a = 015; //换算成十进制为 13
int b = -0101; //换算成十进制为 -65
int c = 0177777; //换算成十进制为 65535
//非法的八进制
int m = 256; //无前缀 0,相当于十进制
int n = 03A2; //A不是有效的八进制数字
//合法的二进制
int a = 0b101; //换算成十进制为 5
int b = -0b110010; //换算成十进制为 -50
int c = 0B100001; //换算成十进制为 33
//非法的二进制
int m = 101010; //无前缀 0B,相当于十进制
int n = 0B410; //4不是有效的二进制数字
十六进制数字的表示用到了英文字母,有大小写之分,要在格式控制符中体现出来:
x
小写,表明以小写字母的形式输出十六进制数;X
大写,表明以大写字母的形式输出十六进制数char c;
c = getchar();
{
语句1;
语句2;
…………
语句n;
}
名字 | 语法 |
1.单分支的选择结构 | if(表达式)语句; |
2.双(多)分支的选择结构 | if(表达式1)语句1; else if(表达式2) 语句2; else 语句3; |
3.分支机构的镶嵌 | if(表达式1) { if(表达式a)语句a; else 语句b; } else 语句2; |
求最大值
#include
int main()
{
int a, b, c, max;
scanf("%d%d%d",&a,&b,&c);
max=a;
if(max
switch (表达式)
{
case 常量表达式1: 语句1 break;
case 常量表达式2: 语句2 break;
┇
case 常量表达式n: 语句n break;
default: 语句n+1 break;
}
switch语句时还应注意以下几点: 1.在case后的各常量表达式的值不能相同。 2.在case子句后如果没有break;会一直往后执行,一直到遇到break;才会跳出switch语句。 3.switch后面的表达式语句(算术表达式)只能是整型或者字符类型。 4.在case后,允许有多个语句,可以不用{}括起来。 5.各case和default子句的先后顺序可以变动,而不会影响程序执行结果。 6.default子句可以省略不用。
while(表达式)
{
语句
}
while语句的语义是:计算表达式的值,当值为真(非0)时, 执行循环体代码块
do
{
语句
}while(表达式)
它先执行循环中的执行代码块,然后再判断while中表达式是否为真,如果为真则继续循环;
如果为假,则终止循环。因此,do-while循环至少要执行一次循环语句。
for(表达式1;表达式2;表达式3;)
{
语句
}
1表达式1是一个或多个赋值语句(用逗号隔开),它用来控制变量的初始值;
2表达式2是一个关系表达式,它决定什么时候退出循环;
3表达式3是循环变量的步进值,定义控制循环变量每循环一次后按什么方式变化。
4这三部分之间用分号 ; 分开,循环结束,程序继续向下执行。
注意:
1 for循环中的“表达式1、2、3”不可均为空,并且两个分号(;;)不能缺省。
2 省略“表达式1(循环变量赋初值)”,表示不对循环变量赋初始值。
3 省略“表达式2(循环条件)”,不做其它处理,永真,循环一直执行(死循环)。
4 省略“表达式3(循环变量增减量)”,不做其他处理,循环一直执行(死循环)。
while,do- while,for循环可以镶嵌,内循环可以并列,但镶嵌不可以交叉。
continue 表示终止本次(本轮)循环。当代码执行到continue 时,本轮循环终止,
进入下一轮循环。具有过滤功能。
int main()
{
one:
int sum = 0;
for (int i = 1;i<=10;i++)
{
sum = sum + i;
if(i==5)// 当i=5时,执行goto跳转语句,跳出循环,直接跳到two:后面执行
{
goto two;
}
printf("%d\n",sum);
}
two: printf("hello world\n");
}
#include
int add(int a,int b)
{
return printf("%d" ,a + b);//关键字return----返回打印a+b打印的值
}
int main()
{
int a,b;
scanf("%d",&a);
scanf("%d",&b);
add(a,b);//调用add()函数
}
一组数据的集合称为数组(Array),它所包含的每一个数据叫做数组元素(Element),所包含的数据的个数称为数组长度(Length),数组中的每个元素都有一个序号,这个序号从0开始,称为下标(Index)。
定义数组:数据类型 数组名【数组长度】
使用数组元素:(指明下标)数组名【下标】。
例如int a[4];
就定义了一个长度为4的整型数组,名字是a
int a[4];/*定义数组*/
a[2]=9;/*使用数组元素,为其赋值*/
#include
int main(){
int nums[10];
int i;
//从控制台读取用户输入
for(i=0; i<10; i++){
scanf("%d", &nums[i]); //注意取地址符 &,不要遗忘哦
}
//依次输出数组元素
for(i=0; i<10; i++){
printf("%d ", nums[i]);
}
return 0;
}
变量 i 既是数组下标,也是循环条件;将数组下标作为循环条件,达到最后一个元素时就结束循环。数组 nums 的最大下标是 9,也就是不能超过 10,所以我们规定循环的条件是 i<10,一旦 i 达到 10 就得结束循环。
数组是一个整体,它的内存是连续的;数组元素之间是相互挨着的,彼此之间没有一点点缝隙。
int a[4];
在内存中的存储情形:
可以只给部分元素赋值。当{ }
中值的个数少于元素个数时,只给前面部分元素赋值。只能给元素逐个赋值,不能给数组整体赋值。如给全部元素赋值,那么在定义数组时可以不给出数组长度。
当赋值的元素少于数组总体元素的时候,剩余的元素自动初始化为 0:
数据类型 数组名【第一维长度】【第二维长度】;
可以将二维数组看做一个 Excel 表格,有行有列,length1 表示行数,length2 表示列数,要在二维数组中定位某个元素,必须同时指明行和列。
二维数组在概念上是二维的,但在内存中是连续存放的;换句话说,二维数组的各个元素是相互挨着的,彼此之间没有缝隙。在C语言中,二维数组是按行排列的。也就是先存放 a[0] 行,再存放 a[1] 行。
#include
int main(){
int i, j; //二维数组下标
int sum = 0; //当前科目的总成绩
int average; //总平均分
int v[3]; //各科平均分
int a[5][3]; //用来保存每个同学各科成绩的二维数组
printf("Input score:\n");
for(i=0; i<3; i++){
for(j=0; j<5; j++){
scanf("%d", &a[j][i]); //输入每个同学的各科成绩
sum += a[j][i]; //计算当前科目的总成绩
}
v[i]=sum/5; // 当前科目的平均分
sum=0;
}
average = (v[0] + v[1] + v[2]) / 3;
printf("Math: %d \nC Languag: %d \nEnglish: %d \n", v[0], v[1], v[2]);
printf("Total: %d\n", average);
return 0;
}
对于数组 a[5][3],按行分段赋值应该写作:
int a[5][3]={ {80,75,92}, {61,65,71}, {59,63,70}, {85,87,90}, {76,77,85} };
按行连续赋值应该写作:
int a[5][3]={80, 75, 92, 61, 65, 71, 59, 63, 70, 85, 87, 90, 76, 77, 85};
用来存放字符的数组称为字符数组
char a[10]; //一维字符数组
char b[5][10]; //二维字符数组
char c[20]={'c', ' ', 'p', 'r', 'o', 'g', 'r', 'a','m'}; // 给部分数组元素赋值
char d[]={'c', ' ', 'p', 'r', 'o', 'g', 'r', 'a', 'm' }; //对全体元素赋值时可以省去长度
字符数组实际上是一系列字符的集合,也就是字符串(String)。在C语言中,没有专门的字符串变量,没有string类型,通常就用一个字符数组来存放一个字符串。C语言规定,可以将字符串直接赋值给字符数组。
char str[30] = {"c.biancheng.net"};
char str[30] = "c.biancheng.net"; //这种形式更加简洁,实际开发中常用
这里需要留意一个坑,字符数组只有在定义时才能将整个字符串一次性地赋值给它,一旦定义完了,就只能一个字符一个字符地赋值了。
char str[7];
str = "abc123"; //错误
//正确
str[0] = 'a'; str[1] = 'b'; str[2] = 'c';
str[3] = '1'; str[4] = '2'; str[5] = '3';
char arr3[] = { ‘1’,‘2’,‘3’,‘4’,‘5’ };
char arr4[] = { “123456” };
char arr4[] = “123456”;
printf(“arr4[]:%s\n”, arr4);// 输出123456
char a[] = "123456";
a[1] = '6';
printf("%s",a);//正常输出:163456
在C语言中,字符串总是以'\0'
作为结尾,所以'\0'
也被称为字符串结束标志,或者字符串结束符。
'\0'
是 ASCII 码表中的第 0 个字符,英文称为 NUL,中文称为“空字符”。该字符既不能显示,也没有控制功能,输出该字符不会有任何效果,它在C语言中唯一的作用就是作为字符串结束标志。
C语言在处理字符串时,会从前往后逐个扫描字符,一旦遇到'\0'
就认为到达了字符串的末尾,就结束处理。'\0'
至关重要,没有'\0'
就意味着永远也到达不了字符串的结尾。由" "
包围的字符串会自动在末尾添加'\0'
。当用字符数组存储字符串时,要特别注意'\0'
,要为'\0'
留个位置;这意味着,字符数组的长度至少要比字符串的长度大 1。
char str[]="C program";
<图片截屏自 C语言字符数组和字符串详解>
我们使用string.h
头文件中的 strlen() 函数来求字符串的长度,它的用法为:
length strlen(strname);
%s
输出字符串,不能自动换行。字符串和其他类型的数据。注:
1.输出字符串时只需要给出名字,不能带后边的[ ]
2.int、char、float 等类型的变量用于 scanf() 时都要在前面添加&
,而数组或者字符串用于 scanf() 时不用添加&
,它们本身就会转换为地址。
#include
int main(){
char str1[30] = {0};
char str2[30] = {0};
char str3[30] = {0};
//gets() 用法
printf("Input a string: ");
gets(str1);
//scanf() 用法
printf("Input a string: ");
scanf("%s", str2);
scanf("%s", str3);
printf("\nstr1: %s\n", str1);
printf("str2: %s\n", str2);
printf("str3: %s\n", str3);
return 0;
}
%s
输入字符串。除了字符串,scanf() 还能输入其他类型的数据。
scanf() 和 gets() 是有区别的:
strcpy 是 string copy 的缩写,意思是字符串复制,也即将字符串从一个地方复制到另外一个地方,语法格式为:
strcpy(arrayName1, arrayName2);
将 str2 复制到 str1 后,str1 中原来的内容就被覆盖了。
strcmp 是string compare的缩写。
字符串比较是指按照字典次序对单个字符或字符串进行比较大小的操作,一般都是以ASCII码值的大小作为字符比较的标准(在数学中,字典或词典顺序(也称为词汇顺序,字典顺序,字母顺序或词典顺序)是基于字母顺序排列的单词按字母顺序排列的方法。)
会根据字典序比较s1和s2, 如果二者相等,则返回0;如果s1较小则返回-1;如果s1较大则返回1。
比如
strcmp("123", "123") 结果为0。
strcmp("123", "456") 结果为-1。
strcmp("456", "123") 结果为1。
strcat 是 string catenate 的缩写,意思是把两个字符串拼接在一起,语法格式为:
strcat(arrayName1, arrayName2);
strcat() 将把 arrayName2 连接到 arrayName1 后面,并删除原来 arrayName1 最后的结束标志'\0'
。
#include
#include
int main(){
char str1[100]="The URL is ";
char str2[60];
printf("Input a URL: ");
gets(str2);
strcat(str1, str2);
puts(str1);
return 0;
}
1。定义函数
(1).定义有参函数
返回值类型名 函数名(形参表说明 类型 形参;类型 形参;……) /*函数首部*/
{
说明语句 /*函数体*/
执行语句
}
(2).定义无参函数
类型名 函数名()
{
函数体
}
或者
类型名 函数名(void)
{
函数体
}
2.调用函数的形式:
函数名(实参列表)
注:在程序中,函数的定义只能有一次,而函数的声明可以有多次。
(1)函数表达式:
函数作为表达式中的一项出现在表达式中,以函数返回值参与表达式的运算。
这种方式要求函数是有返回值的,例如:
z=max(x,y);/*是一个赋值表达式,把max的返回值赋予变量z*/
(2)函数实参:
函数作为另一个函数调用的实际参数出现。这种情况是把该函数的返回值作为实参进行传送,
因此要求该函数必须是有返回值的,例如:
printf("%d",max(x,y));/*把max调用的返回值作为printf函数的实参*/
3 函数调用过程
(1)在定义函数中指定的形参,在未出现函数调用时,它们并不占内存中的存储单元 在发生函数调用时,
函数的形参才被临时分配内存单元。
(2)将实参的值传递给对应形参。
(3)在执行函数期间,由于形参已经有值,就可以利用形参进行有关的运算 例如把x和y比较,把x或y
的值赋给z等。
(4)通过return语句将函数值带回到主调函数。在return语句中指定的返回值就是函数的值
(又称返回值)。
执行return语句就把这个函数返回值带 回主调函数。应当注意返回值的类型与函数类型一致。
(5)调用结束,形参单元被释放。注意:实参单元仍保留并维持原值,没有改变。如果 在执行一个被
调用函数时,
形参的值发生改变,不会改变主调函数的实参的值。
如果函数不需要返回值,则不需要return语句。这时函数的类型应定义为void类型。
注意:实参向形参的数据传递是“值传递”,单向传递,只能由实参传给形参,而不能 由形参传给实参。
实参和形参在内存中占有不同的存储单元,实参无法得到形参的值。
1.函数声明一般形式:
类型名 函数名(形参表);/*对函数原型进行声明,说明函数的参数和返回值类型等*
注:函数必须先定义后调用。
(1)定义:
在调用一个函数的过程中又出现直接或间接的调用该函数本身,称为函数的递归调用。
直接:在调用函数f的过程中又要调用f函数。
间接:如果在调用f1函数的过程中要调用f2函数,而调用f2函数的过程中又要调用f1函数。
(2)递归的两个必要条件:
<1>存在限制条件,当满足这个限制条件的时候,递归便不再继续。
<2>每次递归调用之后越来越接近这个限制条件。
注:函数的递归调用应该是有限次数,有终止。可以通过if语句来控制,
只在某个条件成立时才进行函数递归调用,否则不进行。
递归问题求解可以分为两部分:
回溯 与 递推
数组元素可以作为函数实参,但不能作为形参,向形参变量传递数组元素的值。
int main()
{
XXXXXXXXXXXXXXXX
for(m=a[0],e=1,n=0;e<10;e++)
{
if(max(m,a[e])>m)//若max函数返回值大于m
{
m=max(m,a[e]);//max函数的返回值取代m原值
n=e; //将此数组元素的序号记下来,放在n中
}
XXXXXXXXXXXXXXX
}
}
int max(int x; int y) //定义max函数
{
return (x>y?x:y);//返回x和y中的大者
}
(1)数组名可以作为函数的实参或者形参,数组名作为函数实参时向形参(数组名或者指针变量)传递的是数组首元素的地址。
(2)形参数组定义:
指定大小: float average(float array【10】)
不指定大小: float average(float array[ ])
(3)举例:
选择法排序
#include
void sort (int array[],int n);
int main()
{ int a[10],i;
for(i=0;i<10;i++) scanf("%d",&a[i]);
sort(a,10);
for(i=0;i<10;i++) printf("%d",a[i]);
return 0;
}
void sort (int array[], int n)
{ int i,j,k,t;
for(i=0;i
多维数组可以作为函数的实参和形参。
作为形参在定义时可以忽略第一维大小说明,但二维不可忽略。
在二维相同的情况下,形参数组和实参数组的第一维可以不相同。
#include
int add(int b[][3],int n);
void main()
{
int i,j,s,a[3][3];
for(i=0;i<3;i++)
for(j=0;j<3;j++)
scanf("%d",&a[i][j]);
printf("矩阵:\n");
for(i=0;i<3;i++)
{
for(j=0;j<3;j++)
printf("%4d",a[i][j]);
printf("\n");
}
s=add(a,3);
printf("矩阵的对角线上的元素之和为:%d\n",s);
}
int add(int b[][3],int n)
{
int i,j,s=0;
for(i=0;i
void func1(int a1[], int x);
void func2(int a2[][4], int x, int y);
void func3(int a3[][4][8], int x, int y, int z);
在函数内定义的变量是局部变量
1.在函数内部定义的变量,只在本函数内部范围内有效。
注:<1>,在主函数内定义的变量也只在主函数内有效;
<2>,在不同函数内定义的同名变量,代表不同的对象,互不干扰;
<3>,形式参数也是局部变量。
2.在复合语句内定义的变量,只在复合语句内有效,这种复合语句也称为“分程序”或者“程序快”。
在函数之外定义的变量成为外部变量,又称全局变量。它的有效范围是:从定义变量的位置开始到本源文件结束。
注:<1>全局变量相当于各个函数直接的传递通道,如果在一个函数中改变了全局变量的值,就能影响到其他函数中全局变量的值;
<2>在同一文件中局部变量和全局变量如果同名,那么在局部变量的作用范围内局部变量有效,全局变量被屏蔽不起作用。
存储空间分3类:
(1)程序区(2)静态存储区(3)动态存储区
变量的两种分类:
(1)按照作用域分类:
全局变量局部变量
(2)按照生存期(存在的时间)分类:
静态存储方式
动态存储方式
在静态存储区中的数据: 在函数调用开始时分配动态存储空间,函数调用结束时释放这些空间, 这种分配和释放是动态的进行。 在整个程序执行过程中占据固定的存储单元,而不是动态地进行分配和释放。 动态存储区存放的数据: 局部变量,函数的形式参数,函数中定义的没有用关键字static声明的变量, 函数调用时的现场保护和返回地址,等都存放在动态存储区中。
系统默认的局部变量存储类别。在调用函数时,系统会给函数的形参、函数内定义的局部变量
(包括在复合语句中定义的局部变量)分配存储空间。在函数调用结束时就自动释放这些存储空间,
因此这类局部变量称为自动变量。自动变量使用关键字 auto 作为存储类别的声明,
但auto关键字可以省略,不写则系统默认指定为自动变量。自动变量是动态存储方式,
在动态存储区内分配内存单元,
函数调用结束后立即释放。
int fun(int a) //a为形参
{
auto int b = 3; //b为自动变量
}
函数中的局部变量的值在函数调用结束后不消失而继续保留原值,即其占用的存储单元不释放,
在下一次调用该函数时,函数中的变量已有值(就是上一次函数调用结束时的值)。
这时就要指定该局部变量为“静态局部变量”,使用关键字 static 进行声明。
静态局部变量属于静态存储类别,在静态存储区内分配内存单元,在程序整个运行期间都不释放。
静态局部变量是需要赋初值的,如果在定义时不赋初值,系统自动赋初值为0,字符型自动赋值为’\0’。
*&a
可以理解为*(&a)
,&a
表示取变量 a 的地址(等价于 pa),*(&a)
表示取这个地址上的数据(等价于 *pa),绕来绕去,又回到了原点,*&a
仍然等价于 a。&*pa
可以理解为&(*pa)
,*pa
表示取得 pa 指向的数据(等价于 a),&(*pa)
表示数据的地址(等价于 &a),所以&*pa
等价于 pa。
(1)指针:储存其他变量的地址的变量
(2)指针的定义
指针的指向数据类型 * 指针变量名称
*:指针定义符(类型说明符,说明定义的变量是指针变量)
char ch = 'a';
char *p; // 一个用于指向字符型变量的指针
p = &ch;
//定义普通变量
float a = 99.5, b = 10.6;
char c = '@', d = '#';
//定义指针变量
float *p1 = &a;
char *p2 = &c;
//修改指针变量的值
p1 = &b;
p2 = &d;
(3)指针变量的初始化
1 先定义后初始化
int a = 5;
int *p;//定义指针变量
p=&a;
2 同时定义和初始化
int a=5;
int *p=&a;
3 指针初始化为NULL
int *p=NULL;
*注:1指针变量只可以储存地址(变量),不能储存其他类型;
2给指针变量赋值时不可再加*,多个指针可以指向同一个地址;
3指针的指向可以改变;
(4)指针变量的引用
& 变量名; & 取地址运算符,表示变量的地址。
*变量名; *指针运算符(操作符),代表访问指针所指向的储存空间。
int a = 5;
int *p = &a;//对a取地址,&a是变量a的地址
printf("a = %d", *p); // 访问指针变量
(5)二级指针
1.概念:数组元素的指针:保存了数组元素的地址的指针变量;
2:定义与引用:
int main (void)
{
int a[5] = {2, 4, 6, 8, 22};
int *p; p=a;//数组名a只代表数组首元素的地址,不代表整个数组。
或者 int *p; p = &(a[0]);
或者 int *p=a; //该代码只代表“把a数组的首元素的地址赋值给指针变量p“
或者 int *p=&a[0};
printf(“%d\n”,*p); // 输出结果: 2
}
3.指针访问数组元素
在指针指向数组元素时,可以对指针进行加减运算:
·加,减一个整数(用+,-或+=,-=)
·自加,自减运算,如p++, ++p,p--,--p
·两个指向同一个数组中的元素的指针相减,结果是p2-p1的值(两个地址之差)除以单个数组元素的长度。
表示p1和p2所指元素的相对距离,
*******************
注意:
(1)如果指针变量p已指向数组中的一个元素,则p+1指向同一个数组中的下一个元素,p-1指向同一个数组
中的上一个元素。执行p+1时并不是将p的值(地址)简单地加1,而是加上一个数组元素所占用的字节数。
(2)如果p的初值为&a[0],则p+i和a+i就是数组元素a[i]的地址,
或者说它们指向a数组序号为i的元素。
(3)*(p+i)和*(a+i)都表示a[i],是p+i或a+i所指向的数组元素。
例如,*(p+5)或*(a+5)就是a[5],即这三者等价
(4)因为作为指针变量的p可以改变自身值,如p++,使p的值自增。而数组名a是一个代表数组首地址的常量,
它的值是不能改变的,即a++是不合法的
引用一个数组元素的方法:
(1)下标法:a[i] 或者p[i]
(2)指针法:*(a+i)或者*(p+i)//其中a是数组名,p是指向数组元素的指针变量,其初值p=a。
#include
int main(){
int arr[] = { 99, 15, 100, 888, 252 };
int i, *p = arr, len = sizeof(arr) / sizeof(int);
for(i=0; i
#include
#include
int main(){
char str[] = "http://c.biancheng.net";
char *pstr = str;
int len = strlen(str), i;
//使用*(pstr+i)
for(i=0; i
除了字符数组,C语言还支持另外一种表示字符串的方法,就是直接使用一个指针指向字符串,例如:
或者:
字符串中的所有字符在内存中是连续排列的,str 指向的是字符串的第 0 个字符;我们通常将第 0 个字符的地址称为字符串的首地址。字符串中每个字符的类型都是char
,所以 str 的类型也必须是char *
。
#include
#include
int main(){
char *str = "http://c.biancheng.net";
int len = strlen(str), i;
//直接输出字符串
printf("%s\n", str);
//使用*(str+i)
for(i=0; i
可以返回多个变量
#include
void swap(int *p1, int *p2){
int temp; //临时变量
temp = *p1;
*p1 = *p2;
*p2 = temp;
}
int main(){
int a = 66, b = 99;
swap(&a, &b);
printf("a = %d, b = %d\n", a, b);
return 0;
}
如果一个指针指向的是另外一个指针,我们就称它为二级指针,或者指向指针的指针。
假设有一个 int 类型的变量 a,p1是指向 a 的指针变量,p2 又是指向 p1 的指针变量,它们的关系如下图所示:
将这种关系转换为C语言代码:
int a =100;
int *p1 = &a;
int **p2 = &p1;
指针变量也是一种变量,也会占用存储空间,也可以使用&获取它的地址。C语言不限制指针的级数,每增加一级指针,在定义指针变量时就得增加一个星号*。p1 是一级指针,指向普通类型的数据,定义时有一个*;p2 是二级指针,指向一级指针 p1,定义时有两个*。
#include
int main(){
int a =100;
int *p1 = &a;
int **p2 = &p1;
int ***p3 = &p2;
printf("%d, %d, %d, %d\n", a, *p1, **p2, ***p3);
printf("&p2 = %#X, p3 = %#X\n", &p2, p3);
printf("&p1 = %#X, p2 = %#X, *p3 = %#X\n", &p1, p2, *p3);
printf(" &a = %#X, p1 = %#X, *p2 = %#X, **p3 = %#X\n", &a, p1, *p2, **p3);
return 0;
}
#include
int main(){
int a = 16, b = 932, c = 100;
//定义一个指针数组
int *arr[3] = {&a, &b, &c};//也可以不指定长度,直接写作 int *arr[]
//定义一个指向指针数组的指针
int **parr = arr;
printf("%d, %d, %d\n", *arr[0], *arr[1], *arr[2]);
printf("%d, %d, %d\n", **(parr+0), **(parr+1), **(parr+2));
return 0;
}
arr 是一个指针数组,它包含了 3 个元素,每个元素都是一个指针,在定义 arr 的同时,我们使用变量 a、b、c 的地址对它进行了初始化,这和普通数组是多么地类似。
parr 是指向数组 arr 的指针,确切地说是指向 arr 第 0 个元素的指针,它的定义形式应该理解为int *(*parr)
,括号中的*
表示 parr 是一个指针,括号外面的int *
表示 parr 指向的数据的类型。arr 第 0 个元素的类型为 int *,所以在定义 parr 时要加两个 *。
第一个 printf() 语句中,arr[i] 表示获取第 i 个元素的值,该元素是一个指针,还需要在前面增加一个 * 才能取得它指向的数据,也即 *arr[i] 的形式。
第二个 printf() 语句中,parr+i 表示第 i 个元素的地址,*(parr+i) 表示获取第 i 个元素的值(该元素是一个指针),**(parr+i) 表示获取第 i 个元素指向的数据。
磁盘上的文件就是文件。
但是在程序设计中,我们一般谈的文件有两种:程序文件、数据文件(根据文件功能的角度来分类)。
程序文件(后缀为.c)
目标文件(Windows环境后缀为.obj)
可执行程序(Windows环境后缀为.exe)
文件的内容不一定是程序,而是程序运行时读写的数据,比如程序运行需要从中读取数据的文件,
或者输出内容的文件。
文件名包括三部分:文件路径+文件名主干+文件后缀
Eg:
c:\code\test.txt
一个打开的文件包括文件的当前位置指针,文件缓冲区的地址等基本信息。
这些信息由头文件stdio.h中定义的结构体类型FILE来描述。
文件指针是FILE型指针变量,通过文件指针实现对结构体FILE的各成员的访问(文件指针变量也可以称为FILE类型的结构体指针变量),同时文件指针变量也要先定义后使用。
FILE * 文件指针变量名;
FILE * fp=NULL;/*定义并初始化文件指针变量fp*/
通过定义文件指针指向文件
文章目录
前言
C语言笔记整理
四,
提示:这里对文章进行总结:
例如:以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。
目录
C语言学习笔记整理
一、C语言具体结构
二、C语言中的数学函数
1.头文件
2.常用函数
三,基本数据类型
1·变量
(1)变量的定义与赋值
(2)连续定义多个变量
(3)数据的长度
sizeof 操作符
2·常量
3·输出各种类型数据
不同整形的输出:
4·二进制数、八进制数和十六进制数的表示
(1)定义
(2)输出
四,数据的运算处理
五,程序的基本控制结构
1.顺序结构
编辑编辑编辑
2.选择结构
(1)if循环
(2)switch循环
3.循环结构与循环的镶嵌
(1)当型循环
(2)直到型循环
(3)计数型循环
(4)循环结构的镶嵌
4.四大跳转
(1)break——跳出本层循环
(2)continue———跳出本次循环,进入下一次循环
(3)goon———强制跳转到指定位置
(4)return——返回内容
六,同批次类型数据的组织and字符数据的组织——数组and字符串
(1)一维数组
1.数组的概念和定义
2.数组内存是连续的
3.数组的初始化
(2)二维数组
1.二维数组的定义
2.二维数组的初始化
(3)字符数组和字符串
1.定义与赋值
2.字符串的结束标志
3.字符串的长度
4.字符串的输出
5.字符串的输入
6.字符串复制
7.字符串的比较
8.字符串的 链接
9.字符串的大小转换
七,程序的组装单元——函数
(1)函数的定义与调用
(2)对被调函数的声明和函数原型
(3)函数的镶嵌调用
(4)函数的递归调用
(5)数组作为函数的参数
1.数组元素作为函数的实参
2.一维数组名作为函数参数
3.多维数组名作为函数参数
(6)局部变量与全局变量
1.局部变量
2.全局变量
(7)变量的储存方式与生存期
1·动态储存方式与静态储存方式
2·局部变量的储存类别
<1>自动变量(auto变量)
<2>静态局部变量(static变量)
<3>寄存器变量(register变量)
3·全局变量的储存类别
<1>在一个文件内拓展外部变量的作用域
<2>将外部变量的作用域拓展到其他文件
<3>将外部变量的作用域限制在本文件中
(8)变量的声明与定义
(9)内部函数与外部函数
八,变量的间接访问——指针
1.指针的定义,初始化和引用
2.通过指针引用数组
3.通过指针引用字符串
4.指向函数的指针与返回函数值得指针
5.指针数组与多重数组
6.动态内存分配与指向它的指针变量
九,自定义数据类型
十,文件操作
1.文件定义
(1)程序文件:
(2)数据文件:
2.文件名
3.文件指针
(1)定义:
(2)文件操作步骤:编辑
4.打开文件
总结