C ++で文字列から非整数を削除する
-
03-07-2019 - |
質問
私の本には、コンマを整数に入力してプログラムを台無しにする人々についてのコメントがありましたが、詳細は説明していませんでした。それが私に考えさせられたので、私はstd :: stringを取り、すべての非整数文字を削除する小さなアルゴリズムを書いてみました。このコードはコンパイルされますが、出力はスキップされます。 newstringに何も割り当てられないのはなぜですか? if(isdigit(fstring [i]))は、数字を保持するために指しているアドレスのtrueと評価しますか?
//little algorithm to take the non-integers out of a string
//no idea on efficiency
#include <iostream>
#include <string>
int main()
{
std::cout << "Enter a number with non-integer characters: ";
std::string fstring;
getline(std::cin, fstring);
std::string newstring;
int i = 0, x = 0;
while (i != fstring.length())
{
if (isdigit(fstring[i]))
{
newstring[x] = fstring[i];
i++;
x++;
}
else
{
i++;
}
}
std::cout << std::endl;
std::cout << newstring;
system("PAUSE");
}
二次的な質問、おそらく他の場所に属している:文字列をどのようにint(または浮動小数点数)に変換しますか?
解決
newstringの長さは0であるため、x = 0のnewstring [x]は実際には不正です。 newstring.append(1、fstring [i])
を使用して文字列に追加する必要があります2番目の質問については、atoi()、atof()、strtol(0、strtof()関数を探してください。
他のヒント
文字列は配列に似ていますが、文字列のデフォルトコンストラクターは空の文字列を作成します。必要以上のメモリを割り当てる必要があるのはなぜですか?たとえそれがあったとしても、それがいくらであるか、またはfstringのフィルターされたコピーに対して十分な大きさであるかどうかは言うまでもありません。クラッシュしないことに感心しました。
簡単な変更は変更することです:
std::string newstring;
to:
std::string newstring(fstring.length(), '\0')
そしてループの追加後:
newstring.resize(x);
これにより、newstring
がフィルター処理中に少なくとも十分な(おそらくそれ以上の)スペースを確保し、フィルター処理が終了すると適切なサイズにトリミングされます。 std::remove_copy_if
の <algorithm>
関数にも興味があるかもしれません。
E.g。
struct isnotdigit { bool operator()(char c) { return !isdigit(c); } };
std::string newstring(fstring.length(), '\0');
std::string::iterator i = std::remove_copy_if(fstring.begin(),
fstring.end(), newstring.begin(), isnotdigit());
newstring.erase(i, newstring.end());
すでに説明したatoi
、strtol
、atof
、strtof
などの関数に加えて、文字列を整数/浮動小数点数に変換するために、iostreamライブラリを使用することもできます。
#include <sstream>
std::string integer("23");
std::istringstream iss(integer);
int result;
iss >> result;
std::string floatingpoint("3.14");
std::istringstream iss2(floatingpoint);
double result2;
iss2 >> result2;
また、printfファミリの関数に精通している場合は、scanf
、sscanf
const char *s = "23";
int result;
sscanf(s, "%d", &result);
Shing Yipの回答の拡大:
数字以外を削除するには:
#include <iostream>
#include <functional>
#include <string>
#include <algorithm>
using namespace std;
int main() {
string fstring;
getline(cin, fstring);
fstring.erase(
remove_if(fstring.begin(), fstring.end(),
not1(ptr_fun(static_cast<int(*)(int)>(isdigit)))
),
fstring.end()
);
cout << fstring << "\n";
}
しかし、そのstatic_castが必要な理由はわかりません。私はそれなしでisdigitについて何かが曖昧だと思います。 [編集:<!> quot; using namespace std <!> quot;必要ないので、サンプルコードを書くのが面倒なのは私のせいです。]
これが独自のループをローリングするよりも簡単かどうかは議論の余地があります:
#include <iostream>
#include <string>
using namespace std;
int main() {
string fstring, ins;
getline(cin, ins);
for (string::iterator it = ins.begin(); it != ins.end(); ++it) {
if (isdigit(*it)) fstring.push_back(*it);
}
cout << fstring << "\n";
}
C ++ 0xにはcopy_ifがありますが、これは基本的に偶然に除外されたもので、実装するのは簡単です:
#include <iostream>
#include <string>
#include <algorithm>
#include <iterator>
int main() {
std::string fstring, ins;
std::getline(std::cin, ins);
std::copy_if(ins.begin(), ins.end(),
std::back_inserter(fstring), isdigit);
std::cout << fstring << "\n";
}
int(またはfloat)に変換するには:
int i = boost::lexical_cast<int>(fstring);
またはブーストがない場合:
#include <sstream>
int i = 0;
std::stringstream(fstring) >> i;
iを初期化する必要があることに注意してください。そうしないと、fstringが空の場合は設定されません。
数字を削除するには:
fstring.erase(
std::remove_if(fstring.begin(), fstring.end(), &isdigit),
fstring.end());
文字列をint / float / ...に変換するには:
int n1 = boost::lexical_cast<int>("123");
float n2 = boost::lexical_cast<float>("123.456");
- 浮動小数点数への文字列:
#include <cstdlib>
float strtof(const char *nptr, char **endptr);
例:
float f = strtof("3.4",NULL);
- 文字列から整数
<=>
する必要がありますint atoi(const char *numPtr);
これらはC ++関数ではなくC関数であるため、std :: stringでc_str()メソッドを使用してC文字列を取得する必要があることに注意してください。
const char* c_str ( ) const;