ページ 11

文字列から数値を抜き出す

Posted: 2012年5月09日(水) 17:10
by mo-fu
いつも楽しくこのサイトを見させてもらってます。

早速ですが質問です。
読み込むtxt fileに

Frequencies -- 578.3447 599.0566 637.9770

のような”Frequencies --”から始まる文字列が(不定期に)何度も出現します。
”Frequencies --”の後の実数値の桁数は必ずしも上記の通りにはなっていません。
今は

コード:

double Extract(char *str)//strにはFrequencies --から始まる文字列が入っています
{
	
	char *cut;
	double energy;//文字列の数値を代入するためのものです
	
	 //文字列の確認
			cut = strtok(str," ");//スペースで分断
			while(cut != NULL){
				cut = strtok(NULL," ");//スペース以下の数字をhitに収納
				if(cut != NULL){
					energy = atof(cut);//文字列であるhitを数値に変
				}
			}
		return energy;
}
というような関数を持ちいてスペース部分でいちいち区切って得た数値を返しています。

まあ、これで一応は動いているのですが、文字列を前から読んでいって、数値(実数)だけを読み込んでポインタ(配列)に収納していくような関数ってありませんでしたっけ??

または違う方法で、もっとシンプルなやりかたあるよ!っていう意見をいただきたいです。

一応調べてみたのですが、これだ!と思うものが無かったので、初心者質問で恐縮なのですが皆さんの力を借りたいと思います。


環境はMicrosoft Visual C++ 2010で、C言語を用いています。

何分初心者ですので、つまらない質問かもしれませんが回答お待ちしてます。

Re: 文字列から数値を抜き出す

Posted: 2012年5月09日(水) 17:26
by box
mo-fu さんが書きました: Frequencies -- 578.3447 599.0566 637.9770
先行する文字列は
"Frequencies --"
で固定ですか?

文字列の後ろに来る実数の個数は3個で固定ですか?

Re: 文字列から数値を抜き出す

Posted: 2012年5月09日(水) 17:34
by mo-fu
box さんが書きました: 先行する文字列は
"Frequencies --"
で固定ですか?
返信ありがとうございます。

文字列の後ろに来る実数の個数は3個で固定ですか?
先行する文字列は仰る通り、"Frequencies --"で固定ですが、文字列に続く実数の個数は1‐3個の幅があります。
3個で固定であればsscanfでの抜き出しも考えたのですが><

Re: 文字列から数値を抜き出す

Posted: 2012年5月09日(水) 17:48
by かずま
こんなんでどうでしょうか?

コード:

#include <stdio.h>
 
int Extract(const char *str, double *a, int n)
{
    int i, len;
    for (i = 0; i < n && sscanf(str, "%lf%n", &a[i], &len) == 1; i++)
        str += len;
    return i;
}
 
int main(void)
{
    double a[30];
    const char *str ="Frequencies -- 578.3447 599.0566 637.9770";
    int i, n = Extract(str + sizeof("Frequencies --"), a, 30);
    for (i = 0; i < n; i++) printf("%f\n", a[i]);
    return 0;
}

Re: 文字列から数値を抜き出す

Posted: 2012年5月09日(水) 18:26
by mo-fu
かずま さんが書きました:こんなんでどうでしょうか?

コード:

#include <stdio.h>
 
int Extract(const char *str, double *a, int n)
{
    int i, len;
    for (i = 0; i < n && sscanf(str, "%lf%n", &a[i], &len) == 1; i++)
        str += len;
    return i;
}
 
int main(void)
{
    double a[30];
    const char *str ="Frequencies -- 578.3447 599.0566 637.9770";
    int i, n = Extract(str + sizeof("Frequencies --"), a, 30);
    for (i = 0; i < n; i++) printf("%f\n", a[i]);
    return 0;
}
ほうほう!この場合

コード:

    double a[30];
となっているところを実際には動的に確保しといてやれば、柔軟に対応できるわけですね!
それにしても%nってこんな便利な使い方が出来たんですね!回答ありがとうございました。

ちなみに、Extract関数の中の引数(int n)に30を選んだのは何か理由がありますか??

Re: 文字列から数値を抜き出す

Posted: 2012年5月10日(木) 17:16
by ISLe
最大で3個程度なら。

コード:

#include <stdio.h>
int main(void)
{
	double a[3];
	const char *str ="Frequencies -- 578.3447 599.0566 637.9770";
	int i, n = sscanf(str + sizeof("Frequencies --"), "%lf %lf %lf", &a[0], &a[1], &a[2]);
	for (i = 0; i < n; i++) printf("%f\n", a[i]);
	return 0;
}
sscanfの戻り値で取り込めた数が分かりますけど。

Re: 文字列から数値を抜き出す

Posted: 2012年5月15日(火) 13:38
by mo-fu
ISLe さんが書きました:

コード:

#include <stdio.h>
int main(void)
{
	double a[3];
	const char *str ="Frequencies -- 578.3447 599.0566 637.9770";
	int i, n = sscanf(str + sizeof("Frequencies --"), "%lf %lf %lf", &a[0], &a[1], &a[2]);
	for (i = 0; i < n; i++) printf("%f\n", a[i]);
	return 0;
}
回答ありがとうございます!返信遅れてすみません。
確かに、この方法でやれば、無駄なメモリを使わなくてすみますね!勉強になります!
質問なんですが、この方法で行った時、もし数値が1つや2つで、EOFが返された場合は次の行のfor文の処理が行われ出すんですか?
それとも、このmain関数自体が終わるんでしょうか。

Re: 文字列から数値を抜き出す

Posted: 2012年5月15日(火) 14:20
by h2so5
mo-fu さんが書きました: 質問なんですが、この方法で行った時、もし数値が1つや2つで、EOFが返された場合は次の行のfor文の処理が行われ出すんですか?
それとも、このmain関数自体が終わるんでしょうか。
試せば分かります。

Re: 文字列から数値を抜き出す

Posted: 2012年5月15日(火) 14:30
by mo-fu
h2so5 さんが書きました: 試せば分かります。
ごもっとも(笑)
今のところ文字列に含まれる数値が3つでないデータが出てきてないので、出てきたときに試そうと思います!