Linux和C语言(Day07)
一、学习内容
-
字符数组和字符串
-
字符数组
-
用于存储多个字符的数组。
-
char a[5]={'h','q','y','j'};
-
-
-
字符串
-
用""引起来0个或多个字符。使用指针或者数组存储。计算机会自动添加结束标志'\0'。
-
char *s="hqyj";
-
char s[]="hqyj";
-
空串:0个字符。 ""
-
空格串:只存储空格的串。 " "
-
子串:从主串中分离出的1个或多个连续的字符。
-
-
-
关于字符数组和字符串的初始化
-
全部初始化
-
char a[5]={'h','q','y','j','6'};
-
char a[5]={"hqyj"};
-
char a[5]="hqyj";
-
char a[5]="hqyj6"; //错误的
-
-
部分初始化
-
char a[5]={'h','q'};
-
char a[5]="hq";
-
-
特殊初始化
-
殊初始化
-
char a[]={'h','q','y','j','6','6','6'}; //字节为 7
-
char a[]="hqyj666"; //字节为 8
-
-
错误初始化
-
char a[5];
-
a={'h','q','y','j'}; 错误
-
a="hqyj"; 错误
-
-
-
关于字符数组和字符串的输出
-
字符数组的输出
-
char a[5]={'h','q','y','j','6'}; //存储多个单字符 for(i=0; i<5; i++){ printf("%c",a[i]); putchar(a[i]); } //不常用
-
-
字符串的输出
-
char a[]="hqyj666"; //存储 1个字符串 printf("%s" , a); puts(a);
-
特殊情况
-
char a[5]={'h','q','y','j','\0'}; 该数组可以 printf("%s" , a);
-
char a[5]={'h','q','y','j', 0}; 该数组可以 printf("%s" , a);
-
char a[5]={'h','q','y','j','0'}; 该数组不可以 不可以 不可以 printf("%s" , a);
-
-
-
字符串的输入
-
char a[20];//可以存储多个单字符 也可以存储 1 个字符串
-
scanf("%s" , a); //%s输入时,不加 &
-
gets(a); //gets可以输入空格 scanf()不可以输入空格
-
-
-
-
字符串处理函数 #include <string.h>
-
strlen函数
-
功能:求一个字符串的长度
-
原型:size_t strlen(const char *s);
-
分析:size_t 是返回值【64位返回值是long int %ld 32位系统返回值是int %d】 const char *s是参数 const表示不可变 char *s 传字符串首地址【字符串名/数组名】
-
使用:char a[]="hqyj66"; strlen(a);
-
-
strcat函数
-
功能:将一个字符串连接/追加到另一个字符串的后面
-
原型:char *strcat(char *dest, const char *src);
-
分析:char *返回值 【字符串首地址】 第一个参数char *dest目标字符串,追加到TA后面【定义要尽量大】 第二个参数const char *src源字符串
-
使用:strcat("hyqj" , "666"); 结果是"hqyj666"
-
-
strcmp函数
-
功能:strcmp 函数逐个比较两个字符串 str1 和 str2 中的字符,直到遇到不同字符或到达字符串的结尾。比较时是按照字符的 ASCII 码值进行的。
-
原型:int strcmp(const char *s1, const char *s2);
-
分析:返回值 int 【>0 <0 ==0】 参数1:const char *s1 字符串1 参数2:const char *s2 字符串2
-
使用:strcmp(s1,s2)>0 说明s1>s2 strcmp(s1,s2)<0 说明s1<s2 strcmp(s1,s2)==0 说明s1==s2
-
-
strcpy函数
-
功能:拷贝/复制/赋值
-
原型:char *strcpy(char *dest, const char *src);
-
使用:strcpy(s , "hqyj"); strcpy(name , "孙文雅"); strcpy(s , name);
-
-
-
二维字符数组
-
char a[5][100]; 表示存储5个字符串 其中5表示 5行 5个字符串 100表示 100列 1个字符串的最大长度
-
初始化
-
char a[3][5]={'a','b','c','d','e',\ '1','2','3','4','5',\ 'a','b','c','d','e'}; 【一般不用】 char a[3][5]={"hqyj","1234","hqyj"};
-
-
按字符串输出
-
for(i=0; i<3; i++){ printf("%s " , a[i]); }
-
-
-
脑图
二、作业
1.下列对 C 语言字符数组的描述中错误的是 ( ) (鲁科安全)
A. 字符数组可以存放字符串
B. 字符数组中的字符串可以整体输入、输出
C. 不可以用关系运算符对字符数组中的字符串进行比较
D. 可以在赋值语句中通过赋值运算符 "=" 对字符数组整体赋值
解析:
A: 正确。字符数组可以存放字符串。
B: 正确。字符数组中的字符串可以整体输入、输出(例如 scanf("%s", array)
和 printf("%s", array)
)。
C: 正确。不能用关系运算符 ==
、>
等直接比较字符数组中的字符串。字符串比较应使用函数如 strcmp()
。
D: 在 C 语言中,字符数组不能直接通过 =
运算符整体赋值。你需要逐个字符进行赋值或者使用函数,如 strcpy()
来实现字符串的拷贝.
解答:
D
2.下列描述中不正确的是( )(华三外协)
A.字符型数组中可以存放字符串
B.可以对字符型数组进行整体输入、输出
C.可以对整型数组进行整体输入、输出
D.不能在赋值语句中通过赋值运算符"="对字符型数组进行整体赋值
解析:
A: 正确。字符型数组(char array[]
)可以存放字符串,字符串实际上是以 \0
结尾的字符数组。
B: 正确。字符型数组可以整体输入输出,使用 scanf("%s", array)
或 printf("%s", array)
进行处理。
C: 不正确。整型数组(int array[]
)不能像字符数组一样使用 scanf
或 printf
一次性输入输出整个数组。整型数组的输入和输出需要逐个元素处理,或者通过循环。
D: 正确。不能通过 =
运算符直接对字符型数组进行整体赋值,需要使用字符串操作函数,如 strcpy()
。
解答:
C
3.下列代码片段执行的结果是: (云尖软件开发)
char szTest[] = "ABCDEF";
strncpy(szTest, szTest, 4);
printf("%s", szTest);
A.ABCD B. ABCDE C. ABCDEF D. 以上都不对
解析:
初始字符串 szTest
是 "ABCDEF"
,它包含 6 个字符,再加上字符串结束符 \0
,因此整个数组的内容是 {'A', 'B', 'C', 'D', 'E', 'F', '\0'}
。
strncpy(szTest, szTest, 4):因为源和目标是相同的地址,strncpy
会从 szTest
的开始复制 4 个字符到同样的位置,但这是一个没有效果的操作,因为它本质上是将数组的一部分内容覆盖到相同的地方。换句话说,szTest
的内容不会发生任何变化。
输出:printf("%s", szTest)
将会输出原始的字符串 "ABCDEF"
,因为没有任何修改。
解答:
A
4.以下对字符数组test 赋值方式错误的是( )。 (智洋)
A. char test[10]; strcpy(test, "test");
B. char test[10]; test="test";
C. char test[]={'t', 'e', 's', 't’};
D. char test[10]={'t', 'e', 's', ‘t’};
解析:
A: 正确。strcpy(test, "test");
正确地将字符串 "test"
复制到字符数组 test
中。
B: 错误。test = "test";
是非法的,因为数组名不能用 =
运算符赋值。
C: 正确。字符数组的初始化可以通过列表的方式赋值,如 {'t', 'e', 's', 't'}
,尽管这样没有自动添加 \0
结束符。
D: 正确。字符数组可以显式初始化部分或全部元素,{'t', 'e', 's', 't'}
是有效的方式,数组的剩余部分将被初始化为 0
(包括 \0
)。
解答:
B
5.以下语句不能正确赋值的是( ) (杭州快越科技, 神州安付)
A. char *s = "China";
B. char s3[20] = "China";
C. char s2[]={'C', 'h', 'i', 'n', 'a'};
D. char s1[10]; s1="China";
解析:
A: 正确。char *s = "China";
创建了一个指针 s
,指向常量字符串 "China"
,这是合法的。
B: 正确。char s3[20] = "China";
将字符串 "China"
赋值给字符数组 s3
,并且数组大小足够,这也是合法的。
C: 正确。char s2[] = {'C', 'h', 'i', 'n', 'a'};
将字符逐个赋值给数组 s2
,这也是合法的,尽管没有自动添加字符串结束符 \0
。
D:在 C 语言中,字符数组 s1
的名称是一个常量指针,指向数组的第一个元素。你不能使用赋值运算符 =
给数组名赋值。即数组名不能改变指向,因此 s1 = "China";
是非法的。
解答:
D
6.以下程序运行后输出结果是( ) (杭州快越科技)
main()
{
char ch[2][5] = {"693", "825"}, p[2][5];
int i, j, s = 0;
for(i=0;i<2;i++) p[i]=ch[i];
for(i=0;i<2;i++)
for(j=0;p[i][j]>='0' && p[i][j]<='9';j+=2)
s=10*s+p[i][j]-'0';
printf("%d\n", s);
}
A.6385 B. 33 C. 693825 D. 22
解析:
这个双重循环用于处理每个字符,并每次加到 s
中。j
从 0
开始,每次递增 2
。因此,p[i][0]
和 p[i][2]
这些字符会被处理。对于 p[0]
,即 "693"
,p[0][0]
是 '6'
,p[0][2]
是 '3'
。所以 s
将会是 6
和 3
,计算为 63
。对于 p[1]
,即 "825"
,p[1][0]
是 '8'
,p[1][2]
是 '5'
。所以 s
将会是 63
和 85
,计算为 6385
。
解答:
A
7.为了比较两个字符串s1和s2是否相等,应当使用( ) (杭州快越科技)
A. if(s1 = s2) B. if(s1==s2)
C. if(strcmp(&s1, &s2)==0) D. if(strcmp(s1, s2)==0)
解析:
A. 这是一个赋值语句,不是比较操作。s1 = s2
会将 s2
的地址赋给 s1
,这会导致编译错误,因为 s1
是一个数组名,不能被赋值。
B. 这是一个地址比较操作。s1
和 s2
是字符数组名,它们表示数组的首地址。s1 == s2
比较的是这两个数组的地址,而不是它们的内容。因此,这不会正确比较两个字符串的内容。
C. 这是错误的用法。strcmp
函数的参数应该是两个字符串,而不是字符串的地址。因此,&s1
和 &s2
是错误的参数类型,会导致编译错误或不正确的结果。
D. 这是正确的用法。strcmp
函数用于比较两个字符串的内容。如果两个字符串相等,strcmp
返回 0。因此,这种写法是正确的。
解答:
D
8.编写一个程序。输入一个字符串,将其逆序后输出?(电工时代)
代码解答:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, const char *argv[])
{
char a[100]={0};
scanf("%s",a);
int len=strlen(a);
int i,j;
printf("%d\n",len);
j=len;
for(i=0;i<len;i++){
char temp=0;
temp=a[i];
a[i]=a[len-1];
a[len-1]=temp;
len--;
}
printf("%s",a);
return 0;
}
结果展示:
9.编写一个程序。负责将一个字符串拷贝到另一个字符串,不调用 C++/C 的字符串库函数。(电工时代,泰华智慧,智洋,中安云科,北京拓普空间科技,登虹科技,杭州快越科技,鲁科安全)
代码解答:
#include <stdio.h>
int main() {
char a[100];
char b[100];
printf("请输入原有的字符串a:\n");
scanf("%s",a);
// 输入字符串 b
printf("请输入要复制的字符串 b:\n");
scanf("%s", b);
printf("输入的字符串a为:%s 需要复制的字符串b为:%s\n",a,b);
// 将字符串 b 完全拷贝到 a
int i = 0;
while (b[i] != '\0') {
a[i] = b[i]; // 将 b 中的字符复制到 a
i++;
}
// 添加字符串结束符
a[i] = '\0';
// 输出拷贝后的字符串 a
printf("字符串 a 复制后的内容是: %s\n", a);
return 0;
}
结果展示:
10.编写一个程序。不使用字符串连接函数strcat,实现两个字符串的链接 (若临视讯,福建新大陆)
代码解答:
#include <stdio.h>
int main() {
char a[100];
char b[100];
// 输入字符串 a 和 b
printf("请输入第一段字符:\n");
scanf("%s", a);
printf("请输入第二段字符:\n");
scanf("%s", b);
// 复制字符串 b 到 a 的末尾
int i = 0, j = 0;
// 找到字符串 a 的末尾
while (a[i] != '\0') {
i++;
}
// 将字符串 b 拷贝到 a 的末尾
while (b[j] != '\0') {
a[i] = b[j];
i++;
j++;
}
// 添加字符串结束符
a[i] = '\0';
// 输出结果
printf("结果字符串是: %s\n", a);
return 0;
}
结果展示:
11.编写一个程序。请实现输入一个字符串,这个字符串字符串包含一个或多个数字,把这些数字字符转换为整数,如果字符串参数包含了非数字字符,置零,不必担心算数溢出。(泰华智慧,紫光云数,H3C,拓仓科技)
输入:123abc456
输出:printf(“%d\n” , num); num=123000456
代码解答:
#include <stdio.h>
int main() {
char input[100];
int result = 0;
int i = 0;
// 输入字符串
printf("请输入一个包含数字的字符串:\n");
scanf("%s", input);
// 遍历字符串,检查是否包含非数字字符
while (input[i] != '\0') {
if (input[i] < '0' || input[i] > '9') {
input[i] = '0'; // 包含非数字字符,置为0
}
result = result * 10 + (input[i] - '0'); // 将字符转换为数字并累加
i++;
}
// 输出结果
printf("转换后的整数是: %d\n", result);
return 0;
}
结果展示:
12.编写一个程序。实现输入N个字符串,输出这N个字符串中的最大字符串和最长字符串,可以调用字符串处理函数。
代码解答:
#include <stdio.h>
#include <string.h>
#define MAX_STRINGS 100
#define MAX_LENGTH 100
int main() {
int N;
printf("请输入字符串的数量 N: ");
scanf("%d", &N);
char strings[MAX_STRINGS][MAX_LENGTH]; // 用来存储输入的字符串
char max_string[MAX_LENGTH]; // 用来存储最大字符串
char longest_string[MAX_LENGTH]; // 用来存储最长字符串
int max_length = 0; // 记录最长字符串的长度
// 输入 N 个字符串
printf("请输入 %d 个字符串:\n", N);
for (int i = 0; i < N; i++) {
scanf("%s", strings[i]);
}
// 初始化最大字符串和最长字符串为第一个字符串
strcpy(max_string, strings[0]);
strcpy(longest_string, strings[0]);
max_length = strlen(strings[0]);
// 遍历比较所有字符串
for (int i = 1; i < N; i++) {
// 比较最大字符串
if (strcmp(strings[i], max_string) > 0) {
strcpy(max_string, strings[i]);
}
// 比较最长字符串
if (strlen(strings[i]) > max_length) {
strcpy(longest_string, strings[i]);
max_length = strlen(strings[i]);
}
}
// 输出结果
printf("最大字符串是: %s\n", max_string);
printf("最长字符串是: %s\n", longest_string);
return 0;
}
结果展示:
三、总结
1. 学习内容概述:
字符数组与字符串
学习了如何使用字符数组存储字符串,以及字符串的初始化、长度计算、拼接、比较等操作。
二维字符数组
掌握了如何定义和操作二维字符数组,这部分重点在于理解每一行都是一个字符串,如何遍历和输出二维字符数组中的内容。
字符串处理函数
学习了`<string.h>`头文件中的常用字符串处理函数,包括`strlen`、`strcat`、`strcmp`、`strcpy`等,了解了每个函数的作用、参数和返回值。
2. 学习难点
字符串数组与二维字符数组的区别
字符数组存储的是单个字符串,而二维字符数组可以存储多个字符串。区分这两者的初始化方式和访问方式是学习中的难点。
字符串的自动初始化与手动初始化
通过`char str[] = "hello"`和`char str[] = {'h', 'e', 'l', 'l', 'o', '\0'}`的不同初始化方式理解字符串在内存中的存储结构,注意字符串必须以`'\0'`结尾。
`strcat`的拼接操作
在进行字符串拼接时,理解目的字符串必须有足够的空间来存放拼接后的内容,否则会引发内存溢出问题。
`strcmp`函数的返回值
理解该函数比较字符串时返回的三种结果:`0`表示相等,正值表示字符串1大于字符串2,负值表示字符串1小于字符串2。这对于字符串的排序和查找功能至关重要。
`strcpy`的内存操作
该函数直接将源字符串复制到目标位置,学习时需要注意目标数组要有足够的空间,否则可能会发生溢出。
3. 注意事项
二维字符数组的遍历
在操作二维字符数组时,需要通过双层循环来访问每个字符串的每一个字符,要小心避免越界。
字符串操作函数的安全性
使用`strcat`、`strcpy`等函数时,需要确保目标数组有足够的空间。可以考虑使用`strncat`、`strncpy`等带有长度限制的函数,来避免内存安全问题。
字符串输入
在使用`scanf`读取字符串时,必须注意到它默认会忽略空格,可以使用`gets`函数来读取含有空格的字符串,但`gets`有安全隐患,因此建议使用更安全的`fgets`函数。
4. 未来学习的重点
字符串的动态内存管理
接下来可以学习如何动态分配内存存储字符串,比如使用`malloc`来创建字符串缓冲区,以及如何正确释放内存以避免内存泄漏问题。
更复杂的字符串操作
深入学习更复杂的字符串处理函数,如`strtok`进行字符串的分割,`strchr`和`strrchr`用于查找字符的位置等。
字符编码与本地化处理
理解C语言中不同字符编码(如ASCII和Unicode),以及如何处理多字节字符,这对于处理不同语言的文本至关重要。