2017-04-05 16 views
1

今日私はCで簡単な "プログラム"を作ろうとしていましたが、次のようにしたいと思います:大文字の文字列を入力すると、プログラムはすべての文字を小文字に変換します。しかし、私は好奇心に驚いた。あなたが見ることができるように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未満の文字を検出しません(制御セットなので)。

賢明な、少し読みにくい場合。含まれないもの:

スマートアレックプログラマーも、このコードは

代わりstrlenを使用することを検討していないポータブルC.をASCIIコード化を前提とし、そのためであるという事実を考慮したいと思うかもしれませんが、事前計算 O(N)プロセスをO(N * N)プロセスに変換するときにはループとして条件付きで実行します。ループ本体が変更された場合、神聖なコンパイラはstrlenが反復の間で変化しないことを知ります。文字列iが小さい場合、それはASCIIに「A」として、ASCIIでフォーマット文字列を参照しているので

+0

私はあなたに同意します、それは理由ですが、なぜループにクラッシュがないのですか?いつループを離れる条件に達したか?最後の文字が評価されるとどうなりますか?それは終了しないuppwordの文字にアクセスしようとします –

+2

ループは 'uppword'のヌルティメーターに到達すると終了します。 – Bathsheba

+0

ああ、それは自動的にヌル文字に追加されます –

0

uppword[i]作品は、あなたの配列uppword[26]26よりも常に大きい33です。

uppword[i]が文字列のヌル終了文字を指している場合は、iは0(ヌル文字)より大きくなければならないため、条件はfalseになります。したがって、ループを離れることになります。

これは、ヌル文字に達したときにこのループが停止することを意味します。

0

"i"の配列は先頭が0なので、条件はTRUEではないため、処理を続行できません。

iupword[i]より小さいかどうかをチェックしています。最初は、0upword[0]未満であるかどうかを確認していますが、これはほぼ確実です。

文字列"Hello"を入力するとします。 upwordに格納されるのは、文字列{'H', 'e', 'l', 'l', 'o', 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がインデックス値より大きくなりませんので、それは、0ターミネータに当たったときのループが終了します。Bathsheba氏の言うとおり、このコードでは、文字列に制御文字が含まれないことを前提としています。

書かれているように、これは良いコードではありません。基礎となる文字セットについてあらゆる種類の前提がありますが、明確ではなく、安全ではありません。より良いバージョンはポインターpを使用して文字列による

#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); 

このコードを反復ようになり、それが0文字列の終端を見るまでループします。 a)現在の文字エンコーディング(ASCII、EBCDICなど)を考慮し、b)大文字の同等物がない場合は元の文字を返します(句読点文字など)。toupperライブラリ関数を使用します。