Linux 下C语言学习(六)——二级指针、动态内存分配,函数指针与文件操作

二级指针

  一级指针用来保存普通变量的地址

  二级指针用来保存一级指针变量的地址

 

  数据类型** 变量名;

       Intnum = 0;

一级指针:

       Int*p = #

二级指针:

       Int*pp = &p;

注意:

  (1)二级指针一般用于函数的形参中,用于带回数据 

 

通用类型指针

 void* 通用类型指针,表示一个地址

注意:

 void* v;不能直接取出数据,需要做类型转换

 

动态内存分配

      

动态内存是指程序员通过代码主动向系统申请指定大小的内存,只要是程序员主动申请的(通过申请内存函数)都是放在堆区,申请成功后系统会返回该申请内存的首地址给程序员,但这些内存不能由系统自己释放了,而是由程序员进行释放,假若不释放就会出现内存泄漏

动态内存申请函数:

 

#include<stdlib.h>

   malloc(内存大小),返回值void*表示的首地址,对于申请的内存不做初始化

如:int* p =(int*)malloc(sizeof(int))

       解释:在栈区申请一个名为p的整型指针,该指针保存在堆区申请出来的首地址

calloc(元素个数,每个元素的大小) 返回值也是void*表示的首地址,内存清零

int* p =(int*)calloc(2,sizeof(int))

   realloc(原来内存首地址,新内存的大小)如果新申请的大小可以在原来的内存后面

进行扩展,那么返回原来首地址,如果不能扩展,则重新寻找位置寻找内存,将原来的数

据拷贝过来,释放原来的内存,同时返回新内存的首地址

   free(首地址) 释放指定的内存空间

 

 

函数指针

概念

  数组指针:指向数组的指针

  函数指针:指向函数的指针

 

格式 

  函数:返回值类型 函数名(形参); 

       解释:

              优先级首先是形参括号,之后是函数名称,最后是返回类型             

  函数指针:返回值类型 (*函数指针名)(形参);

       解释:

              优先级首先是左括号,先是一个指针,之后是形参括号,最后是返回类型

 

例子

 int* fn(int i);  //先括号,函数名,再返回值 ——是一个函数

表示fn是一个函数,一个具有int类型形参和int*类型返回值的函数

  int(*fn)(int i);表示fn是一个函数指针,一个指向具有int类型形参和int类型返回值

函数的指针

 

 

       函数指针就是保存一个固定格式函数的变量,这个变量是一个指针

实际应用:

例子

//函数指针的用途
#include <stdio.h>


void fn1(int* num)
{
    printf("num = %d\n",*num);
}


void fn2(int* num)
{
    *num = 118;
}


void fn3(int* num)
{
    (*num)++;
}


//编写一个通用函数,可以分别调用上面的三个函数
void common(int* pNum,void (*pF)(int* num))
{
    pF(pNum);
}


int main(void)
{
    int num = 66;
    fn1(&num);


    fn2(&num);
    fn1(&num);
    
    fn3(&num);
    fn1(&num);


    printf("----------------------------\n");
    common(&num,fn1);
    
    common(&num,fn2);
    common(&num,fn1);
    
    common(&num,fn3);
    common(&num,fn1);
    return 0;
}

 

文件操作

File类型没有存储指向的文件名,File类型定义:
struct{
    int _fd;//文件号
    int _cleft;//缓冲区所剩下的字符数
    int _mode;//文件操作方式
    char* _next;//文件当前读写位置
    char* _buff;//文件缓冲区位置
}FILE;

 

//向文件中写入一个字符串,再读取出来打印到屏幕上

#include <stdio.h>

 

int main(void)

{

    //1.打开一个文件

    FILE* fp= fopen("a.txt","w");

    if(fp ==NULL)

    {

       printf("打开要写入数据的文件失败\n");

       return -1;

    }

    //2.写入一个字符串数据

    charbuf[20] = "GoodAfternoon!";

   fputs(buf,fp);

    //3.关闭这个文件

   fclose(fp);

 

    //4.再次打开这个文件

    FILE*fp2 = fopen("a.txt","r");

    if(fp2== NULL)

    {

       printf("打开读取的文件失败\n");

       return -1;

    }

    //5.读取文件中保存的字符串内容

    charbuf2[20] = {0};

   fgets(buf2,20,fp2);

   printf("读取到的字符串内容是:%s\n",buf2);

    //6.再次关闭这个文件

   fclose(fp2);

    return0;

}

 文件操作的相关函数
 文件定位问题
    int fseek(FILE *stream, long offset, int whence);
功能分析:
    第一个参数为文件指针,第二个参数表示偏移量,第三个参数表示从什么地方开始偏移
,返回值为0表示成功,-1表示失败


   whence的数值:
      SEEK_SET  文件的起始位置 0 
      SEEK_CUR  文件的当前读写位置 1
      SEEK_END  文件的末尾位置  2
  
注意:
  (1)如果偏移量是正数,表示从文件开头向文件末尾的方向移动,如果偏移量是负数,那么
向文件开头的方向移动
  (2)SEEK_END 表示文件中最后一个字符的下一个位置    
 
 ftell和rewind函数
   long ftell(FILE *stream);
功能分析:
   表示将stream指向文件的读写位置偏移量通过返回值返回出来,偏移量指的以文件的开头
位置为基准


   void rewind(FILE *stream);
功能:
   表示将stream指向的文件读写位置移动到文件的开头


fread和fwrite函数
  size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
  size_t fwrite(const void *ptr, size_t size, size_t nmemb,FILE *stream);
功能:
  第一个参数表示内存地址,第二个参数为每一个数据的大小,第三个参数为数据的个数,
第四个参数为具体的文件
  fread表示将文件中的数据读取出来存储到ptr指向的内存中
  fwrite表示将ptr指向的内存中数据存储到文件中 
  返回值为成功读写的数据个数


例子1

//fseek函数的使用
#include <stdio.h>


int main(void)
{
    //1.打开文件
    FILE* fp = fopen("b.txt","r+");
    if(fp == NULL)
    {
        printf("打开文件失败\n");
        return -1;
    }


    printf("开始的读写位置是:%ld\n",ftell(fp));


    //2.调整文件的读写位置
    char c = fgetc(fp);
    printf("读取到的字符是:%c\n",c);
    printf("读取之后的读写位置是:%ld\n",ftell(fp));
    
    fseek(fp,2,SEEK_CUR);
    c = fgetc(fp);
    printf("读取到的字符是:%c\n",c);
    printf("移动之后的读写位置是:%ld\n",ftell(fp));
    
    fseek(fp,3,SEEK_SET);
    c = fgetc(fp);
    printf("读取到的字符是:%c\n",c);
    
    fseek(fp,-1,SEEK_CUR);
    c = fgetc(fp);
    printf("读取到的字符是:%c\n",c);


    //fseek(fp,-2,SEEK_END);
    fseek(fp,-2,2);
    c = fgetc(fp);
    printf("读取到的字符是:%c\n",c);
    
    //移动读写位置到文件的开头
    rewind(fp);
    printf("开始的读写位置是:%ld\n",ftell(fp));


    //3.关闭文件
    fclose(fp);
    return 0;
}

 



例子2

//定义员工结构体,实现信息的存储和读取
#include <stdio.h>


typedef struct Employee
{
    int id;
    char name[20];
    int salary;
}Employee;


int main(void)
{
    //1.打开文件
    FILE* fp = fopen("employee.dat","w");
    if(fp == NULL)
    {
        printf("打开存储文件失败\n");
        return -1;
    }


    //2.输入员工信息并且存储到文件中
    Employee e = {0};
    int i = 0;
    for(i = 0; i < 3; i++)
    {
        printf("请输入第%d个员工的信息:\n",i+1);
        scanf("%d%s%d",&e.id,e.name,&e.salary);
        fwrite(&e,sizeof(Employee),1,fp);
    }
    //3.关闭文件
    fclose(fp);


    //4.再次打开文件
    FILE* fp2 = fopen("employee.dat","r");
    if(fp2 == NULL)
    {
        printf("打开读取文件失败\n");
        return -1;
    }
    
    //5.读取文件信息并且输出到屏幕上
    Employee e2 = {0};
    for(i = 0; i < 3; i++)
    {
        fread(&e2,sizeof(Employee),1,fp2);
        printf("第%d个员工的信息是:%d %s %d\n",i+1,e2.id,e2.name,e2.salary);
    }


    //6.再次关闭文件
    fclose(fp2);
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值