一维数组二维数组与字符数组

1. 数组的基本用法

1.1 概念

数组(Array)是有序元素序列

若将有限个类型相同的变量的集合命名,那么这个名称为数组名。

重点必须是类型相同和连续的变量集合

1.2 定义格式

存储类型 数据类型 数组名[元素的个数];

例如:(auto) int a[5];

数组名:代表数组的首地址,也就是第一个元素的地址。a是地址常量,不能为左值,不能被赋值。

数组定义方法:

(1) 数组名定义规则跟变量名相同,遵循标识符定义规则

(2) 数组名后使用方括号括起来的常量表达式表示元素个数。

(3) 常量表达式中可以包含常量和符号常量(宏定义),不能包含变量。

1.3 访问元素

数组名[下标];

注意:数组元素下标从0开始

例如:

访问第一个元素:a[0];

访问第n个元素:a[n-1];

注意数组越界问题:

特点:

数据元素的数据类型相同

内存连续

注意:

1). 数组的数据类型就是数据元素的数据类型

2). 数组名要符合标识符的命名规则

3) . 在同一个函数中,数组名不要与变量名相同

例如:

int a[5];

int a; //错误

4). 下标从0开始的,到n-1结束

例如:

2. 一维数组

一维数组、二维数组

2.1 一维数组的概念

只有一个下标的数组。

定义格式:存储类型 数据类型 数组名[元素个数];

访问元素:数组名[下标], 下标从0开始。

数组名:数组首地址,也就是第一个元素的地址。

2.2 初始化

(1) 定义时全部初始化

int a[5] = {1, 2, 3, 4, 5};
    printf("%d\n", a[0]);
    printf("%d\n", a[1]);
    printf("%d\n", a[2]);
    printf("%d\n", a[3]);
    printf("%d\n", a[4]);

(2) 定义时部分初始化,未初始化的元素值自动为0。

int a[5] = {1, 2}; //1 2 0 0 0

    printf("%d\n", a[0]); //1
    printf("%d\n", a[1]); //2
    printf("%d\n", a[2]); //0
    printf("%d\n", a[3]); //0
    printf("%d\n", a[4]); //0

(3) 未初始化:只定义不赋值,需要单个元素赋值。(不然局部变量为随机值)

int a[5];
    a[0] = 1;
    a[1] = 2;
    a[2] = 3;
    a[3] = 4;
    a[4] = 5;

    for(int i=0; i<5;i++)  //i的值循环为: 0 1 2 3 4 5(到5不满足循环条件出循环)
        printf("%d\n",a[i]);  //循环打印:a[0] a[1] a[2] a[3] a[4] a[5]

注意数组越界问题:

int a[3] = {4,3,2,1}; //错误,数组越界

a[3] =10; //错误,数组越界了

2.3 定义空数组

● int a[5] = {0,0,0,0,0};

● int a[5] = {0};

● int a[5] = {};

2.4 数组引用

(1) 先定义后引用

(2) 每次只能引用一个数组元素a[i], 如果想引用所有元素可以循环遍历

(3) 打印数组元素地址用%p格式

练习:输入5个数组元素,然后依次打印出来。

int a[5], i;
    for (i = 0; i < 5; i++)
        scanf("%d", &a[i]);
    for (i = 0; i < 5; i++)
        printf("%d\n", a[i]);

2.5 数组的大小

int a[5]; //4*5 = 20
double b[3]; //8*3 = 24
char c[32];  //32

计算方式:

(1) 手算:数元素个数*数据类型大小

(2) 用sizeof: sizeof(数组名);

数组元素的个数 = sizeof(数组名) / 元素大小;

printf("%ld\n", sizeof(a));
    printf("%ld\n", sizeof(a[0]));

练习:计算斐波那契数列前15项并逆序输出

1 1 2 3 5 8 13 21 .....

#include <stdio.h>

int main()
{
    int a[15] = {};
    a[0] = a[1] = 1;

    for (int i = 2; i < 15; i++)
        a[i] = a[i - 1] + a[i - 2];

    for (int i = 14; i >= 0; i--)
        printf("%d ", a[i]);
    printf("\n");
    return 0;
}

2.6 清零函数

2.6.1 bzero() 函数

#include <strings.h>

void bzero(void *s, size_t n);

功能:将内存空间设置为0

参数: s: 要清空的空间首地址

n: 字节大小

返回值:无

#include <stdio.h>
#include <string.h>

int main()
{
    int a[15] = {1, 2, 3};
    bzero(a, sizeof(a));   //从地址a开始,sizeof(a)个字节全部清空

    for (int i = 0; i < sizeof(a) / sizeof(a[0]); i++)
        printf("%d ", a[i]);
    printf("\n");

    return 0;
}

6.2.2 memset()函数

#include <string.h>
void *memset(void *s, int c, size_t n);

功能:将指定内存空间内容设置为0
参数:s:指定内存首地址
    c:要设置的数,一般为0
    n:要设置的内存大小
返回值:无
#include <stdio.h>
#include <string.h>

int main()
{
    int a[15] = {1, 2, 3};
    //bzero(a, sizeof(a)); //从地址a开始,sizeof(a)个字节全部清空
    memset(a, 0, sizeof(a));
    for (int i = 0; i < sizeof(a) / sizeof(a[0]); i++)
        printf("%d ", a[i]);
    printf("\n");

    return 0;
}

2.7 数组的内存分配

int a[5];

a是数组名,也是数组的首地址也就是第一个元素的地址,即&a[0]。

a+1 是数组第二个元素的地址,即&a[1]。

数组再内存中分配如下图:

#include <stdio.h>
#include <string.h>

int main()
{
    int a[5] = {1, 2, 3};
    printf("%p %p\n", &a[0], a);
    printf("%p %p\n", &a[1], a + 1);
    printf("%p %p\n", &a[2], a + 2);

    return 0;
}

通过地址间接取地址表示空间的内容可以通过*:

3. 字符数组

因为C语言没有字符串类型,所以可以用字符数组的形式表示字符串。

概念:类型为字符的数组,也就是数组中每个元素是字符型。可以组成字符串。

3.1 表示形式

(1) 单个字符表示:

char s[5] = { 'h', 'e', 'l', 'l', 'o'}; //sizeof(5) = 5;

char s1[] = { 'h', 'e', 'l', 'l', 'o'}; //sizeof(s1) = 5; //定义数组的同时初始化可以省略元素个数,元素个数取决于你赋值的元素个数。

(2) 用字符串表示,结尾会自动添加上'\0'。

char s2[] = "hello"; //sizeof(s2) = 6

char s3[] = {"hello"}; //sizeof(s3) = 6

char s4[6] ={"hello"}; //sizeof(s4) = 6

char s5[6] ="hello"; //sizeof(s5) = 6 //常用

char s6[] ={}; //错误,如果定义时不赋值则不能省略元素个数

初始化和其他类型数组相同

3.2 输入和输出

3.2.1 输入

(1) scanf:

char s[32] = {};
    scanf("%s", s);

    printf("%s\n", s);

不能输入空格,如果有空格,空格后面的内容不会存入数组。

例如:以下程序输入hello world只能存入hello

如果需要输入空格则:

char s[32] = {};
    scanf("%[^\n]", s);  //除了\n以外所有字符都可以输入到s地址下空间内保存,遇到\n就结束

    printf("%s\n", s);

输入字符串会在后面加上'\0'

(2) 用for遍历输入

char s[6] = "";
    for (int i = 0; i < 6; i++)
        scanf("%c", &s[i]);

(3) gets()

#include <stdio.h>
char *gets(char *s);
功能:从终端获取字符串输入
参数:s:目标字符串首地址
返回值:目标字符串首地址
注意:没有数组越界检查,使用时会报警告。

3.2.2 输出

(1) 用printf()

char s[32]="hello"
printf("%s\n",s);

(2) for循环

char s[32] = "hello";
    for (int i = 0; i < 32; i++)
        printf("%c", s[i]);

(3) puts()函数

int puts(const char *s)
功能:向终端打印字符串
参数:打印的字符串首地址
返回值:字符串长度
char s[32] = "";
    gets(s); //在结尾加个\0,不会接收到回车
    puts(s); //在结尾自动加个回车

例题:看下列程序由哪些错误

char s[10]={};

s[10]="hello"; //错误,数组越界,给字符数组元素赋值不能用字符串

s="hello"; //错误,s地址常量,不能为左值

strcpy(s,"string"); //正确

例: 若准备将字符串“This is a string.”用char s[17]={};记录下 来,错误的输入语句为:

(A)scanf(“%20s”,s); //%[^\n]

(B)for(k=0;k<17;k++)

s[k]=getchar();

(C)while((c=getchar())!=‘\n’)

s[k++]=c;

3.3. 计算字符串长度

char s[32]="hello"; //sizeof(s)=23

3.3.1 用循环统计

char s[32] = "hello";
    int i;
    // int len = 0;
    // for (i = 0; s[i] != '\0'; i++)
    //     len++;
    // printf("%d\n", len);  //5
    i = 0;
    while (s[i] != '\0')
    {
        i++;
    }
    printf("%d\n", i); //5

3.3.2 用strlen()

#include <string.h>
size_t strlen(const char *s);
功能:计算字符串长度
参数:字符串的首地址
返回值:返回字符串实际长度,不包括'\0'在内。
char s[32] = "hello";
    int num = strlen(s);
    printf("%d\n", num); //5

3.3.3 sizeof和strlen的区别

1. sizeof是关键字,strlen是函数。

2. sizeof是计算数据所占空间大小,strlen计算字符串的实际长度。

3. sizeof计算包括\0,strlen计算不包括\0;计算字符串长度时(元素个数省略情况下),sizeof比strlen大1。

练习:

(1)实现字符串大小写的转换

#include<stdio.h>
#include<string.h>
int main()
{
    char s[32]="";
    int len;
    gets(s);
    len=strlen(s);
    for(int i=0;i<len;i++)
    {
        if(s[i]>='A'&&s[i]<='Z')
            s[i]+=32;
       else if(s[i]>='a'&&s[i]<='z')
            s[i]-=32;
    }
    printf("%s\n",s);
}

(2) 将一串字符串进行倒置char buf[32]=”hello”;//olleh

思路:循环长度/2次,每一次前后元素做交换。

#include <stdio.h>
#include <string.h>
int main()
{
    char s[32] = "", t;
    int len;
    gets(s);
    len = strlen(s);                  //5
    for (int i = 0; i < len / 2; i++) //i的值: 0 1
    {
        t = s[i];              //t=s[0]          //t=s[1]
        s[i] = s[len - 1 - i]; //s[0] = s[4]   //s[1]=s[3]
        s[len - 1 - i] = t;    //s[4]=t;      //s[3]=t
        //s[i]和s[len-1-i] 进行交换
    }
    printf("%s\n", s);
}

(3) 在终端输入大写字母、小写字母、空格、数字,分别在终端输出他们的个数

思路: 遍历每个元素然后判断

#include <stdio.h>
#include <string.h>
int main()
{
    char s[32] = "";
    int len, len1 = 0, len2 = 0, len3 = 0, len4 = 0;
    gets(s);
    len = strlen(s);
    for (int i = 0; i < len; i++)
    {
        if (s[i] == ' ')
            len1++;
        else if (s[i] >= 'a' && s[i] <= 'z')
            len2++;
        else if (s[i] >= 'A' && s[i] <= 'Z')
            len3++;
        else if (s[i] >= '0' && s[i] <= '9')
            len4++;
    }
    printf("%d %d %d %d\n", len1, len2, len3, len4);
}
  • 12
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值