字符串的相关知识

1 字符串基本知识

字符串 : 一串字符 , "0个或多个字符"

单个字符 ,C语言中有专门的类型

char/unsigned char ---> 保存的是单个字符的ASCII码(8bits整数)

C语言中,没有字符串的类型.

C语言的字符串是 通过 char*(字符型指针)来实现.

C语言点字符串 是一串字符(0个或多个),这些字符的内存地址是连续的.

如果我们知道"字符串"的首地址(第一个字符的地址) : 0x3000

推出字符串第二个字符的地址 : 0x3001

推出字符串第三个字符的地址 : 0x3002

......

并且我们如果知道每个字符的地址,就可以通过他的地址(char*)来访问每个字符.

通过字符串的首地址,不停地 + 1 ,就可以得到每个字符的地址,但是你通过字符的首地址,

能不能知道这个字符串有多少个字符?

不能知道

所以,C语言中规定任何字符串的末尾加一个"字符串结束标识"

null字符,空字符,0,'\0'

char*用来保存字符串的首地址,并且约定字符串结束的标志为'\0'.

你可以通过char * 来访问或操作字符串.

char s[10];
    //数组名 s,当指针, &s[0],char*
scanf("%s",s);//%s从键盘上输入一串字符,输入到一个char*的地址中去
scanf("%s",&s[0]);//一样的
​
//scnaf("%s",&s);//不行,类型不匹配 %s --> char*
                //typeof(&s) ==> typeof(s) * ==> char[10] *
printf("%s",s);//%s输出一个字符串,后面也需要接一个 字符串类型(char*)

2 字符串常量

字符串常量是不可以被修改的字符串,只能读.

字符串常量保存在一个.rodata的内存区

如 :

C代码中,所有 " "引起来的都是字符串常量
    并且 所有 有 " " 引起的表达式的值,就是这个字符串的首地址
    typeof("abcd123") : const char *
    
    char *p = "abcd123";//表达式 "abcd123" 的值是 字符 'a' 的地址.&'a'

内存:

ro read only 只读区域

存储那些只能读的数据,常量, 如"abcd"

rw read & write 可读可写的区域

存储那些变量

如 : 没加const修饰的 变量,数组,指针变量...

int a;//a存储在可读可写的区域

int b[100];//a存储在可读可写的区域

char c[200];//a存储在可读可写的区域

int *p;//p存储在可读可写的区域

char *p2;//p2存储在可读可写的区域

......

3 字符串变量

把字符串(多个字符) 存储在一个可读可写的区域就可以了

char s[100] ;//s存储在可读可写的区域

你把字符串存储在s这个数组中, 字符串变量.

char *p = (char *)malloc(100);//malloc分配的空间也是 可读可写的

你把字符串存储在p指向的空间,字符串变量

char s[3];
s[0] = 'a';
s[1] = 'b';
s[2] = '\0';
​
==> 
    char s[3] = {"ab"};
    s[0] = 'a';
    s[1] = 'b';
    s[2] = '\0';
​

练习 :

1.

char s1[] = {'a','b','c'};
char s2[] = {"abc"};
请问数组 s1 的元素个数是几个? //3 
    s2的元素个数是几个? //4
sizeof(s1) = ? //3 
sizeof(s2) = ? //4
字符串s1中字符的个数多少? //3
字符串s2中字符的个数是多少? //3
printf("%s\n",s1); //abc
printf("%s\n",s2); //abc

2.

char s3[5] = {'a','b','c'};
char s4[5] = {"abcd"};
sizeof(s3) = ? //5
sizeof(s4) = ? //5
printf("%s\n",s3);//abc
printf("%s\n",s4);//abcd

3.分析如下程序的输出结果

char s[10] = {"abcde"};
//s += 2;//不可以的,s是一个数组名, 常量
​
s[2] = 'A';//可以的.数组s存储可读可写的区域
*(s + 2) = 'A';//可以的
​
printf("%s\n",s);

4.分析如下程序的输出结果

char *s = "abcde";
s += 2;//可以的,s变量
​
//*(s + 2) = 'A';//不可以,s指向的空间是 只读空间
printf("%s\n",s);

5.写一个函数,求一个字符串的长度

"字符串的长度" : 指的这个字符串中有多少个字符,一个一个去数,数到\0为止(不包括\0)

int strlen_m(char *s)
{
    int n = 0;
    while(*s)
    {
        n++;
        s++;
    }
    
    return n;
}

几个常用的字符串处理函数,C标准库已经为我们写好了,我们可以直接用,需要包含他的头文件

#include <string.h>

4 几个常用的字符串处理函数

  • strlen 用来求一个字符串的长度

NAME
    strlen - calculate the length of a string
​
SYNOPSIS
    #include <string.h>
​
    size_t strlen(const char *s);
DESCRIPTION
    The strlen() function calculates the length of the string pointed to by
    s, excluding the terminating null byte ('\0').
​
RETURN VALUE
    The strlen() function returns the number of characters  in  the  string
    pointed to by s.
​

例子 :

int l;
l = strlen("abcde");
l = 5
    
char s[10] = {"abc"};
l = strlen(s);
l = 3
sizeof(s) = 10;
​
strlen : 是一个函数,用来计算一个字符串的长度,算到\0为止
sizeof : 是一个运算符,用来求一个对象(或类型)自己本身所占内存的字节数
    
char s1[4] = {'1','0'};
sizeof(s1) = 4
l = strlen(s1);
l = 2
    
char s2[4] = {'1',0,'3'};
l = strlen(s2);
l = 1
    
l = strlen( "abc\123456\0de");
l = 7
  • strcpy 字符串拷贝函数

    cpy : copy

    NAME
        strcpy, strncpy - copy a string
    ​
    SYNOPSIS
        #include <string.h>
                strcpy用来把src指向的字符串,拷贝到dest指向的空间中去,
                    拷贝到\0为止(\0也会拷贝)
        char *strcpy(char *dest, const char *src);
                dest : 指向 "目的地" ,dest指向的空间,要保证可写,并且空间足够大.
             src : 指向"源字符串",把src指向的字符串拷贝到dest指向的空间中去
                返回值 : 
                        成功 返回拷贝后字符串的首地址(dest)
            strcpy有一个巨大的bug :
                他没有考略到越界的问题,有可能会导致内存的越界访问或非法访问
            
          strncpy 就是为了strcpy的bug而产生的.
                 strncpy 用来把src指向的字符串拷贝到dest指向的空间中去.
                 但是strncoy到底拷贝了多少个字符呢? <==n
                 (1) 遇到\0拷贝结束(此时后面会多拷贝n - strlen(src) 个 \0)
                 (2) 一直没有遇到\0,但是已经拷贝了n个字符,拷贝结束(此时\0不会拷贝)
        char *strncpy(char *dest, const char *src, size_t n);
                    dest : 指向目标空间
                 src  : 指向源字符串
                 n    : 规定拷贝n个字符.一般来说,n为dest指向那个的空间的最大容量
                     返回值 : 
                            成功 返回拷贝后字符串的首地址(dest)
    ​

  • memcpy 内存拷贝

NAME
       memcpy - copy memory area
​
SYNOPSIS
       #include <string.h>
            mencpy用来把str指向的内存中的前n个字节,拷贝到dest指向的空间中去
       void *memcpy(void *dest, const void *src, size_t n);
            dest :指向目标内存块,要保证dest指向的空间足够大
            src  : 指向源内存块
            n    : 要拷贝的字节数
                返回值 : 
                    返回dest的这个地址
DESCRIPTION
       The  memcpy()  function  copies  n bytes from memory area src to memory
       area dest.  The memory areas must not overlap.  Use memmove(3)  if  the
       memory areas do overlap.
​
RETURN VALUE
       The memcpy() function returns a pointer to dest.
​

思考 :

strncpy 和 memcpy 有区别?

strncpy 是字符串拷贝函数,顶多拷贝n个字节(遇到\0拷贝结束,多补几个 n - i 个\0)

memcpy 是内存拷贝函数(没有类型的概念),成功的话,一定会拷贝n个字节

字符串的拷贝,最好用strncpy

其他的内存拷贝,用memcpy

char s1[8];
char s2[8];
​
scanf("%s",s2);
​
memcpy(s1,s2,strlen(s2) + 1 );
    //strlen(s2) + 1 <= 8 没有问题
    //strlen(s2) + 1 > 8 就会有问题,越界
    //"+1" 我想把s2这个字符串后面的\0也拷贝
​
strncpy(s1,s2,8);
    //strncpy(s2) < 8  可以完整地拷贝字符串到s1    
    //strncpy(s2) >= 9 ,也不至于越界,因为顶多拷贝8个
  • bzero 把一个字符串清0

    NAME
           bzero, explicit_bzero - zero a byte string
    ​
    SYNOPSIS
           #include <strings.h>
                bzero 用来把s指向的空间的前面n个字节 清0
           void bzero(void *s, size_t n);
    ​
    ​
  • strcat/strncat 连接两个字符串

    NAME
           strcat, strncat - concatenate two strings
    ​
    SYNOPSIS
           #include <string.h>
                strcat用来把src指向的字符串,连接到dest指向的字符串的末尾去."尾部连接"
                    strcat先找到dest指向的那个字符串末尾(\0处),从\0处开始连接src
                        指向的字符串,最后加一个\0
           char *strcat(char *dest, const char *src);
                dest :指向目标字符串,空间要足够大
                src : 指向原始字符串
                    返回值 : 
                        返回 连接后字符串的首地址(dest)
            strcat 也有bug,没有考虑到dest指向的空间,是否足够大的问题 ...越界风险
                            
                strncat及时用来修复strcat这个bug的
                strncat 也是把src指向的字符串拷贝到dest的末尾
                  但是它顶多拷贝n个字符
                       (1) 遇到\0拷贝结束  <= n
                       (2) 即使没有遇到\0,但是已经拷贝了n个字符,也结束(此时\0不会拷贝)
                            
           char *strncat(char *dest, const char *src, size_t n);
    ​
  • strcmp/strncmp 比较两个字符

    两个字符串如何比较?

    一个一个字符PK,PK他们的ASCII码.

    while(第一个字符串没有结束 || 第二个字符串没有结束)
    {
     if 第一个字符串的第i个字符 < 第二个字符串的第i个字符
         return -1; //表示第一个字符串 小
     else if(第一个字符串的第i个字符 > 第二个字符串的第i个字符)
         return 1;//表示第一个字符串 大
     else //第一个字符串的第i个字符 == 第二个字符串的第i个字符
         i++; //比较下一个
    }
    ​
    return 0;//表示两个字符串相等 ,一模一样
    NAME
        strcmp, strncmp - compare two strings
    ​
    SYNOPSIS
        #include <string.h>
    ​
        int strcmp(const char *s1, const char *s2);
                strncmp只比较前面的n字符
        int strncmp(const char *s1, const char *s2, size_t n);
    ​
    DESCRIPTION
        The  strcmp()  function compares the two strings s1 and s2.  It returns
        an integer less than, equal to, or greater than zero if  s1  is  found,
        respectively, to be less than, to match, or be greater than s2.
    ​
        The  strncmp()  function  is similar, except it compares only the first
        (at most) n bytes of s1 and s2.
    ​

    例子 :

    int m = strcmp("123","ABC");
        m < 0
     
    m = strcmp("123","123\0abc");
        m == 0
    m = strcmp("1234","123");
        m > 0
    m = strcmp("123","12345",3)
     m == 0
  • 1
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值