網站首頁 編程語言 正文
strlen函數的講解
strlen函數我們應該不陌生,它可以幫助我們求字符串的長度(不包括’\0’),但里面還有一些細節需要我們注意。看一下下面這張圖:
strlen函數的頭文件是<string.h>.如果要使用strlen這個函數,別忘記引頭文件。
字符串是以 ‘\0’ 作為結束標志,strlen函數返回的是在字符串中 ‘\0’ 前面出現的字符個數。以下是用strlen函數時可能會遇到的幾種問題,先看代碼:
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[] = "qwer";
char arr2[] = { 'q','w','e','r' };
char arr3[] = { 'q','w','e','r','\0'};
char arr4[10]= { 'q','w','e','r' };
printf("arr1:%d\n", strlen(arr1));
printf("arr2:%d\n", strlen(arr2));
printf("arr2:%d\n", strlen(arr3));
printf("arr2:%d\n", strlen(arr4));
return 0;
}
以上代碼輸出的結果是什么?大家可以先試著算一下。然后再看運行結果。
運行結果如圖所示,arr1初始化的時候存放的是字符串,字符串的是以’\0’ 為結束標志的,所以arr1的大小為4。這個應該問題不大。
重點說一下下面這幾個。
arr2:我在初始化arr2的時候,是對arr2是以字符進行初始化的,但是我沒有設置arr的大小,所以編譯器是不知道arr2的大小的,后面存放的是什么東西也是不知道的,但是strlen它是找’\0’的,并返回’\0’之前字符的個數。所以
在strlen找到’\0’之前,前面有36個字符。
arr3:arr3與arr2不同的是,但是我在最后輸入了’\0’進行初始化,所以arr3很簡單的就找到了’\0’,并返回4。
arr4:arr4與arr2不同的是:我這次設置了arr4的大小,然后我用字符對arr4進行了初始化,雖然是用字符進行的部分初始化,但是編譯器會幫我把沒初始化的地方默認初始化為0,‘\0’的ASCII碼值就是0,C語言字符在內存的形式就是ASCII碼值,所以后面沒初始化的地方存放的都是’\0’。
我們再來看一個東西,由上面的圖,我們還可以知道strlen的返回值是size_t,這是一個無符號數。如果不清楚這個地方,我們也可能會在使用strlen的時候出現一些問題。看一下下面的代碼:
#include<stdio.h>
#include<string.h>
int main()
{
if (strlen("abc") - strlen("qwer") < 0)
{
printf("1");
}
else
{
printf("0");
}
return 0;
}
對于上面的代碼的運行結果是什么?
按常理來說,前面的字符串大小為3,后面的為4,比4小應該會打印1。我們來看運行結果:
它的運行結果是0,難道前面的字符串大小比后面的大嗎,其實不是。關鍵在于它的返回值是一個無符號數。無符號數只有正數,沒有負數。3-4=-1,但是此時的-1并不是有符號數,而是一個無符號數,那么-1此時就是一個很大的正數。所以此時才會輸出0
如果要解決這個問題,有以下兩種解決方案:
方法1:不相減,進行比較:
#include<stdio.h>
#include<string.h>
int main()
{
if (strlen("abc") < strlen("qwer"))
{
printf("1");
}
else
{
printf("0");
}
return 0;
}
方法2:強制類型轉換
#include<stdio.h>
#include<string.h>
int main()
{
if ((int)strlen("abc") -(int)strlen("qwer") < 0)
{
printf("1");
}
else
{
printf("0");
}
return 0;
}
說一下方法1,無符號數只有正數,沒有負數,直接計算大小(正數)就可以直接比較了。方法2是強制轉換為int類型的數據,整型是有符號數,有符號數就可以進行相減,結果為-1,就是-1。兩種結果輸出結果都是1.
strlen函數的模擬實現
講完了strlen函要注意的問題,下面講一下strlen函數的模擬實現。總共有三種方法:計數器方式,遞歸的方式和指針-指針的方式。
計數器方式
實現的思想:設置一個計數的變量,讓一個字符指針遍歷字符數組的每一個元素,如果指針指向的元素不是’\0’,計算器就自增,直到指針指向的元素是’\0’,就停止遍歷,并返回計數器。
因為是模擬實現,我們就只求一致,返回值就設置為size_t。
實現代碼如下:
#include<stdio.h>
#include<string.h>
#include<assert.h>
size_t my_strlen(const char* p)
{
int count = 0;
assert(p != NULL);//如果等于空指針就會報錯
while((*p) != '\0')
{
count++;
p++;
}
return count;
}
int main()
{
char arr[] = "CSDN";
int ret = my_strlen(arr);
printf("%d", ret);
return 0;
}
遞歸的方式
代碼實現的思想:這種方式是不用創建臨時變量的一種方法, 只使用指針進行遍歷,如果指針指向的不是’\0’,那么就返回1和指針指向后一個數據的結果。
size_t my_strlen(const char* p)
{
if ((*p) == '\0')
{
return 0;
}
else
{
return 1 + my_strlen(p+1);
}
}
int main()
{
char arr[] = "CSDN";
int ret = my_strlen(arr);
printf("%d", ret);
return 0;
}
指針減指針的方式
代碼實現的思想:
元素名是首元素的地址,我們就在定義一個指針,指向這個數組,讓這個指針進行遍歷,指向的不是’\0’就讓指針進行自增。最后讓遍歷完數組的指針減去數組名(也就是首元素的地址)。
注意:當兩個指著指向同一塊空間時,指針減指針的絕對值就是兩個指針之間的元素個數,而不是 個數*數據類型所占的空間。
size_t my_strlen(const char* p)
{
char* s = p;
while((*s) != '\0')
{
s++;
}
return s - p;
}
int main()
{
char arr[] = "CSDN";
int ret = my_strlen(arr);
printf("%d", ret);
return 0;
}
原文鏈接:https://blog.csdn.net/m0_63463510/article/details/125823799
相關推薦
- 2024-03-07 使用JdbcTemplate和Druid技術簡化持久層的編寫
- 2022-05-12 linq中的串聯操作符_實用技巧
- 2022-04-28 利用shell命令刪除指定的文件的方法_linux shell
- 2023-04-06 C++中的memset用法詳解_C 語言
- 2022-01-13 macOS 升級后 nvm 安裝的 node 和 npm 出錯
- 2022-09-09 使用Dockerfile腳本定制鏡像的方法_docker
- 2022-05-11 Nginx代理Redis哨兵主從配置
- 2022-05-22 Nginx的基本概念和原理_nginx
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支