当前位置: 首页 > news >正文

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;

        在这里插入图片描述

  • 代码:

    #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");//冒泡排序//外层循环:实现排序轮数的遍历,轮数 = 数组大小 - 1for(i = 0; i < len -1, i++){int flag = 0; //设置一个flag,用来判断是否已经有序//内存循环:实现每一轮的比较次数,比较次数 = 数组大小  - 轮数 - 1for(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;    
    }
    
  • 衍生

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

二维数组

定义

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

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

语法
数据类型 数组名[行数][列数];

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

列数:内层的数组容量

说明
  • 二维数组在初始化的时候,可以省略行数,系统会通过初始化后的数据自动推断行数。
  • 二维数组和一位数组一样,也可以部分初始化,未初始化的元素使用0(整形和浮点型)、\0(字符型,\0对应的ASCII是0),NULL(指数相关)
  • 二维数组的初始化的时候,不能省略列数,否则编译报错。
举例
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

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

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

    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 | 指针类型-NULL

     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
  • 需求:二维数组的遍历

  • 分析:

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

    • 取值:

      数组名[行号][列号];
      
    • 赋值

      数组名 [行号][列号] =;
      
  • 代码

    #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
  • 需求:矩阵的转置

  • 分析:

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

    在这里插入图片描述

  • 代码:

    #include <stdio.h>#define ROW 2
    #define COL 3int main()
    {//定义循环变量i,jint 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语言提供了两种实现方式:

  • 字符数组

    char name[] = "哪吒";
    
  • 字符指针

    char *name = "哪吒";
    
概念

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

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

实验:

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

一维数组:

char 数组名[数组容量];

二维数组:

char 数组名[行容量][列容量]

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

注意:

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

比如:

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

  • 代码

    #include <>int main()
    {//创建一个数组,用来存储 I LOVE YOU,ASCII中对应的空格为' ',其对应的ASCII码为32char 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
  • 需求:输出一个用字符*组成的空菱形图案

  • 代码:

    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;
    }
    
注意
  • 如果定义时,不初始化,元素的值不确定(针对局部定义的数组)

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

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

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

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

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

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

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

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

  • 演示

    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++){//过滤\0if (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;    
    }
    
注意
  • 字符串的长度与字符数组的长度不一定相同。

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

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

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

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

字符串输入

scanf

语法:

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

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

案例:

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

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

fgets

语法:

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

功能:

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

说明:

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

案例:

#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 移出】

语法:

gets(数组名);

功能:

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

说明:

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

案例:

#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

语法:

printf("%s",数组名)

案例:

 #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

语法:

fputs(数组名,shdout)

功能:

​ 输出一个字符串

说明:

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

案例:

#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移出】

语法:

puts(数组名称)

功能:

​ 输出一个字符串

说明:

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

案例:

#include <stdio.h>int main(int argc,char *argv[])
{// 创建一个数组,用来存放人的名字char name[20];printf("请输入您的名字:\n");// gets、fgets和scanf只能多选一gets(name);// 输出puts(name);// 标准的输出return 0;
}

字符串转数值【扩展】

  • strtol

    long strtol (const char *str, char **endptr, int base);
    

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

    参数说明:

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

    unsigned long strtoul(const char *str, char **endptr, int base);
    

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

  • strod

    double strtod(const char *str, char **endptr);
    
  • atoi

    int atoi(const char *str)
    

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

  • atof

    double atof(const char *str);
    

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

案例:

#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();

字符串相关函数

字符串拼接

语法:

strcat(字符串1,需要拼接的字符串2);

解释:

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

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

引入

#include <string.h>

案例:

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

  • 分析:

    在这里插入图片描述

  • 代码:

    #include <stido.h>
    #include <string.h>int main()
    {//创建一个数组,用来接收控制台输入的字符常量,字符串1char 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);

字符串拷贝

语法:

strcpy(数组名,字符串)

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

引入:

#include <string.h>

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

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

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

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

案例:

#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;
}
字符串比较

语法:

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

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

引入:

#include <string.h>

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

返回值:

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

说明:

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

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

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

案例:

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

  • 代码:

    #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");elseprintf("用户名或者密码错误!\n");return 0;
    }
    
  • 运行结果

    在这里插入图片描述

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

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

案例:

  • 需求:字符串长度案例

  • 代码:

#include <stdio.h>
#include <string.h>
int main()
{//测试数据1char s1[] = {'h','i','\0','h','i','\0'};printf("数组长度:%lu,字符串长度:%lu\n", sizeof(s1)/sizeof(s1[0]),strlen(s1)); // 6   2//测试数据2char 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//测试数据4char s4[] = "hello";printf("数组长度:%lu,字符串长度:%lu\n", sizeof(s4)/sizeof(s4[0]),strlen(4));//4  5return 0;
}
  • 运行结果:

    在这里插入图片描述

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

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

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

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

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

    在这里插入图片描述

  • 代码:

    #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 = 0if(isspace(c)){//如果是空格,标记word = 0word = 0}else{//如果是非空格,标记 word = 1//如果上一个字符是否是空格,如果是,就需要统计单词if(!word)   //word == 0{//更改word = 1word = 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]进行比较,得到最大者。

#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*/}
http://www.xdnf.cn/news/493903.html

相关文章:

  • WL-G4048 Multi-Port PCIe 4.0 Switch
  • AI最新资讯,GPT4.1加入网页端、Claude 3.7 Sonnet携“极限推理”发布在即
  • 解决将其他盘可用空间,移植到C盘
  • 2025第三届盘古石杯初赛(计算机部分)
  • 直接从图片生成 html
  • 传统轮椅逆袭!RDK + 激光雷达如何重塑出行体验?
  • TII-2024《AGP-Net: Adaptive Graph Prior Network for Image Denoising》
  • C/C++——动态爱心
  • 信贷风控笔记5——风控贷中策略笔记(面试准备13)
  • 【匹配】Hirschberg
  • Baklib加速企业AI数据智理转型
  • 前台页面卡顿,如何去排查问题
  • 【源码级开发】Qwen3接入MCP,企业级智能体开发实战!
  • 软考第七章知识点总结
  • 力扣-39.组合总和
  • 开源情报如何成为信息攻防的关键资源
  • 科技型中小企业基本条件及与高新技术企业的区别
  • TIP-2021《SRGAT: Single Image Super-Resolution With Graph Attention Network》
  • 多线程代码案例-2 阻塞队列
  • 五月份嵌入式面试总结
  • Hot100-链表-JS
  • PCIeSwitch 学习
  • 技术博客:探索LPG与RDF在知识图谱构建中的作用
  • 智能呼入:云蝠大模型赋能政府热线
  • 文章记单词 | 第86篇(六级)
  • memcached主主复制+keepalive
  • 如何设置线程池大小
  • Spring bean 的生命周期、注入方式和作用域
  • LangGraph 官方文档翻译 - 快速入门及示例教程(聊天、工具、记忆、人工干预、自定义状态、时间回溯)
  • 【全解析】EN18031标准下的SSM安全存储机制