08- c语言字符串 (C语言)

news/2025/2/13 0:03:51/

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

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、字符串的操作

#include <stdio.h>
#include <stdlib.h>
#include <string.h>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);

memset 功能:将指针s所指向的内存空间中的n个字节填充成c
示例代码:

#include <stdio.h>
#include <string.h>int main()
{char ch[10];memset(ch, 0, sizeof(ch)); //memset(ch, 0, sizeof(ch));printf("view the data ch: %d\n", ch[0]);return 0;
}

5、请分析下面代码有何问题?

char *p = "hello";
p[0] = 'A';

二 常见的字符串处理函数

1、atoi函数

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

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

#include <stdio.h>
#include <string.h>
#include <stdlib.h>int main(){char *p = "1234";int val = atoi(p);printf("view the data: %d\n", val);return 0;
}

练习:编写代码实现atoi函数

2、atof函数

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

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

#include <stdio.h>
#include <string.h>
#include <stdlib.h>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);

功能:计算字符串的长度

#include <stdio.h>
#include <string.h>
#include <stdlib.h>int main()
{char *ch = "hello";char arr[] = {'A', 'B', 'C', '\0', 'D'};printf("%d %d\n", strlen(ch), strlen(arr));return 0;
}

思考:为什么strlen(arr)得结果是3呢?
练习:编程实现strlen函数

#include <stdio.h>
#include <string.h>
#include <stdlib.h>int main(){char *ch = "hello";char arr[] = {'A', 'B', 'C', '\0', 'D'};printf("%d  %d\n", strlen(ch), strlen(arr));return 0;
}

思考:为什么strlen(arr)得结果是3呢?
练习:编程实现 strlen函数

#include <stdio.h>
#include <string.h>
#include <stdlib.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";char dst[10] = {0};strcpy(dst, src);printf("src: %s, dst: %s\n", src, dst);return 0;
}

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

#include <stdio.h>
#include <string.h>int main(){char a[4];char b[4];  //hellostrcpy(b, "hello");printf("view the data b: %s\n", b);  //helloprintf("view the data a: %s\n", a);  //0return 0;
}

2、strcpy的实现

char *strcpy(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];memset(ch, 0, sizeof(ch));strcpy(ch, "hello");strcat(ch, "world");printf("view the data: %s\n", ch);return 0;
}

注意:ch的空间要足够大!
strcat的实现:

#include <stdio.h>
#include <string.h>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 <string.h>
#include <stdlib.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");strncpy(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;
}

 区别总结如下:

  • strcat完整地连接源字符串到目标字符串的末尾,直到遇到源字符串的结尾字符。
  • strncat 限制了连接的字符数,只连接源字符串的前n个字符。

9、strcmp函数

#include <string.h>
int strcmp(const char *s1, const char *s2);

功能:strcmp 会按照字典顺序 逐个比较两个字符串的字符。比较规则如下:

  • 首先比较两个字符串的第一个字符,如果相等则继续比较下一个字符。
  • 如果两个字符串在某个位置的字符不相等,那么比较结果就是两个字符的ASCII码差值。
  • 如果其中一个字符串已经结束(遇到了空字符\0),而另一个字符串还有剩余字符,那么较短的字符串被视为小于较长的字符串。

参数:

  • s1:字符串1首地址
  • s2:字符串2首地址

返回值

  • 相等:0
  • 大于:>0 在不同操作系统strcmp结果会不同 返回ASCII差值
  • 小于:<0

原理:
strcmp的执行的逻辑:将s1和s2中对应位置的字符一一比较,直到两个字符串全部遍历完成(如果还没有发现有不同的字符则说明两者相等),或者有两个字符不相等,则比较结束。如果s1中的字符的ASCII码比s2中的大则返回1,否则返回-1
注意:有的编译器两个字符串

int main(){printf("%d\n", strcmp("hello", "hello"));  //前面等于后面,结果为0printf("%d\n", strcmp("hello", "heLlo"));  //前面大于后面,结果为1printf("%d\n", strcmp("Hello", "heLlo"));  //前面小于后面,结果为-1return 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

练习1:
在键盘上输入一串字符串,判断这个字符串和在程序中所设定的字符串是否相等(最多比较6个字符)(不区分大小写)

#include <stdio.h>
#include <string.h>
#include <stdlib.h>int main(){char ch1[10];char key[] = "A18Cd9";memset(ch1, 0, sizeof(ch1));printf("please input the key: %s\n", key);scanf("%s", ch1);printf("view the data ch1: %s\n", ch1);return 0;
}

练习2:
在键盘上输入一串字符串,将其中的非字母和非数字的字符删除!

#include <stdio.h>
#include <string.h>
#include <stdlib.h>int main(){char ch1[10];memset(ch1, 0, sizeof(ch1));printf("plz input the data:\n");scanf("%s", ch1);printf("the data ch1: %s\n", ch1);return 0;
}

11、strstr 函数

strstr是C语言中的一个字符串查找函数,用于 在一个字符串中查找子串的出现位置

#include <string.h>
char *strstr(const char *haystack, const char *needle);

功能:在字符串haystack中查找字符串needle出现的位置
参数:

  • haystack:源字符串首地址
  • needle:匹配字符串首地址

返回值

  • 成功:返回第一次出现的needle地址
  • 失败:NULL
  • 我们经常使用strstr来判断某个字符串是否时另外一个字符串的字串!
int main(){char src[] = "ddddsabcd12233dsfl23dlf09a1";char *p = strstr(src, "abcd");printf("p = %s\n", p);return 0;
}

12、strtok函数

strtok是C语言中的字符串分割函数,用于 将一个字符串按照指定的分隔符进行分割

#include <string.h>
char *strtok(char *str, const char *delim);

功能:来将字符串分割成一个个片段。当strtok()在参数s的字符串中发现参数delim中包含的分割字符时, 则会将该字符改为\0 字符,当连续出现多个时只替换第一个为\0。
参数:

  • str:指向欲分割的字符串
  • delim:为分割字符串中包含的所有字符

返回值

  • 成功:分割后字符串首地址
  • 失败:NULL

注意:

  • 在第一次调用时:strtok()必需给予参数s字符串
  • 往后的调用则将参数s设置成NULL,每次调用成功则返回指向被分割出片段的指针
int main(){char a[100] = "abc-efg-hijk-lmn";char *s = strtok(a, "-");  //将"-”分割的子串取出while (s != NULL){printf("%s\n", s);s = strtok(NULL, "-");printf("view the s: %s\n", s);}
}

字符串知识点完整代码:

int main(){//字符串的复制  strcpy/*char *src = "hello";char dst[10];strcpy(dst, src);printf("%s\n", dst);  //复制char a[4];char b[4];strcpy(b, "hello");printf("b: %s\n", b);printf("a: %s\n", a);*//*char *src = "hello\0world";char dst[10];//char *dst;//dst = malloc(10);memset(dst, 'A', 10);printf("dst:%s\n", dst);    //AAAAAAAAAAstrncpy(dst, src, 3);printf("dst: %s\n", dst);   //helAAAAAAAchar *src1 = "hello";memset(dst, 0, 10);strncpy(dst, src, sizeof(dst)-1);printf("dst:%s\n", dst);    //helloint i;for (i=0; i<10; i++)printf("view the i: %d dst[i]: %c\n", i, dst[i]);printf("\n");*///字符串的拼接 strcat/*char dst[20];memset(dst, 0, sizeof(dst));char *src = "he\0llo";strcpy(dst, "world");strcat(dst, src);printf("dst: %s\n", dst);  //worldhe *///字符串的对比//strcmp函数/*char *s1 = "hello world";char *s2 = "hello";printf("%d\n", strcmp(s2, s1));   //-1char *stus[] = {"zhangsan", "lisi", "wangwu", "liusan", "huangsan"};int i;for (i=0; i<3; i++){if (strcmp(stus[i], "lisi") == 0)printf("hello, lisi: %d\n", i);   //1}printf("view the data strncmp: %d\n", strncmp(s1, s2, 5));   //0 *///strstr函数  查找字符串内部是否存在某个元素/*char *stus[] = {"zhangsan", "lisi", "wangwu", "liusan", "huangsan"};int i;char *p;for (i=0; i<5; i++){//找出名字中带san的学生if (p = strstr(stus[i], "san")){printf("view the data, i: %d, stus[i]: %s\n", i, stus[i]);printf("%p, %p\n", stus[i], p);}}*///字符串的分割  strtokchar data[] = {"##name=zhangsan;score=99.5;age=10##"};//第一步用;分割char *p;int n = 0;int len;p = strtok(data, ";");printf("view the n: %s\n", p);  //##name=zhangsanlen = strlen(p);while (*p != '=' && n<=len){printf("n:%d\n", n);p++;n++;}if (n <= len){p++;char name[10];memset(name, 0, 10);strcpy(name, p);printf("view the n: %d, len: %d, name: %s\n", n, len, name);  //zhangsan}//第二次对剩下的数据使用;分割char name[10];int age;float score;while (p = strtok(NULL, ";")){char *tmp = p;printf("%s\n", p);len = strlen(p);n = 0;while (*p != '=' && n<=len){p++;n++;}printf("view the data p: %c", p);if (n <= len){p++;if (strstr(tmp, "age=") != NULL){age = atoi(p);printf("age: %d\n", age);}else if (strstr (tmp, "score=") != NULL){score = atof(p);printf("score: %f\n", score);}}}p = strtok(NULL, ";");printf("view the strtok p: %s\n", p);len = strlen(p);n = 0;while (*p != '=' && n<=len){p++;n++;}if (n <= len){p++;int age;age = atoi(p);  //18printf("age: %d\n", age);}p = strtok(NULL, ";");printf("+++++ %s\n", p);len = strlen(p);n = 0;while (*p != '=' && n<=len){p++;n++;}if (n <= len){p++;float score;score = atof(p);printf("score: %f\n", score);}return 0;
}


http://www.ppmy.cn/news/558721.html

相关文章

浏览器演变史 详评1991年以来的浏览器

http://www.sina.com.cn 2009年08月26日 13:40 IT.COM.CN 文/Panx 【IT世界整理】Web浏览器如今可谓遍地开花。 你可以选择精悍的Chrome浏览器。 或者有人仍然坚持使用IE(不是特别的符合国际标准&#xff0c;但是市场份额较大&#xff0c;使得开发者也不可能放弃IE) 。…

python制作软件封面_用python给MP3加封面图片,修改作者,专辑等信息

如何给MP3加封面呢&#xff0c;当然用iturns&#xff0c;千千静听当然是可以的&#xff0c;但是如果用程序来自动加封面呢&#xff0c;研究linux的ffmpeg&#xff0c;发现用这个加专辑信息还是容易的&#xff0c;但是封面始终加不上&#xff0c;无法&#xff0c;去研究mp3文件的…

全国OA系统下载地址(全)

1.思道OA http://www.anyoffice.net 微软.NET平台,支持64位 2.金和OA http://www.jinher.com 3.红帆OA http://www.ioffice.cn 4.致远OA http://www.seeyon.com 5.华天动力OA http://www.oa8000.com 6.万户OA http://www.whir.net 7.九思OA http://www.jiusi.net 8.合强OA http…

B站【云E办】在线办公系统 项目源码

B站项目【云E办】在线办公系统 之前学习Springboot的时候就在B站看到了这个项目&#xff0c;一直想着什么时候有空学习一下&#xff0c;从项目开始着手到完成&#xff0c;前前后后经历了一个多月的时间&#xff0c;总算是较为完整的完成了整个项目&#xff0c;其中磕磕绊绊的遇…

如何更改通达OA附件的存储目录

关于更改通达OA附件的存储目录 1、默认路径 通达OA中的附件存储的默认路径为&#xff1a;MYOA/attach&#xff0c;attach以下按照模块的类别建立的文件夹&#xff1a; 标识ID 模块名称 模块代码 1 电子邮件 email 2 工作流 workflow 3 文件柜 file_folder 4 公告…

OA办公系统源码下载_PHPOA源码

csdn下载地址&#xff1a; https://download.csdn.net/download/dujiangdu123/13057557 蓝奏云&#xff1a; https://youyacao.lanzous.com/iDzMnhrnvoh 信呼协同办公OA系统简介 信呼协同办公OA系统是开源的一款办公系统&#xff0c;跨平台的系统&#xff0c;支持APP&#…

通达OA2019安装教程

通达OA2019安装步骤&#xff1a; 1、到官网下载OA2019最新版服务端安装包、用户PC端办公精灵、手机端下载址:https://cdndown.tongda2000.com/oa/2019/TDOA11.6.exe 2、安装OA服务端到电脑或服务器或云主机或VPS主机 3、安装完&#xff0c;在OA服务管理器&#xff08;MYOA\BIN\…

资源网站(电驴替代方案)

0、http://www.emule-project.net/这个不用说了,emule官方,没有它就没有下面的所有一切,德国人开的。只提供官方版emule软件,没有资源下载。秉承理念“eMule是完全免费的,它也决不包含广告软件