2011-11-10 3 views
2

にスペースを入れずに、アレイをcharに、私は、charの配列を持っており、ここにある:char pIPAddress[20]; そして私は、このコードを持つ文字列からこの配列に設定しています:strcpy(pIPAddress,pString.c_str());変換文字列が私のコードでは、C++

このロードした後に、たとえば、pIPAddressの値は "192.168.1.123"です。しかし、私はスペースを必要としません。スペースを削除する必要があります。このため私はこれをしたpIPAddress[13]=0;

しかし、IPの長さのチャンスがあれば、動作しません。どのように私はスペース効率的な方法を計算することができますか?または他の方法?

のthnx

答えて

5

最も簡単な方法は、std::remove_copyアルゴリズムを使用することですあなたはすべてのスペースだけでなく' '文字を削除する場合ではなく、ジェームズの提案を1として

...ポインタを取得するためにc_str()を使用し、その後EDITを文字列からスペースを削除して、あなたはを使用することができますファンクタを使って10。私は直接<locale>ヘッダからstd::isspaceを渡してテストして、動作しているようですが、私は、これは(負であるかもしれない)非ASCII文字で問題になることはないだろうことを確認していない:

#include <locale> 
#include <algorithm> 
int main() { 
    std::string s = get_ip_address(); 
    char ip[20]; 
    *std::remove_copy_if(s.begin(), s.end(), ip, (int (*)(int))std::isspace) = 0; // [1] 
} 

恐ろしい最後の引数にキャストすると、特定のオーバーロードを選択する必要があります。isspace

[1]文字列のNUL終了を確実にするために、*... = 0;を追加する必要があります。 remove_copyおよびremove_copy_ifアルゴリズムは、出力シーケンス(つまり、最後の要素を超えたもの)のイテレータをendに返します。*...=0は、NULを書き込むイテレータを参照していません。あるいは、アルゴリズムchar ip[20] = {};を呼び出す前に配列を初期化することはできますが、文字列の末尾だけでなく、配列内のすべての20文字に\0を書き込むことになります。

+3

もう少し冗長ですが、' remove_copy_if'と標準からの 'isspace'関数の1つを使った' IsNotSpace'関数オブジェクトを使います。 (一般に、空白を取り除きたい場合、空白文字だけでなく空白文字も意味します。) –

+0

@JamesKanze:良い点。 –

+0

あなたの例で@DavidRodríguez – yasin

-1

すべてのケースで解決策を動作させるために、私はあなたの文字列を反復処理を提案し、あなたはそれに対処するスペースを見つけたとき。

より高度な解決策は、自動的に行うことができる文字列メソッドを使用することです。 (参照:http://www.cplusplus.com/reference/string/string/

-1

を、私はあなたが

のstrcpy(pIPAddress、pString.c_str())

を使用しているならば、何も(c_strとして、行われる必要はありませんと思います)*文字を返します。ヌル終了文字列に変換します。したがって、上記の操作を行った後、char配列 'pIPAddress'自体がnullで終了します。あなたが言ったように長さを調整するために何もする必要はありません。

+0

null終了!=スペース – duedl0r

+0

@ duedl0rしかし、彼の例では、彼はpIPAddress [13] = 0について話しました。つまり、彼は実際には空白ではなくヌル終了について話しています。 –

+0

彼はスペースを削除したいので、最初のスペースをヌルに設定します。それは、文字列からの終わりのヌルではありません。 – duedl0r

0

std::stringがあります。

std::string tmp = pString; 
for(std::string::iterator iter = tmp.begin(); iter != tmp.end(); ++iter) 
    while(iter != tmp.end() && *iter == ' ') iter = tmp.erase(iter); 

その後、あなたはchar型の配列にtmpの内容をコピーすることができます:あなたはerase()メソッドを使用することができます。 char配列はC++では完全に非推奨であることに注意してください。絶対にする必要がある場合を除き、char配列は使用しないでください。どちらの方法でも、std::stringを使用してすべての文字列操作を行う必要があります。スペースだけで、あなたの文字列の末尾(または開始)である場合は、handcodeしたい場合は

+0

このコードは未定義の動作です。イテレータを削除した後は、それを使用することはできません(特に、ループの次のパスではインクリメントできません)。さらに、たとえそれがUBでなくても、2つの連続する空白を取り除くことができないので、それでも不正確になります(つまり、最初のものが削除され、2番目のものがその位置をとり、イテレータが1つの位置第2の空間の新しい位置の後)。 –

+0

良い点、私は編集します。 – slaphappy

+0

'(iterator it = tmp.begin(); it!= tmp.end();){if(* it == '')it = tmp.erase(it);これは簡単です。それ以外は++ it; } 'ネストされたループの必要性を避けます(どちらも同じ制御変数を更新します)。そしてもう一度、 'std :: remove_copy'を最初に使用する方がいいです。' string tmp;コードの潜在的なバグを避けてください... –

0

、あなたは最高のboost::trim

#include <boost/algorithm/string/trim.hpp> 

std::string pString = ... 
boost::trim(pString); 
strcpy(pIPAddress,pString.c_str()); 

を使用すると思い、<cctype>locale specific versionを持つ関数isspaceを、持っています。これをしたいと思う理由、それは良いかもしれない配列にコピーしていないので、

std::string ip = read_ip_address(); 
char ipchr[20]; 
*std::remove_copy(ip.begin(), ip.end(), ipchr, ' ') = 0; // [1] 

次の質問は、次のようになります。あなたが行うことができます

+0

''は 'isspace'関数を持つことができません'char'の値が負である可能性があるので' char'で呼び出され、 ''にはスペースのテスト方法がいくつかあります。これらのメソッドはすべて 'std :: locale'オブジェクトまたは' std :: locale'オブジェクトを必要とします:: ctype'ファセット。 –

+0

その情報はすべて私が提供したリンクにありますが、あなたはこれを明示的に指摘するのは正しいです。しかし、彼の例と変数の両方の名前は、IPアドレスから 'boost :: trim'が私の意見では最善の解決策であるという後続のスペースを削除したいだけであることを示唆しています。だから私は 'isspace'をあまり強調したくありませんでした。 – Pieter

+1

私は理解しています。このような "シンプル"の場合、 'boost :: trim'や既に書かれている類似の関数がおそらく最も良い解決策です。まず最初に、 'isspace'を使用し、それを正しく使うでしょう:-) –

関連する問題