字符串[1]:基本概念以及常用的API

原创首发于CSDN,转载请注明出处,谢谢!


什么是字符串

与之前的数组做类比,大致可以将字符串看成一个“字符数组”,里面的每一个成员都是字符(char)。

//数组。
int  arr[3] = {1,2,3}; 
//字符串(最费力的定义方法。)
char str[3] = {'a','b','c'}; 

字符串的定义方式

我们直接在 ubuntu 环境下定义出几个字符串,演示代码 definie.c

/* define.c */
#include <stdio.h>
#include <string.h>

int main()
{	
        //方法一:指定字符串长度。
        char str[3] = "abc";  
        
		//方法二:让编译器自动计算字符串长度。
        char str2[] = "efg"; 

		//方法三:实际开发过程中使用指针偏多且为常量。
		char *str3 = "xyz"; 		
		return 0;
}

根据以上代码中字符串的定义方式,我们可以自然地对第二种定义方式提出一个小小的疑惑:对于这类不标长度的字符串,我们怎样计算它的大小? 进入下一小节 —— 字符串的长度计算


字符串的长度计算

在C语言中提供了两个函数来计算字符串的长度—— s i z e o f ( ) sizeof() sizeof() s t r l e n ( ) strlen() strlen() ,直接将上文中的代码拿来运行 str.c

/* str.c */
#include <stdio.h>
#include <string.h>

int main()
{
        char str[] = "efg";
        printf("sizeof:%ld\n", sizeof(str));
        printf("strlen:%ld\n", strlen(str));
        return 0;
}

运行结果:
sizeof & strlen

根据以上的结果显示,我们可以自然提出:同一个字符串大小为什么不一样?函数 s i z e o f ( ) sizeof() sizeof() 与函数 s t r l e n ( ) strlen() strlen() 的区别是什么?

答:

  • 定义字符串时不指定大小时,编译器回会自动在字符串尾部添加一个空字符 \0 。上文中的字符串看似只有三个,但实际上有四个字符。
  • 函数 s t r l e n ( ) strlen() strlen() 计算的是字符串中的有效位数个字符,当期遇到空字符 \0 后自动停止计数。函数 s i z e o f sizeof sizeof 则计算包含末尾的空字符在内的一切字符个数。

字符串空间的申请及其初始化

演示代码: memoryStr.c

/* memoryStr.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
	//方法一:字符串数组。
	char str[128] = {'\0'};

	//方法二:malloc开辟空间。
	char *pstr = NULL; 
	pstr = (char *)malloc(128); 
	memset(pstr ,'\0',128); 
}

根据以上的代码信心我们提出两个问题:方法二为什么不用野指针而用空指针NULL?方法二相比方法一的优势是什么?

答: 答: 答:

  • 空指针NULL表明指针没有动作,即没有指向内存任意地址,需要认为添加。野指针就是乱指。使用空指针比野指针更加安全。
  • 方法二比方法一更加灵活

字符串常用的API

关于常用的字符串 API 数量不多,仅 strcpy、strcat、strcmp、strchr、strstr、strtok、strlwr、strupr。笔者将相关字符串的运行代码直接发在下文内,读者请自行拷贝运行尝试。

|strncpy(拷贝)

演示代码: strcpy. c

/* strcpy. c */
#include <stdio.h>
#include <string.h>

int main()
{
	char str1[9] = "ABCDEFOPQ";
    char str2[6] = "HIJKLM";

    strncpy(str1,str2,6);
	puts(str1);
	return 0;
}

|strcat(拼接)

演示代码: strcat. c

/* strcat.c */
#include <stdio.h>
#include <string.h>

int main()
{
	char str3[] = "hello,";
    char str4[] = "world!";

    strcat(str3,str4);
	puts(str3);
	return 0;
}

|strcmp(比较)

strcmp()函数是根据ACSII码的值来比较两个字符串的;strcmp()函数首先将s1字符串的第一个字符值减去s2第一个字符,若差值为零则继续比较下去;若差值不为零,则返回差值。

演示代码: strcmp.c

/* strcmp.c */
#include <stdio.h>
#include <string.h>
 
int main()
{
	char *m="xYZ";
	char *n="Xyz";
	
//  函数原型:int strcmp(const char *s1, const char *s2);
	printf("strcmp(m,n):%d\n",strcmp(m,n));
	return 0;	
}

| strchr(单字符查找)

演示代码: strchr.c

/* strchr.c */
#include <stdio.h>
#include <string.h>

int main()
{

        char *str = "chen1,li,chen2";
        char c = 'l';

        char *p = NULL; //char *p aslo work. 
//		函数原型:char *strchr(const char *str, char c)
        p = strchr(str,c);

        if(p == NULL)
        {
                printf("No this char.\n");
        }else{
                printf("Exist.\n");
                puts(p);
        }
        return 0;
}

|strstr(子字符串查找)

函数strstr() 用于判断字符串str2是否是str1的子串。如果是,则该函数返回 str1字符串从 str2第一次出现的位置开始到 str1结尾的字符串;否则,返回NULL。

演示代码: strstr.c

/* strstr.c */ 
#include <stdio.h>
#include <string.h>

int main()
{
        char *str = "chen1,li,chen2";

       
		char *substr = "li";

        char *p2 = NULL;
//      函数原型:string strstr( string1,string2)
        p2 = strstr(str,substr);
        if(p2 == NULL){
                printf("No this substr in str.\n");
        }else{
                printf("Exist.\n");
                puts(p2);
        }
        return 0;
}

|strtok(字符分割)

函数 strtok() 用于分割字符串,具用法可以结合指针数组、循环等。函数原型char *strtok(char s[], const char *delim)。s为要分解的字符串,delim为分隔符字符串。strtok()用来将字符串分割成一个个片段。参数s指向欲分割[字符串,参数delim则为分割字符串中包含的所有字符。当strtok()在参数s的字符串中发现参数delim中包含的分割字符时,则会将该字符改为\0 字符。在第一次调用时,strtok()必需给予参数s字符串,往后的调用则将参数s设置成NULL。每次调用成功则返回指向被分割出片段的指针。

演示代码: strtok.c

/* strtok.c */
#include <stdio.h>
#include <string.h>

int main()
{
        char *p = NULL;
        char str2[] = "chen1,li,chen2";

//		函数原型:char *strtok(char s[], const char *delim)
        p = strtok(str2,",");
        if(p != NULL ){
                printf("First ------ p = %s\n",p);
        }

        p = strtok(NULL,",");
        printf("Second ------- p = %s\n",p);


        p = strtok(NULL,",");
        printf("Three ------ p = %s\n",p);
		
		p = strtok(NULL,",");
        printf("Four -------- p = %s\n",p);
        return 0;
}

运行结果:

First ------ p = chen1
Second ------- p = li
Three ------ p = chen2
Four -------- p = (null)

|strtok()加指针强化版——pstrtok()

演示代码: pstrtok.c

/* pstrtok.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
        char *p = NULL;
        char str2[] = "chen1,jack,chen2,hello,world";
        char *psubs[6];
        int i = 0;

        p = strtok(str2,",");
        if(p != NULL )
        {
                psubs[i] = p;
        }

        while(1)
        {
                i++;
                p = strtok(NULL,",");
                if(p != NULL){
                		psubs[i] = p;
                }else{
//                      printf("No substrs."\n);
                        break;
                }
        }

        int j;
        for(j = 0;j < i; j++)
        {
                printf("%s\n",psubs[j]);
        }
        return 0;
}
//注:字符乱码调试了半小时多,唉!		

运行结果: 运行结果: 运行结果:

chen1
jack
chen2
hello
world

|strlwr (字符转小写)、strupr(字符转大写)

/* strlwrStrupr.c */
#include <stdio.h>
#include <string.h>

int main()
{
        char p[] = "abc";
        char q[] = "ABC";
		
		//字符转大写。
        printf("strupr:%s\n",strupr(p));
        //字符转小写。
        printf("strlwr:%s\n",strlwr(q));
        
        return 0;
}

笔者在此处使用函数 strlwr()strupr(),GCC 编译器直接给出警告。后经搜索才知,原来C语言中标准库函数不包含这两个函数,只能在windows下(VC、MinGW等)使用,Linux 下的 GCC 里需要自己定义函数去实现。
strlwrstrupr.c


更新时间记录

  • “字符串的定义方式”一节完成。 「2021.4.28 21:36」
  • 文章更新到“字符串空间的申请以及初始化”一节。 「2021.4.29 17:46」
  • 文章初次竣工,文本中关于字符串函数仍然有疏漏的地方,待后几日补上。 「2021.4.29 21:37」
  • 原有的函数功能注释移出代码区。 「2021.4.29 21:46」
  • 将文本中原有的错误全部修改了一遍。 「2021.4.30 10:36」
  • 大幅度修改“strlwr & strupr”一节。 「2021.4.30 19:34」
  • 修改文章标题及部分段落格式。「2024.3.27 11:19」

P.S.1 写博客从来就不是一种轻松的活,哪怕是一篇常识性的博文,累! (2021.4.29 21:38)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值