• ベストアンサー

C言語、スキャン集合について

下記のプログラムはスキャン集合を使って入力された文字列の先頭に 並んでいる数字を読み込んで捨て、その後に続く文字列を読み込んで 表示するものです。 #include <stdio.h> int main(void) { char str[80]; printf("数字に続けて文字列を入力してください\n"); scanf("%*[0-9]%s", str); printf("%s", str); return 0; } 【質問】%*[0-9] を %[^0-9] に置き換えてコンパイルして実行すると、 意味不明の文字列が出力されるのはなぜでしょうか? 置き換えても同じ結果になる気がするのですが…

質問者が選んだベストアンサー

  • ベストアンサー
  • aris-wiz
  • ベストアンサー率38% (96/252)
回答No.3

>対応する引数が指している文字配列がstrで、 >%sの引数がないから、意味不明な文字列が表示されるのですか? その認識で概ねいいと思います。 もう少し正確に言うと、scanfなどの書式指定子では、 書式に見合うだけの実引数がないときの動作は未定義なので、 strにはもしかしたら %[^0-9] にマッチするものが 入っているかも知れませんし、入らないかも知れません。 とにかく何が起こるかはわからないのです。

Guchiken
質問者

お礼

返答ありがとうございます! 大変勉強になりました。 回答ありがとうございました。

その他の回答 (5)

  • jacta
  • ベストアンサー率26% (845/3158)
回答No.6

質問に対する回答はすでに出ているようですが... %[^0-9]のように、0-9が0123456789であることを期待しているのであれば、それは処理系の独自仕様に依存しています。 移植性を考慮するなら、%[^0123456789]と書かなければなりません。 一応念のため。

Guchiken
質問者

お礼

ご指摘ありがとうございます! 私が使っている(勉強している)本に、 『厳密にいえば、ハイフンを使って範囲を指定する方法はANSI C標準 には規定されていません。しかし、この方法はほとんどのCコンパイラ で有効です』 と書いてあります。 なので、一応知っているつもりですが…

回答No.5

   言葉足らず。 対応する引数に対する読み込みを止めろ。 です。  

Guchiken
質問者

お礼

回答ありがとうございます!! >" 0-9 以外を読み込め。"ではなく、 >" 0-9 の文字に出会ったら読み込みを止めろ。"です。 >対応する引数に対する読み込みを止めろ。 ご指摘どおり、勘違いしていました・・・0-9がその文字列から捨てられる ものだと勘違いしていました。捨てられるのは「%*」の「フィールドの代入 の抑制」でした

回答No.4

   平たく言うと、[^0-9]は、 " 0-9 以外を読み込め。"ではなく、 " 0-9 の文字に出会ったら読み込みを止めろ。"です。  どんな文字列から、どんな数字を読み飛ばすのかわからないけど、 例えば、 scanf("%*d%s", str) とするとか。  

  • aris-wiz
  • ベストアンサー率38% (96/252)
回答No.2

もう一点。 *は「代入抑止のフラグ」であり、 任意の数にマッチするわけではありません。 %[^0-9]%sでは、実引数がたりません。

Guchiken
質問者

お礼

さっそくの回答ありがとうございます! なぜ、数字を後ろに入力すると取り除かれるのですか? 逆に、文字列の前に入力すると取り除かれる気がするのですが? (%sより前に%[^0-9]があるから) 私の使っている本に、 『scanf()はスキャン集合に出合うと、スキャン集合に対応する引数が指 している文字配列に入力を読み込みはじめます。』 とあるので、%[^0-9] に置き換えた場合、対応する引数が指している文 字配列がstrで、%sの引数がないから、意味不明な文字列が表示される のですか?

  • aris-wiz
  • ベストアンサー率38% (96/252)
回答No.1

正規表現と書式指定子を混合しているように思います。 C言語でのscanfなどの書式指定子では[^]は以下のように動作します 左角括弧の直後がアクサンシルコンフレックス(^)であるときの 走査文字集合は、そのアクサンシルコンフレックスと 「右角括弧の間にある走査文字の並びに現れないすべての文字」 とする。 つまり、「 %[^0-9]」とした場合だと、 数字列を後ろに入力した場合にのみ取り除かれ、 その後の%sにマッチする文字列が無いことでscanfが失敗し 自動変数内の不正な文字列が表示されているのだとおもいます。

関連するQ&A

  • スキャン集合に関して

    #include <stdio.h> int main() { char str[128]; printf("文字列を入力してください>\n"); scanf("%[^\n]" , str); printf("入力された値 = %s\n" , str); can_kansu(str); return 0; } int can_kansu(char *sp) { char strs[128]; printf("%sとは違う文字を入力して下さい。\n", sp); scanf("%[^\n]" , strs); printf("入力された値 = %s\n" , strs); return (0); } このプログラムでは、mainでは正常に入力表示が可能なのに、can_kansuにいくと勝手に入力、表示され、しかもその文字は文字化けして表示されてしまいます。 <実際の入力例> 文字列を入力してください> kkk 入力された値 = kkk kkkとは違う文字を入力して下さい。 入力された値 = �p "kkkとは違う文字を入力して下さい。"の所で入力出来ずにつぎに勝手に進んでしまい、入力されている文字はこの通りです。 原因は何でしょうか?scanfのスキャン集合に原因があるのでしょうか?

  • ポインタについて

    #include<stdio.h> int main(void) { char str[10]; char *ptr = str; printf("文字列を入力してください。\n"); scanf("%s",ptr); printf("文字列は%sです。",str); return 0; } 上記のプログラムのscanf("%s",ptr);の ptrに&をつけるとなぜ先頭の4文字は入力しても 表示されなくなってしまうのでしょうか? よろしくお願いします。

  • C言語 ポインタ エラー

    文字列を入力後改行して入力した文字列を出力したいのですが、エラーがでます。 ハンドルされない例外が 0xFEFEFEFE (helloworld.exe) で発生しました: 0xC00001A5: 無効な例外ハンドラー ルーチンが検出されました。 (パラメーター: 0x00000003)。 調べてみましたが、理解できません 何卒よろしくお願いします。 #include <stdio.h> void put_string(const char *str) { while (*str) putchar(*str++); } int main(void) { char str[100]; printf("文字列を入力してください"); scanf_s("%s", str); put_string(str); putchar('\n'); return(0); }

  • C言語ののポインタについて

    「明解C言語 入門編」p262の演習11-4についての質問です。 このサイトも参考にしてみて、 入力された文字の大文字小文字を反転するプログラムをvimで書いてみたのですが #include <stdio.h> #include <ctype.h> void str_toupper(char *str) { while (*str = toupper(*str)) { *str++; } } void str_tolower(char *str) { while(*str = tolower(*str)) { *str++; } } int main(void) { char str[100]; printf("文字列を入力してください:"); scanf("%s", str); str_toupper(str); printf("大文字:%s\n", str); str_tolower(str); printf("小文字:%s\n", str); return(0); } clangを用いてコンパイルすると4warnings generatedと出ます。 ------------------------------------------------------------ ex11-4.c:6:13: note: use '==' to turn this assignment into an equality comparison while(*str = toupper(*str)){ ^ ------------------------------------------------------------- こんなのや ---------------------------------------- ex11-4.c:7:3: warning: expression result unused [-Wunused-value] *str++; ^~~~~~ ---------------------------------------------------- といった警告が表示されます。 どこをどう訂正すれば良いのでしょうか。 よろしくお願いします。

  • C言語 strcmp 半角スペースがあるとだめ?

    C言語 strcmp 半角スペースが文字列に含まれている場合 文字列の比較がうまくいきません。半角スペースがあると比較できないのでしょうか? プログラム //strcmp #include <stdio.h> #include <string.h> int main(void){ char input[256]; char str[] = "HelloWorld!";   //char str[] = "Hello World!";だとうまくいかない。 printf("%s\n>", str); scanf("%s", input); if ( strcmp(input, str) == 0){ printf("同じです。\n"); }else{ printf("違います。\n"); } return 0; }

  • C言語 ポインタと配列

    #include <stdio.h> /* scanf("%c", &search); ではなく scanf(" %c", &search); であることに注意する */ char *str_chr(const char *str, char c) { char *find; find = NULL; do { if(*str == c) { find = (char*)str; break; } } while(*str++); return(find); } int main(void) { char str[100] = {0}; char search; char *find; printf("文字列を入力してください:"); scanf("%s", str); printf("検索する文字を入力してください:"); scanf(" %c", &search); find = str_chr(str, search); if(find == NULL) { puts("検索した文字は見つかりませんでした。"); } else { printf("検索した文字 %c は\"%p\"にあります。\n", *find , find); } return(0); } このコードのfind = (char*)str;の (char*)str;の部分がどうなっているのかわかりません。 あとこのfindというのは&find[0]という解釈でいいでしょうか? 教えてくださいm(_ _ )m

  • c言語の問題

    以下のプログラムをコンパイルし、実行したところ、次のような画面が表示された。下記の関数定義部分を補いなさい。 gcc test.c ./a.out abc def answer = defabc 以下ソースコード #include<stdio.h> void stradd(char A[], char B[]); int main(){ char str1[100], str2[100]; scanf("%s", str1); scanf("%s", str2); stradd(str1, str2); printf("answer = %s\n", str2); } void stradd(char A[], char B[]){ } よろしくお願いします。

  • C言語 文字列の操作

    文字Cが含まれる個数を求めたいです #include <stdio.h> int str_chnum(const char str[],int c) { int i; int count=0; for(i=0;str[i]!="\0";i++) if (str[i]==c) count++; return(count); } int main(void) { char st[100]; printf("検索文字列を入力してください:"); scanf("%s",st) ; printf("検索文字列数は%uです。\n",st,int str_chnum(const str[],int c)); return(0); } コンパイルできません。なぜですか?printfの行がたぶん間違っていると思うんですが。。。

  • C言語

    文字列を逆順にするプログラムを考えているのですが分かりません。(例)qwerならrewqです。入力終了は、EOFです。考えたのですが、分かりません。(コンパイルエラーです。)教えてください。宜しくお願いします。#include <stdio.h> unsigned str_length(const char str[]) { unsigned len=0; while (str[len]) len++; return (len); } void put_rstring(const char str[]) { unsigned i = str_length(str): while (i-- >0) putchar(str[i]); } int main(void) { char str[30]; int ch; printf("文字列を入力\n"); /* ----この文字列を入力したあとに、Ctrl+Zを押すと、逆から表示               で反対から、文字列が表示----*/ while (1) { ch=getchar(); if (ch==EOF) break; } printf("逆から表示"); put_rstring(str); puts("です。"); return(0); }

  • C言語の問題で困っています。

    C言語の問題で困っています。 途中までできたのですが、この先が分かりません。 教えて頂くようお願いいたします。 【問題】 文字列の長さを求めるプログラムです。このプログラムを、入力した文字列の文字列長を求めるように変更してみましょう。  ただし、入力する文字列は半角で最大 20 文字までとし、指定された範囲外の値( 21 以上)が入力された場合は、正しい値が入力されるまで入力処理を繰り返すこと。 #include <stdio.h> int main(void) { char str[256] = "Hello"; int length, i; printf("文字列:"); scanf ("%s",str); length=0; i=0; while (str[i]!='\0') { i++; length++; } printf("\n文字列長:%d\n",length); }

専門家に質問してみよう