• ベストアンサー

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

専門家に質問してみよう