2023/7/19 -- C语言基础

  作业:

  1. 整理思维导图
  2. 使用数组指针完成二维数组中元素的输入和输出
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    int main(int argc, const char *argv[])
    {
    	int a[3][3] = {0};
    	int (*p)[3] = a;
    	int i = 0;
    	int j = 0;
    	for(i = 0;i < 3;i++){
    		for(j = 0;j < 3;j++){
    			scanf("%d",*(p+i)+j);
    		}
    	}
    	for(i = 0;i < 3;i++){
    		for(j = 0;j < 3;j++){
    			printf("%-2d",*(*(p+i)+j));
    		}
    		printf("\n");
    	}
    	return 0;
    }
  3. 复习从指针开始的内容

【5】指针的运算

指针保存内存地址,所以指针的某些运算没有意义

指针常见的运算,算术运算:+、-,赋值/混合赋值运算,自增自减,关系运算:判断是否是相同的地址,

指针的偏移量:指的是指针,进行加减运算和自增自减运算时,偏移的字节个数(只和数据类型有关)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, const char *argv[])
{
    int a=100;
    int *p = &a;
    printf("p=%p\tp+1=%p\n",p,p+1);  //dc   e0,因为指针是int类型,偏移4个字节
    printf("--p=%p\n",--p);  //让指针p指向前四个字节的空间,向前偏移四个字节


    //关系运算==,!=,>,<
    int b = 79;
    int *p1 = &b;
    int *temp;   //野指针

    if(p==p1)
    {
        printf("p和p1指向同一片空间\n");
    }
    else if(p!=p1)
    {
        printf("p和p1指向不同的空间\n");
    }

    temp = p;  //让temp和p指向相同的空间
    p = p1;
    p1 = temp;
     
    if(p1==temp)
    {
        printf("p1和temp指向同一片空间\n");
    }
    if(p>p1)
    {
        printf("p1指向的空间在p的前面\n");
    }

    return 0;
}

【6】大小端存储问题

小端存储:数据低位存放在地址低位,生活中大部分的计算机都是小端存储

大端存储:数据高位存放在地址低位,网络通信

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, const char *argv[])
{
    int a = 0x12345678;

    char *p = &a;    //隐式强转,偏移量是1Byte
    //int *p1 = &a;    //p1的算术运算,偏移量是4Byte
    
    if(*p==0x78)
    {
        printf("小端存储\n");
    }
    else if(*p==0x12)
    {
        printf("大端存储\n");
    }
    return 0;
}

【7】一维数组和指针结合

数组名是数组的首地址

[i]先偏移i个偏移量,再解引用*

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, const char *argv[])
{
    int arr[5]={19,89,100,8,9};
    
    int *p = arr;    //arr本身就是数组的首地址
 //指针指向的是数据的首地址
 p = &arr[0];
 

    //p+i<==>arr+i
    
    /*for(int i=0;i<5;i++)
    {
        printf("%d\n",p[i]);
    }*/

    printf("arr=%p\tp=%p\n",arr,p);
    printf("arr+1=%p\tp+1=%p\n",arr+1,p+1);
    printf("arr+1=%p\tp+1=%p\n",arr+2,p+2);
    printf("&arr[3]=%p\tarr+3=%p\n",&arr[3],arr+3);
    //printf("arr++=%p\tp++=%p\n",arr++,p++);   //error,arr是一个地址常量不能自增,p虽然只想arr数组,但是p是变量,p++只是让p向后偏移了
    

 printf("%d\n",*(&arr[3]));
    printf("%p\n",&(*(p+3)));   //*和&,可以互相抵消
    printf("%p\n",&arr[3]+1);   //&arr[4]
    
    //值:*(p+i),p[i],arr[i],*(arr+i)    p[i]只出现在指针指向数组时,通过下标的访问
    //地址:p+i,arr+i

    
    //*(p+i)<==>*(arr+i)
    //arr[i]<==>p[i]   [i]<==>先偏移i个偏移量,再解引用*    
    return 0;
}
练习:

1、使用指针,完成冒泡排序

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, const char *argv[])
{
    int arr[5];
    int *p = arr;   //定义了一个指针p指向数组arr
    //指针变量保存的是内存地址,使用数组中元素的首地址赋值给指针变量p
    
    int i,j;
    for(i=0;i<5;i++)
    {
        scanf("%d",p+i);   //p+i表示数组中下标为i的元素的地址
    }

    int temp;
    //冒泡排序
    for(i=1;i<5;i++)
    {
        for(j=0;j<5-i;j++)
        {
            if(*(p+j)>*(p+j+1))
            {
                temp = *(p+j);
                *(p+j) = *(p+j+1);
                p[j+1] = temp;
            }
        }
    }

    for(i=0;i<5;i++)
    {
        printf("arr[%d]=%d\n",i,*(p+i));
    }

 
    return 0;
}

2、终端输入字符串,使用指针实现,字符串的逆置

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, const char *argv[])
{
    char str[100];
    gets(str);
    char *p = str;
    int len=strlen(str),i;
    char temp;   //逆置私服穿,需要char类型的temp中间变量

    /*for(i=0;i<len/2;i++)
    {
        //实现字符串的逆置
        temp = *(p+i);
        *(p+i) = *(p+len-1-i);
        *(p+len-1-i) = temp;
    }*/

    char *end = p+len-1;  //尾指针,指向字符串中最后一个字符
    while(end>p)
    {
        temp = *p;
        *p = *end;
        *end = temp;
        p++;
        end--;
    }

    p = str;   //重置p,让p重新指向str
    puts(p);

    return 0;
}

3、终端输入字符串,使用指针,完成删除字符串中的空格

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, const char *argv[])
{
    char str[100];
    gets(str);
    int len = strlen(str);
    printf("%ld\n",len);

    char *p = str;
    int i=0,j=0;
    //循环遍历字符串中的每一个字符
    while(*(p+i))
    {
        if(*(p+i)!=' ')
        {
            *(p+j) = *(p+i);
            j++;
        }
        i++;
    }
    //拿结尾的'\0'
    *(p+j) = *(p+i);    //此时*(p+i)=='\0'

    //可以直接puts(p)的原因:p没有移动过
    puts(p);

    return 0;
}

【8】指针和一维字符数组

本质上和指针指向一维整形数组一样,只是数据类型从int变成char
char str[100];
char *p = str;

指针直接指向字符串常量:
char *p1 = "hello world";
char *p2 = "hello world";
//p1和p2指向相同的地址,因为同一个字符串常量,只会在.ro段中存在一份     

*(p1+3)='9';   //段错误,修改.ro段的只读内容

内存分区:

练习:

1、使用指针实现,strlen、strcpy、strcat和strcmp。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, const char *argv[])
{
    //strcpy功能
    char str[50]="";
    char str1[]="world";

    //定义两个指针指向字符串
    char *p = str;
    char *p1 = str1;

    gets(str);
    puts(str);

    //strcpy是源字符串中的每一位都拷贝给目标字符串
    while(*p1)
    {
        *p = *p1;
        p++;
        p1++;
    }
    *p = *p1;

    puts(str);

    return 0;
}

 //strcmp
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, const char *argv[])
{
    //实现strcmp的功能,不需要考虑长度
    char str[]="hello";
    char str1[]="hqllo";

    char *p = str;
    char *p1 = str1;

    while(*p==*p1&&*p!='\0')
    {
        p++;
        p1++;
    }
    int ret = *p-*p1;
    
    if(ret>0)
    {
        printf("str>str1\n");
    }
    else if(ret<0)
    {
        printf("str<str1\n");
    }
    else
    {
        printf("str==str1\n");
    }
    return 0;
}

【9】指针和二维数组

一级指针不能指向二维数组的

因为偏移量不一样,一级指针的偏移量:一个数据类型的大小

二维数组的偏移量:一整行元素

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, const char *argv[])
{
    int arr[][3]={1,2,3,4};
    int *p = arr;
    printf("p=%p\n",p); //0x20
    printf("p+1=%p\n",p+1); //0x24
    printf("arr=%p\n",arr);   //0x20
    printf("arr+1=%p\n",arr+1);  //0x2C
    //二维数组的数组名是一个行指针,算数运算时,操作一行元素
    //arr[i][j]
    return 0;
}

【10】数组指针

本质是一个指针,指向一个数组

数组指针常用于指向二维数组

存储类型 (*数据类型)[数组指针指向的数组的长度] 指针名;
//加()为了表示作为指针的优先级是最高的

二维数组的数组名,是一个行指针,行指针降级一次会变成列指针,列指针是指向单个元素的
数组指针,指向一个数组的空间,也是一个行指针,降级一次变成列指针,列指针是指向单个元素的
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, const char *argv[])
{
    int arr[2][3];
    int (*p)[3]=arr;
//arr[i][j]

    int i=1,j=0;
    printf("%p\n",arr[i]);
    printf("%d\n",*(p[i]+j));   //arr[i][j]
    printf("%p\n",*(p+i));
    printf("%p\n",arr[i]+j);
    printf("%d\n",*(*(arr+i)+j)); //<==>*(p[i]+j)
    printf("%p\n",*p);
    printf("%d\n",**p);   //arr[0][0]

    //[i] <==> 先偏移i个偏移量,再解引用
    return 0;
}

【11】指针数组

本质是一个数组,保存的是指针

用于主函数的外部传参

int (*指针名)[二维数组的列数];  //数组指针

存储类型 数据类型 *数组名[长度];   //指针数组

char str[3][9]={"zhangsan","lisi","wangwu"};
//能存下,造成空间的浪费

char *p1="zhangsan";
char *p2="lisi";
char *p3="wangwu";
char *arr[3]={p1,p2,p3};
arr数组名,
char *[3], //能存3个char*的数组

argc和argv[]接收的是,主函数从命令行接收的外部传参,./a.out后面跟的数据

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, const char *argv[])
{
    char *p1="zhangsan";
    char *p2="lisi";
    char *arr[2]={p1,p2};   //定了一个能存2个char*类型的指针数组,并使用p1和p2初始化数组

    /*printf("%d\n",argc);
    printf("%s\n",argv[0]);  //访问argv数组中的第一个元素
    */

    int i;
    //argc记录外部传参的个数
    //argv保存指向外部参数的指针
    for(i=0;i<argc;i++)
    {
        printf("%s\n",argv[i]);
    }
    return 0;
}
练习:

1、使用命令行的外部传参,实现个位数的加减、乘除运算。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, const char *argv[])
{
    //通过命令行传参实现计算器
    /*switch(*argv[2])
    {
    case '+':
        printf("%d\n",(*argv[1]-'0')+(*argv[3]-'0'));
        break;
    case '-':
        printf("%d\n",(*argv[1]-'0')-(*argv[3]-'0'));
        break;
    case '/':
        printf("%d\n",(*argv[1]-'0')/(*argv[3]-'0'));
        break;
    case '*':
        printf("%d\n",(*argv[1]-'0')*(*argv[3]-'0'));
        break;

    }*/

    int a = *argv[1]-'0';
    int b = *argv[3]-48;
    if(0==strcmp(argv[2],"+"))
    {
        printf("%d\n",a+b);
    }
    else if(0==strcmp(argv[2],"-"))
    {
        printf("%d\n",a-b);
    }
    return 0;
}

【12】atoi

把字符串转换成对应的整形数据

需要导入头文件:
    #include <stdlib.h>
int atoi(const char *nptr);
参数:
    const char *类型的指针
功能:
    把字符串转换成相应的整形

【13】二级指针

一级指针:指向数据,保存数据的地址

二级指针:指向一级指针,保存一级指针的地址

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值