質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

解決済

6回答

6000閲覧

strlen()<=0は=0ではないのでしょうか

cingyan

総合スコア29

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

0クリップ

投稿2016/05/29 08:12

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が実行されると解釈して良いのでしょうか。

よろしくお願いします。こんな素人の質問はこちらのサイトではふさわしくないように思い恐縮です。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

coco_bauer

2016/05/31 05:17

Cランタイムライブラリには、文字列に無効なマルチバイト文字が含まれる場合に ((size_t)(-1)) を返す _mbstrlen と _mbstrlen_l という関数が含まれています。 ひょっとすると質問にあるコードは、日本語のようなマルチバイト文字を扱うコードを改変したものかもしれません。
cingyan

2016/06/01 04:01

そうかもしれませんね。
guest

回答6

0

  1. その解釈で合っています。負の値が返ることはありませんので、==0でも良いです。<=0でも良いです。=0は比較じゃ無いので駄目です。

  2. 文字列を"で囲むと言うことはご存じと思いますが、文字列の中に"を含めたいときはどうしたら良いと思いますか?

文字列を囲んでいる"と、中身に含めたい"をどう区別しましょう?

  1. その解釈で合っています。

アドバイスとしては、
関数の仕様がわからないときは、マニュアル(リファレンス)を見ます。Linuxを使っているなら、man strlenとかで。
また、プログラムの記法の意味が分からないときは、入門書(入門サイト)を読みます。

投稿2016/05/29 08:48

編集2016/05/29 08:49
otn

総合スコア84507

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

cingyan

2016/05/30 06:16

ご回答有り難うございました。 =0は、打ち間違いでした。指摘されるまで気づきませんでした。 ==0のみが正解だと思い、わざわざ<=0、と行う理由が知りたかったのです。 関数にマニュアルがあることを知りませんでした。 勉強になりました。 ありがとうございました。。
guest

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文の中は処理されません。

投稿2016/05/29 14:50

ttyp03

総合スコア16998

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

cingyan

2016/05/30 07:04

ご回答有り難うございました。。 大変、良くわかりました。 ありがとうございました。
guest

0

1つ目について、回答します。

「==0」でも問題はありません。

万が一のことを想定して、実装されていると思います。

レビュアーによっては、「== 0」を指摘する場合もあります。
例えば、
永久ループや戻り値を使用する際に影響しないか考慮しているのか!

投稿2016/05/29 14:15

編集2016/05/29 16:00
ai_2013_dev

総合スコア338

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

cingyan

2016/05/30 06:59

ご回答有り難うございました。 念の為ということですね。 ==0と入力しても、無限ループになる恐れが無いとは言えないということですね。 プログラムは思った通りに動かない。指示した通りに動く、ということですね。 ありがとうございました。
guest

0

一つ目
strlenは(標準ならば)仰る通り文字列長(つまり0以上の整数)です。なので「0以下であること」と「0であること」は同条件です。まあ=演算子は代入なので、==演算子で比較しないといけないですが。ちなみに、これよりも直接一文字目を見て終端文字であるかを判断したほうがいいです。strlenだと、文字列が長いとそれだけ時間がかかります。

二つ目
ダブルクオーテーションを表示したいので特殊な記号を使っています。これがないとダブルクオーテーションは文字列の先頭(終端)記号とみなされるためです。

投稿2016/05/29 10:25

HogeAnimalLover

総合スコア4830

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

cingyan

2016/05/30 06:55

ご回答有り難うございました。 =0と間違った件を残念に思います。 >これよりも直接一文字目を見て終端文字であるかを判断したほうがいい 今後の参考としたいと思います。 ありがとうございました。
guest

0

C言語(だけでなくほぼ全てのプログラミング言語)の左辺と右辺の一致は=ではなく==なので気をつけて下さい。
<=0は==0でも問題ありませんが,strlen関数がerrorを返す時-1のコードが返ってくるような実装になっていたとした場合,無限ループに入ってしまう可能性がありますよね。なので安全のために広い範囲で制御ストップするような慣習があります。ちなみに比較は,内部で差分をとって0より上か下か0かで判定しているので,<,=,>などのオーバーヘッドはほぼ無いに等しいので==0じゃないと困るときや関数が0以外を返さないことが分かりきってない限りは不等式で書くのがいいと思います。

おっしゃる通り%sはchar型の変数を出力する記号です。
"はC言語ではただの文字ではなく文字列リテラルを生成する特殊文字なので,文字列中で使うときはエスケープシーケンス"を使います。\は何かと言うと,特殊文字に対して直前に配置すると直後の特殊文字1文字をただの文字として扱うという命令になります。

\は他の普通の文字と組み合わせて制御文字(そのままの文字として出力されないものtabや改行など)にする,エスケープシーケンス(制御文字を表す文字列)を表すのにも使います。例えば,改行は\nが改行のエスケープシーケンスになります。

よくエスケープの意味を特殊文字を普通の文字に直すことであると説明されますが,これは狭義の意味で,本来の意味は,文字出力のプロセスを一時的に抜けて他の処理系に処理を投げることを意味していて,\がエスケープを実行する予約語になっています。(Webだとよく文字列に埋め込まれた処理を無効化するの意味で使われます)
なので,\nなど改行処理などを行うときもプログラムはエスケープされていることに気をつけてください。

投稿2016/05/29 09:32

編集2016/05/29 09:42
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ozwk

2016/05/29 10:17

> ほぼ全てのプログラミング言語 =なのは、 VB、F#、Ocaml、Pascal ほか何かありましたかね
退会済みユーザー

退会済みユーザー

2016/05/30 00:22 編集

==ではない言語としては関数型全般(lisp等),SQL,shellの想定でした。
cingyan

2016/05/30 06:49

ご回答ありがとうございました。 ウィキペディア並に詳しくて、すぐに理解ができず残念です。 =0はケアレスミスです。改めてお詫び申し上げます。 差分とオーバーヘッドが、調べましたが、よく分かりませんでした。しかし、理解できたと思います。 エスケープシーケンスについても詳しい説明をありがとうございました。。
guest

0

文字数がマイナスになることはないので、=0で良いと思うのですが、なぜでしょうか。

strlen関数の戻り値はsize_t型で符号なし整数値なので、おっしゃる通りマイナスになることはありません。ただし、= 0ではなく== 0としてください。
よくは判りませんが、その本を書いた人が何か勘違いしたのでしょう。

文字が無いとEOFを返すのでしょうか、だから、-1を考慮にいれているのでしょうか。分かりません。

EOFは返しません。関数のリファレンスを確認する習慣を付けましょう。

"%s"
これがどう意味か分かりません。

文字列の中に書いたバックスラッシュ(\)はエスケープシーケンスで、\"はダブルコーテーションを意味します。ダブルコーテーションは文字列の始めと終わりという意味で使われているので、文字列中に書く際は「文字としてのダブルコーテーション」であることを明示するために\"と書かないといけません。
「C言語 エスケープシーケンス」などで検索すると出てきますので、他にどのようなものがあるか覚えておくと良いでしょう。

if(fclose(fp)
これですが、クローズに失敗すると、EOFがfcloseの戻り値になるので、ifが実行されると解釈して良いのでしょうか。

その通りです。ただし、プログラム的には、fopenの直後にちゃんとエラーチェックをして成功したときだけ処理を続行しているので、fclose(fp)が失敗することは論理的に起こり得ません。エラーが起こり得ないと判っているときは、エラーチェックを省略することもあります。

投稿2016/05/29 09:10

catsforepaw

総合スコア5938

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

cingyan

2016/05/30 06:25

ご回答有り難うございました。。 =0は、うっかりしていました。失礼いたしました。 関数のリファレンスというのは、ネット上にあるサイトでしょうか、本でしょうか。一応ネットで検索したのですが、解答が得られず、またこちらで質問させていただきました。 <=0と載っているので、マイナスの戻り値がでるのだろうかと思い、EOFかな、と書きました。 エスケープシーケンスも、忘れていました。言われて思い出した次第です。 ありがとうございました。
cingyan

2016/05/31 04:56

ありがとうございました。 参考にします。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問