ログインしてさらにmixiを楽しもう

コメントを投稿して情報交換!
更新通知を受け取って、最新情報をゲット!

C言語とC++言語コミュの入力個数が分からない時の sscanf() の対処

  • mixiチェック
  • このエントリーをはてなブックマークに追加
こんにちは。
sscanf() について質問させてください。


まず scanf() の場合、これから入力される数値の個数がわからなくても、

    while ( scanf( "%d", &n ) == 1 ) {
       printf( "%d\n", n );
    }

で全て画面に出力されます。

つまり、入力が
    10 20 30
でも
    10 20 30 40 50
でも全て出力してくれます。


しかし同じ事を sscanf() でやろうとすると、

    char *s = "10 20 30";

    while ( sscanf( s, "%d", &n ) == 1 ) {
       printf( "%d\n", n );
    }

これでは最初の 10 という数値ばかりを読込んでしまいます。
理由は scanf() のファイルポインタ stdin にあたるものを自動的に進めてくれないためですが、
いったいどうすれば文字列 s の数値を全て出力してくれるようになるのでしょうか。

何卒、よろしくお願いいたします。

コメント(11)

「進めてくれない」ではなく、ソコはプログラマが「進めた値(アドレス)」を渡すべきなのではないかと思われます。
sscanf()内部で「どこまで読み込みを行ったのか」という情報を保持してくれたら…
とお思いなのかもしれませんが、その場合スレッドセーフにするのに問題があるかもしれません。

# 車輪の再発明になりかねませんが、私なら自分で作ります。
# 引数1つ追加することになるかもしれませんが。
strtolのendpを使うとか。
とりあえず関数は作ることになる。
個数に対する制限の度合い、
個数や数値の大きさが想定範囲外のときの動作、
スキップした位置を返すのか(どのように返すのか)さもなくば一括で複数の数値を解釈するのか(それをどのように返すのか)。
流儀は色々あるから要求に応じて作る。
C++ が使える環境なら、sscanf を使わず std::stringstream に投げるのが手っ取り早い気がします。

#include <iostream>
#include <sstream>

int main() {
  char *s = "10 20 30 40 50";
  int n = 0;
  std::stringstream ss;
  
  ss << s;
  while( !ss.eof() ) {
    ss >> n;
    std::cout << n << "\n";
  }
  return 0;
}
strtok の場合は, s の中身が破壊されてしまう。
なので、私なら strtok を使うくらいなら strspn を使ってこんな感じで。

#include <stdio.h>
#include <string.h>

int main(void)
{
   char *s = "10 20 30"; 
   char *p = s;
   int n;

   p += strspn(p," ");
   while (sscanf(p, "%d", &n)  != EOF) {
       p += strspn(p,"0123456789");
       p += strspn(p," ");
       printf( "%d\n", n );
   }
   return 0;
}
>9
数字と空白以外の文字が与えられたら対応できなくなる。
complement spanを使った方が安全。
ありがとうございます。

一応 C++ の stringstream は知っていたので、
それに準じるものが C言語にもあればいいなと思っていました。

意外と難しい問題なんだなぁ・・・

ログインすると、みんなのコメントがもっと見れるよ

mixiユーザー
ログインしてコメントしよう!

C言語とC++言語 更新情報

C言語とC++言語のメンバーはこんなコミュニティにも参加しています

星印の数は、共通して参加しているメンバーが多いほど増えます。

人気コミュニティランキング