C语言(字符串)

一、字符串的定义及基本使用

1、什么是字符串?

被双引号引用的字符集合!例如:"hello"、"world",或者是以'\0'结尾的字符数组

例如:

char a[] = {'a','b','\0'}

注意:"hello" 中其实在末尾也'\0'只是我们看得到,也就是说字符串一定是以'\0'结尾的

//验证"hello"中有字符'\0'

#include <stdio.h>

int main()
{
    char *p;
    p = "hello";
    
    printf("%d\n",*(p+5));

    return 0;
}

 输出结果为0则说明结尾是'0'

2、字符串和字符数组的联系及区别

可以把字符串当作字符数组一样处理,字符数组不一定可以当作字符串处理,因为字符数组中不一定有'0'。

char ch[] = {'a','b','\0','c','d'};

这种情况我们可以把数组ch当成字符串“ab”

在实际工作过程中我们经常会有如下需求,我们需要用一个字符数组用保存多个字符,并且 需要将这多个字符当成字符串 ,但是我们在定义字符数组的时候只知道需要保存的字符的最大 的数目(假设是30),实际存储的时候存储的字符可能会小于30。

char name[ 30 ] ;
memset(name, 0, sizeof(name));
注意:在定义字符数组长度的时候通常要比实际要存储的字节数的数目+1(因为最后需要留一 个字节存 ’ \0 ’ )

3、字符串的操作

#include <stdio.h>

int main()
{
    //字符串的操作
    char *str;
    char a[] = {"hello"};
    
    //可以通过指针str来操作ch
    str = ch;
    
    //方法1:
    str[1] = 'a';  //当一个指针指向了一个数组以后,我们就可以通过指针使用下标法直接访问数组中的元素
    
    //方法2:
    *(str+1) = 'a';

    //也可以将字符串变量赋值给一个指针变量
    char *p = "hello";

    
    return 0;
}

注意:p是一个指针变量,应该保存的是一个地址,因此 char *p = "hello"; 并不是将字符串"hello"赋值给 指针变量p,而是将存储字符串 "hello"的内存空间的首地址赋值给p。

4、将字符数组中的每个元素赋值为'\0'

 我们将要用到函数memset()

#include <stdio.h>

void *memset(void *s,int c,size_t n);
#include <stdio.h>
#include <string.h>

int main()
{
    char a[10];
   
     memset(ch,0,sizeof(a));  //memset(ch,0,sizeof(a));
    
    return 0;
}

二、常见的字符串处理函数

1、atoi函数

#include <stdlib.h>
int atoi(const char *nptr);

功能:将字符串转换成int类型的整数,返回转换后的整数值 

//编写代码实现atoi函数

#include <stdio.h>
#include <stdlib.h>

int main()
{
    char *p = "1234";
    int a = atoi(p);

    printf("%d\n",a);

    return 0;
}

2、atof函数

#include <stdlib.h>
double atof(const char *nptr)

 功能:将字符串转换成double类型的浮点数,返回转换后的浮点数

//将char类型转换为double类型的浮点数,并返回转换后的浮点数

#include <stdio.h>
#include <stdlib.h>

int main()
{
    char *p = "123.456";
    double a = atof(p);

    printf("%f\n",a);

    return 0;
}

3、strlen函数

#include <string.h>
size_t strlen(const char *s);

 功能:计算字符串的长度

//计算字符串的长度

#include <stdio.h>
#include <string.h>

int main()
{
    char *p = "hello";
    char arr[] = ['A','B','\0','D'];

    printf("%d %d\n",strlen(ch),strlen(arr));

    return 0;
}

 练习:编程实现strlen函数

#include <stdio.h>

int my_strlen(char ch[]) //int my_strlen(char *ch)
{
    int cnt = 0;
    int i = 0;
    while(ch[i] != '\0')
    {
        cnt++;
        i++;
    }
    
    return cnt; 
}

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";
    chr ds[10] = {0};

    strcpy(src,dst);
    printf("dst:%s\n",dst);
 
    return 0;
}

 注意:dst的空间一定要大于从src中需要拷贝的内容所占用的空间,至少大1个字节(因为要给'\0'预留空间)

#include <stdio.h>
#include <string.h>

int main()
{
    char a[4];
    char b[4];
    
    strcpy(b,"hello");

    printf("b:%s\n",b);
    printf("a:%s\n",a);

    return 0;
}

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)strcpy最多拷贝n个字节,如果前n个字节中没有'\0',最终也不会拷贝'\0'

(2)如果src的长度小于n,则会写入一些'\0'以保障总共写入n个bytes,strncpy在拷贝的时候如果前面的n个字节中已经有'\0'了,那么只拷贝到'\0',但是依然会往dest中继续写入'\0'以保障总共写入 了n个bytes。


//strncpy的实现

#include <stdio.h>
#include <string.h>

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的空间需要足够大

8、strncat函数

#include <string.h> char *strcat(char *dest, const char *src);
功能:将src字符串连接到dest的尾部,‘\0’也会追加过去
参数:
dest:目的字符串首地址
src:源字符首地址
返回值:
成功:返回dest字符串的首地址
失败:NULL
注意:
(1)如果src中的内容长度为m小于n个字节,那么只追加m+1个字节(最后会自动追加一个'\0')
 
(2)如果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;
}

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码的差
#include <stdio.h>

int main()
{
    printf("%d\n", strcmp("hello", "hello")); //结果为0
    printf("%d\n", strcmp("hello", "heLlo")); //结果为1
    printf("%d\n", strcmp("Hello", "heLlo")); //结果为-1
    
    return 0;
}

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
/*在键盘上输入一串字符串
  判断这个字符串和在程序中所设定的字符串是否相等
 (最多比较6个字符)(不区分大小写)*/

#include <stdio.h>
#include <string.h>

int main()
{
    char ch1[10];
    char key[] = "123456";
    memset(ch1, 0, sizeof(ch1));
    printf("请输入验证码:%s\n", key);
    scanf("%s", ch1);
    printf("%s\n", ch1);

    return 0;
}
//在键盘上输入一串字符串,将其中的非字母和非数字的字符删除!

#include <stdio.h>
#include <string.h>

int main()
{
    char ch1[10];

    memset(ch1, 0, sizeof(ch1));
    printf("请在键盘上输入一串字符(长度小于10)\n");
    scanf("%s", ch1);
    printf("%s\n", ch1);

    return 0;
}

11、strstr函数

#include <string.h>
char *strstr(const char *haystack, const char *needle);
功能:在字符串haystack中查找字符串needle出现的位置
参数:
haystack:源字符串首地址
needle:匹配字符串首地址
返回值:
成功:返回第一次出现的needle地址
失败:NULL

 我们经常使用strstr来判断某个字符串是否时另外一个字符串的字串!

#include <stdio.h>
#include <string.h>

int main()
{
    char src[] = "ddddabcd123abcd333abcd";
    char *p = strstr(src, "abcd");
    printf("p = %s\n", p);

    return 0;
}

12、strtok函数

#include <string.h>
char *strtok(char *str, const char *delim);
功能:来将字符串分割成一个个片段。当strtok()在参数s的字符串中发现参数delim中包含的分 割字符时, 则会将该字符改为\0 字符,当连续出现多个时只替换第一个为\0。
参数:
str:指向欲分割的字符串delim:为分割字符串中包含的所有字符
返回值:
成功:分割后字符串首地址
失败:NULL

注意: 

(1)在第一次调用时:strtok()必需给予参数s字符串

(2)往后的调用则将参数s设置成NULL,每次调用成功则返回指向被分割出片段的指针
#include <stdio.h>
#include <string.h>

int main()
{
    char a[100] = "abc-efg-hijk-lmn";
    char *s = strtok(a, "-");//将"-"分割的子串取出
    while (s != NULL) {
        printf("%s\n", s);
        s = strtok(NULL, "-");
    }

    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值