C 语言学习笔记(数组)

C 语言基础:第 08天笔记

内容提要

  • 数组
    • 排序算法:冒泡排序
    • 二维数组
    • 字符数组

数组

冒泡排序

  • 排序思想(向前冒泡):

    • 一次排好一个数,针对n个数,最差情况需要n - 1次就可以排好
    • 每次排序假定第一个元素是最大或者最小的,相邻的两个元素比较,遇到较大或者较小的元素交换,访问完数组的最后一个元素,就排好了一个数。
    • 在余下的数中,再次应用第2步的操作,直到剩下1个数。
  • 推理:

    例如:将5,4,3,2,1冒泡排序为1,2,3,4,5

    排序演示:

    • 第1轮:5,4,3,2,1 → 4,3,2,1,5 比较4次 = 数组长度5 - 轮数1
    • 第2轮: 4,3,2,1,5 → 3,2,1,4,5 比较3次 = 数组长度5 - 轮数2
    • 第3轮:3,2,1,4,5 → 2,1,3,4,5 比较2次 = 数组长度5 - 轮数3
    • 第4轮:2,1,3,4,5 → 1,2,3,4,5 比较1次 = 数组长度5 - 轮数4
  • 总结:

    • 案例设计到5个数的排序,排序了4轮,得到:轮数 = 元素个数(数组打小) - 1,我们可以通过一个外层for循环实现轮数的遍历。

    • 案例涉及的每一轮中数列的排序次数,得到:次数 = 元素个数 - 轮数[-1],我们可以通过一个内层for循环实现每一轮次数的遍历。

    • 每一次比较过程中,两个数设计到位置交换,比如a = 3,b = 4,交换ab的数据变为a = 4,b = 3,应该如何实现:

      • 引入一个临时变量temp,将a的值赋值给temp,int temp = a;

      • 将b的值赋值给a,a = b;

      • 将temp的值赋值给b,b = temp;

  • 代码:

    c 复制代码
    #include <stdio.h>
    
    int main()
    {
        //创建一个数组,用来存放排序用的数列
        int arr[10];
        
        //定义循环变量和临时变量
        int i,j,temp;
            
        printf("请输入10个整数:\n");
        
        //计算数组的大小
        int len = sizeof(arr) / sizeof(arr[0]); 等价于 sizeof(arr) / sizeof(int);
        
        //通过循环给数组元素赋值
        for(i = 0; i < len; i++) scanf("%d",&arr[i]); //[]优先级高于&,等价于&(arr[i])
        
        printf("\n");
        
        //冒泡排序
        //外层循环:实现排序轮数的遍历,轮数 = 数组大小 - 1
        for(i = 0; i < len -1, i++)
        {
            int flag = 0; //设置一个flag,用来判断是否已经有序
            //内存循环:实现每一轮的比较次数,比较次数 = 数组大小  - 轮数 - 1
            for(j = 0; j < len -i -1; j++)
            {
                //相邻的两个数比较后交换位置
                if(arr[j] > arr[j+1])  //此时,实现升序排序,从小到大
                {
                    temp = arr[j];
                    arr[j] = arr[j+1];
                    arr[j+1] = temp;
                    flag = 1;
                }
    		}
            if(flag == 0) break; //如果进行了一轮排序后flag还是等于0,则说明已经有序
        }
        printf("冒泡排序后从小到大为:\n");
        for(i = o; i < len; i++)  printf("%4d", arr[i]);
        
        pritnf("\n");
        
        return 0;    
    }
  • 衍生

    冒泡排序 → 鸡尾酒排序(摇坠排序) → 摇床排序...

二维数组

定义

二维数组本质上是一个行列式组合,也就是说二位数组由行和列两部分组成。属于多维数组。二维数组数据通过行和列解读(先行后列)。

二维数组可以被视为一个特殊的一维数组,也就是说当一个数组的元素是一维数组的时候,这个数组就是二维数组。(数组的元素的类型可以是数组类型)

语法
c 复制代码
数据类型 数组名[行数][列数];

行数:外层数组的数组容量

列数:内层的数组容量

说明
  • 二维数组在初始化的时候,可以省略行数,系统会通过初始化后的数据自动推断行数。
  • 二维数组和一位数组一样,也可以部分初始化,未初始化的元素使用0(整形和浮点型)、\0(字符型,\0对应的ASCII是0),NULL(指数相关)
  • 二维数组的初始化的时候,不能省略列数,否则编译报错。
举例
c 复制代码
int arr[3][3] = {{11,12,13},{21,22,23},{31,32,33}};  //正确,等价于下面写法
int arr[][3] = {{11,12,13},{21,22,23},{31,32,33}};   //正确,二维数组初始化的时候可以省略行数,推荐写法

int arr[3][3] = {{11,12},{21,22,23},{31}};          //正确,缺失部分情况根据情况补0、\0、NULL、补什么由数据类型决定
int arr[3][3] = {{11,12,0},{21,22,23},{31,0,0}};    //正确,等价于上面写法

int arr[3][3] = {0};                                //正确,所有位置使用0补齐
int arr[3][3] = {};                                 //正确,所有位置用0补齐
int arr[3][3] = {11};                               //正确,除了第0行第0列使用11以外,其他位置用0补齐

int arr[3][3] = {{11,12,13},{21,22,23},{31,32,33}};  //错误,编译报错,不能省略列数
int arr[3][]  = {{11,12,13},{21,22,23},{31,32,33}};  //错误,编译报错,不能省略列数

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

内存存储
应用场景

主要是应对行列有要求的情况。比如说我们先存储所有在班学生的成绩

还有就是字符数组的应用,比如用数组存储学生的姓名。

double scores[28] = {..}; 一维数组初始化

double scores[5][40] = {``{..}..} 二维数组初始化

double scores[6][4][40] = {``{``{..}..}..} 三维数组初始化

特殊写法
  • 下标可以是整型表达式。如:a[2-1][2*2-1] → a[1][3]
  • 下标可以已经有值的变量或者数组元素,如:a[2*x-1][b[3][1]]
  • 数组元素可以出现在表达式中,如:b[1][2] = a[2][3]/2

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

初始化
  • 分行给二位数组赋初值

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

    c 复制代码
    int arr[3][4] = {11,12,13,14,21,22,23,24,31,32,33,34};
  • 可对部分元素赋初值,其余未赋值部分自动填充数值类型默认值-0 | 字符型默认值-\0 | 指针类型-NULL

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

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

    c 复制代码
    int arr[][4] = {{11,12,13},{0},{0,10}};
案例
案例1
  • 需求:二维数组的遍历

  • 分析:

    • 二维数组的遍历需要使用到嵌套for循环,外层训话遍历行,内层循环遍历列

    • 取值:

      c 复制代码
      数组名[行号][列号];
    • 赋值

      c 复制代码
      数组名 [行号][列号] = 值;
  • 代码

    c 复制代码
    #include <stdio.h>
    
    int main()
    {
        //创建一个二维数组
        int arr[][3] = {{11},{21,22},{31,32,33}}; //11,0,0,21,22,0,31,32,33
            
        //获取行容量和列容量
        int row = sizeof(arr) / sizeof(arr[0]);
        int col = sizeof(arr[0]) / sizeof(arr[0][0]);
        
        //遍历数组
        //外层循环:遍历行
        for (int i = 0; i < row; i++)
        {
            for (int j = o; j < col, j++)
            {
                printf("%-3d",arr[i][j]);
    		}
        }
        
        printf("\n");
        
        return 0;
    }
  • 运行结果

案例2
  • 需求:矩阵的转置

  • 分析:

    • 所谓的转置,就是原本的列变行,行变列
  • 代码:

    c 复制代码
    #include <stdio.h>
    
    #define ROW 2
    #define COL 3
    
    int main()
    {
        //定义循环变量i,j
        int i, j;
        
        //准备2个数组用来存储转置前后的数据
        int arr_before[ROW][COL] = {11,12,13,21,22,23};
        int arr_after[COL][ROW] = {0};
        
        //计算数组的大小
        int arr_before_row = sizeof(arr_before) / sizeof(arr_before[0]);
        int arr_before_col = sizeof(arr_before[0]) / sizeof(arr_before[0][0]);
        
        int arr_after_row = sizeof(arr_after) / sizeof(arr_after[0]);
        int arr_after_col = sizeof(arr_after[0]) / sizeof(arr_after[0][0]);
        
        //通过嵌套for循环实现转置
        printf("转置前:\n");
        for (i = 0; i < arr_before_row; i++)
        {
            for(j = 0; j < arr_before_col; j++)
            {
                //打印输出装置前的数据
                printf("%-4d",arr_befire[i][j]);
                //转置。列变行,行变列
                arr_after[j][i] = arr_before[i][j];
            }
            ptintf("\n");
    	}
        
        ptintf("\n");
        
         printf("转置后:\n");
        for (i = 0; i < arr_after_row; i++)
        {
            for (j = 0; j < arr_after_col; j++)
                printf("%-4d",arr_after[i][j]);
            printf("\n");
        }
        printf("\n");
        
        return 0;
            
    }
  • 运行结果

课堂练习
  • 需求:求一个3行3列的矩阵对角线上的元素之和。

字符数组

在C语言中,支持常量字符串,不支持变量字符串,如果想要实现类似的变量字符串,C语言提供了两种实现方式:

  • 字符数组

    c 复制代码
    char name[] = "哪吒";
  • 字符指针

    c 复制代码
    char *name = "哪吒";
概念

元素类型为char(字符型)的数组叫做字符数组。字符数组往往是用来存储字符串数据的。需要注意的,我们C语言中的字符是字节字符(1字符 = 1字节,C语言中没有字节这个表示法,我们一般使用char表示字节,1char = 8bit)。

硬件中存放数据以bir(位)为单位,系统对于内存的操作以char(字节)为单位。系统为内存以1个字节为单位进行编号。

实验:

c 复制代码
char a = 'A';	//正确
char b = '1';	//正确    
char c = '65';	//正确,这里的65是ASCII码,char的值有两种表现形式,一种是字符,一种是字符对应的ASCII码
char d = "A";	//错误,用双引号包裹的内容是常量字符串
char a = '王';	//错误,ASCII中不包括中文字符,中文字符使用的是如GBK、UTF-8等编码,实际上都超过了1个字节
语法

一维数组:

c 复制代码
char 数组名[数组容量];

二维数组:

c 复制代码
char 数组名[行容量][列容量]

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

注意:

​ 如果我们char数组初始化的时候,没有完全初始化值的时候,使用\0进行填充。大家要注意,这里的\0只是起到一个站位或标识的作用,我们是无法通过printf等打印输出到控制台的(不支持输出)。

比如:

c 复制代码
char c[8] = {'H','E','L','L','O'};   //部分初始化,未初始化部分补'\0',等价于下面写法
char c[8] = {'H','E','L','L','O','\0','\0','\0'};
案例1
  • 需求:输出一个字符序列(I LOVE YOU)

  • 代码

    c 复制代码
    #include <>
    
    int main()
    {
        //创建一个数组,用来存储 I LOVE YOU,ASCII中对应的空格为' ',其对应的ASCII码为32
        char arr[] = {'I',' ','L','O','V','E',32,'Y','O','U'};
        
        //计算数组的大小
        int len = sizeof(arr) / sizeof(arr[0]);
        
        //使用for循环遍历
        for (int i = 0; i < len; i++) printf("%c",arr[i]);
        
        printf("\n");
        
        return 0;
    }
案例2
  • 需求:输出一个用字符*组成的空菱形图案

  • 代码:

    c 复制代码
    int main()
    {
        //创建一个二维数组,存放空菱形
        char arr[5][5] = {
            {' ',' ','*',' ',' '},
            {' ','*',' ','*',' '},
            {'*',' ',' ',' ','*'},
            {' ','*',' ','*',' '},
            {' ',' ','*',' ',' '},
        };
        
        //计算行数和列数
        int row = sizeof(arr) / sizeof(arr[0]);
        int col = sizeof(arr[0]) / sizeof(arr[0][0]);
        
        //遍历数组
        for (int i = 0; i < row; i++)
        {
            for (int j = 0; j < col; j++)
                printf("%c", arr[i][j]);
            printf("\n");
        }
        
        printf("\n");
        
        return 0;
    }
注意
  • 如果定义时,不初始化,元素的值不确定(针对局部定义的数组)

    c 复制代码
    char arr1[2];  //如果这个数组是定义在函数中的,此时元素的值是随机的
    char arr2[5] = {'a','b','c'};  //此时属于不完全初始化,未初始化完的元素使用'\0'填充
  • 如果提供的字符个数大于数组长度,按照语法错误处理(会报警告,但是能编译通过);如果字符个数小于数组长度,后面的元素自动补\0

    c 复制代码
    char arr1[2] = {'h','e','e'};  //编译通过,但会报警,不建议写
    char arr2[3] = {'a'};  //正确的,未初始化的元素使用'\0'填充
  • 如果提供的字符个数和数组长度相同,可以省略数组长度,系统会自动确定元素个数,适合字符较多时。

    c 复制代码
    char arr1[] = {'b','u'};  //正确,更具初始化元素,由系统自动计算元素个数
字符串结束标志
说明
  • C语言规定,字符串以字符\0作为结束标志

  • 编译系统对字符串常量自动加一个\0作为结束的标志。比如char *name = "tom",实际上存储为{'t','o','m','\0'}

  • 程序中往往通过判断\0来检测字符串是否结束。举例:while(arr[i] != '\0'){...}

  • \0的ASCII码是0,不是一个可显示可输出的字符,是"空操作符",它什么都不做,不会增加有效字符,仅仅用作一个工程判别的标志或者在字符组中占位。

    c 复制代码
    char a[] = {'h','i'};       //hi
    char a[] = {'h','i','\0'};  //hi
    char c[] = "hello";         //实际存储:hello\0   字符常量,在内存中,默认加了一个\0字符用作结尾标志
字符数组的多样表示

我们的char数组可以以数组的形式一个一个输出每个字符;也可以以字符串的形式整体输出。

  • 演示

    c 复制代码
    int main()
    {
        //字符串的第1种表示:
        char s1[] = {'h','e','l','l','o',' ','w','o','r','l','d','\0'};
        //字符串的第2种表示:
        char s2[] = {"hello world"}; //""包裹的字符串一般默认有一个\0,所以不需要手动加
        //字符串的第3种表示:
        char s3[] = "hello world";
        
        //字符串输出第1种方式:
        int len = sizeof(s3) /sizeof (s3[0]);
        
        for(int i = 0; i < len; i++)
        {
            //过滤\0
            if (s1[i] == '\0' || s2[i] == '\0' || s3[i] == '\0') continue;
            
            printf("%c,%c,%c\n",s1[i],s2[i],s3[i]);
        }
        printf("\n");
        
        //字符串输出的第二种方式
        printf("%s,%s,%s\n",s1,s2,s3);
        printf("\n");
        
        return 0;    
    }
注意
  • 字符串的长度与字符数组的长度不一定相同。

    c 复制代码
    char *name = "hello";  // 数组长度:6,字符串长度:5
  • 利用字符串常量可以对字符数组进行初始化,但不能用字符串常量对字符数组赋值。

    c 复制代码
    //正确演示:利用字符串常量给字符数组初始化
    char arr1[] = "hello";
    
    //错误演示:利用字符串常量给字符数组赋值
    char arr[6]
    arr2 = "hello"; //可以理解为,数组是一个常量
字符串的基础操作

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

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

字符串输入

scanf

语法:

c 复制代码
scanf ("%s",数组名);

注意:数组名对应的数组只能是char类型,从控制台输入字符串之后,默认为追加\0

案例:

c 复制代码
int main()
{
    //创建一个字符数组,用来存储姓名
    char name[20];  //初始化的时候,数组容量可以省略,char name[] = {..},如果只是声明,数组容量不能省略
    
    printf("请输入您的名字:");
    scanf("%s", name); //数组本身没有空间,它的内存空间其实就是其元素空间
    
    printf("您的姓名是:%s\n",name);
    
    return 0;
}

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

fgets

语法:

c 复制代码
fgets(数组名,数组容量,stdin);

功能:

​ 从键盘录入一个字符串常量到字符数组,返回字符数组的地址(首地址,默认返回的地址,一 般用12位16进制数表示)

说明:

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

案例:

c 复制代码
#include <stdio.h>

int main(int argc,char *argv[])
{
    // 创建一个字符数组,用来存储姓名
    char name[20]; // 初始化的时候,数组容量可以省略,char name[] = {..},如果只是声明,数组容量不能省略

    // 计算数组容量
    int len = sizeof(name) / sizeof(name[0]);
    
    printf("请输入您的名字:\n");
    // scanf("%s",name);// 数组本身没有空间,它的内存空间其实就是其元素空间,C语言规定数组名指向第一个元素的首地址
    fgets(name,len,stdin); 
    
    printf("您的姓名是:%s\n",name);
    
    return 0;
}

注意:

①如果输入的字符串不包括空格或换行,可以使用scanf或者fgets

②如果输入的字符串包括空格和换行只能使用fgets

gets危险的【 C11 移出】

语法:

c 复制代码
gets(数组名);

功能:

​ 从键盘录入一个字符串常量到字符数组,返回字符数组的地址(首地址,默认返回的地址,一 般用12位16进制数表示)

说明:

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

案例:

c 复制代码
#include <stdio.h>
 
int main(int argc,char *argv[])
{
    // 创建一个字符数组,用来存储姓名
    char name[20];
    // 计算数组的大小
    int len = sizeof(name) / sizeof(name[0]);
    
     printf("请输入您的名字:\n");
     gets(name);// 数组本身没有空间,它的内存空间其实就是其元素空间,C语言规定数组名指向的就是首地址
 
     printf("您的名字是%s\n",name);
 
     return 0;
 }
字符串输出

printf

语法:

c 复制代码
printf("%s",数组名);

案例:

c 复制代码
 #include <stdio.h>
 
 int main(int argc,char *argv[])
 {
     // 创建一个字符数组,用来存储姓名
     char name[20];
 
     printf("请输入您的名字:\n");
     scanf("%s",name);// 数组本身没有空间,它的内存空间其实就是其元素空间,C语言规定数组名指向的就是
首地址
 
     printf("您的姓名是%s\n",name);
     return 0;
 }

fputs

语法:

c 复制代码
fputs(数组名,shdout);

功能:

​ 输出一个字符串

说明:

​ 字符串可以包含转义字符(以\开头的字符)

案例:

c 复制代码
#include <stdio.h>

int main(int argc,char *argv[])
{
    char arr[] = "hi lucy\trun!\n";
    
    // 第1种输出
    printf("%s",arr);
    
    // 第2种输出
    fputs(arr,stdout);
    
    return 0;
}

puts 危险的【C11移出】

语法:

c 复制代码
puts(数组名称)

功能:

​ 输出一个字符串

说明:

​ 字符串可以包含转义字符

案例:

c 复制代码
#include <stdio.h>

int main(int argc,char *argv[])
{
    // 创建一个数组,用来存放人的名字

    char name[20];
    
    printf("请输入您的名字:\n");
    // gets、fgets和scanf只能多选一
    gets(name);
    
    // 输出
    puts(name);// 标准的输出
    return 0;
}

字符串转数值【扩展】

  • strtol

    c 复制代码
    long strtol (const char *str, char **endptr, int base);

    将字符串转换为长整型数。

    参数说明:

    • str :指向要转换的字符串的指针。
    • endptr :一个指向字符指针的指针。如果提供了这个参数,并且转换成功,*endptr将被 设置为指向第一个未转换字符的指针。如果 endptrNULL ,则不使用它。
    • base :用于指定转换的基数。它可以是 2 到 36 之间的值,或者是特殊值 0。如果 base 是 0,则函数会根据字符串的前缀(如 "0x" 或 "0X" 表示十六进制,"0" 表示八进制,否则默 认为十进制)来自动确定基数
  • strtoul

    c 复制代码
    unsigned long strtoul(const char *str, char **endptr, int base);

    将字符串转换为无符号长整型数。

  • strod

    c 复制代码
    double strtod(const char *str, char **endptr);
  • atoi

    c 复制代码
    int atoi(const char *str)

    将字符串转换为长整型数(不推荐使用,建议使用 strtol)。

  • atof

    c 复制代码
    double atof(const char *str);

    将字符串转换为双精度浮点数(不推荐使用,建议使用strtod )。

案例:

c 复制代码
#include <stdio.h>
#include <stdlib.h>
int main(int argc,char *argv[])
{
    printf("%lo,%ld,%lx\n",strtol("12",NULL,8),strtol("12",NULL,10),strtol("12",NULL,16));
    printf("%lo,%ld,%lx\n",strtol("012",NULL,0),strtol("12",NULL,10),strtol("0x12",NULL,0));
    
    int a = 10;
    
    printf("%p,%lx\n",&a,&a);
    return 0;
}
main()
{
    int a=2,b=-1,c=2;
    if(a<b)
        if(b<0) c=0;
    
    else c+=1;
    printf("%d\n",c);
 }

关于单字符的输入:

  • scanf("%c",...)
  • getchar();

关于单字符的输出:

  • printf("%c",...);
  • putchar();

字符串相关函数

字符串拼接

语法:

c 复制代码
strcat(字符串1,需要拼接的字符串2);

解释:

①这里的字符串,可以是字符串常量,也可以是字符数组或者字符指针。

②这里需要将字符串2拼接到字符串1中,所以需要字符串1有足够大的空间去容纳字符串2.

引入

c 复制代码
#include <string.h>

案例:

  • 需求:将两个字符串拼接为一个字符串

  • 分析:

  • 代码:

    c 复制代码
    #include <stido.h>
    #include <string.h>
    
    int main()
    {
        //创建一个数组,用来接收控制台输入的字符常量,字符串1
        char namr[20];
        
        printf(""请输入您的名字:\n);
        //通过键盘录入字符串
        fegets(name, sizeof(name) / sizeof(name[0], stdin);
        
    	//输出拼接
         fputs(stract(name, "小帅"), stdout);
               
         printf("拼接后字符串所占字节数:%d\n", sizeof(trcat(name,"小帅")));
               
         printf("\n");
               
         return 0;
    }

注意:

字符串1必须是字符数组,长度必须足够大,以便于能够容纳被链接的字符串。

② 连接后系统将自动取消字符串1后面的结束符\0

字符串2可以是字符数组名,也可以是指针,也可以是字符串常量,如:strcat(s1,"def"); strcat(s1,s2);

字符串拷贝

语法:

c 复制代码
strcpy(数组名,字符串);

解释:简单来说,类似于将一个字符串赋值给一个字符数组。这个函数一般用来做赋值处理。

引入:

c 复制代码
#include <string.h>

**说明:**这个函数适合给字符串赋值

c 复制代码
char str[20] = "张三";   //正确,字符数组初始化,字符串初始化
char str[20] = "张三"; str = "李四";  //错误,不能对字符数组进行赋值
char str[20] = "张三"; strcpy(str, "李四");  //正确,借助strcpy完成类似赋值的操作

**注意:**strcat和strcopy的区别:

  • strcat: 张三+李四 → 张三李四 (追加)
  • strcpy:张三+李四 → 李四 (覆盖)

案例:

c 复制代码
#include <stdio.h>
#include <string.h>

int main()
{
    char name[20];
    
    printf("请输入您的姓名:\n");
    
    fgets(name, sizeof(name) / sizeof(name[0], stdin));  // 键盘 → 输入缓冲区 → char name[]
    
    printf("覆盖前:%s\n", name);
    //重新赋值
    strcpy(name, "谢谢惠顾");
    printf("覆盖后:%s\n", name);
    
    return 0;
}
字符串比较

语法:

c 复制代码
strcmp(字符串1,字符串2);

注意:这里的字符串可以是字符常量、字符数组、字符指针。

引入:

c 复制代码
#include <string.h>

**功能:**如果是英文,比较两个字符串对应位置字符ASCII的大小

返回值:

  • 如果字符串1等于字符串2,返回0
  • 如果字符串1大于字符串2,返回正数(>0)
  • 如果字符串1小于字符串2,返回负数(<0)

说明:

①执行这个函数是,自左向右诸葛比较对应字符的ASCII的值,知道发现了不同字符或字符串结束符\0为止

②对字符串不能用数值型比较符。比如:"abc" == "abc",这种比较是错误的。

③字符串1与字符串2可以是字符数组、字符指针、字符串常量。

案例:

  • 需求:通过控制台输入用户名和密码,并进行校验

  • 代码:

    c 复制代码
    #include <stdio.h>
    #include <string.h>
    
    int main()
    {
        //用户登录案例
        
        //创建两个变量,用来接受控制台输入的用户名和密码
        char username[20], password[8];
        
        printf("-----------用户登录-----------");
        printf("请输入您的用户名:\n");
        scanf("%s", username);
        
        printf("请输入您的密码:\n");
        scanf("%s", password);
    	
        //校验
        if(strcmp(username,"admin") && strcmp(password, "123456")) //问题:
            
            printf("登录成功!\n");
        else
            printf("用户名或者密码错误!\n");
        
        return 0;
    }
  • 运行结果

字符串长度
  • 语法:
c 复制代码
strlen(字符串);
  • 引用:
c 复制代码
#include <string.h>

注意:返回字符串种包含的实际个数。遇到\0结束,不包含\0

案例:

  • 需求:字符串长度案例

  • 代码:

c 复制代码
#include <stdio.h>
#include <string.h>
int main()
{
    //测试数据1
    char s1[] = {'h','i','\0','h','i','\0'};
    printf("数组长度:%lu,字符串长度:%lu\n", sizeof(s1)/sizeof(s1[0]),strlen(s1)); // 6   2
    
    //测试数据2
    char s2[] = "hi\0hi\0";
    printf("数组长度:%lu,字符串长度:%lu\n", sizeof(s2)/sizeof(s2[0]),strlen(s2));// 7    2
    
    //测试数据3    
    char s3[] = {'hi','e','l','l','0'};
    printf("数组长度:%lu,字符串长度:%lu\n", sizeof(s3)/sizeof(s3[0]),strlen(3)); // 5  5
    
    //测试数据4
    char s4[] = "hello";
    printf("数组长度:%lu,字符串长度:%lu\n", sizeof(s4)/sizeof(s4[0]),strlen(4));//4  5
    
    return 0;
}
  • 运行结果:

案例
  • 需求:输入一行字符,统计其中有多少个单词,单词之间用空格隔开。举例:I LOVE YOU

  • 分析:采用通过空格统计单词的方法。具体是:

    ① 用连续若干个空格算一个、一行开头的空格不计的方法决定单词数目;

    ② 从第一个字符开始逐个检查字符串中的每一个字符。若查到某一字符非空格,而其前面的字 符是空格,则表示新单词开始,让计数变量num++。否则,当前字符非空格,前面字符也非空 格,则非新单词,num不变;

    ③ 用变量word=0或1来表示前面字符是空格或不是空格。则:

  • 代码:

    c 复制代码
    #include <stdio.h>
    #include <ctype.h>
    
    int main()
    {
        //创建一个字符数组,用来接收控制台输入的字符串
        char string[100];
        
        //创建两个变量,word = 0;用来标记遍历出来的字符是否是空格,01空格,1-非空格;num = 0:记录单词的个数
        int num = 0, word = 0;
        
        //用来接收遍历出来的字符
        char c;
        
        //通过控制台输入字符串(包含空格)
        fgets(string, sizeof(string) / sizeof(string[0])), stdin);
        
        //遍历字符串
        for(int i = 0;(c = string[i]) != '\0'; i++)
        {
            //如果取出来的字符是空格,就设置word = 0
            if(isspace(c))
            {
                //如果是空格,标记word = 0
                word = 0;
            }
            else
            {
                //如果是非空格,标记 word = 1
                //如果上一个字符是否是空格,如果是,就需要统计单词
                if(!word)   //word == 0
                {
                    //更改word = 1
                    word = 1;
                    //统计单词个数
                    num++;
    			}
                word = 1;
    		}
        }
        
        printf("%s\n中有%d个单词");
            
        return 0;    
    }
案例

有三个字符串,要求找出其中最大者。

分析:设计一个二维字符数组str3,即3行20列。

① 可把str[0]、str[1]、str[2]看作3个一维字符数组,各有20个元素;

② 用gets函数分别输入3个字符串到str[0]、str[1]、str[2]中 ;

③ 用字符串函数对str[0]、str[1]、str[2]进行比较,得到最大者。

c 复制代码
#include <stdio.h>
#include <string.h>
void main ( )
{  
     char max[20];
     char str[3][20];// 输入3个字符串   {"abc","bbc","ccc"}
     int i;
     // 完成初始化
     for (i=0;i<3;i++)
         gets(str[i]);              /*输入3个字符串*/
     // fgets(str[i],20,stdin)
 
     if (strcmp(str[0],str[1])>0)   /*比较,若串0>串1*/
         strcpy(max,str[0]);      /*把串0存入string*/
     else 
         strcpy(max,str[1]);      /*否则,把串1存入string*/
 
     if (strcmp(str[2],max)>0)  /*再比较,若串2>string*/
         strcpy(max,str[2]);     /*把串2存入string,否则string不变*/
 
     printf("\nthe largest string is:\n%s\n",max); /*输出string*/
 }
相关推荐
oneDay++5 分钟前
# IntelliJ IDEA企业版安装与配置全指南:避坑详解
java·开发语言·经验分享·学习·学习方法
2303_Alpha42 分钟前
深度学习入门:深度学习(完结)
人工智能·笔记·python·深度学习·神经网络·机器学习
wktomo1 小时前
GO语言学习(二)
学习·golang
姝孟1 小时前
学习笔记(C++篇)—— Day 6
笔记·学习
白白白飘1 小时前
pytorch 15.1 学习率调度基本概念与手动实现方法
人工智能·pytorch·学习
LuckyLay1 小时前
Vue百日学习计划Day16-18天详细计划-Gemini版
前端·vue.js·学习
hnlucky2 小时前
Windows 上安装下载并配置 Apache Maven
java·hadoop·windows·学习·maven·apache
霸王蟹2 小时前
React Fiber 架构深度解析:时间切片与性能优化的核心引擎
前端·笔记·react.js·性能优化·架构·前端框架
~巴哥~2 小时前
mcp学习笔记
笔记·学习
lichuangcsdn3 小时前
【springcloud学习(dalston.sr1)】Eureka 客户端服务注册(含源代码)(四)
学习·spring cloud·eureka