字符串
字符串的定义及基本使用
1、什么是字符串?
被双引号引用的字符集合!例如:”hello” 、”world”,或者是以’\0’结尾的字符数
组!!!
比如:char ch[] = {‘h’, ‘e’, ‘\0’}
注意:”hello” 中其实在在末尾也有’\0’只是我们看得到
也就是说:字符串一定是以’\0’结尾的!!
如何验证”hello”中有字符’\0’呢?
printf(“%d\n”, *(p+5)); 输出的结果为整数0则说明结尾是’\0’
2、字符串和字符数组的联系及区别?
可以把字符串当做字符数组一样处理,字符数组不一定可以当做字符串处理,为什么?
因为字符数组中不一定有’\0’。
char ch[] = {‘a’, ‘b’, ‘\0’, ‘c’, ‘d’};
这种情况我们可以吧数组ch当成字符串“ab”
在实际工作过程中我们经常会有如下需求,我们需要用一个字符数组用来保存多个字符,并且需要将这多个字符当成字符串 ,但是我们在定义字符数组的时候只知道需要保存的字符的最大的数目(假设是30),实际存储的时候存储的字符可能会小于30,如何保障把这些字符当成字符串呢?
c har name[ 30 ] ;
memset(name, 0, sizeof(name));
注意:在定义字符数组长度的时候通常要比实际要存储的字节数的数目+1(因为最后需要留一个字节存 ’ \0 ’ )
3、字符串的操作
int main()
{
//字符串的操作:
char *str;
char ch[] = {"hello"};
str = ch;
//可以通过指针str操作ch
//方法1:
str[1] = 'a'; //当一个指针指向了一个数组以后,我们就可以通过指针使用下标法直接访问数组中的元素
//方法2:
*(str + 1) = 'a';
//也可以将字符串常量赋值给一个指针变量
char *p = "hello";
/*注意:p是一个指针变量,应该保存的是一个地址,因此 char *p = "hello"; 并不是将字符串"hello"赋值给
指针变量p,而是将存储字符串 "hello"的内存空间的首地址赋值给p
*/
return 0;
}
4、将字符数组中的每个元素赋值为’\0’
#include <string.h>
void *memset(void *s, int c, size_t n);
功能:将指针s所指向的内存空间中的n个字节填充成c
示例代码:
#include <stdio.h>
#include <string.h>
int main()
{
char ch[10];
memset(ch, 0, sizeof(ch)); //memset(ch, 0, sizeof(ch));
return 0;
}
常见的字符串处理函数
1、atoi函数
#include <stdlib.h>
int atoi(const char *nptr);
功能:将字符串转换成int类型的整数,返回转换后的整数值
int main()
{
char *p = "1234";
int val = atoi(p);
printf("%d\n", val);
return 0;
}
2、atof函数
#include <stdlib.h>
double atof(const char *nptr)
功能:将字符串转换成double类型的浮点数,返回转换后的浮点数
int main()
{
char *p = "123.456";
double val = atof(p);
printf("%f\n", val);
return 0;
}
3、strlen函数
#include <string.h>
size_t strlen(const char *s);
功能:计算字符串的长度
int main()
{
char *ch = "hello";
char arr[] = {'A', 'B', 'C', '\0', 'D'};
printf("%d %d\n", strlen(ch), strlen(arr));
return 0;
}
4、strcpy函数
#include <string.h>
char *strcpy(char *dest, const char *src);
功能:把src所指向的字符串复制到dest所指向的空间中,'\0’也会拷贝过去
参数:
dest:目的字符串首地址
src:源字符首地址
返回值:
成功:返回dest字符串的首地址
失败:NULL
示例代码:
#include <stdio.h>
#include <string.h>
int main()
{
char *src = "hello";
char dst[10] = {0};
strcpy(src, dst);
printf("dst: %s\n", dst);
return 0;
}
注意:
1、dst的空间一定要大于从src中需要拷贝的内容所占用的空间,至少大1个字节(因为要给’\0’预留空间)
int main() {
/*
char *src = "hello";
char dst[10];
strcpy(dst, src);
printf("%s\n", dst);
*/
char a[4];
char b[4]; //hell
strcpy(b, "hello");
printf("b: %s\n", b); //b: hello
printf("a: %s\n", a); //a: o
return 0;
}
2、stcpy的实现
char *strncpy(char *dest, const char *src, size_t n)
{
size_t i;
for (i = 0; i < n && src[i] != '\0'; i++)
dest[i] = src[i];
for ( ; i < n; i++)
dest[i] = '\0';
return dest;
}
5、strncpy函数
#include <string.h>
char *strncpy(char *dest, const char *src, size_t n);
功能:把src指向字符串的前n个字符复制到dest所指向的空间中,是否拷贝结束符看指定的长
度是否包含’\0’。
参数:
dest:目的字符串首地址
src:源字符首地址
n:指定需要拷贝字符串个数
返回值:
成功:返回dest字符串的首地址
失败:NULL
注意:
1、strncpy最多拷贝n个字节,如果前n个字节中没有’\0’,最终也不会拷贝’\0’
2、如果src的长度小于n,则会写入一些’\0’以保障总共写入n个Bytes
strncpy在拷贝的时候如果前面的n个字节中已经有’\0’了,则只拷贝到’\0’,但是依然会往dest中继续
写入’\0’以保障总共写入n个Bytes
strncpy的实现:
char *strncpy(char *dest, const char *src, size_t n)
{
size_t i;
for (i = 0; i < n && src[i] != '\0'; i++)
dest[i] = src[i];
for ( ; i < n; i++)
dest[i] = '\0';
return dest;
}
6、strcpy和strncpy的区别
如果你能够100%肯定dest的空间比src的空间大,可以使用strcpy在实际工作中为了避免溢出情况的产生我们尽量多使用strncpy。问题又来了!如果使用strncpy的时候n比dest所指向的内存空间的大小要大那不是还是会差生溢出吗?那么如何去规避这种溢出情况的产生呢?
方法:先判断dest的长度len和n的大小,如果len>=n,则拷贝n个元素,如果len<n,则拷贝len个元素!
7、strcat函数
#include <string.h>
char *strcat(char *dest, const char *src);
功能:将src字符串连接到dest的尾部,‘\0’也会追加过去
参数:
dest:目的字符串首地址
src:源字符首地址
返回值:
成功:返回dest字符串的首地址
失败:NULL
示例代码:
#include <stdio.h>
#include <string.h>
int main()
{
char ch[20]; //char *ch;
memset(ch, 0, sizeof(ch)); //ch = (char *)malloc(20);
strcpy(ch, "hello");
strcat(ch, "world");
printf("%s\n", ch);
return 0;
}
注意:ch的空间要足够大!
strcat的实现:
char *strncat(char *dest, const char *src, size_t n)
{
size_t dest_len = strlen(dest);
size_t i;
for (i = 0 ; i < n && src[i] != '\0' ; i++)
dest[dest_len + i] = src[i];
dest[dest_len + i] = '\0';
return dest;
}
8、strncat函数
#include <string.h>
char *strcat(char *dest, const char *src);
功能:将src字符串连接到dest的尾部,‘\0’也会追加过去
参数:
dest:目的字符串首地址
src:源字符首地址
返回值:
成功:返回dest字符串的首地址
失败:NULL
注意:
如果src中的内容长度为m小于n个字节,那么只追加m+1个字节(最后会自动追加一个’\0’)
如果src中的内容长度为m小于n个字节,那么追加n+1个字节(最后会自动追加一个’\0’)
示例代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char *p;
p = (char *)malloc(20);
strcpy(p, "hello");
strncat(p, "world", 3);
printf("%s\n", p);
memset(p, 0, 20); //这是什么意思呢?
strcpy(p, "hello");
strncat(p, "world", 7);
printf("%s\n", p);
return 0;
}
strcat的实现:
char * strncat(char *dest, const char *src, size_t n)
{
size_t dest_len = strlen(dest);
size_t i;
for (i = 0 ; i < n && src[i] != '\0' ; i++)
dest[dest_len + i] = src[i];
dest[dest_len + i] = '\0';
return dest;
}
9、strcmp函数
#include <string.h>
int strcmp(const char *s1, const char *s2);
功能:比较 s1 和 s2 的大小,比较的是字符ASCII码大小。
参数:
s1:字符串1首地址
s2:字符串2首地址
返回值:
相等:0
大于:>0 在不同操作系统strcmp结果会不同 返回ASCII差值
小于:<0
原理:
strcmp的执行的逻辑:将s1和s2中对应位置的字符一一比较,直到两个字符串全部遍历完成
(如果还没有发现有不同的字符则说明两者相等),或者有两个字符不相等,则比较结束。如
果s1中的字符的ASCII码比s2中的大则返回1,否则返回-1
注意:有的编译器两个字符串不同的时不是返回1或者-1, 而是返回两个字符串中第一个不相
等的两个字符的ASCII码的差
printf("%d\n", strcmp("hello", "hello")); //结果为0
printf("%d\n", strcmp("hello", "heLlo")); //结果为1
printf("%d\n", strcmp("Hello", "heLlo")); //结果为-1
10、strncmp函数
#include <string.h>
int strncmp(const char *s1, const char *s2, size_t n);
功能:比较 s1 和 s2 前n个字符的大小,比较的是字符ASCII码大小。
参数:
s1:字符串1首地址
s2:字符串2首地址
n:指定比较字符串的数量
返回值:
相等:0
大于: > 0
小于: < 0
练习1:
在键盘上输入一串字符串,判断这个字符串和在程序中所设定的字符串是否相等(最多比较6个
字符)(不区分大小写)
char ch1[10];
char key[] = "A18Cd9";
memset(ch1, 0, sizeof(ch));
printf("请输入验证码:%s\n", key);
scanf("%s", ch1);
printf("%s\n", ch1);
11、strstr函数
#include <string.h>
char *strstr(const char *haystack, const char *needle);
功能:在字符串haystack中查找字符串needle出现的位置
参数:
haystack:源字符串首地址
needle:匹配字符串首地址
返回值:
成功:返回第一次出现的needle地址
失败:NULL
我们经常使用strstr来判断某个字符串是否时另外一个字符串的字串!
char src[] = "ddddabcd123abcd333abcd";
char *p = strstr(src, "abcd");
printf("p = %s\n", p);
12、strtok函数
#include <string.h>
char *strtok(char *str, const char *delim);
功能:来将字符串分割成一个个片段。当strtok()在参数s的字符串中发现参数delim中包含的分
割字符时, 则会将该字符改为\0 字符,当连续出现多个时只替换第一个为\0。
参数:
str:指向欲分割的字符串
delim:为分割字符串中包含的所有字符
返回值:
成功:分割后字符串首地址
失败:NULL
注意:
在第一次调用时:strtok()必需给予参数s字符串
往后的调用则将参数s设置成NULL,每次调用成功则返回指向被分割出片段的指针
char a[100] = "abc-efg-hijk-lmn";
char *s = strtok(a, "-");//将"-"分割的子串取出
while (s != NULL)
{
printf("%s\n", s);
s = strtok(NULL, "-");
}
评论区