字符串处理函数
1.两种存放和表示字符串的方式
·字符串常量(一旦确定无法更改):“HJY”, “汉金营”
·字符数组
2.字符数组
字符数组的定义
1.先定义一个指定长度的字符数组,再单独赋值
int main()
{
char str[10];
str[0] = 'H';
str[1] = 'J';
str[2] = 'Y';
str[3] = '\0';
``````
}
2.在定义时直接给字符数组初始化
int main()
{
//初始化字符数组的每个元素
char str1[10] = {'H', 'J', 'Y', '\0'};
//不写元素的个数(编译器会自动计算)
char str2[] = {'H', 'J', 'Y', '\0'};
//使用字符串常量初始化字符数组
char str3[] = {"HJY"};
//使用字符串常量初始化,可以省略大括号(最方便)
char str4[] = "HJY";
}
3.获取字符串长度:strlen
获取的是长度,不是尺寸。长度指字符串中从起始位置到结束符的字符个数,不包含\0;尺寸包含\0。
#include <stdio.h>
#include <string.h> //使用字符串处理函数
int main()
{
char str[] = "HJY";
printf("sizeof str = %d\n", sizeof(str));//获取尺寸
printf("strlen str = %u\n", strlen(str));//获取长度,返回值是size_t就是无符号整型(unsigned int)用%u或%d
return 0;
}
4.拷贝字符串:strcpy和strncpy
#include <stdio.h>
#include <string.h>
int main()
{
char str1[] = "Original String";
char str2[] = "New String";
char str3[100];
strcpy(str1, str2);//为了避免溢出,必须确保用于存放的数组(左)长度足以容纳待拷贝的字符串(右),长度需要包含结束符 '\0' 复制str2的时候会将该字符串最后'\0'也一并复制过去
strcpy(str3, "Copy Successful");
printf("str1: %s\n", str1);
printf("str2: %s\n", str2);
printf("str3: %s\n", str3);
return 0;
}
#include <stdio.h>
#include <string.h>
int main()
{
char str1[] = "To be or not to be";
char str2[30];
strncpy(str2, str1, 5);//多一个参数指定拷贝的最大长度
str2[5] = '\0';//不会自动追加结束符,需要手动加
printf("str2: %s\n", str2);
return 0;
}
5.连接字符串:strcat和strncat
#include <stdio.h>
#include <string.h>
int main()
{
char str1[] = "I love";
char str2[] = "HJY";
strcat(str1, " ");
strcat(str1, str2);
printf("str1: %s\n", str1);
return 0;
}
/*strncat:
#include <string.h>
...
char *strncat(char *dest, const char *src, size_t n);
n:指定待连接的源字符串的最大长度
*/
6.比较字符串:strcmp和strncmp
#include <stdio.h>
#include <string.h>
int main()
{
char str1[] = "HJY";
char str2[] = "HJY";
if (!strcmp(str1, srtr2))//完全相等返回0
{
printf("两个字符串完全一致!\n");
}
else
{
printf("两个字符串存在差异!\n");
}
return 0;
}
/*strncmp:
#include <string.h>
...
int strncmp(const char *s1, const char *s2, size_t n);
n:指定待比较的字符数
*/
7.练习
1.请问下面字符串会打印什么内容?
#include <stdio.h>
#include <string.h>
int main()
{
char str[] = "Today is Friday!";
str[7] = '\0';
printf("sizeof str = %d\n", sizeof(str));
printf("strlen str = %d\n", strlen(str));
return 0;
}
答:sizeof运算符是取得字符串的尺寸,即该字符串所处存储空间的大小。
代码开头的char str[] = "I love Fish.com!"决定了该字符数组的尺寸。而字符串的长度则是由第一个遇到的结束符(‘\0’)所定义的。只要编译器读取到结束符(‘\0’),他不管你字数数组后面是否还有其他内容,他都会认为字符串已经结束。
应该打印:
sizeof str = 17
strlen str = 7
2.请指出下面代码中出现的问题?
#include <stdio.h>
#include <string.h>
int main()
{
char str[10];
strncat(str, "Today is Friday!", sizeof(str));
/*
答:
不当使用C标准库中的strncat函数常常会导致差一错误(差一错误是指在计数时由于边界条件判断失误导致结果多了一或少了一的错误)和安全问题。事实上strncat函数会在指定的最大长度之后一字节的位置写入字符串结束符。
上面代码应改为:strnacat(str,"Today is Friday!",sizeof(str)-1);
*/
return 0;
}
3.C标准的strncpy函数经常被推荐为一种替代strcpy函数,strncpy也会存在一些危险,是什么?
答:strncpy函数并不会自动添加末尾的结束符(‘\0’),所以你如果拷贝了n个字符过去,但不包含结束符,问题就来了。
正确的做法是:
……
strncpy(str1, str2, n);
str1[sizeof(str1) - 1] = '\0';
……
4.写一个程序模仿strncpy函数实现比较两个字符串s1和s2,需要满足以下要求。
1.如果s1 < s2,输出一个正数,值是两个不同字符的差
2.如果s1 = s2,输出0
3.如果s1 < s2,输出一个负数,值是两个不同字符的差
#include <stdio.h>
#define MAX 1024
int main()
{
char str1[MAX];
char str2[MAX];
int i = 0;
unsigned int n;
printf("请输入第一个字符串:");
while ((str1[i++] = getchar()) != '\n') //不用scanf函数接收字符串是因为scanf遇到空格会终止
;
printf("请输入第二个字符串:");
i = 0;
while ((str2[i++] = getchar()) != '\n')
;
printf("请输入比较的字符数:");
scanf("%u", &n);
for (i = 0; i < n; i++)
{
if (str1[i] - str2[i])
{
i++;
break;
}
}
printf("比较的结果是:%d\n", str1[i-1] - str2[i-1]);
return 0;
}
5.按下面要求写程序
1.定义一个长度为21的字符数组,用于存放用户输入的文本
2.如果用户输入的文本长度超过20个字符,且文本中存在空格,则截取最接近末尾(第20个字符串)的空格
3.如果用户输入的文本长度超过20个字符,且文本中不存在空格,则打印前20个字符
#include <stdio.h>
#include <string.h>
#define MAX 21 // 包含结束符就是21个字符
int main()
{
int ch, space, i = 0;
char str[MAX];
space = MAX - 1;
printf("请输入一行文本:");
while ((ch = getchar()) != '\n')
{
str[i++] = ch;
if (i == MAX - 1)
{
break; // 到了字符数组最后一个位置
}
if (ch == ' ')
{
space = i; // 记录最后一个空格的位置
}
}
if (i >= MAX - 1)
{
str[space] = '\0';
}
else
{
str[i] = '\0';
}
printf("你输入的文本是:%s\n", str);
return 0;
}
6.根据要求再写一个字符统计程序
1.统计用户输入的所有字符个数
2.统计不同的字符个数,并打印出来
3.找出出现次数最多的字符
#include <stdio.h>
#include <string.h>
#define NUM 128
int main()
{
int ch, i, j = 0, max = 0;
int input_num = 0;
int ascii[NUM] = {0};
char count[NUM] = "";
printf("请输入英文文本:");
while ((ch = getchar()) != '\n')
{
ascii[ch]++; // 字符对应的ASCII码加1
input_num++;
}
for (i = 0; i < NUM; i++)
{
if (ascii[i])
{
count[j++] = i;
if (ascii[i] > ascii[max])
{
max = i;
}
}
}
printf("你总共输入了%d个字符,其中不同的字符个数有%d个。\n", input_num, strlen(count));
printf("它们是:%s\n", count);
printf("出现次数最多的字符是\'%c\',它总共出现了%d次。\n", max, ascii[max]);
return 0;
}