C语言-------第四次笔记


指针

指针的定义
指针的类型
指针的指向内容
指针的运算
数组与指针
指针与函数

动态分配内存

结构体

文件读写

头文件与实现文件实例之计算器

文件操作训练之字符串查找


指针的定义

  • 指针是一个变量
  • 指针只能存地址
  • 指针占据8个字节空间
int main(){
int *a;
char
printf("a的大小:%d\n", sizeof(a)); printf("a的地址:%p\n",a); printfC'XdXn", sizeof(b));
}

输出:

a的大小:8

a 的地址:0000000000000001


指针的声明

int *p;
char *p;
int *arr[5];
int **p;

  • 指针的声明相对于普通变量的声明多了一个一元运算符、”。
  • 运算符”是间接寻址或者间接引用运算符。当它作用于指针时,将访问指针 所指向的对象。
  • P是一个指针,保存着一个地址,该地址指向内存中的一个变量;下则会访问 这个地址所指向的变量。
  • 声明一个指针变量并不会自动分配任何内存。
  • 在对指针进行间接访问之前,指针必须进行初始化:或是使他指向现有的内 存,或者给他动态分配内存,否则这个指针会变成野指针。

指针初始化

int a = 5; int *p = &a;
  • " * "定义的时候表明是一个指针变量,使用的时候表示取地址的值
  • " & "取某一个变量地
int *p;
p = (int *)malloc(sizeof(int) * 10) free(p);
  • 指针的初始化实际上就是给指针一个合法的地址,让程序能够清楚地知道指针的指向,而 不至于变为野指针

指针的类型

  • 判断指针类型的方法:去掉星号*和变量名就是指针的类型

  • P 与 * 结合,所以说明P是一个指针,然后再与int结合,说明指针所指向的内容的类型为 int 型.

  • int p[3]
    P与[]结合.说明P是一个数组,然后与int结合,说明数组里的元素是整型的.

  • int *p[3];
    P与[ ]结合因为其优先级比" * "高,所以 P 先是一个数组,然后再与” * ”结合。说明数组里的元素 是指针类型,然后再与int结合,说明指针所指向的内容的类型是整型的.

  • int(*p)[3];
    P 与 * 结合.说明 P 是一个指针然后再与[ ]结合 (与 ”()” 这步可以忽略,只是为了改变优先级),说明指针所指向的内容是一个数组,然后再与int结合,说明数组里的元素是整型的.

  • int **p;
    P 与 ** 结合,说是 *P 是一个指针,然后再与 * 结合,说明指针所指向的元素是指针,然后再与 int 结合,说明该指针所指向的元素是整型数据.

  • int p(int)
    P 与 () 结合.说明 P 是一个函数,然后进入 () 里分析,说明该函数有一个整型变量的参数, 然后再与外面的int结合.说明函数的返回值是一个整型数据.

  • int (*p)(int);
    P 与指针结合,说明 P 是一个指针,然后与 () 结合,说明指针指向的是一个函数.然后再与 () 里的 int 结合,说明函数有一个int 型的参数,再与最外层的 int结合,说明函数的返 回类型是整型.


指针的指向内容

  • 指针存储的内容为变量的地址,也就是说指针的是一个指向作用,指向变量所存储的内容
int main(){
 int a = 5; 
int *p = &a;
 return 0;
}

指针的运算

  • 指针+(-)整数
    可以对指针变量P进行P++、p--、p + i 等操作,所得錯果也是一个指针,只是指 针所指向的内存地址相比于p所指的内存地址前逬或者后退了 i (对应指针指向类 型对应大小)个操作数。
int main()(

char a = *1'; char *p - &a; printf("p:%p\n",p);

P++;

prirrtf("p++之后始果:%p\n",p);

P—;

printf("p--之后塔果:Xp\n",p); 叶5;

printf("p+5之后结果:%p\n"/p); return 0;

}
输出:
p:000000000062FE17
 p++之后结果:0e000e0eee62FEi8
 p--之后结果:0e0000000e62FE17
 P+5之后结果:0000G0000062FE1C

P是一个char类型的指针,指向内存地址0062FE17处。则 p++ 将指向与 p 相邻的下一 个内存地址,由于 int 型数据占4个字节,因此 p++ 所指的内存地址为1000000b。其余类推,不过要注意的是,这种运算并不会改变指针变量 p 自身的地址,只是改变了它所 指向的地址.
**********************************************************************************8

数组与指针

  • 数组的数组名其实可以看作一个指针,因为数组名是指向数组的第一个元素,上面 num数组指向的也就是第一个元素1,数组名本身是没有占有内存的
int array[10]={0,l,2,3»^,5,6,7,8,9},value; value-array[0];

value=array[3];

value=array[4];

另外一种解释是将数组名指向数组的第0个单元,那么(array+n)也就是一个指向数组 里的第n个单元的指针

P 指向的是数组的首地址,也就是数组的第一个元素,那么 P++ 之后也就是对指针 P 前进了 4(int类型)个操作数,而数组是分配了连续空间,所以相对地址是加减也就是数组元素 的位置变换


指针数组

  • 指针数组.是一个数组,数组中的每一个元素都是指针
    对于上面的定义和初始化,data是指针数组的名字,也就是指向指针数组首元素的指 针.(指针的指
    针).data[i]是data这一个数组的第i个元素,也就是一个指向int的指针 指针可以当成数组来使用。

数组指针

  • 数组指针,是一个指针,它指向一个数组
    数组作为参数传入函数的时候,对于被调用的函数参数就是指针

指针与函数

  • 函数指针是指向函数的指针变量
  • 通常我们说的指针变量是指向一个整型、字符型或数组等变量,而函数指针是指向函数
  • 函数指针可以像一般函数一样,用于调用函数、传递参数,函数指针声明
  • 函数指针变量可以作为某个函数的参数来使用的,回调函数就是一个通过函数指针调用的 函数。也就是
    说回调函数是由别人的函数执行时调用你实现的函数。

动态分配内存

  • 为什么需要动态分配内存:
    1.存储的数据 需要延长生命周期
    2.一个指针变量需要存储数据,变量本身只能存地址
    不能存数据,需要分配内存空间来存储数据
 #include 
 #include 
int main(){
    //char name[100] = {};
    
    //如果使用指针变量接收数据
    //必须先为这个指针变量分配一片指向的内存空间
    //有内存空间 才能存数据 
    
    //导入头文件stdlib.h 
    //使用malloc (memory alloc)申请内存空间 
    char *name ;
    name = (char *)malloc(10*sizeof(char));
    if(name == NULL){
        // 申请内存失败 
        exit(EXIT_FAILURE); 
    }
    scanf("%s", name);
    printf("%s\n",name); 
    
    //使用realloc动态改变已经分配内存的大小 
    //增加或者减少 
    name = (char *)realloc(name, 20*sizeof(char));
    if(name == NULL){
        //退出之前必须将之前分配的内存释放掉
        free(name); 
        exit(EXIT_FAILURE);
    }
    
    //使用完毕必须自己手动释放内存
    free(name); 
    return 0;
}

结构体

  • 为什么要使用结构体
    int , float 只能存单个数据
    int num[] 可存储多个数据 但必须同种类型
    需要一种类型 可以保存多种数据
  • 结构体是什么
    int char
    一种结构体
  • 如何定义结构体类型
    注意定义结构体类型时 内部类型不能赋初值
     struct student{
     
     };
  • 结构体内存计算方式
    对齐方式 小类型 -》大类型对齐
  • 指针使用->访问元素
    p->
#include 

int main(){
    struct person {
        int age;
        float height;
    }; 
 return 0 ;
 }

文件读写

// 创建文件
#include 

int main (){
   FILE*fp =fopen( "C:\\Users\\33573\\Desktop\\test.txt","a+");
   //r:只能读;w:只能写且要覆盖前面的内容;a:可写可读 
   return 0;
}

//打开文件
// 写入内容
   fputc fgetc
   fputc('a',fp);
   fgetc(fp);

// 重新定位文件指针的位置 
   fseek(fp,3,SEEK_SET);//SEEK_SET;SEEK_SET;SEEK_END
   fputs("hello world",fp);
// 按照一定格式写入内容
 int num[5] = {1,2,3,5,5};
   fwrite( num,sizeof(num),1,fp);//写入的是二进制,视频,音频 结构体 
// 读取内容
   fdeto(fp);一行一行读取
   int num2[5]  = {};
   freed(num2,sizeof(num2),1,fp);
      for (int i = 0;i<5;i++){
      printf("%d",num2);
}
//关闭 
   fclost(fp);
   
*/ 
#include 
int main (){

FILE*fp =fopen( "C:\\Users\\33573\\Desktop\\test.txt","a+");
int num[5] = {1,2,3,5,5};
   fwrite( num,sizeof(num),1,fp); 
//fputs("hello world",fp);
  return 0;
}


头文件与实现文件实例之计算器

  1. 程序的入口函数
    main.cpp 为了让阅读者知道我这里面写的是入口函数
  2. 将不同的功能模块用不同的.h.cpp 来封装
    .h 头文件 函数声明 (不能实现)
    .cpp .c 实现文件 函数的具体实现{}
  3. 导入头文件进行使用

主函数 :头文件

#include 

//1.程序的入口函数 
//main.cpp 为了让阅读者知道我这里面写的是入口函数

//2.将不同的功能模块用不同的.h.cpp 来封装
//.h  头文件  函数声明 (不能实现)
//.cpp .c  实现文件 函数的具体实现{}
// 3. 导入头文件进行使用 
#include "calculator.h" 

int main(){
    int a,b;
    scanf("%d %d" ,&a,&b);
    int result = add(a,b) ;
    
    printf("a + b = %d\n",result);
    
    printf("a + b = %d\n",add(a,b));
    printf("a - b = %d\n",minus(a,b));
    printf("a * b = %d\n",mulitply(a,b));
    printf("a / b = %d\n",devide(a,b));

    
    return 0;
}

实现文件

//1. 先导入需要的头文件
//2.实现这个头文件的 所有方法 
#include "calculator.h" 
//加法
int add(int a,int b){
    return a + b; 
} 
//减法 
int minus(int a,int b){
    return a - b;
}
// 乘法 
int mulitply(int a,int b) {
    return a * b;
    
}
//除法  
int devide (int a,int b){
    if (b == 0){
        return 0;
    }else {
        return a/b;
        
    }
    return 0;
}

头文件里声明函数

#include 

//头文件里声明函数
int add(int a,int b);//加法 
int minus(int a,int b);//加法 
int mulitply(int a,int b) ;//乘法 
int devide (int a,int b);//除法 


文件操作训练之字符串查找

头文件

#include 
#include "myString.h"

/*     
 * fafjalfjasdfjsadlf
 * kfjakfj
 * fslf
 * ksdfjlafjalsf
 */
int main(int argc, const char * argv[]) {
    char sentence[100] = {};
    char word[20] = {};
    
    input(sentence, "请输入语句");
    input(word, "请输入查找的单词");
    
    int count = find(sentence, word);
    printf("出现%d次\n", count);
    return 0;
}

实现文件

#include 
#include "myString.h"

//%s 遇到空格或者\n
//scanf不能输入带空格的字符串
//只能自己定义一个输入语句的方法
void myScanf(char *p){
    int i = 0;
    while (1) {
        char c = getchar();
        if (c == '\n') {
            p[i] = '\0';
            break;
        }
        p[i] = c;
        i++;
    }
}

void input(char *p, char *des){
    //提示用户操作
    printf("%s:", des);
    //输入语句
    myScanf(p);
}

//计算字符串的长度
int length(char *p){
    int i = 0;
    //for (; p[i] != '\0'; i++);
    while (1) {
        if (p[i] == '\0') {
            break;
        }
        i++;
    }
    return i;
}

int find(char *sentence, char *word){
    //1.获取两个字符串的长度
    int sLength = length(sentence);
    int wLength = length(word);
    //2.判断查询的字符串长度是否比句子短
    if (sLength < wLength) {
        return 0;
    }
    /*
     hjako jack ,jac;
     i = 2
     jac
     j = 2
     */
    int start = 0;
    int count = 0;
    for (int i = 0; i < sLength; i++) {
        //记录当前开始的位置
        start = i;
        
        //从当前位置开始去和查找的单词进行比较
        int j = 0;
        for(; j < wLength; j++){
            //判断j对应的值和start+j比较
            if (sentence[start+j] != word[j]) {
                break;
            }
        }
        
        //判断怎么出来的
        if (j == wLength){
            //都相同
            //将i的值定位到start+j的位置
            i = start + j-1;
            
            count++;
        }
    }
    
    return count;
}

导入函数

#include 
#include "myString.h"
void input(char *p,char *des);
int find(char *sentence,char *word);

你可能感兴趣的:(C语言-------第四次笔记)