No.1ベストアンサー
- 回答日時:
int a ;
scanf("%d",&a);
とほぼ同じことをするのに
int a ;
char buf[256] ;
fgets(buf, 256, stdin) ;
a = (int) strtol(buf,NULL, 10);
となり、
・文字列用の変数(charの配列)
bufは変数名だからbufでなくてもよい
256は適当
・FILE* stdin を使った入力
・long→intのキャスト(暗黙のキャストでもできるけど)
が「おまじない」になります。
これだと、さすがに「おまじない」が長過ぎるでしょう。
int a,b ;
scanf("%d",&a);
scanf("%d",&b);
を
int a,b ;
char buf[256] ;
fgets(buf, 256, stdin) ;
a = (int) strtol(buf,NULL, 10);
char buf[256] ;
fgets(buf, 256, stdin) ;
b = (int) strtol(buf,NULL, 10);
って書いちゃう人が続出しそうです。
ご回答ありがとうございます。
>これだと、さすがに「おまじない」が長過ぎるでしょう。
ここが、感覚の相違ですね。
1個のchar配列の宣言の追加と2行での処理を「長すぎる」と考えるか、今後応用の利く記法として例示しておいても構わないと考えるか、だと思います。質問文からご推察いただけるように、私の立場は後者です。
>って書いちゃう人が続出しそうです。
これは、確かにその通りかもしれません。scanf()を使った例題を書く段階って、宣言の意味がまだ定着していないでしょうね。まあ、そこで叱られて痛い目を見て覚えろ、というのは不親切ですかね。
No.2
- 回答日時:
No1の方の言う通りなのですが、更に言えば、実際の業務では、strtol等も使いません。
例えば、CSV形式でデータ(数値)が入力される場合(スペース区切りでも良いですが)、
scanfで入力データを取得する場合を例にとると、
入門書では、データが正しく入力されることを前提にプログラミングを行っています。
もし、数値でないデータ、CSV形式にならないデータ等が入力された場合、どうなるか結果は保証されません。
一方、実際の業務では、そもそも、入力データが正しくない場合があることを前提に、プログラミングを行います。
もし、数値でないデータ、CSV形式にならないデータ等が入力された場合は、どの行でそのエラーが発生したのか、
どのデータが正しくないのか等の正確なエラー情報をオペレータに出力する必要があります。
(そうしないと、データを正しく修正して、やり直しして修正することができません)
その為に、CSVの構文解析ルーチンのようなものを自前で作るか、あるいは、ライブラリのようなものを利用することになります。
そして、全てのデータが正しいことが、保証された時、初めてそのデータを使って処理をおこないます。
入門書では、上記の実際の業務ようなことをさせるわけにはいかない為、簡単にscanfで扱っているのが現状かと思います。
又、入門書は、scanfの使用方法の取得が本来の目的ではなく、scanfで取得したデータを使って、
そのデータをどのように処理するかが本来の入門書での説明の目的になります。
その為、データの取得については、scanfで簡単にすましているかと思います。
ご回答ありがとうございます。
>更に言えば、実際の業務では、strtol等も使いません。
えー、使わないのですか?不整値のチェック等非常にやりやすいので、私は文字列→数値変換では常用しています。
もしよろしければ、文字列→数値変換でstrtol()以外のベストな方法を教えてください。
#業務では文字列→数値変換する機会がない、ということでしたらスミマセン
>一方、実際の業務では、そもそも、入力データが正しくない場合があることを前提に、プログラミングを行います。
これはその通りです。
業務どころか、実際に使えるプログラムを書くという場面では、入力を正しくチェックすることは必須でしょう。そういったときに、非常に使いづらいscanf()を「最初の」知識として与えるのが本当に適当なのだろうか、ということが疑問なのです。
>入門書では、データが正しく入力されることを前提にプログラミングを行っています。
...
>入門書では、上記の実際の業務ようなことをさせるわけにはいかない為、簡単にscanfで扱っているのが現状かと思います。
No.1の方がご親切に例示していただいたstrtol()の第2引数をNULLにしているのも、データが正しく入力されることを前提としているという意味では同様ですよね(つまりatoi()と等価な用法)。
入門書の段階では、それはそれでいいと思います。
さすがに、比較的コード量が短くて済むstrtol()のエラー処理でも、
char *e;
a = strtol(buf, &e, 10);
if (errno == ERANGE) {
...
}
if (*e != '\n') {
...
}
ぐらいの量になるので本来の目的がぼやけてしまい、本末転倒だと思います。
でも、数行増える程度だったら、scanf()よりも今後多用するであろう記法を刷り込んでおいてもいいんじゃないかな、と思うのですが・・・
No.3
- 回答日時:
>えー、使わないのですか?不整値のチェック等非常にやりやすいので、私は文字列→数値変換では常用しています。
>もしよろしければ、文字列→数値変換でstrtol()以外のベストな方法を教えてください。
いやいや、strtolを使うのがだめだと言ってるわけではありません。
例えば、"+1234"の文字列をstrtolで処理すると正常になりますが、
+、-の符号はエラーにして、0~9の数字の場合だけを正常にしたいケースの場合は、strtolは使っていません。
そして、そのようなケースは非常に多いのです。
以下は、私が業務で使っている方法です。(これがベストとは言ってません。念のため)
条件としては、
1)int型で扱える範囲の数
2)0以上の整数
上記の2つを扱う場合に使います。
尚、int型で扱える範囲の上限は、2147483647ですが、
これを厳密におこなうなら、算出した結果が、この上限を超えないことのチェックまで行います。
但し、これまでの数値を必要としない場合(9桁以内の数字で間に合う場合)は、文字列長が9桁以内であればOKにしています。
以下は、私がよく使用している数字チェック関数です。
OKなら0以上の値を返し、エラーなら-1を返します。
int check_numeric( char *str)
{
int i;
int num = 0;
int len = strlen(str);
char *p = str;
if (len < 1 || len > 9) return -1;
for (i = 0; i < len;i++,p++){
if (*p < '0' || *p >'9') return -1;
num = (10 * num) + (*p - '0');
}
return num;
}
この関数の場合、"001"等をOKにしていますが、最初から"0"で始まる数字はエラーにしたい
場合は、更にチェックを追加する必要があります。その場合は、そのように作りこみます。
結局、私が言いたいのは、strtolで充分なら、それで良いし、それで不十分なら、strtolに近いものを
(極力簡単になるように条件を絞り)自前で実装すればよいということです。
再びご回答ありがとうございます。
>+、-の符号はエラーにして、0~9の数字の場合だけを正常にしたいケースの場合は、strtolは使っていません。
なるほど、+-を正負号ではない記号として使われることが多いのですね、納得です。
私はめんどくさがりなので、先頭文字の判定だけが必要なら次の文字からstrtol()使っちゃうし、数字判定ならif (isdigit((int)*p))しちゃいますが、このあたりはわかってて自分のスタイルで書くことには全く異論はありません。
「実際の業務では」を「プロの書くコードでは」と勘違いしてしまいました。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# C言語 3 2022/10/04 15:07
- C言語・C++・C# 至急教えてください!プログラミングの問題です。 割られる整数と割る整数を受け取って、商と余りを出力す 3 2022/07/05 10:23
- 日本語 「~でも」(~で)「~さえ」の細かい違い その2 2 2023/08/20 17:20
- 日本語 https://eprints.lib.hokudai.ac.jp/dspace/bitstream 6 2022/05/22 18:54
- 日本語 複合名詞(造語)について教えて欲しいです 2 2022/05/22 17:14
- 家具・インテリア ニトリからなんとか補償を取れないでしょうか 5 2023/05/20 22:36
- C言語・C++・C# C言語でif文が予想と違う動きをする件について7 4 2023/03/20 00:26
- C言語・C++・C# プログラミング c言語 4 2023/03/07 01:05
- 書籍・本 化学入門問題精講についての質問です。 本書は問題集ですが、初学者でも解けるような構成になっているので 2 2022/10/09 15:10
- 物理学 大学で物理学を学んでいる人、大学で物理を学んでいた人へ質問です。 私は現在大学1年で、物理を学んでい 2 2022/10/03 20:00
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
C言語のfor文です。 繰り返しの...
-
fgetsなどのときのstdinのバッ...
-
間接操作のレベルとは
-
CStringをwchar_tに変換したい
-
バイトスワップをやりたい
-
c言語でユーザ関数を利用して入...
-
C言語の入力した文字を反転させ...
-
atoi( ) の反対をやりたい
-
文字列から空白を取り除きたい...
-
Linuxでフォルダ内全ファイル名...
-
enumの記述について。
-
配列をnビットシフトする
-
ユニコード文字列の分割
-
DPマッチング
-
C言語です
-
RGB→YUV変換のプログラム
-
C言語のビットフィールドについて
-
c++ 文字列を入力して、一文字...
-
C言語のポインターで詰まっている
-
ワイルドカードを用いた文字列検索
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
fgetsなどのときのstdinのバッ...
-
charでの計算?
-
C言語のfor文です。 繰り返しの...
-
charからLPTSTRへの変換方法
-
文字列から空白を取り除きたい...
-
C言語の入力した文字を反転させ...
-
'const char *' 型は 'char *' ...
-
配列をnビットシフトする
-
str系関数を使わずに二つの文字...
-
int main()の・・・
-
atoi( ) の反対をやりたい
-
CStringをwchar_tに変換したい
-
c++ 文字列を入力して、一文字...
-
switch文で文字を比較すること...
-
干支のプログラム
-
3桁区切(コンマ)記号をつけ...
-
絶対パスからのファイル名の切...
-
間接操作のレベルとは
-
間接参照のレベルが異なっています
-
型変換
おすすめ情報