2017-04-05 113 views
1

今天我試圖在C中做一個簡單的「程序」,我想要做的事情如下:當你輸入大寫字符串時,程序會將所有字符轉換爲小寫。但我st to好奇。C - 字符串與數組的條件

char uppword[26]; 
int i; 
printf("Gimme a word in uppercase.: "); 
scanf("%s", uppword); 
for (i=0; i < uppword[i]; i++){ 
    uppword[i] = uppword[i] + 32; 
} 

printf("%s", uppword); 

return 0; 

正如你所看到的,在for循環的條件i < uppword[i],但我不知道,這是爲什麼作品。換句話說,我可以用i < strlen(uppword)代替這個條件,它也會起作用。但我不認爲這與陣列相同。爲什麼這個數組工作?數組中的「i」在開始0處,因此條件不是TRUE,並且不能繼續。

+0

C沒有字符串類型。 – Olaf

回答

6

uppword[i]將在字符串末尾爲0(scanf這樣做對你來說,除非你試圖閱讀太多的字符,在這種情況下,編譯器可能會吃你的貓)。 i < 0將在此時爲0。根據一些假設,在這一點上它只有只有:這些假設是(i)uppword至多少於32個字符(你允許25加一個零終止符),和(ii)在ASCII中至少你通常不會遇到小於32的字符(因爲它們是控制集)。

聰明,如果有點難以閱讀。

智能亞歷克程序員可能還需要考慮,此代碼假定ASCII編碼,因此是不可移植C.

考慮使用strlen而不是事實,但預先計算說:不包括它作爲循環的條件,因爲您將O(N)進程轉換爲O(N * N)進程 - 只有來自神性的編譯器纔會知道strlen在迭代之間不會更改,因爲您的循環體發生了變化字符串。

+0

我同意你的看法,這就是原因,但爲什麼在循環中沒有崩潰?什麼時候達到離開循環的條件?當最後一個字符被評估時會發生什麼?它將嘗試訪問uppword中不會退出的字符 –

+2

當循環到達uppword中的nul-terimator時,循環結束。 – Bathsheba

+0

呵呵,它會自動添加nul字符 –

0

uppword[i]作品,因爲當i小,它是在ASCII提到與ASCII格式的字符串,如「A」是33總是比26更大,你的陣列uppword[26]

i正在增加,直到uppword[i]指向字符串的空終止字符,則條件將爲假,因爲i必須大於0(空字符)。因此它會離開循環。

這意味着該循環在到達空字符時將停止。

0

數組中的「i」在開始0,因此條件不是TRUE,並且不能繼續。

條件是檢查i是否小於upword[i];在開始時,您要檢查0是否小於upword[0],這幾乎肯定是真的。

假設您輸入字符串"Hello"。在upword中存儲的是字符序列{'H', 'e', 'l', 'l', 'o', 0 }。每循環一次,你讓下面的比較:當它擊中的0終止

0 < 'H' (72) true 
1 < 'e' (101) true 
2 < 'l' (108) true 
3 < 'l' (108) true 
4 < 'o' (111) true 
5 < 0   false 

退出循環,因爲0不會比指數值。就像Bathsheba所說,這段代碼假定字符串永遠不會包含任何控制字符。

正如所寫,這不是很好的代碼 - 它會對底層字符集做出各種假設,但不清楚,也不安全。一個更好的版本會像通過串

#include <ctype.h> 
... 
scanf("%25s", upword); // use an explicit field with modifier so that 
          // we don't try to store more characters than 
          // upword is sized to hold. Leave room for trailing 0 

for (char *p = upword; *p != 0; p++) 
    *p = toupper(*p); 

此代碼循環使用指針p,並且循環,直到它看到0字符串結束。它還使用toupper庫函數,其中a)將當前字符編碼(ASCII,EBCDIC,任何)考慮在內,並且b)如果沒有可用的大寫字母(例如標點字符),則返回原始字符。