字符串
字符串基础操作
在用格式化说明符%s进行输入输出时,其输入输出项均为数组名。但在输入时,相邻两个字符串之间要用空格分隔,系统将自动在字符串后加\0
。在输出时,遇到结束符\0
作为输出结束标志。
对于字符串的操作,我们需要使用到一些系统提供的API函数。
字符串输入
scanf
语法:
scanf("%s",数组名);
注意:数组名对应的数组只能是char类型,从控制台输入字符串之后,默认为追加\0
案例:
#include <stdio.h>
int main(int argc,char *argv[])
{
// 创建一个char数组,用来存储姓名
char name[20];
printf("请输入您的名字:\n");
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]; // 只是创建数组,必须指定容量;如果初始化,可以省略容量。
// 计算数组容量
int len = sizeof(name) / sizeof(name[0]);
printf("请输入您的姓名:\n");
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);
printf("您的姓名是%s\n", name);
return 0;
}
字符串输出
printf
语法:
printf("%s",数组名);
案例:
#include <stdio.h>
int main(int argc,char *argv[])
{
// 创建一个字符数组,用来存储姓名
char name[20]; // 只是创建数组,必须指定容量;如果初始化,可以省略容量。
// 计算数组容量
int len = sizeof(name) / sizeof(name[0]);
printf("请输入您的姓名:\n");
fgets(name, len, stdin);
printf("您的姓名是%s\n", name);.// %s支持字符串常量,也支持字符数组,都是以字符串形式输出
return 0;
}
fputs
语法:
fputs(数组名,stdout);
功能:
输出一个字符串
说明:
字符串可以包含转义字符(以\
开头的字符)
案例:
#include <stdio.h>
int main(int argc,char *argv[])
{
char arr[] = "hi xiaojiao\neat!\n";
// 第1种输出
printf("%s", arr);
// 第2种输出
fputs(arr, stdout);
return 0;
}
运行效果:
puts 危险的【C11移出】
语法:
puts(数组名称);
功能:
输出一个字符串
说明:
字符串可以包含转义字符
案例:
#include <stdio.h>
int main(int argc,char *argv[])
{
char arr[] = "hi xiaojiao\neat!\n";
// 第1种输出
printf("%s", arr);
// 第2种输出
puts(arr);
return 0;
}
运行效果:
字符串相关函数
字符串拼接
语法:
strcat(字符数组,需要拼接的字符串或者字符数组或者字符指针);
解释:
① 参数1必须是字符数组;参数2可以是字符数组、可以是字符串常量、还可以是字符指针。
② 这里的参数2被拼接到了参数1,所以参数1的剩余空间足够大,要能够容纳参数2。
引入:
#include <string.h>
案例:
-
需求:将两个字符串拼接为一个字符串
-
分析:
-
代码:
#include <stdio.h> // 使用字符串相关函数需要引入必要的头文件 #include <string.h> int main(int argc,char *argv[]) { // 创建一个字符数组,用来接收控制台输入 char name[20]; printf("请输入您的名字:\n"); // 通过控制台输入字符串(支持空格) fgets(name, sizeof(name) / sizeof(name[0]), stdin); // 输出拼接 strcat返回拼接后的字符串 fputs(strcat(name, "你好!"), stdout); printf("\n"); // char str[50]; // fputs(strcat(str, strcat(name, "你好!")), stdout); 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, "**鸿");// 正确,利用函数实现类似赋值的操作
注意: strcat和strcpy的区别:
- strcat:
**殇
+**鸿
→**殇**鸿
(追加) - strcpy:
**殇
+**鸿
→**鸿
(覆盖)
案例:
#include <stdio.h>
#include <string.h>
int main(int argc,char *argv[])
{
// 需求:对数组赋值
char name[50] = "hello";
printf("打印初始化后的数组:%s\n", name);
// 对一个数组赋:
// name = "**殇"; // 数组一旦创建,就无法改变,所以不能对数组进行赋值
// 通过 strcpy(字符数组,字符数组/字符常量/字符指针)实现给数组赋值
strcpy(name, "my");// my | myllo
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(int argc,char *argv[]) { // 用户登陆案例 // 创建两个变量,用来存储用户名和密码 char username[20], password[8]; printf("---------用户登录--------\n"); printf("请输入您的用户名:\n"); scanf("%s",username);// 数组名本身就是一个地址(首元素的首地址) printf("请输入您的密码:\n"); scanf("%s",password); // 校验 if (!strcmp(username,"admin") && !strcmp(password,"123456")) // 相等:strcmp(..) == 0 printf("登录成功!\n"); else printf("用户名或者密码错误!\n"); return 0; }
-
运行结果:
字符串长度
语法:
strlen(字符串);
引用:
#include <string.h>
注意:返回字符串中包含的字符的实际个数。遇到\0结束,不包含\0;如果数组中不存在\0,就以数组的实际长度作为字符串长度。
案例
-
需求:字符串长度案例
-
代码:
#include <stdio.h> #include <string.h> int main(int argc,char *argv[]) { // 测试数据1 char s1[] = {'h','i','\0','h','i','\0'}; printf("数组长度:%lu\n字符串长度:%lu\n", sizeof(s1)/sizeof(s1[0]), strlen(s1));// 数组长度:6,字符串长度:2 // 测试数据2 char s2[] = "hi\0hi\0";// 使用双引号包裹的内容称之为 字符串常量,字符串常量默认会有一个结尾的\0 printf("数组长度:%lu\n字符串长度:%lu\n", sizeof(s2)/sizeof(s2[0]), strlen(s2));// 数组长度:7,字符串长度:2 // 测试数据3 char s3[] = {'h','e','l','l','o'};// strlen()判断一个字符串的长度,优先判断是否存在\0,如果不存在,就返回数组实际长度,因编译器原因,处理机制也有所不同。 printf("数组长度:%lu\n字符串长度:%lu\n", sizeof(s3)/sizeof(s3[0]), strlen(s3));// 数组长度:5,字符串长度:5,这种写法不安全,不同编译器编译结果不同 // 测试数据4 char s4[] = "hello"; printf("数组长度:%lu\n字符串长度:%lu\n", sizeof(s4)/sizeof(s4[0]), strlen(s4));// 数组长度:6,字符串长度:5 return 0; }
运行结果:
案例
-
需求:输入一行字符,统计其中有多少个单词,单词之间使用空格隔开。举例:I LOVE YOU
分析:采用通过空格统计单词的方法。具体是:
① 用连续若干个空格算一个、一行开头的空格不计的方法决定单词数目;
② 从第一个字符开始逐个检查字符串中的每一个字符。若查到某一字符非空格,而其前面的字符是空格,则表示新单词开始,让计数变量num++。否则,当前字符非空格,前面字符也非空格,则非新单词,num不变;
③ 用变量word=0或1来表示前面字符是空格或不是空格。则:
-
代码:
#include <stdio.h> #include <ctype.h> int main(int argc,char *argv[]) { // 创建一个数组,用来接收控制台录入的字符串 char string[100]; // 创建2个变量,word:统计字符是否是空字符(空字符:0,非空字符:1),num:用来统计单词个数 int num = 0, word = 0; // 创建一个变量,用来存储遍历到的字符 char c; // 通过控制台录入字符串 printf("请输入一句话:\n"); fgets(string, sizeof(string)/sizeof(string[0]), stdin); // 遍历 for (int i = 0; (c = string[i])!='\0'; i++) { if (isspace(c)) // 判断一个字符是否是空格,等价于 if (c == ' ') { // 如果是空格,标记 word = 0; } else { // 如果上一个字符是空格,就需要统计单词 if (!word) // 等价于 word == 0 { // 标记word为非空格 word = 1; // 统计单词个数 num ++; } } } printf("%s\n中有%d个单词!\n", string, num); 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>
int main(int argc,char *argv[])
{
// 创建一个数组,用来存储最大的字符串
char max[20];
// 创建一个数组,用来存储3个用来参与比较的字符串
char str[3][20];
int i;
// 通过循环控制台输入
printf("请输入3个测试字符串:\n");
for (i = 0; i < 3; i++)
{
fgets(str[i],20,stdin);
// 移除fgets读取的换行符
str[i][strcspn(str[i], "\n")] = '\0';
}
// 比较
if (strcmp(str[0],str[1]) > 0) strcpy(max, str[0]);
else strcpy(max,str[1]);
if (strcmp(str[2],max) > 0) strcpy(max,str[2]);
printf("\n三个字符串中最大的字符串是%s\n!", max);
return 0;
}
运行结果: