字符串的介绍及常用API总结

本期主要介绍字符串的使用以及常用的API!

目录

一、定义字符串的几种方式

二、字符数组的存储方式

三、sizeof和strlen的区别

四、动态开辟字符串

1.malloc

2.free

3.realloc(扩容)

4.memset

五、几种字符串常用的API      

         1.puts、printf、sprintf                 

 2.scanf、fscanf、gets                

 3.gets和getchar                 

 4.strcpy                 

 5.strncpy

        5.1自己封装strcpy的原型

        5.2 自己封装strncpy的原型

 6.断言assert                

 7. strcat 拼接                    

          7.1自己封装的strcat

  8. strcmp 比较

           8.1自己封装的strcmp

  9. strstr查找字符串

            9.1自己封装的strstr

  10.strtok分割字符

  11.chdir改变当前目录

  12.access函数

   13. fflush函数


一、定义字符串的几种方式

//1.和整型数组一个道理 char str[]={'h','e','l','l','o'};

char str[]={'h','e','l','l','o'};

//2.改进. char str[]="hello";

char str[]="hello";

//3.一般用 char *p = "hello";

char *p = "hello";

#include <stdio.h>

int main()
{
    //字符串的定义方式
    //1.和整型数组一个道理 char str[]={'h','e','l','l','o'};
    char str[]={'h','e','l','l','o'};
    //2.改进. char str[]="hello";  是字符串变量,可改变里面的值
    char str1[]="hello";
    //3.一般用  char *p = "hello";    是字符串常量,不可改变里面的值
    char *p = "hello";
    
    printf("str1的字符串为%s",str1);
    printf("p的字符串为%s",p);
    return 0;
}

二、字符数组的存储方式

注:字符串会多了以'\0'结束为标志 char cdata[] = "hello";   

#include <stdio.h>

int main()
{
    int data[] = {1,2,3,4,5};
    char cdata[] = "hello";
    char cdata2[] = {'h','e','l','l','o'};  //字符串的结束标志
    int lendata;
    int lencdata;
    int lencdata2;
    //计算数组data的元素
    lendata = sizeof(data)/sizeof(data[0]);
    lencdata = sizeof(cdata)/sizeof(cdata[0]);
    lencdata2 = sizeof(cdata2)/sizeof(cdata[0]);
    
    printf("%d\n",lendata);
    printf("%d\n",lencdata);
    printf("%d\n",lencdata2);
    return 0;
}

 

三、sizeof和strlen的区别

sizeof 是操作符, strlen 为函数;

sizeof 可以使用类型作为参数,如 int char; strlen 只能使用 char*做参数且以\0 为结尾

sizeof 为数组时候,不退化, 传递给 strlen 时数组会被退化成指针; 

1.strlen 计算有效字符的长度  

eg:

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

int main()
{
    char data[128] = "hello";
    
    printf("sizeof的大小:%d\n",sizeof(data));
    printf("strlen的大小:%d\n",strlen(data));
    
    return 0;
}

 2.sizeof一个char*时,得出是计算机用多少字节来表示一个地址。

eg:

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

void test()
{
    
}
int main()
{
    char data[128] = "hello";
    
    //printf("sizeof的大小:%d\n",sizeof(data));
    //printf("strlen的大小:%d\n",strlen(data));
    
    char *pdata = "hello";
    void (*ptest)();
    ptest = test;
    
    //pdata是一个char * sizeof来计算的时候,得出是计算机用多少字节来表示一个地址。
    printf("sizeof pdata的大小: %d\n",sizeof(pdata));
    printf("sizeof char *的大小:%d\n",sizeof(char *));
    printf("sizeof int * 的大小:%d\n",sizeof(int *));
    printf("sizeof char 的大小: %d\n",sizeof(char));
    printf("sizeof test 的大小: %d\n",sizeof(test));
    printf("sizeof ptest 的大小: %d\n",sizeof(ptest));
    printf("strlen的大小:%d\n",strlen(data));
    
    return 0;
}

 四、动态开辟字符串

1.malloc

原型:void *malloc(size_t size),其中size_t size是指开辟多少个字节。

malloc函数的作用是动态分配内存,以解决静态内存定长、不能手动释放等缺陷。

char *p;
p = (char *)malloc(1);//防止野指针
*p = 'c';

2.free

原型: void free(void *ptr);

作用:1.释放,防止内存泄露 2.防止悬挂指针——野指针的一种

 char *p;
p = (char *)malloc(1);//防止野指针
*p = 'c';
free(p);
p = NULL;

3.realloc(扩容)

原型: void *realloc(void *ptr,size_size); 其中size_siz表示在原基础上增加多少字节

尝试重新调整之前调用malloc或calloc 所分配的ptr所指向的内存块的大小。

char*p;
p = (char *)malloc(12);
p = "hasdhsiafpoasda12";
int len = strlen("hasdhsiafpoasda12");
int newlen = len-12+1;
realloc(p,newlen);

4.memset

原型: void *memset(void *str,int c,size_t n);

用来对一段内存空间全部设置为某个字符,一般用在对定义的字符串进行初始化为‘ ’或‘/0’;

char*p;
p = (char *)malloc(12);
memset(p,'\0',12);//把开辟的内存空间全部初始化为\0 

五、几种字符串常用的API

1.puts、printf、sprintf

原型:

#include <stdio.h>
int puts(const char *s);

int printf ( const char * format, ... );

eg: 

#include <stdio.h>

int main()
{
    char *p = "hello";
    puts(p);
    printf("%s",p);
    return 0;
}

1.2 sprintf

原型: 

int sprintf( char *buffer, const char *format [, argument,...] );

除了前两个参数类型固定外,后面可以接任意多个参数。而它的精华,显然就在第二个参数:格式化字符串上。

2.scanf、fscanf、gets

scanf("%s",p);

gets();//char gets(char * str);

注:本函数可以无限读取,易发生溢出。如果溢出,多出来的字符将被写入到堆栈中,这就覆盖了堆栈原先的内容,破坏一个或多个不相关变量的值。

#include <stdio.h>

int main()
{
    char *p = "hello";
    char str[128] = {'\0'};
    scanf("%s",p);
    printf("请输入str:\n");
    gets(str);
    puts(str);
    return 0;
}

#include <stdio.h> 

原型:int fscanf(FILE*stream, constchar*format, [argument...]);

功能:为根据数据格式(format)从输入流(stream)中写入数据(argument);

参数:stream为文件指针,format为格式化字符串,argument 为格式化控制符对应的参数。

3. gets与getchar

区别:

1、gets函数是输入一行字符串,以回车结束,并且回车键会被过滤掉,不会被读回到字符串中。

2、而getchar()是读答取一个字符,包括回车键也会被读成一个字符。这个程序在输入name[i]前,用getchar()把之前scanf("%d",&num[i]);中,输入整数后按的回车键给读走,否则这个回车键会导致gets直接读到一个空字符串。

4. strcpy

原型:char * strcpy( char * dst, const char * src );

dst ->destination  -指向用于存储复制内容的目标数组。

str ->source– 要复制的字符串。

strcpy是一种C语言的标准库函数,strcpy把从src地址开始且含有’\0’结束符的字符串复制到以dest开始的地址空间,返回值的类型为char*。

5. strncpy

原型:char *strncpy(char *dest, const char *src, size_t n)

把 src 所指向的字符串复制到 dest,最多复制 n 个字符。 当 src 的长度小于 n 时,dest 的剩余部分将用空字节填充。

eg:

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

int main()
{
    char des[128] = {'\0'};
    char des1[128] = {'\0'};
    
    char *stc = "hello";
    char *p = "niaho";
    strcpy(des,stc);
    puts(des);
    strncpy(des1,p,2);
    puts(des1);
    return 0;
}

5.1自己封装strcpy的原型

#include <stdio.h>
char* mystrcpy3(char *des,char *src)
{
    if(des == NULL || src == NULL){
        
        return NULL;
    }
    
    char *bak = des;
    
    while(* src != '\0'){
        *des++ = *src++;
        
    }
    *des = '\0';
    return bak;
}

char* mystrcpy2(char *des,char *src)
{
    if(des == NULL || src == NULL){
        
        return NULL;
    }
    
    char *bak = des;
    
    while(* src != '\0'){
        *des = *src;
        *des++;
        *src++;
    }
    *des = '\0';
    return bak;
}

char* mystrcpy(char *des,char *src)
{
    if(des == NULL || src == NULL){
        
        return NULL;
    }
    
    char *bak = des;
    
    while( (*des++ = *src++) != '\0');
    *des = '\0';
    return bak;
}
int main()
{
    char str[128] = {'\0'};
    char *p = "hello";
    
    mystrcpy3(str,p);
    puts(str);
    return 0;
}

 比较高级的

while((*des++ = *src++) !='\0')`

类似于

char a = 'm';
char b;

if((b=a)==m){
    printf("ok~!");
}

5.2 自己封装strncpy的原型

#include <stdio.h>
char* mystrncpy3(char *des,char *src,int count)
{
    if(des == NULL || src == NULL){
        
        return NULL;
    }
    
    char *bak = des;
    
    while(* src != '\0' && count > 0){
        *des++ = *src++;
        count--;
    }
    if(count > 0){
        count--;
        *des++ = '\0';
        return des;
    }
    *des = '\0';
    return bak;
}

char* mystrcpy2(char *des,char *src)
{
    if(des == NULL || src == NULL){
        
        return NULL;
    }
    
    char *bak = des;
    
    while(* src != '\0'){
        *des = *src;
        *des++;
        *src++;
    }
    *des = '\0';
    return bak;
}

char* mystrcpy(char *des,char *src)
{
    if(des == NULL || src == NULL){
        
        return NULL;
    }
    
    char *bak = des;
    
    while( (*des++ = *src++) != '\0');
    *des = '\0';
    return bak;
}
int main()
{
    char str[128] = {'\0'};
    char *p = "hello";
    
    mystrncpy3(str,p,2);
    puts(str);
    return 0;
}

6.断言assert

它是个宏,并且作用并非"报错"。

assert() 的用法像是一种"契约式编程"

if(假设成立)
{
     程序正常运行;
}
else
{
      报错&&终止程序!(避免由程序运行引起更大的错误)  
}
 

assert 宏的原型定义在 assert.h 中,其作用是如果它的条件返回错误,则终止程序执行。

assert 的作用是现计算表达式 expression ,如果其值为假(即为0),那么它先向 stderr 打印一条出错信息,然后通过调用 abort 来终止程序运行。

assert 的缺点是,频繁的调用会极大的影响程序的性能,增加额外的开销。

7. strcat 拼接

原型:char *strcat(char *des,const char *src);  

char str[128] = "nihaoa";
char *p = "1245";
strcat(str,p);
puts(str);

7.1自己封装的strcat          

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

char* mystrcat(char *des,char *src)
{
    assert(des != NULL && src != NULL);
    char *bak =des;
    
    while(*des != '\0'){
        *des++;
    }
    while((*des++ = *src++) != '\0');
    *des = '\0';
    return bak;
}

char* mystrcat2(char *des,char *src)
{
    assert(des != NULL && src != NULL);
    char *bak =des;
    
    strcpy(des+strlen(des),src);//des+strlen(des) 指把指针便宜strlen(des)这么长。
    return bak;
}
int main()
{
    char str[128] = "niha";
    char *p = "hh";
    
    mystrcat2(str,p);
    puts(str);
    return 0;
}

 规则:把src所指向的字符串(包括‘\0’)复制到dest所指向的字符串后面(删除dest原来末尾的'‘\0'),要保证des足够长,以容纳被复制进来的src。src中原有的字符不变,返回指向des的指针。

7.2 c语言中 “=”和”==“的区别

1.“=” 是把“=”右边的值赋值给左边。

2.“==” 是将“==”左右的值作比较。 

8. strcmp 比较

原型:int strcmp(const char* s1,const char *s2);

若s1=s2,则返回零;若s1<s2,则返回负数;若s1>s2,则返回正数;

if(!strcmp("ls","cmd")) return LS;

在if(表达式){语句} 条件语句里,如果表达式值为真的话,刚执行花括号里的语句;若表达式为假,刚不执行 对于if(!a)来说,要看你给a的初值是什么,如果是一个非零值的话,那么!a就是假,不执行语句; 如果a的初值为零,那么!a就是真,执行语句(另外,C++中把非零的数看作是真,零为假)

8.1自己封装的strcmp

#include <assert.h>
#include <stdio.h> 
int  MyStrCmp(const char* str1, const char* str2)
{
    assert((str1 != NULL) && (str2 != NULL));//用于检查,如果为空就停止
    while ((*str1 == *str2) && (*str1 != '\0') && (*str2 != '\0'))
    {
        str1++;
        str2++;
    }
    return  (*str1 - *str2); 
}  
int main(int args, char* argv[])
{
    char s1[256]={0};
    char s2[256]={0};

     int ret;
    printf("please input s1:\n");
    gets(a1);
    printf("please input s2:\n");
    gets(a2);
    ret = MyStrCmp(s1,s2);

      if(ret ==0){

                printf("s1 s2 is same\n");

        }

}
 

9. strstr查找字符串

C语言中,strstr()函数用于找到子串在一个字符串中第一次出现的位置,在string.h头文件中。 例如:char *strstr(const char *str1, const char *str2) str1是总串,str2是需要匹配的第一个字串位置,返回值为char * 类型

9.1自己封装的strstr

#include <stdio.h>
#include <assert.h>
char *my_strstr(char const *pdest, char const *psrc)
{
    const char *pstr1 = pdest;
    const char *pstr2 = psrc;
    const char *ptr = NULL;
    assert(pdest);
    assert(psrc);
    if (*pstr2 == '\0')
    {
        return (char *)pstr1;
    }
    while (*pstr1 != '\0')
    {
        ptr = pstr1;
        pstr2 = psrc;
        while (*ptr != '\0' && *pstr2 != '\0'
            && *ptr == *pstr2)
        {
            ptr++;
            pstr2++;
        }
        if (*pstr2 == '\0')
        {
            return (char *)pstr1;
        }
        pstr1++;
    }
    return NULL;
}
int main()
{
    char *des = "abbbcdef";
    char *str= "bcd";

    char *ret =NULL;
    ret = my_strstr(des,str) ;

     printf("分割后:%s\n",ret);       
    return 0;

10.strtok分割字符

strtok的函数原型: char* strtok (char* str, const char* sep)

1.包含在string.h头文件中

2.sep是个字符串,定义了用作分隔符的字符集合

3.第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标记

4.strtok函数找到str中的下一个标记,并将其用’\0’结尾,返回一个指向这个标记的指针。(注意:strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容并可修改)

5.strtok函数的第一个参数不为NULL,函数将找到str中的第一个标记,strtok函数将保存它在字符串中的位置。

6.strtok函数的第一个参数为NULL,函数将在同一个字符串被保存的位置开始,查找下一个标记。

7.如果字符串中不存在更多的标记,则返回NULL指针。

11.chdir改变当前目录

chdir(const char * path);

函数说明:chdir()用来将当前的工作目录改变成以参数path 所指的目录

返回值执:行成功则返回0, 失败返回-1, errno 为错误代码.

12.access函数

int access(const char *pathname, int mode);

access函数用来判断指定的文件或目录是否存在(F_OK),已存在的文件或目录是否有可读(R_OK)、可写(W_OK)、可执行(X_OK)权限。F_OK、R_OK、W_OK、X_OK这四种方式通过access函数中的第二个参数mode指定。如果指定的方式有效,则此函数返回0,否则返回-1。

13. fflush函数

fflush函数 更新缓存区

函数定义:int fflush(FILE *stream); 函数说明:调用fflush()会将缓冲区中的内容写到stream所指的文件中去.若stream为NULL,则会将所有打开的文件进行数据更新

2、fflush(stdin):刷新缓冲区,将缓冲区内的数据清空并丢弃 fflush(stdout):刷新缓冲区,将缓冲区内的数据输出到设备

  • 10
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值