字符数组与字符串——C语言描述
文章目录
1 字符数组
字符数组用关键字char定义的。内存结构为顺序存储,如下图1.1所示
char ch1[] = {'w', 'e'};
#include <stdio.h>
/*
目的:
1. 测试字符数组
*/
int main() {
char ch1[2] = {'w', 'e'};
int i = 0;
for (i = 0; i < sizeof(ch1); ++i) {
printf("ch1[%d] = %c\n", i, ch1[i]);
}
getchar();
return 0;
}
结果:
ch1[0] = w
ch1[1] = e
1.2 ASCII码表
参考链接:
一共有128(0 - 127)个ASCII码,其中ASCII控制字符是0 - 31和127,ASCII可显示字符是32 - 126。可显示字符中:空格字符ASCII值为32,数字字符(0 - 9)为48 - 57,大写字母字符(A - Z)是65 - 90(26个),小写字母字符(a - z)是97 - 122(26个),对应的大写字母和小写字母相差32个。
例子:
测试ASCII码表的值。
#include <stdio.h>
#include <stdlib.h>
/*
Requirement:
1. test ASCII
*/
int main() {
char ch1[] = { 'w', 0, 'e', 48, 20, 65, 97};
int i = 0;
for (i = 0; i < sizeof(ch1); ++i) {
printf("ch1[%i] = %c\n", i, ch1[i]);
}
getchar();
return 0;
}
结果:
ch1[0] = w
ch1[1] = ——空字符
ch1[2] = e
ch1[3] = 0
ch1[4] = ——空格
ch1[5] = A
ch1[6] = a
1.3 转义字符
如下图1.2所示,主要是针对特殊功能和特殊字符的实现,如换行(\n),打印或者存储特殊字符,如(‘,“,\)。其中转义字符’\0’就是表示ASCII值0(空字符)
例子:
测试转义字符,一般打印这种转义字符,多加一次下划线 \
#include <stdio.h>
#include <stdlib.h>
/*
Requirement:
1.test CharArr
*/
int main() {
char ch1[] = {'w', 'e', '\\', '\'', '\"', '\;'};
int i = 0;
for (i = 0; i < sizeof(ch1); ++i) {
printf("ch1[%i] = %c\n", i, ch1[i]);
}
getchar();
return 0;
}
结果:
ch1[0] = w
ch1[1] = e
ch1[2] = \
ch1[3] = ’
ch1[4] = "
ch1[5] = ;
1.4 常见问题——字符数组初始化没填满或者越界访问
**(1)**测试字符数组没填充满的定义与越界访问
①初始化的字符个数 < 字符数组定义的个数
其他的成员会以空字符进行填充。访问ch2[2]时,结果是空字符。当访问ch2[4],ch2[5],返回的值是乱码。
char ch2[3] = {'w', 'e'};
②初始化的字符个数 > 字符数组定义的个数
//char ch3[1] = {'w', 'e'};//直接报错
例子:
测试字符数组没填充满,溢出的定义与访问
#include <stdio.h>
#include <stdlib.h>
/*
Requirement:
1.测试没填充满,溢出
*/
int main() {
char ch1[2] = {'w', 'e'};
char ch2[3] = {'w', 'e'};
//char ch3[1] = {'w', 'e'};//定义溢出的直接报错
int i = 0;
//测试正常
printf("测试正常:\n");
for (i = 0; i < sizeof(ch1); ++i) {
printf("ch1[%d] = %c\n", i, ch1[i]);
}
//测试没填充满
printf("测试没填充满:\n");
for (i = 0; i < sizeof(ch2); ++i) {
printf("ch2[%d] = %c\n", i, ch2[i]);
}
//测试越界访问
printf("测试越界访问:\n");
printf("ch1[3] = %c\n", ch1[3]);
printf("ch1[4] = %c\n", ch1[4]);
getchar();
return 0;
}
结果:
测试正常:
ch1[0] = w
ch1[1] = e
测试没填充满:
ch2[0] = w
ch2[1] = e
ch2[2] = ——空字符
测试越界访问:
ch2[4] = ? ——乱码
ch2[5] = ? ——乱码
2 字符串
2.1 字符串的描述
字符串是以’\0’为结束符的字符数组。’\0’是一个转义字符,转义成ASCII码值为0,也是空字符的意思。在c语言中,字符串用字符数组的形式来定义。定义的方式有两种:第一种,使用{},需要把’\0’加上;第二种:使用””,编译器会自动在后面补’\0’。字符串的内存结构如图2.1所示。理解建议全转换成内存结构来理解。
char c01[] = {'w', 'e', '\0'};
char c02[] = "we";
例子:
测试字符串
#include <stdio.h>
#include <stdlib.h>
/*
目的:
字符串
*/
int main() {
//字符数组方式
char c01[3] = { 'm', 'e', '\0' };
//字符串
char c02[3] = "me";
int i = 0;
//打印字符数组
printf("sizeof(c01) = %d\n", sizeof(c01));
for (i = 0; i < sizeof(c01); ++i) {
printf("c01[%d] = %c\n", i, c01[i]);
}
printf("c01 = %s\n\n", c01);
//打印字符串
printf("sizeof(c02) = %d\n", sizeof(c02));
for (i = 0; i < sizeof(c02); ++i) {
printf("c02[%d] = %c\n", i, c02[i]);
}
printf("c02 = %s\n", c02);
getchar();
return 0;
}
打印结果:
sizeof(c01) = 3
c01[0] = w
c01[1] = e
c01[2] = ——空字符
c01 = wesizeof(c02) = 3
c02[0] = w
c02[1] = e
c02[2] = ——空字符
c02 = we
1.2 常见问题
(1)测试字符串的打印
打印时使用%s占位符进行打印,由于字符串是以’\0’结尾,打印字符串时,系统会去找’\0’,当识别到’\0’时,会结束打印。
例子:
测试以%s的方式打印字串.
#include <stdio.h>
/*
Requirement:
1.测试以%S的方式打印字串
*/
int main() {
//'\0'在中间
char ch1[4] = {'w', 'e', '\0', 'a'};
char ch2[5] = "we\0a";//用""定义字符串会在后面加'\0'
int i = 0;
//测试ch1
printf("测试ch1:\n");
printf("ch1 = %s\n", ch1);//遇见空字符'\0'就停止
for (i = 0; i < sizeof(ch1); ++i) {
printf("ch[%d] = %c\n", i, ch1[i]);
}
//测试ch2
printf("测试ch2:\n");
printf("ch2 = %s\n", ch2);//遇见空字符'\0'就停止
for (i = 0; i < sizeof(ch2); ++i) {
printf("ch2[%d] = %c\n", i, ch2[i]);
}
getchar();
return 0;
}
结果:
测试ch1:
ch1 = we
ch[0] = w
ch[1] = e
ch[2] =
ch[3] = a
测试ch2:
ch2 = we
ch2[0] = w
ch2[1] = e
ch2[2] =
ch2[3] = a
ch2[4] =
(2)测试字符数组没填充满,即初始化的字符个数 < 字符数组定义的个数
#include <stdio.h>
/*
Requirement:
1.测试没填满
*/
int main() {
char ch3[6] = "wea";//在'a'后面会自动添加'\0'
int i = 0;
//测试ch3
printf("测试ch3:\n");
printf("ch3 = %s\n", ch3);//遇见空字符'\0'就停止
for (i = 0; i < sizeof(ch3); ++i) {
printf("ch3[%d] = %c\n", i, ch3[i]);
}
getchar();
return 0;
}
结果:
测试ch3:
ch3 = wea
ch3[0] = w
ch3[1] = e
ch3[2] = a
ch3[3] =
ch3[4] =
ch3[5] =
1.2 常用的字符串函数
函数 | 功能 |
---|---|
strlen(str); | 返回字符串str1的长度 |
strcpy(str1, str2); | 复制字符串str2到字符串str1 |
strcat(str1, str2); | 把字符串str2连接到字符串str1的末尾 |
strcmp(str1, str2); | 比较字符串的长度。当str1等于str2,返回0,当str1 > str2,返回值 > 0 ,否则 < 0 |
strchr(str1, ch); | 返回一个指针,指向字符串第一次出现出现字符ch的位置 |
strstr(str1, str2); | 返回一个指针,指向字符串第一次出现出现字符串str2的位置 |
(1)strlen
返回字符串str1的长度。不包括’\0’;
sizeof函数
存储空间的字节个数,所以计算的时候要按内存空间来理解。
(2)复制:strcpy_s
参考:
①函数原型:
第二个参数(numberOfElements)是为了保证strSource的缓冲长度
errno_t strcpy_s( char *strDestination, size_t numberOfElements, const char *strSource );
例子:
//test strcpy_s
void test08() {
char str1[6] = "we go";
char *str = NULL;
int i = 0;
str = (char *)malloc(sizeof(str1));
strcpy_s(str, sizeof(str1), str1);
printf("str = %s\n", str);
for (i = 0; i < sizeof(str1); ++i) {
printf("str[%d] = %c\n", i, str[i]);
}
free(str);
str = NULL;
}
结果:
str = we go
str[0] = w
str[1] = e
str[2] =
str[3] = g
str[4] = o
str[5] =
②溢出情况
目标数组的长度小于源数组的长度,程序会报错。
//test strcpy_s overflow
void test09() {
char str1[6] = "we go";
char str2[2];
strcpy_s(str2, sizeof(str1), str1);
printf("str = %s\n", str2);
}
结果:
程序报错