• ベストアンサー

char形配列の整数を抜き出したい

char str="今週,23位"; int a; という配列の数字の部分(23)を抜き出してaに放り込みたいのですが、便利な関数とかあれば教えて頂けないでしょうか。お願いします。 

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

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

> ただ、"%*[^0123456789]%d"の部分がわかりにくいです。 ひとつづつ解説します。 %の直後の'*'ですが、これは実引数への格納を抑止するという意味です。'*'がないと、(型が違うのに)aに無理やり格納されてしまいます。 [^0123456789]ですが、[]内で'^'を最初に指定した場合、それに続く文字群以外からなる文字列を走査します。この場合には数字以外がこの部分に合致するようにしています。処理系によっては[^0-9]とすることもできますが、厳密に規格に合致させるには、[^0123456789]のように全部ダラダラ並べる必要があります。 strが"今週,23位"を指す場合、数字以外ですから、このフィールドは"今週,"の部分を読み込んで、その内容を破棄します。 %dは十進数値を走査します。直前のフィールドで"今週,"が読み飛ばされていますから、続く"23位"から最初の十進数値、すなわち23を読み込み、整数値としてaに格納します。

bonbontarou
質問者

お礼

アスタリスクは検索で何でもOKという使い方しか知りませんでした。この書式は覚えておこうと思います。どうもありがとうございました。

その他の回答 (7)

  • ency
  • ベストアンサー率39% (93/238)
回答No.7

No5, 6 ency です。 > ただchar *pで23を差すは理解できにくいですが、思った結果が > 返ってきましたので、これを使おうかと思います。 atoi() がどのような関数なのかはご存知ですか? 数字 (文字列) を int型の数値に変換してくれる関数です。 たとえば。。。 -------------------------------------------------------- int hoge; hoge = atoi( "1234" ); -------------------------------------------------------- という場合には、文字列 "1234" から int型の数値 1234 になるわけです。 atoi() は数字 (文字列) を数値に変換するのが目的の関数ですが、後ろの数字以外の文字がついている場合、それは無視してくれるんです。 というわけで、"23位" を atoi() に渡すと 23 という数値が返ってくるわけです。 回答されている皆さんのどれもが、先頭の数字を見つけるための方法です。 phoenix343 さんと私の場合、それが関数化されているものをご紹介したに過ぎません。 「難しい」という一言で一蹴するのではなく、それを理解できるように努力することもお忘れなく。 No1 jacta さんのご回答は「正規表現」(ですよね?) をうまく利用した方法で、応用範囲もかなり広いと思います。 理解して使えるようになれば、かなり大きな力になると思います。 No2 komakana さんのご回答は標準関数を使えない環境なんかではよく使う方法です。 # 私も組込み系な人間なもので。。。 # 最近は標準ライブラリもしっかりしてきていますが、ちょっと前 # なんかは、「標準関数使用禁止!」などというお達しがでたくらい # 信用のないものでした。。。 …なんか、いろいろと書きすぎましたね。 勉強し始めのころは、いろいろなパターンを考えてみるのが良いと思いますよ。 そうするうちに、「手を抜いて楽する」方法も身についてきますから。。。 がんばってくださいね、bonbontarou さん!

bonbontarou
質問者

お礼

そうですね、勉強頑張ります。組込み系の人間だってわかりますか?w 難しいですが頑張ります。

  • ency
  • ベストアンサー率39% (93/238)
回答No.6

No5 ency です。 ポインタ p の NULL チェックしてませんでしたね。 -------------------------------------------------------- int a; char str[] = "今週,23位"; char *p; p = strpbrk( str, "1234567890" ); if ( p != NULL ) /* ←数字が見つかった! */ a = atoi( p ); --------------------------------------------------------

bonbontarou
質問者

お礼

この関数が私には一番わかりやすいです。 ただchar *pで23を差すは理解できにくいですが、思った結果が返ってきましたので、これを使おうかと思います。 皆さん本当時間割いてくれて有難う御座いました。

  • ency
  • ベストアンサー率39% (93/238)
回答No.5

こんな方法もありますね。 # 標準関数だけでやってみました。。。 -------------------------------------------------------- int a; char str[] = "今週,23位"; char *p; p = strpbrk( str, "1234567890" ); a = atoi( p ); -------------------------------------------------------- strpbrk() は1番目の引数に設定した文字列の中で、2番目の引数に設定した文字列に含まれるどれかの文字が現れる位置を指すポインタを返す関数です。 # 要するに、この場合 str の '2' の場所を指すポインタが返ります。 あとは、atoi()/atol() なり、strtol() なり、sscanf() なり、お好きなものを使えば良いでしょう。

  • phoenix343
  • ベストアンサー率15% (296/1946)
回答No.4

#3です。 すみません、返す値はインデックスでしたね。 だから、次のようになりますね。 int a; int idx = strcspn(str, "0123456789"); if ( 0 <= idx ) {  a = atoi(str + idx); }

bonbontarou
質問者

お礼

返答有難う御座います。 この関数も短くていいですね。 しかしstrpbrk()同様、結果はバッチリなのですが。idxは2ではなくidxは23になるのは不思議な気がします。

  • phoenix343
  • ベストアンサー率15% (296/1946)
回答No.3

次の関数を使えば、その位置へのポインタを取得できます。 strcspn、wcscspn、_mbscspn http://www.microsoft.com/japan/msdn/library/default.asp?url=/japan/msdn/library/ja/vclib/html/_crt_strcspn.2c_.wcscspn.2c_._mbscspn.asp だからこうなりますか。 int a; char *p = strcspn(str, "0123456789"); if ( p ) {  a = atoi(p); } どうでしょう?

  • komakana
  • ベストアンサー率14% (1/7)
回答No.2

#include <stdio.h> main(){ char str[] = "今週,23位"; int a = 0; int i = 0; int j = 0; while(str[i] != NULL){ if(str[i] - '0' > 0 && str[i] - '0' < 9){ a = a*10 + (int)(str[i]-'0'); } i++; } printf("%d ", a); } ごちゃごちゃしてしまいましたがこんな感じでどうでしょうか? 前の回答者の方の言っているとおり、 char str[] = "今週23位"だと思います。 char だけだと一文字を表します。 char * または charの配列を用いて文字列を表します。 str[i] - '0'というのは数字を表す文字が数字の順に並んでいることを利用したものです。 文字コードについては、 http://e-words.jp/p/r-ascii.html を参照してください。 駄文しつれいいたしました!がんばってくださいね!

bonbontarou
質問者

お礼

有難うございます。 私にはむずかしすぎます。 丁寧に有難うございました

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

まず、char str[] = "今週,23位";の間違いではないでしょうか?そうだと解釈して以下回答します。 int a; sscanf(str, "%*[^0123456789]%d", &a); とすれば概ね問題ないと思いますが、文字コードにISO-2022-JPなどを使っていると期待通りに動作しません。 ワイド文字が使えるのであれば、いったんmbstowcsでワイド文字列に直してから、swscanfを使うなどした方がよいかもしれません。

bonbontarou
質問者

お礼

すっきりしてていいと思います。 ただ、"%*[^0123456789]%d"の部分がわかりにくいです。

関連するQ&A

  • c言語 int型の数字をchar型の配列に

    c言語についてです。 int型の数字をchar型の配列に入れたいです。 関数に対してint型の数字を文字列として渡し、 関数内でchar型の配列に格納したいです。 例として、 a(char a[]){  ~~  ~~ } int main(void){ int x = 5678;  ~~  a(x); } とできるようにしたいです。 しかしこれだと5678という値がそのままchar型の一つの配列に入る?ため正しくないです。 欲しい結果としてはちゃんとa関数内で、 a[1] = '5' a[2] = '6' a[3] = '7' a[4] = '8' となってほしいです。 もともと渡す値が”5678”となっていれば結果は正しく出るのですが、 渡す値がint型と決まっているためどうにかして5678を”5678”とすればいいのではないかと考えています。 つまり5678を単純に文字列に変換すればいいのでしょうか? またプログラム内ではsprintfやatolを使用しないで実現させたいです。 難しいかもしれませんがお願いします。 なんだか説明が下手ですみません。 お願いいたします。

  • char型配列をint型に代入するには

    char型の配列(文字列)の各要素ににそれぞれ数字が一つ入れました。 str[0] = '0' str[1] = '1' : str[5] = '5' これをfor文を使ってint型変数に入れたい代入するにはどうれればいいですか? str[0] → dat1 str[1] → dat2 : str[5] → dat5

  • C言語のint型の配列が分かりません

    #include<stdio.h> int main(void) { int str[ ]={0,1,2} printf("%s\n", str); return 0; } というプログラムをC言語でつくってみましたが動きません.(012と表示されて欲しかったのですが) int str[ ]={1,2,3}の部分をchar str[ ]={'0','1','2'}とすれば動きます. そこで質問なのですが, printf("~%s~", (配列名));  はchar型の配列にしか適応できないのですか? ※追記 puts関数の定義は int puts (const char *str); であるそうなので char型の仮引数にはchar型のアドレスを渡さなければいけません. ではprintf関数の定義は一体どんなものなのですか?

  • char型配列について

    基本的なことですが、 char str[5]="Hello"; --> str[0]='H' str[1]='e' str[2]='l' str[3]='l' str[4]='o' str[5]='\0' では、ないのでしょうか? エラーが出ます。 //error C2117: 'str' : 指定された配列には、初期化子が多すぎます。 char str[6]="Hello"; では、コンパイルできます。 ---------------------------------- また、 #include<iostream> using namespace std; int main() { char str[6]="Hello"; cout << str << endl; for(int i=0;i<7;i++) { cout << "i=" << str[i]; if(str[i]=='\0'){cout << " NULL" << endl;} else{cout << endl;} } getchar();return 0; } ----------------------------------------------- とすると、 Hello i=H i=e i=l i=l i=o i= NULL <--ここで、NULLなら、 i=フ <--このぶんは、いらないと思うのですが、、、 となります。 str[6] i=6 は、何を意味するのでしょうか? Visual C++ NET を使用しています。 よろしくお願いします。

  • String型をchar型配列にしたい

     VC++2005ExpressEdition + PlatformSDKを使用しています.  String型をchar型配列に変換したいと思っています.  自分なりに調べてみたのですが, > String^ str = gcnew String("test"); > char chr[5]; > chr = str->ToCharArray(); などとしても次のようなエラーが出ます. > error C2440: '=' : 'cli::array<Type,dimension> ^' から 'char [5]' に変換できません。  String型からchar型配列への変換はどのようにすればいいのでしょうか.

  • 構造体で配列を使用しない方法。

    構造体で配列を使用せずに、メモリ領域を獲得する関数を使用する場合はどうすればよろしいですか??  例 char *str; struct seiseki{ char name[20]; int eig; int suu; int kok; char rank[3]; }; str = ()malloc();

  • 配列で混乱しています

    c言語を勉強中のものです。文字列を配列で扱う場合とポインタで扱う場合の違いにこんらんしています。 たとえば char str[] = "hello"; str = "goodby"; のように文字列の再格納はダメですが、 char *str = "helllo"; str = "goodby" は大丈夫です。 また char[100]; scanf("%s",str) は大丈夫ですが char *str; scanf("%s",str) はいけません。この2つの違いは何によるのでしょうか? またポインタはそもそも int a; int *pa; pa = &a; のように、宣言したあとはアドレスを入れる専用のハコのように考えていたのですが、 char *str = "helllo"; str = "goodby" のようにいきなりアドレスでない文字列を代入するのも納得がいきません。誰か解説をお願いします。

  • char* を渡したとき、不適切なPtrが出る問題

    こんばんは。プログラムを勉強中の学生です。 詰まった部分があり、関連しそうな部分を勉強しましたが、問題が解決しなかったので、 こちらで質問させて頂きます。 今、とあるクラスで、 class Test{ ........................................ public: int Func1(char* str,){ unsigned int n = 0; while(str != "\0"){ n += *str; str++;}          ←ここに<不適切なPtr> return n % 3; } void Func2(char* str){ int i; i = Calc(str); ..................................... ............................ } }; のように宣言し、main()関数で、 int main(){ Test test; test.Func2("ABC"); // Case1: エラーは起こらない char s[]={"ABC"}; //Case2:不適切なPtrとなる。 test.Func2( s ); } としていますが、上記のように、"ABC"を直接入れたときのみ、うまくいき、 他の方法で、char型のポインタを代入した際には、不適切なPtrと出てしまいます。 この原因を教えていただけないでしょうか? 最終的には、 cin >> s ; などのように、キーボードから入力した値(文字列)を使いたいのですが、 現段階ではmain関数で "ABC"のように書かなければならず困っています。

  • 文字を整数(int)に変換

    char型の数字文字を、int型に変換したいのですが、どんな方法があるでしょうか? 具体的には、 char s[6] = "12345"; int line[5]; のようなchar配列の文字を、int型のline配列に移したいのです。(line[0]=1,line[1]=2,...,line[4]=5となるように。) "文字 int 変換"などで検索でも調べたのですが、 int→文字のsprintfしか見つかりませんでした。 感覚的にはこの逆のような操作をしたいです。 何か関数を用いる方法でも、そうでない方法でもよいので、 教えてください。よろしくお願いします。

  • 二次元配列による文字列の配列の受渡しについての質問です。

    二次元配列による文字列の配列の受渡しについての質問です。 #include <stdio.h> void print_pname(char str[][5], int n) { int i, j; for (i = 0; i < n; i++) { printf("str[%d] = \"", i); for (j = 0; str[i][j] != '\0'; j++) putchar(str[i][j]); printf("\"\n"); } } int main(void) { char ary[][5] = {"Lisp", "C", "Ada"}; print_pname(ary, sizeof(ary) / sizeof(ary[0])); return 0; } 上のプログラム中の関数print_pnameの引数char str[][5]についてですが char (*str)[5](配列のポインタ)と変更した場合にwarningが多数発生します。 これはどうしてでしょうか? また、上のプログラムを配列のポインタを使って変更することは可能でしょうか? 以上、よろしくお願いします。

専門家に質問してみよう