自学内容网 自学内容网

10_C语言 -数组(常规)

数组

引例

如果我们要在程序中表示一个学生的成绩,我们会使用一个int来表示,如:int score。假如我们要在程序中表示一组成绩,此时我们所学的常规数据类型就无法再表示,这个 时候我们就需要使用到一种新的表现形式,这种表现形式就是我们的数组。

什么是数组

数组是相同类型有序数据的集合。

在这里插入图片描述

数组的特征

  • 数组中的元素被称为数组的元素,是同构的。
  • 数组中的元素存放在内存空间里(如:char ct_name[20]:在内存中申请20块连续 的基于char类型的变量空间)
衍生概念:下标(索引)
  • 下标或索引代表了数组中元素举例第一个元素的偏移位置(距离第一个地址的偏移位置,所以从0开始)。
  • 数组中的元素的地址值,下标越大,地址值越大。(每一块内存空间都有一个独有的内存地址,变量空间以字节为单位进行地址的标注,我们也可以说一个1内存单元=1字节
  • 数组的下标是从0开始。

一维数组

数组的定义

语法:

类型说明符 数组名[数组的容量];

说明:

  • 数组的类型说明符由数组中的元素来决定,也就是元素是什么类型,数组就是什么类型
  • 数组名也是 标识符,我们所说的数组 (名),大家可以理解为数据类型是数组的变量(名)。命名规则于变量名相同。遵循标识符 命名 规则
  • 数组容量也可以叫做元素个数或者常量表达式,表达式必须为整型,==可以包含常量和符号常量,但不能是变量。 ==
int arr[5]; // 常量

#define COUNT 5
int arr[COUNT]; // 符号常量

int arr[800 * 400]; // 常量表达式

类型:代表了数组中元素的类型

容量:数组中能存储多少元素,数组容量可以是常量、常量表达式、符号常量。但必须是整数

深入理解:

  • 定义一个数组,相当于申请了 一个可以容纳所指定元素数量的内存空间。所申请的内存单元是连续的。
  • 定义一个数组,相当于定义了多个匿名的变量,这些变量可以通过 数组名[下标]来标识。

举例:

// 定义一个数组
int arr[10]; // 最小索引:0,最大索引 = 数组元素 个数 -1

经过上面的案例,分析得到:

数组的最大下标 = 数组元素个数(数组容量)- 1
数组元素的访问

原则:数组中的元素不能一次性访问所有元素,只能一个一个的访问。

语法:

数组名[下标]

说明:以上语法,既能实现数组中元素的取,也能够实现数组中元素的存。

举例:

// 定义一个能够容纳10个元素的int数组
int arr[10];
// 给数组的第一个元素进行赋值
arr[0] = 89;
arr[0] = 88;

// 访问数组的第一个元素
int a = arr[0]; // 88

// 问题:以下访问是否正确
int b = arr[10]; // error:下标越界异常

注意:数组元素的访问一定不能越界

案例:

#include <stdio.h>
// 数学库
#include <math.h>

#include <string.h>
#include <time.h>
#include <stdlib.h>

/**
 * 需求:数组案例:利用循环给数组 元素赋值0~9,并且逆序输出。
 */
int main()
{
    // 创建一个数组
    int arr[10];

    // 利用for循环给数组元素赋值
    for( int i = 0; i < 10; i++ )
    {
        arr[i] = i + 10;
    }
    // 逆序 输出
    // 通过一个循环将数组中的每一个元素取出,称之为遍历
    for( int j = 9; j >= 0; j-- )
    {
        printf("%-4d", arr[j]);
    }
    printf("\n");

    return 0;
}
数组的初始化

定义数组的同时,用指定数据来给对应元素赋值。

简化数组 定义后,需要对元素一一赋值操作。

语法:

类型 数组名[容量大小] = {常量1,常量2,常量3...};

注意:

  • 数组可以部分初始化:也就是可以给数组中的前几个元素初始化,未被初始化的元素系统将自动初始化;如果定义数组时未被指定数据容量,则系统会根据初始化元素的个数来决定数组容量。

    // 1.如果 定义数组时只给数组前几个元素初始化,后续剩余元素自动完成初始化
    int arr[10] = {11,12,13,14,15}; // 推荐写法,部分初始化
    int arr[10] = {11,12,13,14,15,0,0,0,0,0};// 等价于上面的写法
    
    // 2.如果定义数组时未指定数组容量,根据初始化 元素的个数量来决定容量
    int arr[] = {1,2,3,4,5}; // 推荐写法,等价于以下写法
    int arr[5] = {1,2,3,4,5};
    

    衍生概念:

    • ==柔性数组:==柔性数组的概念在C99标准,针对结构体的最后一个成员可以是一个未指定大小的数组;

      ​ 广义简单理解:数组容量待定或者待确定的数组,举例:int arr[] = {1,2,3,4,5}

      面试题:

      • 在不知道数组类型的情况下,如何确定数组元素的个数

        int length = sizeof(arr)/sizeof(arr[0]);
        

        说明:

        1. arr就是我们计算的数组本身,sizeof(arr)用来计算该数组中总的字节大小。
        2. sizeof(arr[0])用来计算数组中第一个元素所占的字节大小,因为数组中元素类型相同,所以计算哪一个都行。
        3. sizeof(arr)/sizeof(arr[0])就是用数字中总的字节数除以每一个元素所占的字节数,从而得到元素的个数

        在这里插入图片描述

冒泡排序

向后冒泡

思想:

  1. 一次只排好一个数,针对n个数,最差情况需要 n-1次就可以排好
  2. 每次排序将相邻数据两两比较,将较大或较小的数据向后交换,等所有数据都比较完成,将

较大/较小的数就会出现在最后,这也是该数应该有的位置。

  1. 在余下的数中,再次应用第2步的操作,直到只剩下一个数。

向前冒泡

思想:

  1. 一次只排好一个数,针对n个数,最差情况需要n-1次就可以排好
  2. 每次排序假定第一个元素是最大/最小的,用第一个元素的后面的元素一一与第一个元素比

较,遇到较大/较小的和第一个元素交换,访问完数组的最后一个元素,就排好了一个数;

  1. 在余下的数中,再次应用第2步的操作,直到只剩下一个数。
一维数组案例

案例1:

#include <stdio.h>


/**
 * 需求:一维数组案例:斐波拉契数列n = (n - 1)+(n - 2)。
 */
int main()
{
    int i; // 循环变量
    int f[20] = {1,1}; // 定义一个数组,用来存储数列,默认存储第一位和第二位

    // 计算获取数组的大小,主要用于 遍历数组
    int len = sizeof(f) / sizeof(f[0]);

    // 将生成的序列存入数组
    for(int i = 2; i < len; i++)
    {
        // 给数组元素赋值,从数组的三个元素开始
        f[i] = f[i-1] + f[i-2];
    }

    // 遍历数组
    for( int j = 0; j < len; j++ )
    {
        // 遍历的时候,要求一行显示5个数
        if( j % 5 == 0)
        {
            printf("\n");
        }

        printf("%-6d", f[j]);
    }

    printf("\n");

    return 0;
}

案例2:

#include <stdio.h>


/**
 * 需求:一维数组案例:冒泡排序
 */
int main()
{
    // 创建一个数组,用来存储排序的数列
    int arr[10];
    // i: 外层-比较的轮数,j:内层-每一轮比较的次数,temp:临时变量,用来比较交换的数据
    int i, j, temp;

    printf("请输入:\n");

    int le = sizeof(arr)/sizeof(arr[0]);
    // 循环录入数据
    for( int a = 0; a < le; a++ )
    {
        scanf("%d", &arr[a]);
    }
    printf("\n");

    // 对数组arr使用冒泡排序(注意:我们使用的是标准的冒泡排序)
    // 外层循环:控制比较轮数,轮数 = 数组容量 -1
    for( i = 0; i < le -1; i++ )
    {
        // 每一轮比较的次数
        for( j = 0; j < le - i - 1; j++ )
        {
            // 相邻的两个数比较,满足条件就交换位置
            if( arr[j] > arr[j+1] )
            {
                temp = arr[j];
                arr[j] = arr[j+1];
                arr[j+1] = temp;
            }
        }
    }

    printf("冒泡排序后遍历数组:\n");

    for( int a = 0; a < le; a++ )
    {
        printf("%-4d", arr[a]);
    }

    return 0;
}

案例3:

#include <stdio.h>


/**
 * 需求:一维数组案例:从键盘输入年,月,日,并计算输出是该年的第几天
 */
int main()
{
    // 定义变量:年,月,日,统计总天数,循环变量,用来遍历当前月前面的月份
    int year,month,day,sum,k;
    // 定义一个数组,用来存放1~12月每月的天数
    int t[] = { 31,28,31,30,31,30,31,31,30,31,30,31};

    printf("请输入年月日:");
    scanf("%d.%d.%d", &year, &month, &day);// 2024.12.3

    //
    if((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) // 优先级: 算术>关系>逻辑
    {
        // 先将输入的天记录到总天数
        t[1] = 29;
    }

    // 先输入记录到总天数
    for( k = 0; k < month -1; k++ )
    {
        sum += t[k];
    }

    printf("%d月%d日是%d年的第%d天。\n", month, day, year, sum);

    return 0;
}

二维数组

定义

二维数组本质上是一个行列式的组合,也就是说 二维数组是由行和列两部分组成。二维数组数据是通过行列进行解读.

二维数组可以被视为一个特殊 的一维数组,相当于二维数组又是一个一维数组,只不过它的元素是一维数组。

{3,,5}
{{1,2,3},{4,5,6}} // 数组的元素可以是数组类型
语法
类型 数组名[行数][列数];  

举例:不能省略数组内的数组的大小

int arr1[3][3] = {{11,12,13},{21,22,23},{31,32,33}}; // 二维数组的定义并初始化
int arr1[][3] = {{11,12,13},{21,22,23},{31,32,33}}; // 等价于上面的写法,柔性数组

int arr1[][3] = {{11,12},{21,22,23},{31}}; // 等价于下面写法 (柔性数组,根据最大的元素个数分配)
int arr1[][3] = {{11,12,0},{21,22,23},{31,0,0}}; 

int arr1[][] = {{11,12,13},{21,22,23},{31,32,33}}; // 这种写法会编译报错

注意:在C语言中,二维数组在计算机的储存顺序是按行进行的,即第一维的下标变化慢,第二维的下标变化快。

应用场合

主要应用 在数据有行列要求的情况,比如说我们现在要 存储粤嵌目前在读班级的学生的成绩。

{1,2,3} // 一个班的成绩
{{1,2,3},{4,5,6}}  // 管理两个班的数组
特殊写法
  • 下标可以是整型表达式,如:a[2-1][2*2-1]
  • 下标可以是已经有变量或数组元素,如a[2*x - 1][b[3]][1]
  • 数组元素可以出现在表达式中,如:b[1][2] = a[2][3]/2

注意:使用数组元素的下标应在已定义数组的大小范围内;应注意区别定义 数组大小和引用数组元素的区别。

  • 分行给二维数组赋初值

    int arr[3][4] = {{11,12,13,14},{21,22,23,24},{31,32,33,34}};
    
  • 可以用 将所有数据写在一对花括号内,按照排序对元素赋值

    int arr[3][4] = {11,12,13,14,21,22,23,24,31,32,33,34};
    
  • 可以对部分元素赋初值,其余未赋值部分自动补充0,整型表现形式:0,字符型表现形式:‘\0’,浮点型表现形式:0.0

    int arr[3][4] = {{11},{21,22},{31}};
    
  • 若对全部元素赋初值,自定义 数组时可以省略第1维数组的长度,第2维数组的长度必须指明

    int a[][4] = {11,12,13,14,21,22,23,24,31,32,33,34};
    
  • 在分行赋初值时,也可以省略第1维的长度

    int arr[][4] = {{11,12,13},{0},{0,10}};
    
二维数组的遍历

案例1:

/*************************************************************************
  > File Name:    work11.c
  > Author:       sgc
  > Description:  二维数组的遍历
  > Created Time: 2024年12月04日 星期三 10时29分37秒
 ************************************************************************/

#include <stdio.h>

int main(int argc,char *argv[])
{
    // 创建一个二维数组,经过 论证:二维数组我们必须指定列的大小,行的大小可以省略
    int arr[][3] = {{11},{21,22},{31,32,33}};

    // 获取二维数组的大小,其实就是行数
    int len = sizeof(arr)/sizeof(arr[0]);
    //
    int len1 = sizeof(arr[0])/sizeof(arr[0][0]);

    // 遍历二维数组,因为二维数组是行列式,所以要使用双层循环
    // 先遍历外层数组,获取行
    for( int i = 0; i < len; i++ )
    {
        for( int j = 0; j < len1; j++ )
        {
            printf("%-3d", *(*(arr+i)+j)); // 等价于arr[i][j],(arr[i])[j],*(arr[i]+j)
        }
        printf("\n");
    }

    return 0;
}

案例2:

数组的转置:

/*************************************************************************
  > File Name:    work11.c
  > Author:       sgc
  > Description:  二维数组的-矩阵的转置(就是将一个2行3列转换成3行2列的数组)
  > Created Time: 2024年12月04日 星期三 10时29分37秒
 ************************************************************************/

#include <stdio.h>

int main(int argc,char *argv[])
{
    // 准备两个数组,存放转置前后的数列
    int arr_before[2][3] = {11,12,13,21,22,23};
    int arr_after[3][2] = {0};

    for( int i = 0; i < 2; i++ )
    {
        for( int j = 0; j  < 3; j++ )
        {
            arr_after[j][i] = arr_before[i][j];
            printf("%-3d", arr_before[i][j]);
        }
        printf("\n");
    }
    printf("\n");
    for( int i = 0; i < 3; i++ )
    {
        for( int j = 0; j  < 2; j++ )
        {
            printf("%-3d", arr_after[i][j]);
        }
        printf("\n");
    }
    return 0;
}

字符数组

概念

元素类型为char字符类型的数组往往是用来存储字符串数据的。需要注意的一点是,我们C语言中的字符是字节字符。

字节字符:也就是1个字符占一个字节,在C语言中,我们使用char标识字节。

测试题:

char a = 'A'; // 正确
char b = '1'; // 正确
char c = 65;  // 正确,ASCII码
char d = "A"; // 错误,这是字符串的写法,也是char数组的写法,char d[1] = "A";
char e = '司'// 错误,中文一个字符超过一个字节,中文以字符串的形式存储
语法
char 数组名[容量];
char 数组名[行容量][列容量];

字符数组的语法就是我们前面所学的一维数组和二维数组的语法,只不过数据类型是char而已。

注意:

​ 如果我们的char数组初始化的时候,没有完全赋值的时候,空出来的地方使用\0进行填充。

​ 比如:char c[8] = {'h','e','l','l','o'}等价于char c[8] = {'h','e','l','l','o','\0','\0','\0'}

案例:

/*************************************************************************
  > File Name:    work11.c
  > Author:       sgc
  > Description:  字符数组案例
  > Created Time: 2024年12月04日 星期三 10时29分37秒
 ************************************************************************/

#include <stdio.h>

int main(int argc,char *argv[])
{
    /**     输出一个字符串(I LOVE YOU!)     */
    // 准备一个测试数组 ASCII中码0和32对应的不是同一个意义的空
    char c[12] = {'I',32,'L','O','V','E',' ','Y','o','u','!'};

    // 通过一个for循环进行遍历输出
    for( int i = 0; i < sizeof(c)/sizeof(c[0]); i++ )
    {
        printf("%c", c[i]);
    }

    return 0;
}

案例2:

/*************************************************************************
  > File Name:    work11.c
  > Author:       sgc
  > Description:  字符数组案例
  > Created Time: 2024年12月04日 星期三 10时29分37秒
 ************************************************************************/

#include <stdio.h>

int main(int argc,char *argv[])
{
    /**     输出一个用字符组成的菱形     */
    // 准备数据
    char arr[5][5] = {
            { ' ',' ','*',' ',' ' },
            { ' ','*','*','*',' ' },
            { '*','*','*','*','*' },
            { ' ','*','*','*',' ' },
            { ' ',' ','*',' ',' ' }
    };
    // 遍历数组
    for( int i = 0; i < sizeof(arr)/sizeof(arr[0]); i++ )
    {
        for(int  j = 0; j < sizeof(arr[i])/sizeof(arr[0][0]); j++)
        {
            printf("%c", arr[i][j]);
        }
        printf("\n");
    }

    printf("\n");


    return 0;
}

注意:

1.如果定义时不初始化,元素值 不确定;

char arr1[2]; // 此时属于未初始化,元素值是不确定的(随机的)
char arr2[5] = {'a','b','c'}; // 此时属于不完全初始化,未初始化的时候,用'\0'填充 
字符串和字符串结束标志
说明
  • C语言规定,字符串以字符\0作为结束标志。
  • 编译系统对字符串常量自动加一个\0作为结束标志。
  • 程序中往往通过判断\0来检测字符串是否结束。
  • \0的ASCII码为0,不是一个可显示的字符,是“空操作符”,它什么都不做,不会增加有效字符,仅有一个供判别的标志。
字符数组的多样表示

我们的char数组可以以数组的方式一个个输出每个字符;我们的char数组也可以以字符串的方式整体进行输出所有字符。

/**
* 需求:字符数组→ 字符串
*/
#include <stdio.h>
int main()
{
    // 字符串的第1种表示:
    char s1[] = {'h','e','l','l','o',' ','w','o','r','l','d'};
    // 字符串的第2种表示:
    char s2[] = {"hello world"};
    // 字符串的第3种表示:
    char s3[] = "hello world";
    // 输出字符串,
    printf("%s,%s,%s\n",s1,s2,s3);// hello world,hello world,hello world
}

注意:

  • 字符串的长度于字符数组的长度不一定相同。

  • 利用字符串的常量可以对字符数组进行初始化,但不能用字符串常量为字符数组赋值。

     // 正确演示,利用字符串常量可以对字符数组进行初始化
    char arr1[6] = "hello";
    
    // 错误演示,用字符串常量为字符数组赋值。
    char arr2[6];
    arr2 = "hello";
    
字符数组
字符串的基础操作

在用格式化说明符%s进行输入输出时,其输入输出项均为数组名,但在输入时,相邻两个字符串之间要用空格分隔,系统将自动的在字符串最后加结束符“\0”。在输出时,遇到结束符"\0"作为输出结束标志。

对于字符串的操作,我们需要使用到一些系统提供的函数。

字符串的输入

语法:

scanf(“%s”, 数组名);
scanf("%s", 数组名);

案例:

/*************************************************************************
  > File Name:    work11.c
  > Author:       sgc
  > Description:  字符串操作函数
  > Created Time: 2024年12月04日 星期三 10时29分37秒
 ************************************************************************/

#include <stdio.h>

int main(int argc,char *argv[])
{
    /**     字符串的输入
     *      语法:scanf("%s",数组名);
     * */
    // 创建一个数组,用来存放人的名字
    char name[20];

    printf("请输入您的姓名:");
    scanf("%s", name); // 注意:如果是字符串,这里不是变量地址,是变量名,数组本身不占内存空间,数组名默认指向第一个元素的首地址

    printf("%s\n", name);
    return 0;
}

注意:采用scanf()进行字符串输入,要求字符串中不能存在空格,否则字符串遇到空格会结束。

fgets(数组名,数组容量,sdtin);

功能:

从键盘录入一个字符串到字符数组,返回字符数组的地址。

说明:

采用fgets进行字符输入,可获取所有输入的字符串,包含\n,在实际的字符串处理时,我们可能需要

/*************************************************************************
  > File Name:    work11.c
  > Author:       sgc
  > Description:  字符串操作函数
  > Created Time: 2024年12月04日 星期三 10时29分37秒
 ************************************************************************/

#include <stdio.h>

int main(int argc,char *argv[])
{
    /**     字符串的输入
     *      语法:fgets(数组名, 数组容量, stdin);
     * */
    // 创建一个数组,用来存放人的名字
    char name[20];
    printf("请输入您的名字:");

    // fgets和scanf只能二选一
    fgets(name, sizeof(name)/sizeof(char), stdin);

    printf("%s\n", name);
    return 0;
}

注意:

  1. 如果输入的字符不包括空格换行,可以使用scanf()|fgets();
  2. 如果输入的字符串需要包含空格换行,只能使用fgets();
  3. 经过对比,我们发现,在字符串的输入中,fgets();
字符串的输出
printf(“%s”, 数组名);

案例:

/*************************************************************************
  > File Name:    work11.c
  > Author:       sgc
  > Description:  字符串操作函数
  > Created Time: 2024年12月04日 星期三 10时29分37秒
 ************************************************************************/

#include <stdio.h>

int main(int argc,char *argv[])
{
    /**     字符串的输出
     *      语法:printf("%s", name);
     * */
    // 创建一个数组,用来存放人的名字
    char name[20];
    printf("请输入您的名字:");

    // fgets和scanf只能二选一
    fgets(name, sizeof(name)/sizeof(char), stdin);

    printf("%s\n", name);
    return 0;
}

puts(数组名);

功能:

输出一个字符串

说明:

字符串可以包含转义字符

案例

/*************************************************************************
  > File Name:    work11.c
  > Author:       sgc
  > Description:  字符串操作函数
  > Created Time: 2024年12月04日 星期三 10时29分37秒
 ************************************************************************/

#include <stdio.h>

int main(int argc,char *argv[])
{
    /**     字符串的输出
     *      语法:puts(数组名);
     * */
    // 创建一个数组,用来存放人的名字
    char name[20];
    printf("请输入您的名字:");

    // fgets和scanf只能二选一
    fgets(name, sizeof(name)/sizeof(char), stdin);

    puts(name); // 无法进行字符串拼接,只能直接输出
    return 0;
}

字符串的拼接
strcat(数组名(字符串1), “需要拼接的字符串(字符串2)”);

引用:

#include <string.h>

案例:

/*************************************************************************
  > File Name:    work11.c
  > Author:       sgc
  > Description:  字符串操作函数
  > Created Time: 2024年12月04日 星期三 10时29分37秒
 ************************************************************************/
#include <string.h>
#include <stdio.h>

int main(int argc,char *argv[])
{
    /**     字符串的拼接
     *      语法:strcat(数组名, "需要拼接的字符串");
     * */
    // 创建一个数组,用来存放人的名字
    char name[20];
    printf("请输入您的名字:");

    // fgets和scanf只能二选一
    fgets(name, sizeof(name)/sizeof(char), stdin);

    strcat(name,"快跑"); // 进行拼接,并返回拼接后的字符串

    puts(name); // 无法进行字符串拼接,只能直接输出
    return 0;
}

注意:

  1. 字符数组(字符串1)的长度必须足够大,以便能容纳被连接的字符串。
  2. 连接后系统将自动取消字符串1(字符数组1)后面的结束符"\0"
  3. 字符串2可以是字符数组名,也可以是字符串常量,如:strcat(s1,“def”);
字符串的拷贝
strcpy(数组名,字符串);

引入:

#include <string.h>

说明:

这个函数适合给字符串赋值用

char str[16] = "司高超"; // 正确,初始化

char str[16];
str[16] = "司高超"; // 错误,赋值

char str[16];
strcpy(str,"司高超"); // 正确,借用函数完成赋值

案例:

/*************************************************************************
  > File Name:    work11.c
  > Author:       sgc
  > Description:  字符串操作函数
  > Created Time: 2024年12月04日 星期三 10时29分37秒
 ************************************************************************/
#include <string.h>
#include <stdio.h>

int main(int argc,char *argv[])
{
    /**     字符串的拷贝
     *      语法:strcpy(数组名, "需要拷贝的字符串");
     * */
    // 创建一个数组,用来存放人的名字
    char name[20];
    printf("请输入您的名字:");

    // fgets和scanf只能二选一
    fgets(name, sizeof(name)/sizeof(char), stdin);

    strcpy(name, "sgc");

    puts(name); // 无法进行字符串拼接,只能直接输出
    return 0;
}

字符串比较
strcmp(字符串1,字符串2);

引入:

#include <string.h>

功能:

比较两个字符串对应位置字符ASCII的大小(字典顺序比较)。

返回值:

​ 若字符串1等于字符串2返回0

​ 若字符串1大于字符串2返回正整数

​ 如字符串1小于字符串2返回负整数

说明:

  1. 执行这个函数时,自左到右逐个比较对应字符的ASCII的值,直到发现了不同字符或者字符串结束符\0为止。
  2. 对字符串不能用数值型比较符
  3. 字符串1与字符串2可以是字符数组名,也可以是字符串常量。

案例:

/*************************************************************************
  > File Name:    work11.c
  > Author:       sgc
  > Description:  字符串操作函数
  > Created Time: 2024年12月04日 星期三 10时29分37秒
 ************************************************************************/
#include <string.h>
#include <stdio.h>

int main(int argc,char *argv[])
{
    /**     字符串的比较
     *      语法:strcmp(字符串1,字符串2);
     * */
    // 创建一个char数组,用来存放账户和密码
    char username[20], password[8];
    printf("请输入您的账户:");
    scanf("%s", username);
    printf("请输入您的密码:");
    scanf("%s", password);

    if( !strcmp(username,"admin") && !strcmp(password,"123456") )
    {
        printf("登录成功!\n");
    }
    else
    {
        printf("账号或密码错误");
    }

    return 0;
}

获取字符串长度
strlen(字符串)

引用:

#include <string.h>

注意:

返回字符串中包含的字符的实际个数,不含\0

案例:

/*************************************************************************
  > File Name:    work11.c
  > Author:       sgc
  > Description:  字符串操作函数
  > Created Time: 2024年12月04日 星期三 10时29分37秒
 ************************************************************************/
#include <string.h>
#include <stdio.h>

int main(int argc,char *argv[])
{
    /**     字符串的长度
     *      语法:strlen(字符串);
     * */
    // 创建一个char数组,用来存放账户和密码
    char username[20];
    printf("请输入您的账户:");
    scanf("%s", username);

    unsigned long len = strlen(username);

    if( strcmp(username,"admin")  )
    {
        printf("账户输入错误%d\n", len);
    }
    else
    {
        printf("账户输入正确%d\n", len);
    }

    return 0;
}

gets和fgets的区别

1.fgets 允许指定最大读取字符数(包括终止空字符\0),这可以防止缓冲区溢出,因为函数会确保不超过指定的字符数。
gets 函数没有参数来指定最大读取字符数,它会一直读取直到遇到换行符或文件结束符,但如果输入字符串过长,可能会覆盖数组以外的内存。

2.fgets 会读取最多 n-1 个字符,并在最后添加终止空字符 \0。如果遇到换行符或文件结束符,它会停止读取。
gets 会读取字符直到遇到换行符或文件结束符,并将换行符替换为终止空字符 \0。

这两个函数的返回值都是如果成功,返回str(是一个指向字符数组的指针),如果遇到文件结束符或读取错误,返回 NULL。


原文地址:https://blog.csdn.net/weixin_70953765/article/details/144292683

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!