strlen()<=0は=0ではないのでしょうか
解決済
回答 6
投稿
- 評価
- クリップ 0
- VIEW 2,697
C言語によるプログラミング 基礎編という本に載っていたコードから質問です。
ネットユーザーのホームページ閲覧から、人気のあるホームページをランキングするというプログラムで、本ではランクと閲覧回数とアクセスしたURLを並び替える所まで終わり、最後にファイル出力するという段階です。
/* アドレスの出力処理 */
int WriteAccessRank(void)
{
int i;
FILE *fp;
fp=fopen("access_rank.txt","w");
if(fp==NULL)
{
fprintf(stderr,"ファイル作成ができません。access_rank,txt\n");
return -1;
}
fprintf(fp,"rank count address\n");
fprintf(fp,"-----------------------------------------------\n");
for( i = 0; i < COUNT_RANK; i++)
{
if(strlen(AccessRank[ i ].address)<=0)
{
break;
}
fprintf(fp,"%2d %6d \"%s\"\n",i+1,AccessRank[i].count,AccessRank[i].address);
}
if(fclose(fp))
{
fprintf(strerr,"クローズに失敗しました。access_rank.txt\n");
exit(EXIT_FAILURE);
}
return 0;
}
お伺いしたいのは、
1つ目。
strlen関数のところで、
<=0
と0以下になっているのが疑問です。
strlenで文字数を数えて、0ならば、それでデーターの終端だから、
break するのだと思うのですが、
文字数がマイナスになることはないので、=0で良いと思うのですが、なぜでしょうか。
文字が無いとEOFを返すのでしょうか、だから、-1を考慮にいれているのでしょうか。分かりません。
2つ目は、
fprintf(fp,"%2d %6d \"%s\"\n",・・・・
のところで、
\"%s\"
これがどう意味か分かりません。
sは文字列の表示だからだと思いますが、
二つの[ \ ]バックスラッシュと、[ " ]ダブルクオーテーションが不明です。
最後に、
if(fclose(fp)
これですが、クローズに失敗すると、EOFがfcloseの戻り値になるので、ifが実行されると解釈して良いのでしょうか。
よろしくお願いします。こんな素人の質問はこちらのサイトではふさわしくないように思い恐縮です。
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
+5
その解釈で合っています。負の値が返ることはありませんので、
==0
でも良いです。<=0
でも良いです。=0
は比較じゃ無いので駄目です。文字列を
"
で囲むと言うことはご存じと思いますが、文字列の中に"
を含めたいときはどうしたら良いと思いますか?
文字列を囲んでいる"
と、中身に含めたい"
をどう区別しましょう?その解釈で合っています。
アドバイスとしては、
関数の仕様がわからないときは、マニュアル(リファレンス)を見ます。Linuxを使っているなら、man strlenとかで。
また、プログラムの記法の意味が分からないときは、入門書(入門サイト)を読みます。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
checkベストアンサー
0
1つ目
プログラマによって解釈が異なるところかもしれません。
strlen関数の戻り値はsize_t型(恐らくunsigned int型と同じ)なので、負の値は返却されません。
ですので、仰るとおり==0
という比較でも何ら問題ありません。
ではなぜ<=0
と書くのか。
解釈は2つあると思います。
・エラーを意味する戻り値を負にする習慣があるので、それに合わせた
・提示されたコードの場合、0より大きい値の時に処理をしたい、つまりその否定の意味で0以下としている
個人的には後者の意味合いを推したいですね。
2つ目
文字列の中にダブルクォーテーション"
を含めたい時の決まりです。
エスケープシーケンスといいます。
3つ目
解釈としてはあっています。
ではなぜそうなるかというのを説明しておきます。
fcloseの戻り値は次のとおりです。
操作が成功したとき: 0
操作が失敗したとき: EOF
EOFは一般的にはstdio.hの中で-1
として定義されています。
if文には条件を書きますが、if文としては、真(0以外)か偽(0)かで処理されます。
つまりfcloseが失敗したときは、if(EOF)ということになり、EOF(-1)は真なのでif文の中が処理されます。
逆に成功した時は、if(0)ということで、偽になり、if文の中は処理されません。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
0
文字数がマイナスになることはないので、=0で良いと思うのですが、なぜでしょうか。
strlen
関数の戻り値はsize_t
型で符号なし整数値なので、おっしゃる通りマイナスになることはありません。ただし、= 0
ではなく== 0
としてください。
よくは判りませんが、その本を書いた人が何か勘違いしたのでしょう。
文字が無いとEOFを返すのでしょうか、だから、-1を考慮にいれているのでしょうか。分かりません。
EOFは返しません。関数のリファレンスを確認する習慣を付けましょう。
\"%s\"
これがどう意味か分かりません。
文字列の中に書いたバックスラッシュ(\
)はエスケープシーケンスで、\"
はダブルコーテーションを意味します。ダブルコーテーションは文字列の始めと終わりという意味で使われているので、文字列中に書く際は「文字としてのダブルコーテーション」であることを明示するために\"
と書かないといけません。
「C言語 エスケープシーケンス」などで検索すると出てきますので、他にどのようなものがあるか覚えておくと良いでしょう。
if(fclose(fp)
これですが、クローズに失敗すると、EOFがfcloseの戻り値になるので、ifが実行されると解釈して良いのでしょうか。
その通りです。ただし、プログラム的には、fopenの直後にちゃんとエラーチェックをして成功したときだけ処理を続行しているので、fclose(fp)
が失敗することは論理的に起こり得ません。エラーが起こり得ないと判っているときは、エラーチェックを省略することもあります。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
0
C言語(だけでなくほぼ全てのプログラミング言語)の左辺と右辺の一致は=ではなく==なので気をつけて下さい。
<=0は==0でも問題ありませんが,strlen関数がerrorを返す時-1のコードが返ってくるような実装になっていたとした場合,無限ループに入ってしまう可能性がありますよね。なので安全のために広い範囲で制御ストップするような慣習があります。ちなみに比較は,内部で差分をとって0より上か下か0かで判定しているので,<,=,>などのオーバーヘッドはほぼ無いに等しいので==0じゃないと困るときや関数が0以外を返さないことが分かりきってない限りは不等式で書くのがいいと思います。
おっしゃる通り%sはchar型の変数を出力する記号です。
"はC言語ではただの文字ではなく文字列リテラルを生成する特殊文字なので,文字列中で使うときはエスケープシーケンス\"を使います。\は何かと言うと,特殊文字に対して直前に配置すると直後の特殊文字1文字をただの文字として扱うという命令になります。
\は他の普通の文字と組み合わせて制御文字(そのままの文字として出力されないものtabや改行など)にする,エスケープシーケンス(制御文字を表す文字列)を表すのにも使います。例えば,改行は\nが改行のエスケープシーケンスになります。
よくエスケープの意味を特殊文字を普通の文字に直すことであると説明されますが,これは狭義の意味で,本来の意味は,文字出力のプロセスを一時的に抜けて他の処理系に処理を投げることを意味していて,\がエスケープを実行する予約語になっています。(Webだとよく文字列に埋め込まれた処理を無効化するの意味で使われます)
なので,\nなど改行処理などを行うときもプログラムはエスケープされていることに気をつけてください。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
0
一つ目
strlenは(標準ならば)仰る通り文字列長(つまり0以上の整数)です。なので「0以下であること」と「0であること」は同条件です。まあ=演算子は代入なので、==演算子で比較しないといけないですが。ちなみに、これよりも直接一文字目を見て終端文字であるかを判断したほうがいいです。strlenだと、文字列が長いとそれだけ時間がかかります。
二つ目
ダブルクオーテーションを表示したいので特殊な記号を使っています。これがないとダブルクオーテーションは文字列の先頭(終端)記号とみなされるためです。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
0
1つ目について、回答します。
「==0」でも問題はありません。
万が一のことを想定して、実装されていると思います。
レビュアーによっては、「== 0」を指摘する場合もあります。
例えば、
永久ループや戻り値を使用する際に影響しないか考慮しているのか!
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.23%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
質問への追記・修正、ベストアンサー選択の依頼
coco_bauer
2016/05/31 14:17
Cランタイムライブラリには、文字列に無効なマルチバイト文字が含まれる場合に ((size_t)(-1)) を返す _mbstrlen と _mbstrlen_l という関数が含まれています。 ひょっとすると質問にあるコードは、日本語のようなマルチバイト文字を扱うコードを改変したものかもしれません。
cingyan
2016/06/01 13:01
そうかもしれませんね。