1. 程式人生 > >8. 演算法筆記——gets()的不安全性,sizeof()求陣列大小

8. 演算法筆記——gets()的不安全性,sizeof()求陣列大小

gets()的不安全性

在PAT的題目測試系統中,PAT B1009題,演算法筆記於P97頁的參考程式碼中,寫下了gets(str)的程式碼,但是這條程式碼並不被PAT的測試系統所認可,後來發現是由於gets()的不安全性,已經被停用了。關於其不安全性的原因之後再做補充,解決方案如下:

const char *str;
string ss;
getline(cin,ss);
str = ss.c_str();

這樣,就可以把string轉換為char[]陣列,方便了我們的處理。

C++中sizeof()求陣列的大小

之前我利用網上的這種辦法,試圖求解出陣列中的元素個數,程式碼如下:

int greedySelect
(int s[], int f[], bool a[]){ int count = sizeof(s) / sizeof(s[0]); return count; }

後來發現不管怎麼樣,結果都是1,最後才知道上面形參雖然定義的是一個數組,使用sizeof()求大小時,就會退化為一個數組指標,實際上求得的是一個指標的大小,4位元組,而一個int也是四位元組,所以結果一直為1.

下面對sizeof()與strlen()之間的區別做一些詳細講解。

c/c++ strlen(str)和str.length()和str.size()都可以求字串長度。 其中str.length()和str.size()是用於求string類物件的成員函式 strlen(str)是用於求字元陣列的長度,其引數是char*。

舉例:

1)char* ss = “0123456789”; sizeof(ss)為4,ss是指向字串常量的字元指標,sizeof 獲得的是指標所佔的空間,則為4 sizeof(*ss)為1,*ss是第一個char字元,則為1

2)char ss[] = “0123456789”; sizeof(ss)為11,ss是陣列,計算到’\0’位置,因此是(10+1) sizeof(*ss)為1,*ss是第一個字元

3)char ss[100] = “0123456789”; sizeof(ss)為100,ss表示在記憶體中預分配的大小,100*1 strlen(ss)為10,它的內部實現用一個迴圈計算字串的長度,直到’\0’為止。

4)int ss[100] = “0123456789”; sizeof(ss)為400,ss表示在記憶體中預分配的大小,1004 strlen(ss)錯誤,strlen引數只能是char,且必須是以’\0’結尾

5)char[] a={‘a’,‘b’,‘c’}; sizeof(a)的值應該為3。 char[] b={“abc”}; sizeof(b)的值應該是4。 若string str={‘a’,‘b’,‘c’,’\0’,‘X’}; 那麼sizeof(str)為5,strlen(str)為3。

sizeof()、strlen()兩者區別:

  1. 1)sizeof操作符的結果型別是size_t,它在標頭檔案中typedef為unsigned int型別。 該型別保證能容納實現所建立的最大物件的位元組大小。 2)sizeof是運算子,strlen是函式。 3)sizeof可以用型別做引數,strlen只能用char*做引數,且必須是以’’\0’'結尾的。 sizeof還可以用函式做引數,比如: short f(); printf("%d\n", sizeof(f())); 輸出的結果是sizeof(short),即2。 4)陣列做sizeof的引數不退化,傳遞給strlen就退化為指標了。 5)大部分編譯程式 在編譯的時候就把sizeof計算過了 是型別或是變數的長度。這就是sizeof(x)可以用來定義陣列維數的原因 char str[20]=“0123456789”; int a=strlen(str); //a=10; int b=sizeof(str); //而b=20; 6)strlen的結果要在執行的時候才能計算出來,用來計算字串的長度,不是型別佔記憶體的大小。 7)sizeof後如果是型別必須加括弧,如果是變數名可以不加括弧。這是因為sizeof是個操作符不是個函式。 8)當使用了一個結構型別或變數時, sizeof 返回實際的大小, 當使用一靜態地空間陣列, sizeof 返回全部陣列的尺寸。 sizeof 操作符不能返回被動態分配的陣列或外部的陣列的尺寸