No.7ベストアンサー
- 回答日時:
LippmanのC++プライマー(第4版)のp.340~p.342に、
8.5 stringストリーム
という節があって、p.342に、
「istringstream を使って format_message(数値と文字列の並びが格納された ostringstream オブジェクト)を読めば数値を取り出すことができる。
文字列表現を数値に自動変換してくれるのである。
istringstream input_istring(format_message.str());
string dump;
input_istring >> dump >> val1 >> dump >> val2; 」
て書いてありました。
input_istring の内容構成について知っていなければならない条件付きですけど。
ちなみにヘッダは sstream です。
No.6
- 回答日時:
>#5さん
>※ "整数だけを取り出す"問題
1桁限定ならば、OKですね。
2桁以上の数値を取り出すことがあるならば、別の手立てが必要になりそうです。
まあ、そういう仕様があるかどうかは質問者さんしだいですけれど…。
No.5
- 回答日時:
C言語で単純に書いてみました。
#include <stdio.h>
#include <stdlib.h>
int main( void )
{
char str[] = "(1,1,4,4,2,3,2,3)";
char *test;
for (test=str; '\0' != (*test); test ++ ) {
if ( ( *test >= '0' ) && ( *test <= '9' ) ) {
printf("%c", *test );
} else {
printf("%c", ' ' );
}
}
printf( "\n" );
}
数値のみを取り出したいという事で、目的をそのまま書きました。
入力値が"(1,1,4,4,2,3,2,3)"ではなく"#(1,1,4,4,2,3,2,3)"や"[1,1,4,4,2,3,2,3]","($1,&1#4!4,%2,=3,A2,BC3)"でも動作します。
※ "整数だけを取り出す"問題でtokenが"(,"と固定されている問題ではなかったと感じましたので。
数字の確認部分、isdigit() 使っても良いし、符号("+-")や小数点(".")等も数値同様出力する様する事も可能です。
No.4
- 回答日時:
strtok()関数は文字列を破壊してしまうので複製を作りますが…
「複製を作らなければならない」のなら、デリミタを統一した複製を
初めに作ってしまおうというコードです。
---
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NUMERIC "-0123456789"
#define DELIMIT ","
int main( void )
{
char *string = "(1,1,(4,4),2,3,2,3),[-5,10],{20,-40}";
char *token, *delimit = DELIMIT;
char *str;
int i;
if (str=(char *)malloc(strlen(string)+1)) {
strcpy(str,string);
for (i=0;*(str+i)!=0;i++)
if (!strchr(NUMERIC,*(str+i))) *(str+i)=*delimit;
token = strtok(str, delimit);
while (token) {
printf("%d\n", atoi(token));
token = strtok(NULL, delimit);
}
free(str);
}
return 0;
}
---
但し、このコードは「123-123」という「-」で繋がっている場合の考慮を
していません。よって「この形が出現しない」という前提でしか使えません。
この点を踏まえた上で参考にして下さい。
No.3
- 回答日時:
こんな感じでどうですか?
char *s = "(1,1,4,4,2,3,2,3)";
while (*s != '\0')
{
char *ss = strpbrk(s, "+-0123456789");
if (ss == NULL) break;
s = ss;
errno = 0;
long value = strtol(s, &s, 10);
if (errno != 0) perror("error");
else printf("%ld\n", value);
}
No.2
- 回答日時:
C++言語で実装してみました。
・()が複数あっても正しく動作する
ex (0,1), (1,2)
オーバーフロー対策
(符号付き)整数に収まらない場合は処理しない
上に述べた事は”仕様"の問題で色々あると思います。
絶対に()は一組しか存在しないとか
オーバーフロー時はエラーを表示するとか
今回の場合
strtoken()でももちろん実装できますし、
その方がスマートでもあるのですが、
ちょっとした弱点も抱え込むと考えます。
それは、"融通がきかない"ということです。
()の他に{}でくくられている場合もある
さらに、[]もあることがわかった
....
その度にプログラムに修正を入れなければなりません。
デリミタ(区切り文字)をプログラムに埋め込む(ハードコーディング)
でなく、設定ファイル等から読み込ませることにすれば
かなり融通が利くようになりますが、
高々整数を取り出すのに、
その他の文字として何が使われいるか
調査しなければいけないのもつらいです。
整数なのだから
数字, 符号からなり
それ以外は区切り文字にしてしまう方が扱い易いと思います。
それでは、ソースを載せます
====== ここから ソース ==========================================
// StringTest.cpp : コンソール アプリケーションのエントリ ポイントを定義します。
//
#include "stdafx.h"
#include <string>// 文字列処理にC++標準のStringクラスを用います
#include <list>// 結果データ格納用
#include <errno.h>
#include <iostream>
using namespace std;
// 文字が"整数"構成文字かチェックします
static bool IsIntegerChar(char c)
{
if (isdigit(c))
return true;
else if (c == '+' || c == '-')
return true;
else
return false;
}
int main(int argc, char* argv[])
{
// 元々の文字列です
const char src[] = "(0, 1),(+2147483647, -2147483648, 2147483648, -2147483646)";
string s;// "整数"の候補格納用
list<int> tbl;// 結果の
// 文字列を先頭から最後までサーチします
for (const char* p = src; *p != '\0'; p++)
{
// 取り扱うのが整数のみなので
// 文字としては数字及び+,-の符号のみが許されます。
char c = *p;
if (IsIntegerChar(c))
{
// 整数の候補を検出しました
// まだ候補でしかないので保存しておきます
s += c;
}
else
{
// 整数を表しえない文字です
// 整数候補文字列の開始前か終了後です
if (!s.empty())
{
// 整数候補文字列の終わりです
// 整数かどうかチェックを行います
int n = atoi(s.c_str());
if (errno != ERANGE)
{
// 整数として変換できました
// 後でまとめて表示するため
// リストに格納します
tbl.push_back(n);
}
// 新たな整数候補を探すため
// 格納域をクリアします
s.clear();
}
}
}
// 文字列全体のサーチが終了しました
// 整数を表示します
for(list<int>::iterator it = tbl.begin(); it != tbl.end(); ++it)
{
cout << *it << endl;
}
return 0;
}
======= ここまでソース =============================================
なお、この種の問題
(文字列を文字のパターンで区切ったり、パターンに該当する部分文字列を
検索したりする)
は古くから研究されていて、ライブラリも多くあります。
正規表現
もその一つです
正規表現をサポートしたライブラリはたくさんありますので
探してみてください
日本語にきちんと対応した
(ex Shift-JISでも"表"という文字と'\'を混乱しない)
ものもたくさんあります
この回答へのお礼
お礼日時:2009/04/11 14:59
C++で実装しているため非常に助かります。
おっしゃる通り、strtokを使うやり方では確かに融通が利かないところもありますね。
この方法でも試してみようと思います。ついでに正規表現についても調べてみます。
どうもありがとうございました。
No.1
- 回答日時:
C言語での一例です。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main( void )
{
char str[] = "(1,1,4,4,2,3,2,3)";
char *token, *dlm = "(,";
token = strtok(str, dlm);
while (token) {
printf("%d\n", atoi(token));
token = strtok(NULL, dlm);
}
return 0;
}
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- その他(プログラミング・Web制作) プログラミング pythonの問題について 2 2022/04/19 00:41
- Java Java 南京錠 2 2023/02/04 11:46
- その他(プログラミング・Web制作) プログラミング python pandas 固定長データの出力 2 2022/08/16 11:22
- Excel(エクセル) Excelの文字列を数字に変換する方法について 6 2023/07/31 21:18
- Excel(エクセル) エクセル関数の変わった使い方 3 2022/05/13 17:12
- Excel(エクセル) エクセルでセルに何らかの文字が入力されたらそれを任意の数値として認識させる方法がしりたいです。 3 2023/03/16 20:19
- Excel(エクセル) エクセルのマイナス表示 3 2022/03/28 16:35
- Excel(エクセル) エクセルの数式で教えてください。 1 2023/06/15 14:11
- Excel(エクセル) 【Excel】複数列ごとに取得するセルを変更したい 2 2023/03/23 21:04
- Excel(エクセル) Excelにの以下の設定方法について教えてください! C列にデータ入力の設定をしています。(出、入を 3 2022/06/22 01:33
このQ&Aを見た人はこんなQ&Aも見ています
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
fgetsなどのときのstdinのバッ...
-
charでの計算?
-
atoi( ) の反対をやりたい
-
テキストデータをそのままバイ...
-
下記のプログラムがコンパイラ...
-
_TCHAR*での引数の読み込み
-
C言語のfor文です。 繰り返しの...
-
str系関数を使わずに二つの文字...
-
至急!C言語文字列置換
-
C言語の入力した文字を反転させ...
-
型変換
-
charからLPTSTRへの変換方法
-
strlen関数と同じ働きをする関...
-
'const char *' 型は 'char *' ...
-
C言語 ミリ秒を日付に変換には
-
文字列から空白を取り除きたい...
-
C言語 共用体について コマンド...
-
C言語 文字列操作
-
c言語プログラミング実行時エラ...
-
間接参照のレベルが異なっています
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
charからLPTSTRへの変換方法
-
charでの計算?
-
配列をnビットシフトする
-
'const char *' 型は 'char *' ...
-
型変換
-
テキストデータをそのままバイ...
-
文字列から空白を取り除きたい...
-
CStringをwchar_tに変換したい
-
絶対パスからのファイル名の切...
-
fgetsなどのときのstdinのバッ...
-
ネットワークにつながっている...
-
str系関数を使わずに二つの文字...
-
3桁区切(コンマ)記号をつけ...
-
atoi( ) の反対をやりたい
-
double型の値をchar配列に変換...
-
C言語のfor文です。 繰り返しの...
-
switch文で文字を比較すること...
-
ファイル名である文字列からbas...
-
c++ 文字列を入力して、一文字...
-
strncpyと_tcsncpy_sのヌルの扱...
おすすめ情報