C语言 day07 基础知识学习

1.函数和指针的关系
   int a = 123;
   int b = 234;
   int *pa = &a;
   int * pb = &b;
   请用一个函数,修改pa和pb的指向,实参和形参同时修改(day07/01fun.c))。
  备注:在函数中,如果想修改形参一级指针指向,需要传入二级指针。
   注意: 不可以返回局部变量的地址。()
 2.malloc和函数的关系
   案例:
    int*  funmalloc()
    {
      //    int a = 123;
    int* p =(int*)malloc(sizeof(int));
      //    p = &a;
    *p = 123;
    //    return p;     
     }
    注意: 在函数中动态申请的内存,需要在函数内部是否,要么需要返回首地址给调用者,否则会出现内存泄漏。
    注意:
     /* 错误 p所指向的内存空间不允许修改,*p指向一级指针,所以不可以修改一级指针指向(查看大门01fun.c)查看图片(函数和malloc)
      void funconst( const int** p)
     {
    *p = (int*)malloc(sizeof(int));

      }*/
 3.函数指针和指针函数
  指针函数:是返回值是指针的函数 int* fun(int a){ }
  函数指针:是一个指针,指向某一个函数。
  函数指针格式: int (*fun)(int a); fun是指针,指向参数是int 返回值是int的函数,指针的类型 int (*) (int a);  fun指向的类型 int p(int a);
   使用:函数指针名(参数);    例如void (*pfun)(int a) = fun;  pfun(10);
   命别名:  typedef int (*pf)(int a,int b) ;其中pf是指针类型。
                  定义了一个函数指针类型为int (*)(int ,int)
   定义指针变量: 函数指针类型 指针变量= 函数名
   注意:给指针变量赋值,需要匹配相同的指针类型,则返回返回值和函数的参数要和指针类型相匹配,否则是类型不匹配错误。
           一般情况下 函数指针名都会用callback
          当数组作为函数参数时,会隐式转换成指针使用。
    回调函数:把函数指针当做函数参数,系统回调函数是系统自动调用函数。
     
    案例如下:用一个函数计算两个数的加减乘除。
   #include<stdio.h>
   void fun(int a){printf("a = %d\n",a);}
   //定义一个函数指针类型
   typedef int (*pf)(int a,int b) ; 其中 pf是类型,不是变量名
   //可以这么理解typedef int(*)(int a)   pf; pf是别名,是类型,这个格式会语法错误。
    void fun(int a){    printf("a = %d\n",a);}
   int add(int a,int b){    printf("add = %d\n",a);}
   int sub(int a,int b){    return a-b;}
   int jisuan(int a,int b,pf function)//pf function = sub 
   {
    return function(a,b);
               //function只是一个变量,实参是什么则funciotn是什么。
    }
int main(int argc,char *argv[]){
    //pfun是指针名,是变量,不是类型
    void (*pfun)(int a) = fun;
    pfun(10);//实际调用的是fun函数,打印a=10;
    pf pmyfun = add;//pmyfun指向add函数,
       pmyfun(1,3);
    printf("a-b=%d\n",jisuan(2,4,sub));
               return 0;

}
二、数组和指针的关系
   1.数组名: 数组名就是数组的首地址。数组名是const指针,不可以指向其他的位置,只可以指向数组的首地址。int arr[10] = {0},arr 和&arr[0]相同。arr++是错误的。
   练习:定义一个数组,10个指向int类型的指针。int* arr[10];
   2.指针数组: 是数组,在数组中存放 指针  int* arr[10];
   3.数组指针:是指针,指向某一个数组。
            意义: int (*arr)[10]; 一个指针,指向一个数组,数组大小是10个元素;  int (*arr)[10] = &arr;
            定义一个结构体数组指针。指向3个元素的数组。结构体(id ,age)(代码:day07/04arrPointTest.c)
              
 
    4.指针数组指针:是一个指针,指向一个数组,数组中存放的是指针。
     int* (*arr)[10];  stu* (*arr)[10]   ;
     自学: 定义一个数组指针,数组中粗放的是10个元素的数组指针。

     5.二维数组和指针关系
       二维数组名是指针,指向第一行的第一个元素。
       二维数组名加1实际加了一行元素
       二维数组名[下标] 表示某一行的首地址。类型是一维数组,加一实际加了一行。
       二维数组名[行标][列标];某一行行的某一个元素,加一实际加了一个元素的值。
      案例:
     #include<stdio.h>

typedef struct student
{
    int id;
    int age;
}stu;
int main(int argc,char *argv[])
{
    //定义结构体数组
    stu arr[3]={{1,2},{2,3},{3,4}};
   //strcpy 给字符串赋值才用
   //定义一个结构体数组指针。
    stu (*parr)[3] = &arr;
    //如下代码,理解方式如下
    //parr = &arr;   *parr = arr =&arr[0]
    //**parr=arr[0];
    (**parr).id = 123;  //arr[0].id
    (*parr)[1].id =  234;//arr[1].id
    printf("parr = %p\nparr+1=%p\n",parr,parr+1);//加24,指针加一加的是一个类型大小。
   
    stu doubleArr[2][3] = {0};
    parr = doubleArr;
    printf("parr        = %p\n",parr);
    printf("parr+1      = %p\n",parr+1);
    printf("doubleArr   = %p\n",doubleArr);
    printf("doubleArr+1 = %p\n",doubleArr+1); :
    printf("doubleArr[0] = %p\n",&doubleArr[0]);
    printf("doubleArr[0] +1 = %p\n",&doubleArr[0]+1);  加一行
    printf("doubleArr[0][0]+1 = %p\n",&doubleArr[0][0]+1);  加一个

    printf("doubleArr[1]    = %p\n",&doubleArr[1]);
    printf("doubleArr[1][0] = %p\n",&doubleArr[1][0]);

    return 0;

}

三、指针和结构体关系
      1.定义结构体 :struct 结构体名{  };
      2.定义结构体指针:struct student* pa;
      3.案例:
      4.使用:通过结构体指针操作结构体中的成员变量,需要用到->
      5.例子:
         #include<stdio.h>
struct student
{
    int id;
    int age;
    char name[10];
};

int main(int argc,char *argv[])
{
    struct student danny;
    struct student huqing;
    struct student* pd = &danny;
    danny.id = 123;
    pd->age = 12;
    //pd.id = 123; 错误
    pd=&huaqing;
    pd->id = 12;
    printf("%d\n",huaqing.id);
    printf("%d\n",pd->id);
    

    return 0;

}
      案例:定义一个结构体指针数组,有3个学生信息(int id;int age;char name[10];)请通过scanf输入的方式对结构体数组进行赋值。
         #include<stdio.h>
        #include <stdlib.h>
        typedef struct student{    int id;    int age;    char name[10];}stu,*pstu;
      //这么理解typedef struct student* pstu;
      //这么理解typedef struct student  stu;

      int main(int argc,char *argv[]){
    pstu pa[3] = {0};//等价于struct student* pstu
      pa[0] = (pstu)malloc(sizeof(stu)*3);
    printf("请输入学生信息(id,age,name)");
    scanf("%d %d %s",&(pa[0]->id),&(pa[0]->age),pa[0]->name);
    printf("%d\t%d\t%s\n",pa[0]->id,pa[0]->age,pa[0]->name);
    return 0;
}
      
四、指针和字符串的关系
   1.字符串的保存方式
         字符串数组: char arr[10] = "abc";
         字符串指针: char * p = "bac";
   2.字符指针指向的是字符串的首地址,第一个字符的地址
    3.相同的字符串常量在内存中只会存储一份,但凡有字母不一样则是不同的字符串。
   
五、文件操作
    1. 文件存在磁盘中,是长期存储的。
     2.使用:一般用于写日志文件,日志是程序运行中的各种信息,当程序出现bug时定位问题的位置。一般日志文件都是.log结束,和txt文件一样。
     3.文件可以长期保存信息,比如passwd文件。
     文件:存储在外部介质上的数据的集合,操作系统管理数据的最小单位。长期存储,不会因为断电而丢失,分为文本文件和二进制文件。
     4.读文件:从磁盘上的文件中读取到计算机内存中
        写文件:从计算机内存中的内容写入到文件中。
     5.文件操作四步骤(文件FILE,和文件操作相关的函数是以f开头)
        1> 打开文件:fopen
         FILE *fopen(const char *path, const char *mode);
         作用:打开文件或者创建文件
         参数: path 需要打开或者创建的文件路径,默认是当前目录下,也是字符串
                    mode:打开或者创建的模式,是字符串
         返回值:FILE的指针,文件指针,保存的是文件的基本信息(文件大小等)后续所有的函数操作都需要用到文件指针FILE*
          模式如下:
       r      只读的方式打开文件.文件指针在文件的开始位置,如果文件不存在则打开失败

       r+ 以读写的方式打开文件,指针在文件开始的位置.如果文件不存在则打开失败

       w   以写的方式打开文件,文件的长度初始化成0,所有内容会清空.如果文件不存在则创建.

      w+ 读写的文件打开文件,如果文件存在则清空,不存在则创建
      a      追加(只写)的方式打开文件,文件不存在则创建,光标在文件末尾;

       a+   读写的追加方式打开文件,光标在文件末尾,如果文件不存在则创建,存在不会清空。
    
           读写文件:fgets fputs fgetc fputs fscanf fprintf fread   fwrite
           文件偏移:ftell  fseek  rewind
           文件关闭:fclose
            int fclose(FILE *stream);          
            作用:关闭文件
            参数:stream是文件指针,是fopen的返回值。


作业:
void strcat1(char *a ,const char *b)
{
    int n,m,i,j;
    n=strlen(a);
    m=strlen(b);
    for(i=n,j=0;i<n+m;i++,j++)
    {
        a[i]=b[j];
    }
    a[i]='\0';

}

int main(int argc,char *argv[])
{
    char W[100];
    char M[50];
printf("请输入两个字符串!\n");
scanf("%s %s",W,M);
strcat1(W,M);
printf("之后:%s\n",W);
return0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值