生活随笔
收集整理的這篇文章主要介紹了
strlen() Bug
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
C語言strlen()以NUL作為字符串結(jié)束標(biāo)記,自定義一個字符串長度統(tǒng)計函數(shù)消除這個Bug
分享到:
QQ空間 新浪微博 騰訊微博 豆瓣 人人網(wǎng)
我們知道,字符串長度統(tǒng)計函數(shù) strlen() 以NUL作為字符串結(jié)束標(biāo)記,但是很不幸的是,有時候字符串并不以NUL結(jié)束,例如: 復(fù)制純文本復(fù)制
char strA[ 5 ] = { '1' , '2' , '3' , '4' , '5' } ; char strA[5] = {'1', '2', '3', '4', '5'}; 這個時候使用 strlen() 函數(shù)會出現(xiàn)莫名其妙的結(jié)果,因為 strlen() 會一直統(tǒng)計內(nèi)存中的字符,直到遇到NUL,而什么時候遇到是不可預(yù)知的。
請大家編寫一個安全的字符串長度統(tǒng)計函數(shù),即使字符串未以NUL結(jié)尾,也不會出錯。
注意:你需要向自定義函數(shù)傳遞一個參數(shù),它的值就是字符串緩沖區(qū)的長度。 復(fù)制純文本復(fù)制
#include <stdio.h> #include <string.h> #include <stddef.h> ? @function @param @param size_t my_strlen ( char const * string, size_t size ) { register size_t length; ? for ( length = 0 ; length < size; length++ ) if ( * string++ == ' \0 ' ) break ; ? return length; } ? int main () { char strA[ 5 ] = { '1' , '2' , '3' , '4' , '5' } , strB[ 10 ] = "123456789" ; ? printf ( "The length of strA is %d -- By strlen() \n " , strlen ( strA) ); printf ( "The length of strA is %d -- By my_strlen() \n " , my_strlen ( strA, 5 ) ); printf ( "The length of strB is %d -- By strlen() \n " , strlen ( strB) ); printf ( "The length of strB is %d -- By my_strlen() \n " , my_strlen ( strB, 10 ) ); ? return 0 ; } #include <stdio.h>
#include <string.h>
#include <stddef.h>/*** @function 安全的字符串長度函數(shù)* * @param string 要計算長度的字符串* @param size 字符串緩沖區(qū)長度
**/
size_t my_strlen( char const *string, size_t size ){register size_t length;// 統(tǒng)計范圍不超過 sizefor ( length = 0; length < size; length++ )if( *string++ == '\0')break;return length;
}int main(){char strA[5] = {'1', '2', '3', '4', '5'},strB[10] = "123456789";// 對比 strlen() 和 my_strlen() 的結(jié)果printf("The length of strA is %d -- By strlen()\n", strlen(strA) );printf("The length of strA is %d -- By my_strlen()\n", my_strlen(strA, 5) );printf("The length of strB is %d -- By strlen()\n", strlen(strB) );printf("The length of strB is %d -- By my_strlen()\n", my_strlen(strB, 10) );return 0;
} 運行結(jié)果: The length of strA is 17 -- By strlen()
The length of strA is 5 -- By my_strlen()
The length of strB is 9 -- By strlen()
The length of strB is 9 -- By my_strlen() 注意:17 明顯超出了字符數(shù)組范圍。
C語言實現(xiàn)動態(tài)數(shù)組,克服靜態(tài)數(shù)組大小固定的缺陷 分享到:
QQ空間 新浪微博 騰訊微博 豆瓣 人人網(wǎng) C語言中,數(shù)組長度必須在創(chuàng)建數(shù)組時指定,并且只能是一個常數(shù),不能是變量。一旦定義了一個數(shù)組,系統(tǒng)將為它分配一個固定大小的空間,以后不能改變,稱為靜態(tài)數(shù)組。但在編程過程中,有時我們所需的內(nèi)存空間無法預(yù)先確定,對于這個問題,用靜態(tài)數(shù)組的辦法很難解決。
動態(tài)數(shù)組是相對于靜態(tài)數(shù)組而言。靜態(tài)數(shù)組的長度是預(yù)先定義好的,在整個程序中,一旦給定大小后就無法改變。而動態(tài)數(shù)組則不然,它可以隨程序需要而重新指定大小。動態(tài)數(shù)組的內(nèi)存空間是從堆(heap)上分配(即動態(tài)分配)的。是通過執(zhí)行代碼而為其分配存儲空間。當(dāng)程序執(zhí)行到這些語句時,才為其分配。程序員自己負(fù)責(zé)釋放內(nèi)存。
那么,如何創(chuàng)建動態(tài)數(shù)組,按照需要設(shè)置數(shù)組大小呢?
下面是一個創(chuàng)建動態(tài)數(shù)組的例子: 復(fù)制純文本復(fù)制
#include <stdio.h> #include <stdlib.h> ? int main () { int arrLen; int * array; int i; ? printf ( "輸入數(shù)組長度:" ); scanf ( "%d" , & arrLen); array = ( int *) malloc ( arrLen* sizeof ( int ) ); if (! array) { printf ( "創(chuàng)建數(shù)組失敗! \n " ); exit ( 1 ); } for ( i= 0 ; i< arrLen; i++) { array[ i] = i+1 ; } for ( i= 0 ; i< arrLen; i++) { printf ( "%d " , array[ i]); } printf ( " \n " ); free ( array); system ( "pause" ); return 0 ; } #include <stdio.h>
#include <stdlib.h>int main(){int arrLen; // 數(shù)組長度int *array; // 數(shù)組指針int i; // 數(shù)組下標(biāo)printf("輸入數(shù)組長度:");scanf("%d", &arrLen);// 動態(tài)分配內(nèi)存空間,如果失敗就退出程序array = (int*)malloc( arrLen*sizeof(int) );if(!array){printf("創(chuàng)建數(shù)組失敗!\n");exit(1); }// 向內(nèi)存中寫入數(shù)據(jù)for(i=0; i<arrLen; i++){array[i] = i+1;}// 循環(huán)輸出數(shù)組元素for(i=0; i<arrLen; i++){printf("%d ", array[i]);}printf("\n");free(array); system("pause");return 0;
} 運行結(jié)果:
輸入數(shù)組長度:10
1 2 3 4 5 6 7 8 9 10
請按任意鍵繼續(xù). . .
malloc()函數(shù) 這里重點說明的是malloc()函數(shù),這是一個非常重要和常用的函數(shù)。
malloc() 用來動態(tài)分配指定大小的內(nèi)存空間,以字節(jié)計,其原型為:
? ?void *malloc( size_t size );
size_t 是一種自定義數(shù)據(jù)類型,在 stddef.h 頭文件中定義為:
? ?typedef unsigned int size_t; ?// 無符號整型
malloc()返回值類型為 void *,這并不是說該函數(shù)調(diào)用后無返回值,而是返回一個內(nèi)存結(jié)點的地址,該地址的類型為void(無類型或類型不確定),即一段存儲區(qū)的首址,其具體類型無法確定,只有使用時根據(jù)各個域值數(shù)據(jù)再確定。可以用強制轉(zhuǎn)換的方法將其轉(zhuǎn)換為別的類型。例如: 復(fù)制純文本復(fù)制
double * pd= NULL; pd=( double *) malloc ( 10 * sizeof ( double )); double*pd=NULL;
pd=(double*)malloc(10*sizeof(double)); 表示將向系統(tǒng)申請10個連續(xù)的double類型的存儲空間,并用指針pd指向這個連續(xù)的空間的首地址。并且用(double)對malloc()的返回類型進(jìn)行轉(zhuǎn)換,以便把double類型數(shù)據(jù)的地址賦值給指針pd。
sizeof 上面的代碼中,array = (int*)malloc( arrLen*sizeof(int) ); 用來分配arrLen*sizeof(int)個字節(jié)的內(nèi)存空間,并將返回的指針強制轉(zhuǎn)換為int。這里注意,int 類型的長度在不同平臺下可能不同,不要把int的長度指定為2或4,要用sizeof()來計算int的長度,以更好的跨平臺。
使用內(nèi)存中的數(shù)據(jù) 上面的代碼中,我們通過下標(biāo)(array[i])來引用數(shù)組元素,這個靜態(tài)數(shù)組沒有什么區(qū)別。另外還可以通過指針來引用數(shù)組元素,對上面的程序稍作修改: 復(fù)制純文本復(fù)制
#include <stdio.h> #include <stdlib.h> ? int main () { int arrLen; int * array; int * arrayCopy; int i; ? printf ( "輸入數(shù)組長度:" ); scanf ( "%d" , & arrLen); arrayCopy = array = ( int *) malloc ( arrLen* sizeof ( int ) ); if (! array) { printf ( "創(chuàng)建數(shù)組失敗! \n " ); exit ( 1 ); } for ( i= 0 ; i< arrLen; i++) { * arrayCopy++ = i+1 ; } arrayCopy = array; for ( i= 0 ; i< arrLen; i++) { printf ( "%d " , * arrayCopy++); } printf ( " \n " ); free ( array); system ( "pause" ); return 0 ; } #include <stdio.h>
#include <stdlib.h>int main(){int arrLen; // 數(shù)組長度int *array; // 數(shù)組指針int *arrayCopy; // 數(shù)組指針副本 int i; // 數(shù)組下標(biāo)printf("輸入數(shù)組長度:");scanf("%d", &arrLen);// 動態(tài)分配內(nèi)存空間,如果失敗就退出程序arrayCopy = array = (int*)malloc( arrLen*sizeof(int) );if(!array){printf("創(chuàng)建數(shù)組失敗!\n");exit(1); }// 向內(nèi)存中寫入數(shù)據(jù) for(i=0; i<arrLen; i++){*arrayCopy++ = i+1;}// 循環(huán)輸出數(shù)組元素arrayCopy = array;for(i=0; i<arrLen; i++){printf("%d ", *arrayCopy++);}printf("\n");free(array); system("pause");return 0;
} 可以發(fā)現(xiàn),我們必須另外定義一個指針變量 arrayCopy,用來指向具體的數(shù)組元素。數(shù)組賦值完成后,要將 arrayCopy 重置到數(shù)組首地址,以便后面循環(huán)輸出。
這里注意:free() 函數(shù)必須釋放整塊內(nèi)存,不能只釋放一部分,或者釋放不存在的內(nèi)存空間,否則程序會出錯。所以,要多定義一個變量 arrayCopy,不斷改變它的值,以指向不同的數(shù)組元素。這樣可以保證 array 變量的值不變,始終指向內(nèi)存首地址,用于free()整塊內(nèi)存。
例如,如果改變了 array 的值,使其指向第5個數(shù)組元素,那在free(array)時只釋放掉了后半部分內(nèi)存,而沒有釋放掉前半部分內(nèi)存,這將引起程序錯誤。
總結(jié)
以上是生活随笔 為你收集整理的strlen() Bug 的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔 推薦給好友。