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
- 第1轮:5,4,3,2,1 → 4,3,2,1,
-
总结:
-
案例设计到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
将被 设置为指向第一个未转换字符的指针。如果endptr
是NULL
,则不使用它。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*/}
相关文章:
C 语言学习笔记(数组)
C 语言基础:第 08天笔记 内容提要 数组 排序算法:冒泡排序二维数组字符数组 数组 冒泡排序 排序思想(向前冒泡): 一次排好一个数,针对n个数,最差情况需要n - 1次就可以排好每次排序假定第一…...
jvm安全点(二)openjdk17 c++源码垃圾回收安全点信号函数处理线程阻塞
1. 信号处理与桩代码(Stub) 当线程访问安全点轮询页(Polling Page)时: 触发 SIGSEGV 信号:访问只读的轮询页会引发 SIGSEGV 异常。信号处理函数:pd_hotspot_signal_handl…...
uni-app 开发HarmonyOS的鸿蒙影视项目分享:从实战案例到开源后台
最近,HBuilderX 新版本发布,带来了令人兴奋的消息——uni-app 现在支持 Harmony Next 平台的 App 开发。这对于开发者来说无疑是一个巨大的福音,意味着使用熟悉的 Vue 3 语法和开发框架,就可以为鸿蒙生态贡献自己的力量。 前言 作…...
【赵渝强老师】在PostgreSQL中访问Oracle
在PostgreSQL数据库中,oracle_fdw是PostgreSQL数据库支持的外部扩展。通过使用oracle_fdw扩展可以读取到Oracle数据库中的数据。它是一种非常方便且常见的PostgreSQL与Oracle的同步数据的方法。使用oracle_fdw扩展需要依赖Oracle的Instance Client环境。 视频讲解如…...
板凳-------Mysql cookbook学习 (二)
生成一个包含cookbook数据库中的表备份的名为backup.sql的dump文件。 sql C:\Users\lenovo>mysqldump -u root -p --default-character-setutf8mb4 cookbook > D:\sql\Mysql_learning\backup.sql mysqldump 不是内部或外部命令,也不是可运行的程序 或批处理文…...
sudo apt update是什么意思呢?
非常好的问题! ✅ sudo apt update 是什么意思? 它的作用是: 更新你的 Ubuntu 系统中软件列表的信息(但不安装软件) 就像你每天先去超市了解今天上架了哪些新商品(只是“查看”而不是“买”)&a…...
.NET Core 中 Swagger 配置详解:常用配置与实战技巧
随着微服务架构和 RESTful API 的广泛应用,API 文档的管理和自动化生成成为了开发中的重要部分。Swagger(现为 OpenAPI)是一款功能强大的工具,它可以自动生成 API 文档,并提供交互式 UI,帮助开发者、测试人…...
spring cache使用指南
Spring cache Spring Cache 是一个框架,实现了基于注解的缓存功能,只需要简单地加一个注解,就能实现缓存功能。 Spring Cache 提供了一层抽象,底层可以切换不同的缓存实现。 例如:EHCache,Caffeine,Redi…...
9.DMA
目录 DMA —为 CPU 减负 DMA 的简介和使用场景 DMA 的例子讲解 STM32 的 DMA 框图和主要特性 编辑 DMA 的通道的对应通道外设 – DMA 和哪些外设使用 编辑编辑ADC_DR 寄存器地址的计算 常见的数据滤波方法 ADCDMA 的编程 DMA —为 CPU 减负 DMA 的简介和使用场…...
Python自学笔记3 常见运算符
常用运算符 加减法 python的自动数据类型转换 整形转为浮点型 实数转为复数 数字类型不能和浮点数类型相加减 乘除法 数据转换基本同加减法, 但字符串可以和整数相加减,作用是字符串的自我复制 反斜杠 成员运算符 判断一个元素是不是一个序列的成员…...
【C/C++】C++中constexpr与const的深度对比
文章目录 C中constexpr与const的深度对比1. 编译期确定性2. 更严格的优化保证3. 适用范围更广4. 类型安全与错误检查5. 现代 C 的演进方向何时使用 const?constexpr应用场景1. 配置常量与全局参数2. 数据验证与业务规则检查3. 数学计算与业务逻辑优化4. 模板元编程与…...
劳特巴赫trace32负载率测试
按照下图步骤点击即可...
牛客OJ在线编程常见输入输出练习--Java版
目录 一、链接 二、题目 一、链接 牛客输入输出链接:牛客网 - 找工作神器|笔试题库|面试经验|实习招聘内推,求职就业一站解决_牛客网 二、题目 1.只有输出 public class Main {public static void main(String[] args) {System.out.println("H…...
STM32 | FreeRTOS 递归信号量
递归信号量 一、概述 互斥量的使用比较单一,因为它是信号量的一种,并且它是以锁的形式存在。在初始化的时候,互斥量处于开锁的状态,而被任务持有的时候则立刻转为闭锁的状态。 递归类型的互斥量可以被拥有者重复获取。拥有互斥量…...
STM32 | 软件定时器
01 一、概述 软件定时器是用程序模拟出来的定时器,可以由一个硬件定时器模拟出成千上万个软件定时器,这样程序在需要使用较多定时器的时候就不会受限于硬件资源的不足,这是软件定时器的一个优点,即数量不受限制。但由于软件定…...
2025年EB SCI2区TOP,多策略改进黑翅鸢算法MBKA+空调系统RC参数辨识与负载聚合分析,深度解析+性能实测
目录 1.摘要2.黑翅鸢优化算法BKA原理3.改进策略4.结果展示5.参考文献6.代码获取7.读者交流 1.摘要 随着空调负载在电力系统中所占比例的不断上升,其作为需求响应资源的潜力日益凸显。然而,由于建筑环境和用户行为的变化,空调负载具有异质性和…...
互联网大厂Java面试:从Spring到微服务的全面探讨
文章简述 本文模拟了一个互联网大厂Java求职者的面试场景,涵盖了Java核心语言与平台、构建工具、Web框架、微服务与云原生等多个技术栈。通过面试问答的形式,展示了在真实业务场景下如何应用这些技术点,帮助初学者理解和学习。 场景介绍 在…...
Python爬虫之路(14)--playwright浏览器自动化
playwright 前言 你有没有在用 Selenium 抓网页的时候,体验过那种「明明点了按钮,它却装死不动」的痛苦?或者那种「刚加载完页面,它又刷新了」的抓狂?别担心,你不是一个人——那是 Selenium 在和现代前…...
Elasticsearch Fetch阶段面试题
Elasticsearch Fetch阶段面试题 🚀 目录 基础原理性能优化错误排查场景设计底层机制总结基础原理 🔍 面试题1:基础原理 题目: 请描述Elasticsearch分布式搜索中Query阶段和Fetch阶段的工作流程,为什么需要将搜索过程拆分为这两个阶段? 👉 点击查看答案 查询流程…...
RAGFlow Arbitrary Account Takeover Vulnerability
文章目录 RAGFlowVulnerability Description[1]Vulnerability Steps[2]Vulnerability Steps[3]Vulnerability Steps RAGFlow RAGFlow is an open-source RAG (Retrieval-Augmented Generation) engine developed by Infiniflow, focused on deep document understanding and d…...
框架之下再看HTTP请求对接后端method
在当今的软件开发领域,各类框架涌现,极大地提升了开发效率。以 Java 开发为例,Spring 框架不断演进,Spring Boot 更是简化到只需引入 Maven 包,添加诸如SpringBootApplication、RestController等注解,就能轻…...
机器学习中的过拟合及示例
文章目录 机器学习中的过拟合及示例1. 过拟合的定义2. 过拟合的常见例子例1:图像分类中的过拟合例2:回归任务中的过拟合例3:自然语言处理(NLP)中的过拟合 3. Python代码示例:过拟合的直观演示示例1…...
机器学习-人与机器生数据的区分模型测试 -数据筛选
内容继续机器学习-人与机器生数据的区分模型测试 使用随机森林的弱学习树来筛选相对稳定的特征数据 # 随机森林筛选特征 X data.drop([city, target], axis1) # 去除修改前的城市名称列和目标变量列 y data[target] X_train, X_test, y_train, y_test train_test_split(X…...
第9讲、深入理解Scaled Dot-Product Attention
Scaled Dot-Product Attention是Transformer架构的核心组件,也是现代深度学习中最重要的注意力机制之一。本文将从原理、实现和应用三个方面深入剖析这一机制。 1. 基本原理 Scaled Dot-Product Attention的本质是一种加权求和机制,通过计算查询(Query…...
无监督学习在医疗AI领域的前沿:多模态整合、疾病亚型发现与异常检测
引言 人工智能技术在医疗领域的应用正经历着从辅助决策向深度赋能的转变。无监督学习作为人工智能的核心范式之一,因其无需大量标注数据、能够自动发现数据内在规律的特性,在医疗AI领域展现出独特优势。尤其在2025年,无监督学习技术在医疗AI应用中呈现出多模态整合、疾病亚…...
PostgreSQL内幕剖析——结构与架构
大家好,这里是失踪人口bang__bang_,从今天开始持续更新PostgreSQL内幕相关内容,让我们一起了解学习吧✊! 目录 1️⃣ DB集群、数据库、表 🍙 数据库集群的逻辑结构 🍙 数据库集群的物理结构 &am…...
架构师论文《论模型驱动架构软件开发方法及其应用》
摘要 在当前的软件开发领域,模型驱动架构(MDA)作为一种重要的开发方法,强调通过抽象化模型指导系统设计与实现,能够有效提升开发效率并降低复杂性。本文结合笔者参与的某医疗信息管理系统的开发实践,探讨MD…...
当硅基存在成为人性延伸的注脚:论情感科技重构社会联结的可能性
在东京大学机器人实验室的档案室里,保存着一份泛黄的二战时期设计图——1943年日本陆军省秘密研发的“慰安妇替代品”草图。这个诞生于战争阴霾的金属躯体,与2025年上海进博会上展出的MetaBox AI伴侣形成时空对话:当人类将情感需求投射于硅基…...
最小二乘法拟合直线,用线性回归法、梯度下降法实现
参考笔记: 最小二乘法拟合直线,多个方法实现-CSDN博客 一文让你彻底搞懂最小二乘法(超详细推导)-CSDN博客 目录 1.问题引入 2.线性回归法 2.1 模型假设 2.2 定义误差函数 2.3 求偏导并解方程 2.4 案例实例 2.4.1 手工计算…...
机器学习 day04
文章目录 前言一、线性回归的基本概念二、损失函数三、最小二乘法 前言 通过今天的学习,我掌握了机器学习中的线性回归的相关基本概念,包括损失函数的概念,最小二乘法的理论与算法实现。 一、线性回归的基本概念 要理解什么是线性回归&…...
数据分析_Python
1 分析内容 1.1 数据的整体概述 提供数据集的基本信息,包括数据量、时间跨度、地理范围和主要字段. import pandas as pd# 创建示例数据 data {姓名: [张三, 李四, 王五, 赵六, 钱七, 孙八, 周九, 吴十],年龄: [25, 30, 35, 40, 45, 50, 55, 60],性别: [男, 男, 女, 女, 男,…...
精益数据分析(63/126):移情阶段的深度潜入——从用户生活到产品渗透的全链路解析
精益数据分析(63/126):移情阶段的深度潜入——从用户生活到产品渗透的全链路解析 在创业的移情阶段,成功的关键不仅在于发现用户的表面需求,更在于深入潜入用户的日常生活,理解其行为背后的真实动机与场景…...
【MySQL】第五弹——表的CRUD进阶(三)聚合查询(上)
文章目录 🌅聚合函数🌊1.COUNT();统计所有行🌊2. SUM(列名); 求和🌊3. AVG() 求平均🌊4. MAX(),MIIN() 🌅分组查询🌊GROUP BY 子句🌊HAVING 🌅联合查询🌊联合…...
英语学习5.16
recede 【动词】 👉 关键词:后退、减弱、退去 ✅ 释义: 后退,远离 指物体逐渐远离、移开或变得不明显,常用于描述水面、声音、军队、头发线等的“退却”或“后移”。 如:The floodwaters receded.&#x…...
创建react工程并集成tailwindcss
1. 创建工程 npm create vite admin --template react 2.集成tailwndcss 打开官网跟着操作一下就行。 Installing Tailwind CSS with Vite - Tailwind CSS...
2025 年九江市第二十三届中职学校技能大赛 (网络安全)赛项竞赛样题
2025 年九江市第二十三届中职学校技能大赛 (网络安全)赛项竞赛样题 (二)A 模块基础设施设置/安全加固(200 分)A-1 任务一登录安全加固(Windows,Linux)A-2 任务二 Nginx 安全策略&…...
STM32IIC实战-OLED模板
STM32IIC实战-OLED模板 一,SSD1306 控制芯片1, 主要特性2,I2C 通信协议3, 显示原理4, 控制流程5, 开发思路 二,HAL I2C API 解析I2C 相关 API1,2,3,4…...
BMVC2023 | 多样化高层特征以提升对抗迁移性
Diversifying the High-level Features for better Adversarial Transferability 摘要-Abstract引言-Introduction相关工作-Related Work方法-Methodology实验-Experiments结论-Conclusion 论文链接 GitHub链接 本文 “Diversifying the High-level Features for better Adve…...
C++ deque双端队列、deque对象创建、deque赋值操作
在deque中,front()是头部元素,back()指的是尾部元素。begin()是指向头部的迭代器,end()是指向尾部的下一个元素的迭代器。 push_front 头部进行插入 pop_front 尾部进行删除 push_back 尾部进行插入 pop_back 尾部进行删除 deque如果同时…...
【论文阅读】人脸修复(face restoration ) 不同先验代表算法整理2
文章目录 一、前述二、不同的先验及代表性论文2.1 几何先验(Geometric Prior)2.2 生成式先验(Generative Prior)2.3 codebook先验(Vector Quantized Codebook Prior)2.4 扩散先验 (Diffusion Pr…...
2025年渗透测试面试题总结-百度面经(题目+回答)
网络安全领域各种资源,学习文档,以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具,欢迎关注。 目录 百度面经 百度安全工程师面试深度复盘与优化指南 一、项目经验反思与优化策略 二、技术问题深度解析 …...
muduo库TcpConnection模块详解——C++
muduo库中的TcpConnection模块详解 TcpConnection是muduo库中处理TCP连接的核心模块,负责管理单个TCP连接的生命周期、数据读写、状态转换以及事件回调。每个TCP连接对应一个TcpConnection对象,其设计体现了高性能、线程安全和灵活回调的特点。 一、核心…...
aksharetools:大模型智能体框架agno可直接获取A股金融数据
原创内容第889篇,专注智能量化投资、个人成长与财富自由。 今天说说金融智能体开发。 智能体开发需要一个多agent框架。这样的框架,现在太多了,langchain, langgraph,autogen,crewai等等,还有各种低代码平…...
使用Maven部署WebLogic应用
使用Maven部署WebLogic应用 在Maven项目中部署应用到WebLogic服务器可以通过以下几种方式实现: 1. 使用WebLogic Maven插件 (官方推荐) Oracle提供了官方的WebLogic Maven插件,这是最直接的部署方式。 基本配置 <build><plugins><pl…...
[Java][Leetcode simple] 13. 罗马数字转整数
一、自己想的 只有提到的六种情况是-,其他都是 public int romanToInt1(String s) {int res 0;int n s.length();Map<Character, Integer> map new HashMap<>();map.put(I, 1);map.put(V, 5);map.put(X, 10);map.put(L, 50);map.put(C, 100);map.pu…...
【论文阅读】针对BEV感知的攻击
Understanding the Robustness of 3D Object Detection with Bird’s-Eye-View Representations in Autonomous Driving 这篇文章是发表在CVPR上的一篇文章,针对基于BEV的目标检测算法进行了两类可靠性分析,即恶劣自然条件以及敌对攻击。同时也提出了一…...
Ansible模块——设置软件仓库和安装软件包
设置软件仓库 ansible.builtin.rpm_key ansible.builtin.rpm_key 用于在 Fedora/RHEL 上导入或移除 GPG 公钥。 参数名 类型 默认值 说明 fingerprintstrnull 指定公钥的完整指纹(long-form)。在导入前会比对公钥是否匹配此指纹,增强安全…...
基于CentOS7制作OpenSSL 1.1的RPM包
背景:CentOS7 已经不再维护了,有时候需要升级某些组件,网上却没有相关的资源了。尤其是制作OpenSSH 9.6 的RPM包,就会要求OpenSSL为1.1的版本。基于此,还是自己制作吧,以下是踩坑过程。 1、官网提供的源码包…...
【Element UI】表单及其验证规则详细
Form表单 Form表单验证1. 使用方法2. rule参数3. validator回调函数异步服务器验证 Form表单验证 Form组件提供了表单验证的功能,需要通过rules属性传入约定的验证规则,并将Form-Item的prop属性设置为需校验的字段名 1. 使用方法 结构: &…...
使用 Python 打造一个强大的文件系统结构创建器
本文将深入分析一个基于 wxPython 的文件系统结构创建器程序,展示如何通过 CustomTreeCtrl 组件实现文件夹和文件的可视化管理,并提供添加、删除、导入、清空以及创建文件系统结构的强大功能。这个程序不仅适合开发者快速构建文件系统原型,还…...