入门学习计算机第十七天—字符串函数使用和剖析
发布日期:2021-06-28 16:38:50 浏览次数:2 分类:技术文章

本文共 6767 字,大约阅读时间需要 22 分钟。

入门学习计算机第十七天—字符串函数使用和剖析

编译器:Microsoft Visual Studio 2019

前言:

C语言中对字符和字符串的处理很是频繁,但是C语言本身是没有字符串类型的,字符串通常放在 常量字符串 或者 字符数组中,字符串常量适用于那些对它不做修改的字符串函数。

字符函数介绍 :

strlen: 字符串长度

size_t strlen (const char* str)//typedef unsigned int  size_t
  • 字符串以’\0’作为结束标志,strlen函数返回的是在字符串中’\0’ 前面出现的字符个数。
  • 参数指向的字符串必须要以’\0’结束。
  • 注意函数的放回值为size_t ,是无符号的(易错)
int main(){
if (strlen("abc") - strlen("abcdef") > 0) {
printf("hehe"); } else {
printf("haha"); } return 0;}

输出的结果是 “hehe”

strlen 返回值的类型是无符号数,两个无符号数相减,得到的结果依然是无符号数

不创建临时变量,求字符串长度

int my_strlen(char* a){
if (*a != 0) return 1 + my_strlen(a + 1); else return 0;}int main(){
char arr[] = "abcdef"; printf("%d\n", my_strlen(arr)); return 0;}

输出的结果是6。

strcpy 字符串拷贝

char*  strcpy(char* destination ,const char* source);
  • 原字符串以’\0’结束
  • 会将字符串中的’\0’拷贝到目标空间
  • 目标空间必须足够大,以确保能存放原字符串
  • 目标空间必须可变

模拟实现strcpy

char* my_strcpy(char* dest, const char* src){
assert(dest != NULL); assert(src != NULL); char* ret = dest; //拷贝src指向的字符串到dest指向的空间,包含'\0' while (*dest++ = *src++) {
; } //返回目的空间的起始地址 return ret;}int main(){
char arr1[] = "abcdefghi"; char arr2[] = "bit"; my_strcpy(arr1, arr2); printf("%s\n", arr1); return 0;}

strcat 字符串追加

char* strcat (char* destnation, const char* source);
  • 原字符串以’\0’结束
  • 目标空间必须足够大,以确保能容纳原字符串的内容
  • 目标空间必须可修改
  • 字符串自己给字节追加?

模拟实现 strcat

char* my_strcat(char* dest, const char* src){
assert(dest); assert(src); char* ret = dest; //1.找到目的字符串的'\0' while (*dest != '\0') {
dest++; } //2.追加 while (*dest++ = *src++) {
; } return ret;}int main(){
char arr1[50] = "hello"; char arr2[] = "world"; my_strcat(arr1, arr2); printf("%s\n", arr1); return 0;}

strcmp 字符串比较

int strcmp(const char *str1 , const char * str2)
  • 第一个字符串大于第二个字符串,则返回大于0的数字
  • 第一个字符串等于第二个字符串,返回0
  • 第一个字符串小于第二个字符串,返回小于0的数字
int main(){
const char* p1 = "chen"; const char* p2 = "wen"; int rent = (strcmp(p1, p2)); printf("%d\n", rent); return 0;}

输出的值是 -1

模拟实现strcmp

int my_strcmp(const char* a1, const char* a2){
while (*a1 ==*a2) {
if (*a1 == '\0') {
return 0;//相等 } a1++; a2++; } if (*a1 > *a2) return 1;// else return -1;}int main(){
const char* p1 = "chen"; const char* p2 = "when"; printf("%d\n", my_strcmp(p1, p2)); return 0;}

strncpy 长度受限制的字符拷贝

char* strncpy(char* strDest, const* strSource , size_t count) //count 的单位是字节
  • 拷贝num个字符从原字符串到目标空间
  • 如果原字符串的长度小于num,则拷贝完原字符串之后,在目标的后边追加0,直至num个
int main(){
char arr1[10] = "abcdefgh"; char arr2[] = "hello bit"; strncpy(arr1, arr2, 5); printf("%s\n", arr1); return 0;}

输出的结果是

在这里插入图片描述
模拟实现strncpy

char* my_strncpy(char* arr1, char* arr2, int count){
char* start = arr1; while (count && (*arr1++ = *arr2++)) {
count--; } if (count) {
while (--count) {
*arr1++ = '\0'; } } return start;}int main(){
char arr1[10] = "ab"; char arr2[] = "hello bit"; my_strncpy(arr1, arr2, 10); printf("%s\n", arr1); return 0;}

strncat 长度受限制的字符追加

char* strncat(char* strDest, const char* strSource, size_t count)
int main(){
char arr1[30] = "hello\0XXXXXXX"; char arr2[] ="world"; strncat(arr1,arr2,3);//strncat会主动补\0 printf("%s\n",arr1);}

在这里插入图片描述

模拟实现strncat

char* my_strncat(char* front, const char* back, size_t count){
char* start = front; while (*front++) {
; } front--; while (count--) {
if (!(*front++ = *back++)) {
return start; } } *front = '\0'; return start;}int main(){
char arr1[30] = "hello"; char arr2[]= "world"; my_strncat(arr1, arr2, 3);//strncat会主动补\0 printf("%s\n", arr1);}

strncmp 长度受限制的字符比较

int strncmp(const char* str1 , const char* str2 ,size_t num);
  • 比较到出现另个字符不一样或者一个字符串结束或者num个字符全部比较完。
int main(){
char arr1[30] = "hello"; char arr2[]= "helle"; int ret = strncmp(arr1, arr2, 4);//strncat会主动补\0 printf("%d\n",ret ); return 0;}

输出的结果是0

模拟实现strncmp

strstr 寻找子字符串

char* strstr(const char* string, const char * strCharSet)
int main(){
char* p1 = "abcdef"; char* p2 = "def"; char* ret = strstr(p1,p2); if(ret == NULL) {
printf("子串不存在\n"); } else {
printf("%s\n",ret); } return 0;}

模拟实现

char* my_strstr(const char* str1, const char* str2){
assert(str1); assert(str2); const char* s1 = str1; const char* s2 = str2; const char* cur = str1; if (*str2 == '\0') {
return (char*)str1; } while (*cur) {
s1 = cur; s2 = str2; while ((*s1!='\0') && (*s2 != '\0') && *s1 == *s2) {
s1++; s2++; } if (*s2 == '\0') {
return (char*)cur; } if (*s1 == '\0') {
return NULL; } cur++; } return NULL;//找不到子串}int main(){
char arr1[30] = "abcdefgih"; char arr2[]= "defasdawrawra"; const char* len = my_strstr(arr1, arr2); printf("%s\n",len ); return 0;}

strtok 提取被符号分割的字符串

char* strtok(char* str ,const char* sep)
  • sep参数是个字符串,定义了用作分隔符的字符集合
  • 第一个参数指定一个字符串,它包含了0个或者多个由sep字符串一个或者多个分隔符分割的标记
  • strtok 函数找到了str中的下一个标记,并将其用\0结尾 ,返回一个指向这个标记的指针(注:strtok函数会改变被操作的字符串找到str中的下一个标记,所以使用strtok函数切分的字符串一般都是临时拷贝的内容并且可修改)
  • strtok函数的第一个参数不为NULL,函数将找到str第一个标记,strtok函数将保存它在字符串中的位置
  • strtok函数的第一个参数为NULL,函数将同一个字符串中被保存的位置开始,查找下一个标记
  • 如果字符串不存在更多的标记,则返回NULL指针

函数的基本使用

int main(){
char arr[] = "abcd.ad.w@er"; const char* p = "@."; char* len = NULL; for (len = strtok(arr, p); len != NULL; len = strtok(NULL, p)) {
printf("%s\n", len); } return 0;}

在这里插入图片描述

strerror 错误信息函数 需要引头文件<errno.h>

char* strerror(int errnum);//返回错误码,所对应的错误信息

errno 是一个全局的错误码变量

当C语言的库函数在执行过程中,发生了错误,将会把对应的错误码,赋值到errno中
函数使用:打开text.txt文件

int main(){
FILE* pf = fopen("text.txt", "r");//打开文件 if (pf == NULL) {
printf("%s\n", strerror(errno)); } else {
printf("open file success\n"); } return 0;}

当code文件夹下没有text.txt文件时:

在这里插入图片描述
没有该文件或者目录
当文件下有text.txt文件时
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述字符转换:需要引头文件 <ctype.h>

int tolower(int c);//大写转小写 int toupper(int c);//小写转大写
int main(){
char arr = tolower("Q"); putchar(arr);}

输出的结果是q

将一个字符串全部打印成小写

int main(){
char arr[] = "I Am A Student"; int i = 0; while (arr[i]) {
if (isupper(arr[i]))//判断是否为大写 {
arr[i] = tolower(arr[i]); } i++; } printf("%s\n", arr); return 0;}

输出的结果为:

在这里插入图片描述

内存函数

memmove: 内存移动函数

void* memmove(void* destination ,const void* soure,size_t num);
  • 和mencpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的
  • 如果源空间和目标空间出现重叠,就得使用memmove函数处理

memcpy: 内存拷贝函数

void* memcpy(void* destination , const void* source, size_t num)
  • 函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置
  • 这个函数在遇到’\0’的时候并不会停下来
  • 如果source和destination有任何的重叠,复制的结果都是未定义的
int main(){
int arr1[] = {
1,2,3,4,5,6}; int arr2[] = {
0}; memcpy(arr2,arr1,6);}

在这里插入图片描述

模拟实现memcpy函数:

void* my_memcpy(void* dest, const void* src, size_t num){
assert(dest); assert(src); void* ret = dest; while(num--) {
*(char*)dest = *(char*)src; ++(char*)dest; ++(char*)src; } return ret;}int main(){
int arr1[] = {
1,2,3,4,5,6 }; int arr2[10] = {
0 }; my_memcpy(arr2, arr1,sizeof(arr1)); return 0;}

计算机知识/代码知识(零碎)

阅读文档的时候:

NULL - 空指针
NUL / Null - ‘\0’

转载地址:https://blog.csdn.net/xiaotangyu7dong/article/details/116559906 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:入门学习计算机第十八天——自定义数据类型(结构体)
下一篇:指针与数组笔试题解析

发表评论

最新留言

哈哈,博客排版真的漂亮呢~
[***.90.31.176]2024年04月04日 11时22分58秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章