printfとscanfについて

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
組木紙織

printfとscanfについて

#1

投稿記事 by 組木紙織 » 17年前

はじめまして、組木紙織です。
時々掲示板で、printfとscanfは使わないほうがよいという話を聞くのですが、その理由を今まで聞いたことがありません。
速度が遅いということは知っているのですが、それ以外にこれらの関数を使わない理由があるのでしょうか?
知っている方がいたら教えてください。

box

Re:printfとscanfについて

#2

投稿記事 by box » 17年前

> 時々掲示板で、printfとscanfは使わないほうがよいという話を聞くのですが、その理由を今まで聞いたことがありません。

scanfは、例えば数値の入力を求めている場合に数値以外を入力すると
平気で暴走してしまう、というような問題点があります。
fgetsとsscanfの組み合わせで、ある程度は回避できます。

絶対に暴走しないとわかっている場合や、
暴走した場合の影響が狭い範囲にとどまる(例:自分だけが使うプログラム)
のであれば、scanfで十分だと思います。

printfについては、私からのコメントはありません。

組木紙織

Re:printfとscanfについて

#3

投稿記事 by 組木紙織 » 17年前

コメントありがとうございます
/**************/
<p>
#include<stdio.h>
#include<stdlib.h>


int main(void)
{
int i;
scanf("%d",&i);
printf("%d",i);


return EXIT_SUCCESS;
}

//input
/*as*/
//output
/*9445828*/
</p>
/*****************/

>scanfは、例えば数値の入力を求めている場合に数値以外を入力すると
>平気で暴走してしまう、というような問題点があります。
というのは上記のようなことになるということでしょうか?

プログラムが不正終了したり、フリーズすることはないのですか?

box

Re:printfとscanfについて

#4

投稿記事 by box » 17年前

> >scanfは、例えば数値の入力を求めている場合に数値以外を入力すると
> >平気で暴走してしまう、というような問題点があります。
> というのは上記のようなことになるということでしょうか?

不正な結果を得てしまう、という点では、提示された内容はそのとおりですね。
その他、for文やwhile文などで構成するループの中でscanfを使っていて、
想定しない入力のために無限ループに陥ってしまう場合もあります。

> プログラムが不正終了したり、フリーズすることはないのですか?

入力内容によっては、ユーザープログラムがアクセスできない領域に
アクセスしようとした結果、そうなってしまうことがあるかもしれません。
そういうおそれがある、という話で、絶対そうなるとも絶対そうならないともいえません。

組木紙織

Re:printfとscanfについて

#5

投稿記事 by 組木紙織 » 17年前

>入力内容によっては、ユーザープログラムがアクセスできない領域に
>アクセスしようとした結果、そうなってしまうことがあるかもしれません。

私はこれを配列やポインタを利用したときのことだと想定しますが、
そのあたりはコードを記述するときに気をつければ問題はないと思います。

例えば
void sample(int i)
{
if(!i){
abort();
}
}
というような状況がscanf関数を使うことによって存在する。ということが気になったので先ほどの質問をさせていただきました。
このような状況は存在するのでしょうか?

box

Re:printfとscanfについて

#6

投稿記事 by box » 17年前

> というような状況が

これが、scanfを使うこととどのように結びつくのか、よくわかりませんでした。
sample関数のコードは、引数 i の値によってはabort関数を実行する、というだけですよね。

組木紙織

Re:printfとscanfについて

#7

投稿記事 by 組木紙織 » 17年前

説明の仕方が悪くてすみません。

int i = 1, j =0;
i/j;

としたり

char ch[2];
int i= 3;
ch[3] = '1';

というようなプログラムが正しく動かない可能性のある状況が、
scanf("%d",&i);
ch = '1';
ということをせずに、

int main(void)
{
char ch;
scanf("%c", &ch);//ここの中身は必要に応じて変える。

return EXIT_SUCCESS;
}

というプログラムを実行して入力をすることによって正しく動かない可能性のある状況を作り出せるのかどうかを前回の質問ではたずねたつもりです。

これでも意味が通じなかったらどうしよう。

管理人

Re:printfとscanfについて

#8

投稿記事 by 管理人 » 17年前

boxさんのおっしゃる、
fgetsとsscanfの具体的な説明が書いてあるサイトを紹介します。

http://www.kyoto-su.ac.jp/~kbys/proC/fi ... n-out.html

scanfを用いない方がよいのは、バッファのオーバーフローを全く考慮していない関数だからです。
つまり
scanfによって、1万文字でも2万文字でもバッファにつめようとしてしまうのです。
ch型1万文字なら1万バイトですが、1万バイト内に使用してはいけない領域があったとしたら、不具合が生じてしまいます。

ですから大量の文字列を入力したら不具合が出る可能性があります。
printfに関して使っては成らない利用は良く知りません。

Justy

Re:printfとscanfについて

#9

投稿記事 by Justy » 17年前

scanfを用いない方がよいのは、バッファのオーバーフローを全く考慮していない関数
 必ずしもそんなことはないかと。

 char str[10];
 scanf("%9s", str);

 なら何文字入力しても9文字分しか格納されません。

 結局のところ、scanfを避けた方がいいのは後述した理由と、
正しい使い方・・・バッファを制限する、入力が正しく行われたか
(整数のところでアルファベットを入力したとか)のチェックをする、
不正なら入力バッファをクリアする、など・・・を知らない人が多いから、なのでは
ないでしょうか。

 参考書とかでも scanfで入力した後、エラーチェックしたり、
ストリームをクリアしたりしてるのを見たことがないですし・・・。


printfとscanfは使わないほうがよいという
 多分どちらも、可変引数であるのもそう言われる要因ではないでしょうか。
 可変引数は型安全ではないので、使い方を間違えると参照するアドレスがずれたりして、
結果不正なプログラムが実行される事になりかねません。

管理人

Re:printfとscanfについて

#10

投稿記事 by 管理人 » 17年前

はい、Justyさんに以前教えて貰いましたね
scanf("%9s", str);
この書き方^^;

正しく使わないと、エラーを起こしかねない関数ということですね><;

あ、関係ないですけど、昇進おめでとうございますヽ(*^∇゜)oC□☆□Do(゜∇^*)ノ
ランク最高まで後1つですねw

組木紙織

Re:printfとscanfについて

#11

投稿記事 by 組木紙織 » 17年前

皆様書き込みありがとうございます。
ようやくscanfを使わないほうがよい理由が分かりました。

普段はC++を使っているのであまり関係はなかったのですが、気になっていることが解消できてよかったです。

閉鎖

“C言語何でも質問掲示板” へ戻る