c语言入门下
第六章 数组
1. 定义
int a[] []内必须注明元素个数
注意数组的定义和引用
(1).和变量一样,先定义后使用。
[]内必须为常量或常量表达式
如
#define FD 5
main()
{ int a[FD];
float b[3+2];
}
(2).引用数组元素时[]内下标可以为变量但是必须为整型,不能为实型
(3).定义时赋初值
将各初值依次写出包括在一对{}内
如int a[5]={0,2,3,4,};
错误示范
int a[5]
a={0,2,3,4,};
当{}内的元素个数少于少于[]内规定元素的个数时只依次给前面部分元素赋初值后面不够元素自动补0
对于char型数组,0对应的字符是'\0'
2. 输入与输出
scanf(“%d”,&a[]);
printf("%d",a[]);
3. 通过循环输入输出赋值给数组元素
for(i=0;i<5;i++)
a[i]=1; //赋值
printf("%d",a[i]); //输入
scanf("%d",&a[i]); //输出
数组元素的和
for(i=0;i<5;i++)
sum=sum+a[i];
求平均值只要sum/5.0就可以啦
模板
for(i=0;i<元素个数;i++)
对a[i]进行操作;
例6.1 p139
#include<stdio.h>
main()
{ float score[10];
int i,cut;
float sum=0.0,aver=0.0;
for(i=0;i<10;i++)
scanf("%f",&score[i]);
cut=0;
for(i=0;i<10;i++)
{ if(score[i]>=60) cut++;
sum+=score[i];
}
aver=sum/10.0;
printf("及格人数=%d\n",cut);
printf("平均成绩=%5.1f\n",aver);
例6.2
#include<stdio.h> //删除数组b中下标为2的元素75
main()
{ int i,b[6]={99,60,75,86,92,70};
int n=6;
for(i=2;i<n-1;i++)
b[i]=b[i+1]; //使75后面的元素往后移动
n=n-1; //规定元素个数-1
for(i=0;i<n;i++)
printf("%d ",b[i]);
}
**元素删除的步骤**
1.是被删除元素后面的元素顺次前移一个位置。
2.规定元素个数-1
例6.3
#include<stdio.h> //给数组b中下标为2的元素75之前插入100
main()
{ int i,b[6]={99,60,75,96,92};
int n=5;
for(i=n;i>=3;i--)
b[i]=b[i-1];
b[2]=100;
n=n+1;
for(i=0;i<n;i++)
printf("%d ",b[i]);
}
一维数粗的应用
1.数组的归纳
#include<stdio.h>
main()
{
int a[50];
int n,i,j;
j=0;
for(n=1;n<=50;n++)
if(n%7==0||n%11==0) a[j++]=n;
printf("共有%d个数据符合条件,它们是:\n",j);
for(i=0;i<j;i++)
printf("%d ",a[i]);
printf("\n");
}
例6.3 p148
//将50-100的所有素数存放到数组b中
#include<stdio.h>
main()
{
int b[50],n,i,j;
j=0;
for(n=50;n<=100;n++)
{ for(i=2;i<n;i++)
if(n%i==0) break;
if(i>=n) b[j++]=n;
}
printf("共有%d个素数,它们是:\n",j);
for(i=0;i<j;i++)
printf("%d ",b[i]);
}
例6.5 p149
//10名学生的考试成绩已存入数组s,在成绩及格的学生中,低于70分的学生还要加强训练。请编程将其中60-70分(含60不含70)成绩挑出存入数组d中
#include<stdio.h>
#define N 10
main()
{ float s[N]={ 58.5,69.5,60.0,42.0,75.0,64.0,86.5,92.5,100.0,70.0},d[N];
int i,j;
j=0;
for(i=0;i<N;i++)
if(s[i]>=60&&s[i]<70) d[j++]=s[i];
for(i=0;i<j;i++)
printf("%5.1f",d[i]);
}
例6.6
#include<stdio.h>
#define N 10
main()
{ float s[N]={ 58.5,69.5,60.0,42.0,75.0,64.0,86.5,92.5,100.0,70.0},d[N];
int i,j;
j=0;
for(i=0;i<N;i++)
if(s[i]>=60&&s[i]<70) s[j++]=s[i];
for(i=0;i<j;i++)
printf("%5.1f",s[i]);
}
小试牛刀6.3 p151
#include<stdio.h>
main()
{
int i,b[6]={99,60,75,85,92,70};
int n=6,j=0;
for(i=0;i<n;i++)
if(i!=2) b[j++]=b[i];
n=j;
for(i=0;i<n;i++)
printf("%d ",b[i]);
}
随讲随练6.4 //请编程删除一维数组a中所有相同的数,使之只剩一个。数组中的数据个数也应存入变量n
#include<stdio.h>
main()
{
int a[20]={2,2,2,3,4,4,5,6,6,6,6,7,7,9,9,10,10,10,10},n=20;
int i,j=0,k;
k=0;
for(i=0;i<n;i++)
if(k!=a[i])
{a[j++]=a[i];
k=a[i];
}
n=j;
printf("删除后的数组中的数据是:\n");
for(i=0;i<n;i++)
printf("%3d ",a[i]);
printf("\n");
}
例6.7 数组元素求最值
#include<stdio.h>
# define N 4
main()
{
double a[N]={13.0,29.0,99.0,17.0};
int i; double max;
max=a[0];
for(i=0;i<4;i++)
if(max<a[i]) max=a[i];
printf("最大元素为:\n");
printf("%5.1f\n",max);
}
查找
1.顺序查找
例6.8
#include<stdio.h>
main()
{
int a[9]={12,32,5,20,28,18,25,38,3};
int i;
for(i=0;i<9;i++)
if(a[i]==25) break;
if(i>=9)
printf("未找到25\n");
else
printf("找到25,下标是%d\n",i);
}
2.二分查找
注意:使用二分查找数组里的数据必须按照由大到小或由小到大;
例 6.9
#include<stdio.h>
main()
{
int a[9]={3,5,12,18,20,25,28,32,38};
int low=0,high=8;
int mid;
while(low<=high)
{ mid=(low+high)/2;
if(a[mid]<25)
low=mid+1;
else if (a[mid]>25)
high=mid-1;
else
break;
}
if(low>high)
printf("没有找到25。\n");
else
printf("找到25,它的下标是%d\n",mid);
}
排序技术
1.(简单)选择排序法 p156
#include<stdio.h>
#define N 5
main()
{
int b[N]={5,2,8,3,1};
int t,i,j;
for(i=0;i<N-1;i++)
for(j=i+1;j<N;j++)
if(b[i]>b[j])
{t=b[i];b=[i]=b[j];b[j]=t;}
for(i=0;i<N;i++)
printf("%d ",b[i]);
}
2.冒泡排序法
#include<stdio.h>
#define N 5
main()
{
int b[N]={1,5,3,2,8};
int t,i,j;
for(i=0;i<N-1;i++)
for(j=0;j<N-1-i;j++)
if(b[j]<b[j+1])
{t=b[j];b[j]=b[j+1];b[j+1]=t;}
for(i=0;i<N;i++)
printf("%d ",b[i]);
}
二维数组
1.定义
int a[2][3]={{1,2,3},{1,2,3}}
int x[][3]={{1},{2},{3}};
int y[][3]{ {0,1},{},{3}};
int z[][3]={{0,1},{2}};
任何情况下都不能省略列数(第二个括号[]内的数字)
给出初值时,可省略行数(第一个括号内的数[])
矩阵转置
例6.14 p167
#include<stdio.h>
#define N 4
main()
{
int a[N][N]={ {21,12,13,24},{25,16,47,38},{29,11,32,54},{42,21,33,10} };
int i,j,t;
for(i=1;i<N;i++)
for(j=0;j<i;j++)
{t=a[i][j];a[i][j]=a[j][i];a[j][i]=t;}
for(i=0;i<N;i++)
{ for(j=0;j<N;j++)
printf("%4d",a[i][j]);
printf("\n");
}
}
第七章 函数
主调函数调用被调函数
一,函数的定义及其调用
函数返回值类型 函数名(参数类型1 参数名1,参数类型2 参数名2, ...)
{}
函数调用方法
1.
(1).函数名(参数,参数,,,);
(2).表达式.....函数名(参数,参数,,,)。
2.形式参数与实际参数
(1)在函数头部中的参数,成为形式参数
(2)在调用函数时实际给出的具体参数,称为实际参数
(3)形参一定是变量,实参可以使常量也可以是变量或表达式
如 int x25,y=73;
maxnum(x*3,y);
3.函数调用过程
(1)每个函数都有自己独立的空间,被调函数的内存空间只有函数被调用后运行时才存在,不调用不运行其空间不存在,称为“独立空间”
(2)实参单向传递给形参。
(3)被调函数运行结束后空间被系统回收不再存在,但对于有返回值的函数,返回值不会消失。
(4)(5) p177
例7.1 简单函数调用
#include<stdio.h>
void fun(int p)
{ int d=2;
p=d++;printf("%d",p);
} //d++ 先取d原来的值用
main()
{ int a=1;
fun(a);
printf("%d",a);
}
4.函数的返回值
用return语句使函数返回值
例7.3
#include<stdio.h>
int max(int a,int b)
{
int c;
if(a>b) c=a;
else c=b;
return c;
}
void Printstar()
{
printf("**********\n");
}
main()
{ int x,y,z;
Printstar();
printf("输入两个数:\n");
scanf("%d%d",&x,&y);
z=max(x,y);
printf("%d较大\n",z);
Printstar();
}
关于return:
(1)同一函数内允许出现多个return语句,但在函数每次调用时只能有其中一个return语句被执行,函数只能返回一个值。
(2)return兼有返回值和强制跳出函数的双重作用
(3)return比break更加强大,return可以跳出所有循环,
5.函数的声明
(1)声明形式: 函数声明时可以省略形参名字如double min(double,doble); 完整 double min(double a,double b;);
(2)声明位置:1. 函数外 2.函数内
注意 函数声明可以出现多次 但是函数定义只能出现一次。
6.函数的嵌套和递归调用
例7.6 函数嵌套调用
#include<stdio.h>
void fun1();
void fun2();
main()
{
fun2();
printf("main\n");
}
void fun1()
{
printf("fun1\n");
}
void fun2()
{
fun1();
printf("fun2\n");
}
函数递归调用
#include<stdio.h>
long fact(int n)
{long r;
if(n==0||n==1)
r=1;
else
r=n*fact(n-1);
return r;
}
main()
{
int n;long y;
printf("input an integer number:");
scanf("%d",&n);
y=fact(n);
printf("%d!=%1d",n,y);
}
汉诺塔问题
#include<stdio.h>
move(int n,char x,char y,char z)
{ if(n==1)
printf("%c-->%c\n",x,z);
else
{ move(n-1,x,z,y);
printf("%c-->%c\n",x,z);
move(n-1,y,x,z);
}
}
main()
{
int n;
printf("请输入圆盘数:");
scanf("%d",&n);
printf("%3d个圆盘的移动步骤是:\n",n);
move(n,'A','B','C');
}
变量的作用域及其储存类别
作用域是指变量在程序中能够起作用的地域范围
局部变量和全局变量
函数内定义为局部变量
函数外定义全局变量
局部变量
(1)
(2)
(3)
(4)
(5)
局部变量生存期及其作用域
(1)生存期
(2)作用域
2.全局变量
特点:
(1)从定义开始到本源程序文件末尾的所有函数都共享此变量
(2)如定义时未赋初值,初值自动补0,而不是随机数。
例7.10使用全局变量
#include<stdio.h>
int sum;
void fun1()
{ sum+=20;}
int a;
void fun2()
{a=20;sum+=a;}
main()
{ sum=0;
fun1();
a=8;
fun2();
printf("sum%d,a=%d",sum,a);
}
例7.11全局变量的屏蔽
#include<stdio.h>
int a=3,b=5;
max(int a,int b)
{int c;
if(a>b) c=a;else c=b;
return(c);
}
main()
{int a=8;
printf("a=%d\n",a);
printf("b=%d\n",b);
printf("max=%d\n",max(a,b));
}
全局变量
生存期:整个程序的开始运行
作用域:起始于变量的定义,终于本源程序文件末尾。
3.扩大全局变量的作用域
extern int a;
注意:声明不会开辟变量的储存空间,而定义就要开辟储存空间了,因此全局变量声明课出现多次,而定义只能是一次。
在程序7.10中fun1函数使用全局变量a
include<stdio.h>
extern int a;
int sum;
void fun1()
{ sum+=20;}
int a;
void fun2()
{a=20;sum+=a;}
main()
{ sum=0;
fun1();
a=8;
fun2();
printf("sum%d,a=%d",sum,a);
}
只有先使用全局变量后面的声明才有必要
4.多文件编程的指挥艺术
extern总结
(1)全局变量和声明或函数的声明前加extern,表示该全局变量或函数是在其他文件中定义的,或是本文件稍后定义的,这里extern用于扩大作用域范围。注意声明并不可开辟新的空间。
(2)函数定义前extern或不写extern,都表示该函数允许被其他文件调用。
如果不让其他文件调用本文件定义的全局变或函数在定义前加static,可限制其只能在本文件中使用,在其他文件中用extern声明也不行。
static int a;
总结:static的使用
(1)全局变量定义时或函数定义时加static;表示限制其只允许在本文件内被使用。
(2)局部变量定义前加static,表示静态变量。
注意:声明与定义
(1)声明:不分配内存,可出现多次
(2)定义;分配内存,写出执行语句,只能出现一次。
变量的储存类别
有三种储存位置分别为:
(1)内存动态储存区 定义变量时,变量名加auto,变量将位于内存动态储存区 。
(2)内存静态储存区 定义变量时,变量名前用关键字static,变量将位于内存静态储存区 。未赋初值则为0。
(3)CPU寄存器 定义变量时,变量名前用关键字 register变量将位于CPU寄存器。
这里仅指局部变量
例7.12 使用static变量
#include<stdio.h>
f(int a)
{ auto b=5;
static c=3;
b=b+1;
c=c+1;
return (a+b+c);
}
main()
{ int a=2,i;
for(i=0;i<3;i++)
printf("%d ",f(a));
}
12 13 14
static c=3;只有第一次调用时才会被真正执行,分配c的空间,并为它赋初值3,在以后的量词调用中不会执行而直接被跳过,第一次调用后c空间一直存在。
局部变量和全局变量的储存类别
(1)全局变量:只能是static型的,即只能位于内存静态储存区。
(2)函数中,或{ }中的局部变量:可以使auto,static,或register。
(3)函数的形参,可以使auto或register型的,不能为static型的。
注意:在定义全局变量时,有无static都时静态的,如有static则是另外的含义,它不允许被其他源文件使用。
预编译处理
宏定义
#define命令的用法:
#define 宏名 替换文本
注:为一种命令,而不是语句。
1.无参数宏定义
#define M (y*y+3*y)
2.有参数宏定义
#include<stdio.h>
#define F(x,y) 3*x+y
main()
{
printf("%d",f(1,2));第一步:printf("%d",3*x+y)第二部:printf("%d",3*1+2);
}
3.嵌套的宏定义
#define PI 3.14
#define S PI*Y*Y
执行printf("%f"S);
宏展开
printf("%d"3.14*y*y);
宏定义的取消
(#undef 宏名)
第八章 指针
地址和指针的基本概念
指针就是地址,地址就是编号。
指针变量
(1)定义
int a=1;
int *p;
变量名是p
变量p的类型int*。
地址的保存
p=&a;
(2)指针变量的基类型(指针变量所能指向的数据的类型)
int a,b;
double c,d;
int *p;
p=&a;p=&b;//正确
q=&c;q=&d;//错误
万能指针
void *x 可以指向任意型变量
(3)指针变量的赋值
int a=1; //定义时初始化int *p=&a;
int *p;
p=&a;
p=a;//错误,p不能保存普通整数
注:变量之间彼此赋值基类型相同才能赋值
但是允许把数值0直接赋值给指针变量
int *p;p=0;p=NULL;系统在stdio.h头文件中定义有符号NULL(#define NULL 0)
总结 关于*
(1)定义指针变量时必须写*
(2)使用指针变量时可以写*也可以不写*
写*表示取指针变量所指向的内容或改写所指向的内容
不写*表示指针变量本身所保存的地址。
int a=1;
int *p;
p=&a;
上语句中p &p *p各表示什么
p:表示指针变量p本身所保存的值是地址。
&p:表示指针变量p本身的地址。
*p:表示指针变量p所指向的数据,变量a的值。
#include<stdio.h>
main()
{
double *p1,*p2,*p,a,b;
p1=&a;p2=&b;
scanf("%lf%lf",&a,&b);
if(a<b){p=p1;p1=p2;p2=p;}
printf("max=%lf,min=%lf\n",*p1,*p2);
}
#include<stdio.h>
main()
{
int m=1,n=2,*p=&m,*q=&n,*r;
r=p;p=q;q=r;
printf("%d,%d,%d,%d\n",m,n,*p,*q);
}
通过交换指针所保存的地址,来交换指向。
数组与指针
一.指针的运算
int a[5];//定义整数数组,每元素占4字节,设起始地址为1000
int *p;//定义指针变量p,用于指向一个整形变量;
p=&a[0];//把a[0]地址赋给p,p指向a[0],p的值为地址1000
P=&a[1];//把a[1]地址赋给p,p指向a[1],p的值为地址1004
(1)指针变量加减整数
p=&a[0];
p=p+1;//p++或++p
此时p保存了a[1]的地址1004
p+-n=p中所保存的地址值=-(每元素字节数*n)
对于char型数组每元素占1字节p+-n恰好时+-n个字节
(2)指针变量之间相减
double d[6];
double *p1,*p;
p1=&d[1];
p2=&d[3];
p2-p1的值为2;
数组元素的地址与下标的转换
p-数组0号元素的地址
#include<stdio.h>
main()
{
int a[10],i;
for(i=0;i<10;i++)
a[i]=i;
int *p,*q=&a[0];
for(p=q;p-q<10;p++)
printf("下标为%d的元素是%d\n",p-q,*p);
}
(3)指针变量互相比较大小
#include<stdio.h>
#define N 7
main()
{
int a[N]={1,2,3,4,5,6,7};
int i,t;
int *p=&a[0],*q=&a[N-1];
while(p<q)
{ t=*p;*p=*q;*q=t;
p++;q--;
}
for(i=0;i<N;i++)
printf("%d ",a[i]);
printf("\n");
}
以上语句交换指针变量保存的地址;
一维数组的指针
1.指针变量
int a[5];
(1)a是数组名
(2)a一个假想"指针变量"
(3)0指针变量a保存了该数组的首地址
(4)指针变量a本身的地址是数组的地址数值上与a[0]的地址相等
(5)a的值不可以改变,是常量。
2.两个重要共公式
a+i=&a[i]
*(a+i)=a[i]
例 a+0等价a
a+等价&a[1]
3.指针变量与一维数组名是等效的
int a[10],*p;
等效的前提条件
(1)指针变量p的值可以被改变,“指针变量”a的值永远不能被改变。
(2)p的值必须为数组a的首地址,执行语句p=a或p&a[0]
4.间接访问运算符++,--谁更优先
#include<stdio.h>
main()
{
int a[ ]={1,3,5,7},*p=a+1;
printf("%d ",*p++);
printf("%d ",++*p);
printf("%d ",(*p)++);
printf("%d ",*++p);
}
运行结果:3, 6, 6, 7
间接访问符(*)与++,--是同一优先级,同时出现按照“从右至左”的顺序计算
二维数组指针和行指针
1.二维指针变量
二级指针
*可以取出一级地址的值
**可以取出指针所指向的数据
2.二维数组名是“二级指针变量”
int b[3][4];
(1)b是数组名
(2)b是一个假想的“二级指针变量”,保存了另一之指针量的地址
(3)指针变量b所保存的值为数组首地址,数组即0行地址,数值上与元素b[0][0]的地址相等,不过是二级的。
(4)指针变量b本身的地址是二维数组的地址,数值上与元素b[0][0]的地址相等
(5)b的值不可被改变,是常量。
小结:
(1)b为二级
(2)b[0],b[1]为一级
(3)b[0][0],b[0][1],等保存整数数据,不是指针,可看做0级。
(4)指针变量只能相同级别的地址
3.行指针
(1)定义
int (*q) [4];
q=b ;//保存b中的二级地址
二维数组名或航指针加减=地址值加减数组每行元素个数*每元素字节数*n
二维数组名b和这种二级指针变量q,他们它们都是加减一行移动的,
4.行指针与二维数组名是等效的
int (*q)[4]与二维数组b
q[0][0]=b[0][0]....
q[i][j]等价*(q[i]+j) b[i][j]等价*(b[i]+j)
q[i][j]等价*(*(q+i)+j) b[i][j]等价*(*(b+i)+j)
要访问b[i][j]除了以上还有
(1)*(q+i)[j]
(2)*(&b[0][0]+4*i+j)//当b[0][0]的地址移动4*i+j个单位
注意:要达到等效效果的条件
(1)指针变量q的值可以被改变,“指针变量”b的值永远不能被改变,在不改变b的情况下,q与b二者才能等效
(2)q的值必须为二维数组的首地址,即0行的地址,也等于b的值,一般需要先将指针变量q赋值为二维数组的首地址,如执行q=b,或q=&b[0].
下列语句正确
q=b ; q=&b[1]; q++; q=0; q=NULL;
下列错误
b=q ; b=&q[1]; b++; b=0; b=NULL;
小试牛刀8.3
你能写出q[0][0]或b[0][0]的*运算的等价形式吗?
*(*(q+0)+0);**q
*(*(b+0)+0);**b
指针数组和指针的指针
1.指针数组(第二类二级指针)
int *r[3];或int *(r[3]);
[]与()的优先级相同且高于*
2.指针数组名是“二级指针变量”
二级指针分为两类 行指针 第二类二级指针
3.指向指针的指针
(1)定义
int **s; //称为指向指针的指针
s=r;
(2)第二类二级指针变量或指针数组加减n
r等价r+0等价&r[0]
(3)应用
#include<stdio.h>
main()
{
int a=1,*p=&a;
int **q;
q=&p;
printf("%d\n",*q);
printf("%d\n",**q);
}
4.指针的指针与指针数组名是等效的
s[0]=r[0] ; s[1]=r[1];
等效条件:......
指针小结 p242
函数与指针
1.指针变量做函数参数
向主调函数书传回数据
例8.5
输入两个整数,分别输出较大值和较小值。用函数处理且用指针作参数
#include<stdio.h>
swap(double *p,double *q)
{
double temp;
temp=*p;
*p=*q;
*q=temp;
}
main()
{
double a,b,*p1,*p2;
p1=&a;p2=&b;
scanf("%lf%lf",&a,&b);
if(a<b) swap(p1,p2);
printf("max=%lf,min=%lf\n",a,b);
}
通过访问地址交换数据进行数据返回
指针变量作函数参数,所传递的内容永远是一个4字节的地址,
本例中变量a,b均为double,占8个字节,然而他们的地址仍是4个字节,注意是参合形参的基类型必须相同。
例8.6
通过函数fun计算两个整数的和,两个整数的差。
#include<stdio.h>
int fun(int x,int y,int *p)
{ int sum,sub;
sum=x+y;
sub=x-y;
*p=sub;
return sum; //用return去返回数据
}
main()
{ int a,b,m1,m2;
printf("Please input two numbers:");
scanf("%d%d",&a,&b);
m1=fun(a,b,&m2);
printf("sum is %d,sub is %d\n",m1,m2);
}
数组作函数参数
例8.7
数组a中存放了一名学生5门成绩。求平均值
#include<stdio.h>
float aver(float b[5],int n)
{ float av,s=0;int i;
for(i=0;i<n;i++)
s=s+b[i];
av=s/5;
return av;
}
void main()
{
float a[5]={97.0,85.0,90.5,70.5,75.0};
float av;
av=aver(a,5); //&a[0]也可以
printf("average score is %5.2f",av);
}
注意:要理解ab为统一数组c语言规定,即使将函数的形参写为数组的形式,形式参数仍是一个指针变量。
以下也可以
float ave(float b[5],int n)
float ave(float b[],int n)
float ave(float b[500],int n)
float ave(float *b,int n)
数组做形参,就是指针变量作形参
#include<stdio.h>
#define M 6
void discount(float *p,int n,float *g)
{ int i,j=0;
for(i=0;i<M;i++)
{ p[i]=p[i]*0.85;
if(p[i]>500) g[j++]=p[i];
}
g[j]=-1;
}
void main()
{ float price[M]={238.0,985.0,1050.0,599.0,799.0,198.0};
float gift[M+1]; int i;
printf("打折前价格:\n");
for(i=0;i<M;i++) printf("%7.1f",price[i]);
discount(price,M,gift);
printf("\n\n打折后的价格是:\n");
for(i=0;i<M;i++)
printf("%7.1f",price[i]);
printf("\n打折后满500元的价格有:\n");
for(i=0;gift[i]>=0;i++) printf("%7.1f",gift[i]);
printf("\n");
}
在函数形参中,以下写法是等价的
(1)int a int *a
(2)int b[N][4] int(*b)[4],第一个[]内的值可以忽略
(3)int *c[N] int **c
例8.9
二维数组做函数参数
#include<stdio.h>
void fun(int p[2][3],int m,int n)
{ int i,j;
for(i=0;i<m;i++)
{ for(j=0;j<n;j++)
printf("%d ",p[i][j]);
printf("\n");
}
}
main()
{ int a[2][3]={1,3,5,7,9,11};
fun(a,2,3);
}
形参p的值为数组a的首地址,在fun函数中可以把p当做“二维数组名”来用,对p[i][j]进行操作就是对a[i][j]进行操作
p[i][j]等于*(*(p+i)+j) a[i][j]等于*(*(a+i)+j)
返回地址值得函数
一个函数的返回值也可以是一个地址,需要在函数名前加*号标志。
例8.10
#include<stdio.h> //未运行
double *pmax(double *p,double *q);
main()
{ double a,b,*pm;
scanf("%lf%lf",&a,&b);
pm=pmax(&a,&b);
printf("max=%lf \n"*pm);
}
double *pmax(double *p,double *q)
{
if(*p>*q) return p;else return q;
}
函数的指针
(1)定义
指向函数的指针
int (*pf)();
int (*pf)(int a,int b);
它可以保存一个函数的地址,但只能保存函数的地址
(2)指针变量指向函数的方法
pf=函数名;
调用方法(*pf)(参数,参数,......);或pf(参数,参数,......)
例8.11
#include<stdio.h>
int max(int a,int b)
{
if(a>b) return a;
else return b;
}
main()
{ int max(int a,int b);
int (*pmax)();//或 int (*pmax)(int,int);
int x,y,z;
pmax=max;//让指针变量指向函数
printf("input two numbers: ");
scanf("%d%d",&x,&y);
z=(*pmax)(x,y);
printf("maxmum=%d",z);
}
字符串的储存
1.用char型数组保存字符串
可以用一个char型的一维数组来保存一个字符串,只能保存一个。
字符串末尾必须有'\0'这个字符表示字符串的结束,用char型数组保存字符串,数组中必须有'\0'元素,否则它只是一个数组而已,并没有保存字符串。
(1)char c=['B','M','W','','5','3','0','I'];
解释:定义了一个数组c,[]内没有给出元素个数,但在{}内给出了初值,初值有8个字符,因此数组c将有8个元素,由于没有‘\0’元素,所以数组c没有保存字符串。
(2)char d=['B','M','W','','5','3','0','I','\0'];
有'\0'这个元素所以保存了字符串
字符串的修改d[4]='x';d[5]='6';d[6]='\0'
执行后为‘BMW X6’
(3)char f[9]={'B','M','W','','5','3','0','I'};
{}中有八个元素 初值不足最后一个f[8]被自动补0(\0)
char型数组保存字符串的特殊用法
char d[]={"BMW 530i"] ;可以省略{} char d[]="BMW 530i";
2.以char *型指针变量保存字符串字符串的首地址
一个“”引起来的字符串常量可被看做是表达式,表达式的值就是字符串常量的首地址。
(1)char *ps="iPhone";
(2)char *ps;
ps="iPhone"; 变量ps只保存了字符串的首地址,ps只占了4个字节,是存不下一个字符串这么多的内容,ps是指针变量,不是"字符串常量"!
(3)char s[]="iPhone"
char *ps;
ps=s;
字符串的输出和输入
1.字符串的输出
函数 功能 是否自动换行
printf("%s",一级地址);从一级地址开始,逐个字符输出 不会自动换行
puts(一级地址); ,直到遇到‘\0’为止。 输出一串字符自动换行
以上含函数应包含在头文件stdio.h。
如有字符变量char ch;一维数组 char a[10]; 二维数组 char b[5][10];
正确 printf("%s",a) printf("%s",b[1]) puts(b[0]);
错误 printf("%s",ch); printf("%s",b); puts(ch);puts(b);
单个字符的输出
printf("%c",ch);
printf("%c",a[1]);
printf("%c",b[2][3]);
例8.12
#include<stdio.h>
main()
{
char s[]="iPhone";
char *ps;
ps=s;
printf("%s\n",s);
printf("%s\n",ps);
printf("%s\n",s+1);
printf("%s\n",&s[2]);
ps=ps+2;
printf("%s\n",ps+3);
printf("%c\n",s[0]);
printf("%c\n",ps[2]);
}
结果:iPhone
iPhone
Phone
hone
e
i
n
puts(x);等价printf("%s\n",x);
小游戏
#include<stdio.h>
main()
{
char a[4]={'a','b','c','d'};
printf("%s\n",a);
}
结果:abcd€.
2.字符串的出输入
函数 功能 是否能的空格或Tab符
scanf("%s",一维地址); 读入键盘键入的一个字符(最后键入回车表示结束,但不键入'\0') 不读空格和Tab
gets(一位维地址); 存入"一维地址"开始的一段内存空间(回车符不存入),并自动在最后添加\0 空格或Tab一起读入
例 8.13 输入字符串
#include<stdio.h>
main()
{ char s[100];
printf("请输入您所使用的手机名称:");
scanf("%s",s);//或写为&s[0],不能写为&s。
printf("您使用%s的手机\n",s);
}
结果:请输入您所使用的手机名称:iPhone 5s
您使用iPhone的手机
#include<stdio.h>
main()
{ char s[100];
printf("请输入您所使用的手机名称:");
gets(s);//或写为&s[0],不能写为&s。
printf("您使用%s的手机\n",s);
}
结果:请输入您所使用的手机名称:iPhone 5s
您使用iPhone 5s的手机
字符串的处理
1.字符计数和字符转换
以数组处理字符串的编程套路是(设字符串已保存在char 型数组s中)
for(i=0;s[i]!='\0';i++)//for(i=0;s[i];i++)
用s[i]处理每个字符;
s[i]!='\0'就是s[i]!=0;也可以直接写为s[i]。
#include<stdio.h>
main()
{
char str[20]="iPhone 5s";
int i,count=0;
for(i=0;str[i]!='\0';i++)
count++;
printf("字符串的长度为:%d",count);
}
答案:字符串的长度为:9
以指针处理字符串的编程套路
p=字符字符串首地址
while(*p!='\0') 或while(*p)
{
用*p处理每个字符;
p++;
}
#include<stdio.h>
main()
{
char str[80],*p=str;
int n=0,flag=0;
printf("请输入一行字符串:\n");gets(p);
while(*p)
{ if(*p==' ')
flag=0;
else
{ if(flag==0) n++;
flag=1;
}
p++;
}
printf("单词的个数是:%d\n",n);
}
运行结果:
请输入一行字符串:
This is a C Languag program
单词的个数是:6
例8.16
大写字母变小写
#include<stdio.h>
main()
{
char s[80];int i;
printf("请输入一个字符串:"); gets(s);
for(i=0;s[i]!='\0';i++)
if(s[i]>='A'&&s[i]<='z') s[i]=s[i]+32;
printf("将大写字母变为小写,新字符串是:%s\n",s);
}
例 随讲随练 8.15
#include<stdio.h>
void fun(char *b)
{
int i;
for(i=0;b[i]!='\0';i++)
if(i%2==1&&b[i]>='a'&&b[i]<='z') b[i]-=32;
}
main()
{
char s[80];int i;
printf("请输入一个字符串:"); gets(s);
fun(s);
printf("将小写字母变为大写,新字符串是:%s\n",s);
}
123456
#include<stdio.h>
void fun(char **b)
{
int i;
for(i=0;**b[i]!='\0';i++)
if(i%2==1&&**b[i]>='a'&&**b[i]<='z') **b[i]-=32;
}
main()
{
char *s[80];int i;
printf("请输入一个字符串:"); gets(*s);
fun(*s);
printf("将小写字母变为大写,新字符串是:%s\n",*s);
}
随讲随练8.17 字符串转换为对应面值的整数
#include<stdio.h>
long ctod(char *s)
{
long d=0;
while (*s)
{
if(*s>='0'&&*s<='9') d=d*10+*s-'0';
s++;
}
return d;
}
main()
{
char str1[10]="32468", str2[10]="12345";
printf("str1转换整数为%d:str2转换整数为%d:两数之和为%d\n",ctod(str1),ctod(str2),ctod(str1)+ctod(str2));
}
也可以直接调用c语言提供的系统函数来将字符串转换为对应面值的数值
atoi函数:将字符串转换为对应面值的函数。例atoi("12345")将返回整数12345;
atof函数:将字符串转换为对应面值的浮点数(double 型)。例atof("98.76")将返回double型的浮点数98.76。
注意:调用atoi和atof应包含头文件stdlib.h>
小游戏:编程对字符串的加密
#include<stdio.h>
main()
{
char s[80]; int i;
printf("请输入原文字符串:"); gets(s);
for(i=0;s[i];i++) s[i]=s[i]+3;
printf("加密后的字符串为:"); puts(s);
}
2.字符串中字符的定位与字符串的连接
字符串以‘\0’结束
将字符串t连接到字符串s的末尾,连接后的内容仍存入s。
#include<stdio.h>
main()
{
char s[20]="iphone",t[]=" 5s";
char *ps=s, *pt=t;
while(*ps) ps++;
while(*pt) //或while(*ps=*pt)
{ *ps=*pt; ps++; pt++; } // {ps++;pt++}无需*ps='\0';
*ps='\0';
printf("连接后的字符串是:%s\n",s);
}
让char *型的指针p指向字符串的最后一个字符的方法
while(*p) p++;p--; 或while(*p++) p--;p--;
程序 例8.18 p274
应用:
#include<stdio.h>
#define N 80
main()
{
char s[N];
char *p,*q;
printf("本程序判断字符串是否是回文,请输入一个字符串:\n"); gets(s);
p=s;q=s;
while(*q) q++;
q--;
while(p<q)
{
if(*p!=*q) break;
p++;q--;
}
if(p>=q) printf("是回文!\n"); else printf("不是回文!\n");
}
3.字符串的截断
char *pstr="iPhone 5s"
如果只保留前面六个字符,那么?
*(pstr+6)='0';
程序8.19 删除字符串str尾部的若干个*号
#include<stdio.h>
fun(char *s)
{ while(*s!='\0')
s++; s--;
while(*s=='*')
s--;s++;
*s='\0';
}
main()
{
char str[20]="**I*Love*You!****";
fun(str);
printf("删除末尾*号后的字符串为:%s\n",str);
}
4.字符串中字符的删除复制
字符串编程套路
j=0;
for(i=0;s[i]!='\0';i++)
if(要保留字符s[i]) s[j++]=s[i];
s[j]='\0';
程序8.20 删除字符串str中的所有空格
#include<stdio.h> //
fun(char *s)
{ int i,j;
j=0;
for(i=0;s[i];i++)
if(s[i]!=' ') s[j++]=s[i];
s[j]='\0';
}
main()
{ char str[20]=" I Love You! ";
fun(str);
printf("%s\n",str);
}
随讲随练8.19 将形参ss所指字符串中所有下标为偶数且ASCII值为期数的字符删除,字符串第一个字符0为偶数。
#include<stdio.h>
void fun(char *ss)
{ int i,j;
j=0;
for(i=0;ss[i];i++)
if(!(i%2==0&&ss[i]%2==1)) ss[j++]=ss[i];
ss[j]='\0';
}
main()
{ char str[20]="ABCDEFG12345";
fun(str);
printf("%s\n",str);
}
随讲随练8.20 删除非字符元素
#include<stdio.h>
main()
{ char s[20]="asd123fgh5##43df",t[20];
int i,j;
j=0;
for(i=0;s[i];i++)
if(s[i]>='0'&&s[i]<='9') t[j++]=s[i];
t[j]='\0';
printf("%s\n",t);
}
随讲随练 8.21
#include<stdio.h>
{
char s[81]="***A*BC*DEF*G*******";
char *h,*p; int i,j;
h=s; p=s;
while(*h=='*') h++;
while(*p) p++;p--;
while(*p=='*') p--;
j=0;
for(i=0;s[i];i++)
if(!(i>h-s&&i<p-s&&s[i]=='*')) s[j++]=s[i];
s[j]=\0';
printf(%s\n",s);
5.字符串处理函数
(1)c语言常用字符串函数
函数(地址)
strlen(串1地址,串2地址) 求字符长度
strcat (串1地址,串2地址) 字符串连接
strcpy (串1地址,串2地址) 字符串赋复制
strcmp(串1地址,串2地址) 字符串比较
应用以上函数需包含头文件string.h
#include<stdio.h>
#include<string.h>
main()
{
char pw[80],name[80],str[90];
printf("请输入密码:");gets(pw);
if(strcmp(pw,"good")==0)
{
printf("欢迎使用本系统!\n请输入您的名字:");
gets(name);
strcpy(str,"您好,");
strcat(str,name);
printf("%s\n",str);
printf("您的名字中有%d个字符。\n",strlen(name));
}
else
printf("密码不正确,禁止使用本系统。\n");
}
例8.23 p281
char s[10]="123\0abcd",则strlen=4 \0处结束
char c[10]={'v','c','+','+','\0','v','b'}; char d[]="6.0"则strcat="vc++6.0"
求字符串所占字节数的另一个方法 sizeof(数据或类型说明符)
sizeof 是关键字不是函数而是运算符
所有字符串都以“\0”结束(无论是连接字符串,复制字符串,比较字符串,求字符串长度等)sizeof在计算总字节时,是计算"\0"的,因为"\0"也占一个字节。
#include<stdio.h>
#include<string.h>
main()
{
int a=10;double b=6;float c[5];
char *p;char x[]="STRING";
int s,t,r;
s=sizeof(a);t=sizeof(b);r=sizeof(c);
printf("%d, %d, %d\n",s,t,r);
printf("%d, %d, %d\n",sizeof(p),sizeof(x),strlen(x));
printf("%d, %d, %d\n",sizeof(char),sizeof(int),sizeof(float));
}
答案:
4, 8, 20
4, 7, 6
1, 4, 4
c语言常用字符函数
6.字符串数组与多个字符串的处理
(1)char型的二维数组 //保存多个字符串
char ke[]={"shuxue","yuwen","yingyu","zhengzhi"};
ke[0]表示"shuxue"ke[1]表示"yuwen" ,注意ke[0],ke[1]都是字符串的首地址,并不是内容本身。
(2)用指针数组处理多个字符串
char *pke[4]={"shuxue","yuwen","yingyu","zhengzhi"};
ke[0]表示"shuxue"ke[1]表示"yuwen" ,注意ke[0],ke[1]都是字符串的首地址,并不是内容本身。
ke和pke有着本质的不同:
ke[i]是二维数组中一行的“一维数组”的数组名,是假想的指针变量,值不能改。pke[i]是一个指针变量,是数组pke的一个元素,占4个字节。
例8.22 找出四门课程中名称最长的课程
#include<stdio.h>
#include<string.h>
main()
{
char ke[4][9]={"shuxue","yuwen","yingyu","zhengzhi"};
int i,m=0;
printf("四门课是:\n");
for(i=0;i<4;i++)
printf("%s\n",ke[i]); //或写为puts(ke[i]); put() 自带\n
for(i=0;i<4;i++)
if(strlen(ke[i])>strlen(ke[m])) m=i;
printf("最长名称的课程是:%s,长度为:%d",ke[m],strlen(ke[m]));
}
删除串长小于6的课程名
#include<stdio.h>
#include<string.h>
main()
{
char ke[4][9]={"shuxue","yuwen","yingyu","zhengzhi"};
int i,j=0;
for(i=0;i<4;i++)
if(strlen(ke[i])>=6) strcpy(ke[j++],ke[i]);
printf("删除后的课程名为:\n");
for(i=0;i<j;i++)
printf("%s\n",ke[i]);
}
例8.23
将5个城市的名称按照字母顺序排列输出;
#include<stdio.h>
#include<string.h>
#define N 5
void sort(char *s[N],int n);
main()
{
char *pcs[N]={"shanghai","guangzhou","beijing","tianjin","chongqing"};
int i;
sort(pcs,N);
printf("排序结果为:\n");
for(i=0;i<N;i++) printf("%s\n",pcs[i]);
}
void sort(char *s[N],int n)
{char *t;int i,j;
for(i=0;i<n-1;i++)
for(j=i+1;j<n;j++)
if(strcmp(s[i],s[j])>0)
{t=s[i];s[i]=s[j];s[j]=t;}
}
结构体和共用体
定义
不是变量的定义,而是定义一种新的数据类型,是基于已有的数据类型进行创造和组装,这中新的数据类型称为结构体。
struct student //struct 为关键字 student为新类型的名字
{ // {}内定义变量为结构体的成员
int num;
char name[10];
char sex;
float score;
};
注意:新类型的名字为struct student,在c语言中,提及结构体的类型名,必须带有struct关键字。
结构体变量的使用‘
(1)结构变量的定义和使用
struct student boy1,boy2;
c语言用结构体变量名+符号点(.)+成员名
boy1.num=101;
. 称为选择运算符相当于“的”。
boy1.sex='M'
boy1.score=85.0
strcpy(boy1.name,"zhao")
最后一句写为boy1.name="zhao";是不行的,因为name是数组名,不能被赋字符串
2.结构变量的彼此赋值
boy2=boy1;可进行全部内容的复制并赋值,两个变量的类型相同才能彼此赋值。
3.结构类型和结构体变量
struct是结构体类型。boy1,boy2是结构体变量
定义时有三种方式:
(1)
struct student
{
int num;
char name[10];
char sex;
float score;
};
struct student boy1,boy2;
(2)
struct student
{
int num;
char name[10];
char sex;
float score;
}boy1,boy2;
(3)
struct
{
int num;
char name[10];
char sex;
float score;
}boy1,boy2;需一次将所有变量定义齐全
4.结构体变量的初始化
struct student boy2,boy1={101,'zhao','M',85.0};
结构体类型的数组
例9.1 计算学生的平均分和不及格人数
#include<stdio.h>
#define N 5
struct student
{
int num;
char name[10];
char sex;
float score;
}boy[N]={{101,"zhao",'M',85.0},{101,"zhao",'M',85.0},{101,"zhao",'M',85.0},{101,"zhao",'M',85.0},{101,"zhao",'M',85.0}};
main()
{ int i,c=0;
float ave,s=0;
for(i=0;i<N;i++)
{ s+=boy[i].score;
if(boy[i].score<60) c+=1;
}
ave=s/N;
printf("平均分=%f 不及格人数=%d\n",ave,c);
}
结构指针变量
struct student *pstu;
pstu=&boy1;
pstu=&boy1.num;错误类型不同
访问结构体的两种方式
(1)通过变量名 用点.:结构体变量.成员 boy1.num=101
(2)通过地址 1.指针变量->成员 2.(*指针变量).成员 pstu->num=101; 或(*pstu).num=101;
C语言中四种运算符优先级
小括号(),中括号[],点号.,箭头号-> 出现从右往左
struct student boy[5],*pstu;
pstu=boy;
pstu=pstu+1;
pstu则指向b[1]
结构体类型数据做函数参数
#include<stdio.h> //未运行出结果
struct student
{ int num;
char name[10];
char sex;
float score;
};
void fun1(struct student t) //结构体变量做参数
{ t.num=102; strcpy(t.name,"Zhang");
t.sex='F'; t.score=90;
}
void fun2(struct student *p) //结构体指针做参数
{
p->num=102;strcpy(p->name,"Zhang");
p->sex='F';p->score=90;
}
main()
{ struct student x={101,"Zhao",'M',85};
struct student y={101,"Zhao",'M',85};
printf("(1)x: %d %s %c %f\n",x.num,x.name,x.sex,x.score);
fun1(x);
printf("(2)x: %d %s %c %f\n",x.num,x.name,x.sex,x.score);
printf("(1)y: %d %s %c %f\n",y.num,y.name,y.sex,y.score);
fun2(&y);
printf("(2)y: %d %s %c %f\n",y.num,y.name,y.sex,y.score);
}
随讲随练 例9.4
#include<stdio.h>
#include<string.h>
struct A
{ int a; char b[10]; double c;};
struct A f(struct A t); //函数声明
main()
{ struct A a={101,"ZhangDa",1098.0};
a=f(a); printf("%d, %s, %6.1f\n",a.a,a.b,a.c);
}
struct A f(struct A t)
{t.a=102; strcpy(t.b,"ChangRong"); t.c=1202.0; return t;}
//运行结果 102, ChangRong, 1202.0 返回t时将全部赋值
结构体类型的嵌套
struct point
{ double x;
double y;
};
struct circle
{ struct point center;
double r;
};
访问方式
cc.center.x=1;
cc.center.y=2;
cc.r=3;
指针变量访问方式
struct circle *pc=&cc;
pc->center.x=1;
pc->center.y=1;
pc->r=3;
共用体
共用体变量所占字节数为各成员占字节数中最大的那个成员所占的字节数
定义
union un
{ int i;
char c;
double d;
}ul;,*pul=&ul;
类型定义符typedef //给数据类型起别名
为 int起别名INTEGER
typedef int INTEGER;
typedef struct student
{
char name[10];
int age;
char sex;
float score;
}STU; //STU为struct student的别名
也可用宏定义来代替tyedef的功能
#define STU struct student
STU
{int num;char name[10];char sex;float score; };
STU boy1,boy2;
函数指针的类型定义
tpedef int (*PM)(int,int);
动态储存分配
内存管理库函数 功能 用法
malloc 分配1块长度为size字节的连续空间(不清零),函数返回该空间的首地址,分配失败返回0 (类型说明符*)malloc(size)
calloc 分配n块,每块长度为size字节的连续内存空间(n*size字节),并将该空间中的内容全部清零, (类型说明符*)calloc(n,size)
函数返回该空间首地址,失败返回0
free 释放ptr所指向的一块内存空间,ptr是由malloc或calloc含糊是所分配空间的地址,即是这两个函数的返回值 free(ptr) (ptr为任意类型的指针)
运用以上函数需要包含头文件stdlib.h
要使用上述函数分配好的空间需要用过地址来进行访问
由于返回值是void型地址所以,要强制类型转换后进行赋值
int *p;
p=(int *)malloc(sizeof(int));
空间的释放
free(p);
或 free(p); p=0; //释放空间后降将地址清0
free函数与malloc或calloc函数配对使用,不能用free函数释放普通变量的空间。
用calloc函数分配内存,calloc的参数就可以是变量
p=(double *)calloc(n,sizeof(double)) //n由键盘输入
可以将此空间当做含n个元素的double型数组使用。
用*(p+1)或p[i]访问各数组元素
文件指针
FILE *fp;
FILE是系统定义好的一份结构体类型的“别名”
文件的打开 //是指将文件指针与文件建立关联的意思
建立关联时需要调用库函数fopen,用法如下
fp=fopen("c:\\folder1\\filel.dat","r");
fopen函数的第一个参数就是文件名,它将返回值赋给变量fp,就建立了联系
第二个参数"r"表示文件打开的方式
//注意:c语言中读与写严格区分,提前说明要读的文件坚决不能再写,提前说明要读写的文件坚决不能再读,当然也可以即读又写。
文本文件也成为ASCII码文件,包括txt文件,c源程序文件(.c)配置文件(.ini)等。它以每个字符占一个字节的格式储存,每字节保存对应的ASCII码。
二进制文件:他将数据的二进制编码直接保存到文件中,与数据在内存中的状态基本一致,如可执行文件(.exe)压缩文件(.rar)图片文件(.jpg),是二进制文件还是文本文件是由储存格式决定的,也就是当时保存这个文件h时的保存方式,而与文件后缀名无关。
因此,在fopen函数的第二个参数中,就要说明以上这两件事:(1)是读还是写(2)是文本文件还是二进制文件。
r:读且文件必须存在,否则出错w:允许覆盖写文件a:允许追加写文件,文件不存在时新建否则旨在原文件末尾添加数据。+:即允许读也允许写。b:以二进制文件打开。t:以文本格式打开文件。
fopen的返回值是一个FILE *类型的地址,返回的这个值是地址,保存到fp中。
文件打开失败时,fopen的返回时是0或NULL,打开成功则返回至。
include<stdio.h>
main()
{ FILE *fp;
if(( fp=fopen("填文件路径","r"))==NULL)
printf("文件打开失败\n");
else
printf("文件打开成功");
}
文件的关闭
关闭文件需要用到库函数fclose
只有一个文件指针的参数
,把要解除文件的文件指针(如fp)传给它
fclose(fp);
文件操作流程
(1)定义指针:FLIE
(2)打开文件(是文件指针关联文件):fp=fopen(文件名,打开方式);。
(3)读写文件;通过调用系统函数读写文件
(4)关闭软件(断开文件指针与文件的关联)
例10.1
项文件中写入一个字符串
#include<stdio.h>
main()
{ FILE *fp;
fp=fopen("filea.txt","w");
fprintf(fp,"abc");
fclose(fp);
}
文件的读写
文件指针和文件位置的指针
文件指针是一个指针变量(如FILE *fp;中的fp),他用与关联整个文件的,只要不用fclose解除它的关联或重新为它赋值,他的还是不变的。
文件位置指针是位于文件内部的,用于指向文件中的当前读写位置,他不需要我们定义变量,由系统自动设置,且随着文件读写,该指针会自动后移。
文本文件的读写
函数 功能 用法
fgetc或getc 从当前位置读取一个字符
fputc或putc 从当前位置写入一个字符
fgets 读取一个字符串结束条件有三(1)读到换行符(2)读到文件结束(3)读满n-1个字符
fputs
fscanf 读取文件中多个数据
fprintf 向文件中写入多个数据
应包含头文件stdio.h
例10.2
#include<stdio.h>
#include<math.h>
main()
{ FILE *fp; int i,n; double a,sum=0;
fp=fopen("myfile.dat","w");
for(i=0;i<=5;i++)
fprintf(fp,"%d %lf\n",i,log(i));
fclose(fp);
fp=fopen("myfile.dat","r");
for(i=1;i<=5;i++)
{ fscanf(fp,"%d %lf",&n,&a);
sum+=a;
}
fclose(fp);
printf("sum=%lf\n",sum);
}
}
例10.3
#include<stdio.h>
int fun(char *fname)
{ FILE *fp;char ch,ss[80];
if((fp=fopen(fname,"w"))==0) return 0;
for(ch='A';ch<='Z';ch++) fputc(ch,fp);
fclose(fp);
if((fp=fopen(fname,"r"))==0) return 0;
fgets(ss,80,fp);
printf("%s\n",ss);
fclose(fp);
return 1;
}
main()
{ if(fun("c:\\alphabet.txt")) printf("成功!\n");
else printf("失败!\n");
}
二进制文件的读写
对读写二进制文件的库函数
函数 功能 用法
fread 从当前位置读取文件中的一批字节 fread(buffer,size,count,fp)
由count个数据块,每个数据块size个字节组成,
所读取的字节存入参数buffer地址开始的一段内存空间,
fwrite 由count个数据块,每个数据块size个字节组成, fread(buffer,size,count,fp)
所读取的字节存入参数buffer地址开始的一段内存空间,
应包含头文件stdio.h
例10.4 用fread和fwtrite函数读写文件
#include<stdio.h>
main()
{ FILE *fp;
int a[3]={1,2,3},b[6],i;
fp=fopen("mydata.dat","wb");
fwrite(a,sizeof(int),3,fp);
fwrite(a,sizeof(int),3,fp);
fclose(fp);
fp=fopen("mydata.dat","rb");
fread(b,sizeof(int),6,fp);
fclose(fp);
for(i=0;i<=6;i++) printf("%d ",b[i]);
}
1 2 3 1 2 3
例10.5编写程序创建一个图片文件(.bmp),图片像素32*32.
#include<stdio.h>
main()
{ FILE *fp; int i;
char ht[]="BM";long head[]={190,0,62};
long inf[10]={40,32,32,65537,0,128};
char pa10[4]={0,0,0},pall[4]={255,255,255};
char data0[]={255,0,255,0},data1[]={0,255,0,255};
fp=fopen("mybmp.bmp","wb");
fwrite(ht,2,1,fp);
fwrite(head,4,3,fp);
fwrite(inf,4,10,fp);
fwrite(pa10,1,4,fp);
fwirte(pall,1,4,fp);
for(i=0;i<8;i++)fwrite(data0,1,4,fp)
for(i=0;i<8;i++)fwrite(data1,1,4,fp)
for(i=0;i<8;i++)fwrite(data0,1,4,fp)
for(i=0;i<8;i++)fwrite(data1,1,4,fp)
fclose(fp);
printf("位图文件生成成功!\n");
}
文件的随机读写
c语言入门下
最新推荐文章于 2023-06-02 11:03:38 发布