菜鸟日记之数组、指针

  • 数组的概念

 由相同类型的多个元素所组成的一种复合数据类型,一次性定义多个相同的变量,并存储到一片连续的内存中。

  • 定义数组的格式

 类型说明符 数组名[整型常量表达式];

eg:

int a[5];//该数组由五个int类型的数据组成

其中,数组名存储的是数组首元素的地址。数组申请的是一片连续的空间,从低地址到高地址依次连续存储每个元素。

  • 数组初始化

在定义时对数组进行赋值,称为数组的初始化。注:若初始化时,列表个数小于数组个数,未赋值的数组成员都被默认赋值为0.

  • 练习题

编写一个程序,不使用格式控制符%x的情况下,将十进制数转换为十六进制数。

/*
将十进制数转化成十六进制数
*/
#include <stdio.h>
int main()

{
    int a;
    printf("请输入:");
    scanf("%d", &a);
    char x[32];//定义一个数组存储十进制数每次对16取余的余数
    int count = 0;//对余数进行计数
    while (a != 0)
    {
        x[count] = a % 16;
        a /= 16;  
        count++;
    }
    printf("count=%d\n",count);
    for (int i = count - 1; i >= 0; i--)//将数组逆序输出,得到十六进制数
    {
        if (x[i] < 10)
        {
            printf("%c", x[i] + '0');//得到的十六进制数在0 ~ 9
        }
        else
        {
            printf("%c", x[i] - 10 + 'A');//得到的十六进制数在 10 ~ 15 (A ~ F)
        }
    }

    printf("\n");
    return 0;
}
  • 字符数组

概念:专门用于存放字符的数组,称为字符数组。

char s1[5] = {'a', 'b', 'c', 'd', 'e'};       // s1存放的是字符序列,非字符串
char s2[6] = {'a', 'b', 'c', 'd', 'e', '\0'}; // s2存放了一个字符串

char s[6] = {"abcde"}; // 使用字符串直接初始化字符数组
char s[6] =  "abcde" ; // 大括号可以省略

  • 数组元素解引用

通过对数组元素解引用,可以获取地址空间里面的数据。

eg:

 

 int a = 10;
    printf("%d\n",a);

    printf("%p\n",&a);
    // * 表示将地址里面的内容取出,我们把它称为解引用
    printf("%d\n",*(&a));

    //--------------------------
    char Array[5] = {'j','a','c','k'};
    printf("%c\n",Array[0]);
    printf("%c,%c\n",*(Array+0),*(&Array[0]));
    printf("%c,%c\n",*(Array+1),*(&Array[1]));
    printf("%c,%c\n",*(Array+2),*(&Array[2]));
    printf("%c,%c\n",*(Array+3),*(&Array[3]));

[ ]的作用就是解引用,Array[0]等价于*(Array+0)

  • 多维数组

多维数组,简而言之,就是一维数组的集合

eg:

char buf [2] [5] ={"jack","rose"};//该二维数组有两个元素,每个元素又由五个元素组成,或者该二维数组由两个一维数组组成,一维数组有五个元素。

  • 二维数组解引用

// 二维数组初始化字符串
char buf1[2][5] = {"jack","rose"};
printf("%s,%s\n",&buf1[0][0],buf[0]);
printf("%s,%s\n",&buf1[1][0],buf[1]);

// 取二维数组中的某个字符
printf("%c,%c,%c,%c\n",buf1[0][1],*(&buf1[0][1]),*(buf1[0]+1),*(*(buf1+0)+1));//输出'a'
printf("%c,%c,%c,%c\n",buf1[1][2],*(&buf1[1][2]),*(buf1[1]+2),*(*(buf1+1)+2));//输出's'

  • 数组的万能拆解法
  • 任意的数组,不管有多复杂,其定义都由两部分组成。
    1 部分:说明元素的类型,可以是任意的类型(除了函数)
    1 部分:说明数组名和元素个数

eg:

int a [ 4 ]; // 2 部分: a[4]; 1 部分: int
int b [ 3 ][ 4 ]; // 2 部分: b[3]; 1 部分: int [4]
int c [ 2 ][ 3 ][ 4 ]; // 2 部分: c[2]; 1 部分: int [3][4]
int * d [ 6 ]; // 2 部分: d[6]; 1 部分: int *
int ( * e [ 7 ])( int , float ); // 2 部分: e[7]; 1 部分: int (*)(int, float)
  • 指针

  • 指针的概念:一个用于存储内存地址的变量。
  • 指针的定义:
指向的对象的类型 * 变量名 ;
eg :
// 有一个整型变量 a, 定义一个指针 p 来保存 a 的地址
int * p ; // 整型指针
char* p1 ; // 字符型指针
double * p2 ;
  • 指针的赋值:赋给指针的地址,类型需跟指针的类型相匹配。
int a = 100 ;
int * p = & a ;
char b ;
char * p1 = & b ;
  • 野指针

概念:指向一块未知区域的指针,被称为野指针。野指针是危险的。
危害:
1. 引用野指针,相当于访问了非法的内存,可能会导致段错误( segmentation fault
2. 引用野指针,可能会破坏系统的关键数据,导致系统崩溃等严重后果
产生原因:
1. 指针定义之后,未初始化

2. 指针所指向的内存,被系统回收

  • 数组指针

概念:本质上是一个指针,指向的对象是数组

定义格式:eg:char a [3][5]={"jack","rose","ken"};

char (*p) [5]=a;//此时p为一个数组指针

  • 指针数组

概念:本质上是一个数组,数组中存储的是指针

定义格式:eg:char a [3][5]={"jack","rose","ken"};

char *p [3]={"jack","rose","ken"};//此时p为一个指针数组

  • 指针常量

概念:本质上是与一个常量,指针类型的常量。

本身不可更改,但是指向的空间可以更改
int a = 1, b = 1;
int* const p = &a;// p 此时是一个指针常量,本身不可改,指向的对象可改 要记得初始化
  • 常量指针

概念:是一个指针变量, 指向的对象不可更改

int a = 1;
int const *p;// 常量指针:指向的对象不可改, 本身可改
p = &a;
//*p = 100;
a = 100;
printf("a = %d\n", a);
const int *p;// // 常量指针:指向的对象不可改, 本身可改
注:观察const的位置,离谁近谁就不可更改。
  • 指针运算
指针作加减的问题:
p + i (p 是一个指针, i 是一个整数 ) 不是简单地加减数值,
而是加减 i 个指向单元的长度 .
指向的单元的长度:指向的对象类型所占的空间大小
注意:指针作加减还是指针
  • 练习

字符串去重

/*
华为笔试题:字符串去重
*/
#include <stdio.h>
#include <string.h>
int main()
{
    char str[128] = {0};
    printf("请输入字符串:");
    gets(str);
    int num = strlen(str);
    printf("num:%d\n", num);
    for (int i = 0; i < num; i++)//遍历数组中的每个元素
    {
        for (int j = i + 1; j < num; j++)//从i+1开始遍历
        {
            if (str[i] == str[j])//如果两个元素相同
            {
                for (int k = j; k < num; k++)
                {
                    str[k] = str[k + 1];//从 下标k开始移位,后面一位覆盖前面一位的数据
                }
                str[num]=0;
                num--;//字符长度减一
                j--;
            }
        }
    }
    for (int i = 0; i < num; i++)//循环输出去重后的字符数组
    {
        printf("%c", str[i]);
    }
    printf("\n");
    return 0;
}
  • 30
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值