• 締切済み

sscanf() 関数の第 1 引数の型

 カーニハン/リッチー・著,石田晴久・訳の「プログラミング言語 C・第 2 版」で,「付録 B」にある sscanf() 関数のプロトタイプが   int sscanf(char *s, const char *format, ...) とあって,疑問に思いました。この第 1 引数の型は,「char *」ではなくで「const char *」のほうが合理的のように思えるのです。JIS X 3010-2003 では,const がついていましたし,さまざまな解説・マニュアルでも const つきで示されています。  そこで,ANSI C または JIS X3010-1993 の仕様書をお持ちの方,それらの仕様書の中で sscanf() 関数がどのようなプロトタイプを持っているか,ご教示願えませんでしょうか。ひょっとしたら本当に const がついていないのかもしれないし,書籍から何らかの理由で const が抜け落ちてしまったのかもしれません。  細かい点で恐縮ですが,ご回答くだされば幸いです。

みんなの回答

  • chie65535
  • ベストアンサー率43% (8520/19368)
回答No.2

>  int sscanf(char *s, const char *format, ...) >とあって,疑問に思いました。 K&Rの本が書かれた頃は「const char *と言う書き方は存在しなかった」ので、constが付いてなくて当たり前です。この本が書かれた頃は「constなんて無かった」んですから。 ま、訳注として「現在の仕様では、第一引数はconst char *である」と追記してないのは不親切ですが。 >お尋ねしたいことは,この「const がついていない」ことに対して >「ANSI C または JIS X3010-1993 の仕様書・規格書ではどのように >書かれているか」 「constが付いている」と書かれています。 Cライブラリの仕様、C言語の仕様は「昔から、今の形になったのではなく、より合理的になるように進化して来た」のです。 >書籍から何らかの理由で const が抜け落ちてしまったのかもしれません。 「合理的な仕様が無かった時代の古文書」に「何かの理由で抜け落ちたのでは」と言いわれても困ります。 交通信号機が発明されてなかった時代の交通法規を持ち出して「赤信号では止まれ、と書いてない」と言われても困ります(笑)

elttac
質問者

補足

 恐れ入ります。しかし,わたしが参照したのは「第 2 版 ANSI 規格準拠」で,問題の sscnaf() 以外では,const がつくべき(といえばよいのでしょうか)箇所では const がついています。これは,ご回答の要旨と矛盾しますが,いかがでしょうか。

  • asuncion
  • ベストアンサー率33% (2126/6288)
回答No.1

sscanf() の中で第1引数の内容を改変することはない、 という意味で、おっしゃるとおり const の付いている方が 合理的であろうと思います。 K&R の訳本に const が付いていない(私は原語本は未確認)のは、 「本に書いてあることがすべて正しいとは限らない」ということの 一例ではないでしょうか、たぶん。

elttac
質問者

補足

 ご回答ありがとうございます。  ですが,お尋ねしたいことは,この「const がついていない」ことに対して,「ANSI C または JIS X3010-1993 の仕様書・規格書ではどのように書かれているか」です。これについてご存じはないでしょうか。

関連するQ&A

  • strchr() の第2引数はなぜ int 型なのでしょうか

    もしかすると、ちょい前の質問(https://okauth.okwave.jp/qa4151232.html)と同じことを聞いているような気もしますが、気にせずポスト。 その質問を読んだ時に strchr() のマニュアルを見たわけなんですが、そのプロトタイプ宣言は char* strchr(const char* s, int c); なんですね。どうして第 2 引数の型が int なのでしょう?「文字」c を検索するんだから普通に考えれば char ではないかと思うのですが、誰か教えて下さい。 ソースはこんな感じだったので、int である必要はないように思えるのですがどうなんでしょうか? 負数を与えたときに「何らかの動作」を期待してのことなのでしょうか? char* strchr(const char* s, int c) {  char ch;  ch = c; /* <= 結局 char 型にしている */  for ( ; ; ++s) {   if ( *s == ch ) {    return (char*)s;   }   if ( *s == '\0' ) {    return NULL;   }  } }

  • C++で他のファイルの関数の引数を引きだす方法

    C++初心者です。 あるCプログラムに関数: testFunction(const char x[ ], int a, int b, int c)があり、 この関数はchar y[ ]を戻り値として返します。 次の段階で、別のC++を作成し、その中で、上記testFunctionを呼び出し、 使用している引数を引き出して以降のプログラムで使用する仕様のプログラムを組んでいます。 他のファイルに存在する関数を呼び出す方法は、 std::cout << testFunction(x[], a, b, c) << std::endl; ではないかと思っているのですが、ここから先が進まず困っている状況です。 戻り値だけではなく、引数も呼び出すことは可能でしょうか。 可能であれば、どのようにして呼び出すことができるのでしょうか。 アドバイスをお願いいたします。

  • sscanf エラー

    sscanfで整数が読み込めません。 コマンドプロンプトの画面は以下のようです。 文章を入力してください。 aaaa 11 14 aaaa 4201776 4201870 1 以下が実行したコードです。 #include<stdio.h> int main(void){ int a,b,c,i; char name[20]; printf("文章を入力してください。\n"); scanf("%s",x); c=sscanf(x,"%s %d %d",name,&a,&b); printf("%s %d %d %d\n",name,a,b,c); return(0);} aaaa 11 14と表示されるように、御指摘おねがいします。

  • main の引数には const 付けた方が

    C言語での質問です。 引数を取るような main 関数は int main( int argc, char *argv[]){~} とされていますが、argvの指す文字列を変更する、というのはいくら何でもまずいので、 int main( int argc, const char *argv[]){~} あるいは int main( int argc, const char const * const * argv){~} の方がいいのではないでしょうか? 何故、constを付けない形が出回っているのでしょうか?

  • sscanfでフォーマットに合っているかを調べるには。

    今,Cの関数で0-9,A-Zの4文字以内の文字列かどうか を調べたいのですが, int main() { int i; char str[] = "ABCD" /* 調べたい文字列1 */ char str1[]= "ABC@" /* 調べたい文字列1 */ char str2[]= "ABCDE" /* 調べたい文字列1 */ char *p; p = str; /* ここをstr1,str2に変える */ if (strlen(p) != 4) printf("エラーです\n"); for (i = 0; i < 4; i++) { if (!isupper(p[i]) && !isdigit(p[i])) { printf("えらーです\n"); return EXIT_FAILURE; } } printf("すべてOKです\n"); return EXIT_SUCCESS; } というようにすれば,strとstr1とstr2がフォーマットに合うかわかるのですが,これをsscanfの正規表現を使用して実装したいのですが,可能でしょうか。 int main() { int ret; char str[] = "ABCD" /* 調べたい文字列1 */ char str1[]= "ABC@" /* 調べたい文字列1 */ char str2[]= "ABCDE" /* 調べたい文字列1 */ char *p; chat tmp[30]; p = str; ret = sscanf(p, "%4[0-9A-Z]", tmp); if (ret != 1) { printf("エラーです\n"); return EXIT_FAILURE; } printf("すべてOKです\n"); return EXIT_SUCCESS; } といしょうとするならば,str1のときは,@までのABCの文字列がとれて,retには1が帰ってきてしまいます。 なにか4文字以内ということを実装できる正規表現の使い方はあるのでしょうか? ちなみに sscanf(str, "%1[0-9A-Z]%1[0-9A-Z]%1[0-9A-Z]%1[0-9A-Z]", tmp1, tmp2, tmp3, tmp4) という以外でわかる方,よろしくおねがいします。

  • C++の関数テンプレートで分からないところがあります。

    C++の関数テンプレートで分からないところがあります。 C++の入門書を読んで勉強しているのですが、その演習問題(答えはついてないです)で、以下のような問題がありました。 ----------------------------------------------------- 配列の全要素の最小値を求める関数テンプレートを作成せよ。 teplate <class Type> Type minof(const Type x[], int n); という形で作ること。 なお、最も小さい文字列を求められるようにするために、const char *型に明示的に特殊化したものも合わせて作成すること。 ------------------------------------------------ という問題なのですが、これにたいして僕は以下のように答えました。ヘッダのインクルードなどは省きます。 template<class Type> Type minof(const Type x[], const int n) {     int min = 0;     for(int i = 1; i < n; i++)         if(x[min] < x[i])             min = i;     return x[min]; } template<> const char* minof<const char *>(const char x[][64], const int n) {     int min = 0;     for(int i = 1; i < n; i++)         if(strcmp(x[min], x[i]) < 0)             min = i;     return x[min]; } int main() {     const int n = 5;     int a[n];     char s[n][64];     for(int i = 0; i < n; i++){         cout << i + 1 << "番目---";         cin >> a[i];     }     cout << "文字列\n";     for(int i = 0; i < n; i++){         cout << i + 1 << "番目---";         cin >> s[i];     }     cout << "整数の最小値---" << minof(a, n) << "です\n";     cout << "文字列の最小値---" << minof<const char *>(s, n) << "です\n"; } これをコンパイルすると、エラーで 明示的な特殊化; 'const char *minof<const char*>(const char [][64],const int)' は関数テンプレートの特殊化ではありません と 'minof' : 1 番目の引数を 'char [5][64]' から 'const char *const []' に変換できません。 とでてしまいます。 色々探してみたのですが、解決できませんでした・・。 特に最初のほうのエラーがよくわかりません。ちゃんと特殊化してる気はするのですが・・。 間違っている箇所の正当を載せていただけるとわかりやすくて、ありがたいです。 よろしくお願いします!

  • 関数の引数をvoid*でキャストする

    最近見かけたCのプログラムで、関数の引数の型は void* なのですが、その関数を使うときに 引数をvoid*でキャストしていました。 例えば、 func ( (void*) p ); こういうことです。 私の知っている知識では、 void* と 任意の型のポインタは キャストなしに相互に代入可能です。 関数の引数でも、キャストは要らないものだと思っていました。 そうすると、引数を void* でキャストするのは無意味だと思うのですが、・・・ 違うのでしょうか。処理系によるとか。 逆に、関数の引数の型がchar*などで、渡すものが void* のときはどうなのでしょうか。 下のプログラムは、関数byte_orderの引数の型はvoid*ですが、int型へのポインタ( &a )を設定しています。私の環境では、コンパイルエラーも警告もないし、動作も正常です。 #include <stdio.h> #include <string.h> void byte_order(void *vp) { char char_array[4]; strncpy(char_array, vp, 4); printf("出力します:%x %x %x %x\n", char_array[0], char_array[1], char_array[2], char_array[3]); } int main(void) { int a = 0x12345678; byte_order(&a); return 0; } このプログラムは単なる一例であって、質問はバイトオーダに関するものではありません。 また、C言語の質問であって、C++ではありません。

  • C言語の標準関数の引数の順番について

    C言語標準関数の引数についての質問です。 strcpy、memsetなど C言語の標準関数の引数に注目したところ 前に出力パラメータを持ってきているものが多いように思えます。 例えば、 char *strcpy(char *dest, const char *src); の場合、 第1引数の"dest"が出力パラメータで 第2引数の"src"が入力パラメータとなっています。 入力よりも出力を前に持ってきている理由が何かあるのでしょうか。 今後、自分が設計をするときの参考にしたいと考えているので 理由を知っている方がいたら教えて下さい。

  • Objective-CでCの関数に引数をわたしてあげたいのですが。

    NSArray *filetype = [ NSArray arrayWithObject : @"'TEXT'" ]; NSOpenPanel *opfile = [ NSOpenPanel openPanel ]; と書いた後に[opfile filename]にファイルパスが入っているとゆうことなんですが、これをchar型の変数に渡してCの関数に渡してあげたいのですがいろいろ試してみたんですがやり方がさっぱりわからず周りの人たちもObjective-Cはわからないので困っています。このあと aaaaa(char *file,int aaa); みたいな関数を呼びたいんですが初めにプロトタイプ宣言してそのまま呼んでも大丈夫なんでしょうか? わたくしObjective-C歴2日、C歴3ヵ月半の若輩者です。経験者のみなさんよろしくお願いいたします。 動作環境はMacOSX、ProjectBuilderのcocoaでやってます。 参考にしたサイトは「cocoaはやっぱり」で勉強してます。 本は「MacOSXプログラミング入門OBjective-C」を昨日買いました。 その他注意事項ありましたら言ってくださると助かります。

  • 関数について

    char *str_char(const char *str, int c) { while (*str++) if (*str == c) return ((char *)str); return (NULL); } /*文字列strから文字cを検索し最初に存在する文字へのポインターを返す*/ 上記関数なのですが 5行目を return (str); にしてはなぜいけないのでしょうか。

専門家に質問してみよう