文字の置換の仕方

[戻る]
としや 2009/05/27(水) 04:08:41
/*入力した文字列で!があったらすべて!?に置換するプログラムを作っています。
insertを使いたいのですが、うまくいかなくて困っています。
insert以外の部分はちゃんんとできていると思います。
c++を勉強し始めたばかりでよくわかっていませんので、ご教授お願いします。
*/

#include<iostream>
#include<string>
#include<cstdlib>
using namespace std;

int main(void) {

    string a,s;

    cout <<"文字列を入力してください"<<endl;
    getline(cin,s);

    int i,j=0;

    while( j!= s.npos) {
        i=s.find_first_of("!",j);

        if(i==s.npos){
 
            cout << s.substr(j) << endl; 
            break;
        }
        if( i>0) {
            cout << s.substr(j, i-j);
            j=i;
        }
        
        i=s.find_first_not_of("!",j); 

        if( i== s.npos) {
            a=s.substr(j);
            j=i;
        }
        else{
            a=s.substr(j,i-j);
            j=i;
        }
        cout<< s.insert(a.c_str(),"!?")<<endl;    
    }    return 0;
}

tetrapod 2009/05/27(水) 08:53:19
std::basic_string (std::sting) には replace というメンバーがあるし
std::replace っつ関数もあるわけだが(こっちは語長が変わる目的には使いづらい)

目的が「置換したい」のであれば自作せず素直に replace
目的が「自作したい」「insert が使いたい」のであればそう言ってくれ

Ban 2009/05/27(水) 09:12:33
とりあえず、replaceではなくて?

Ban 2009/05/27(水) 09:12:50
とりあえず、std::string::replaceではなくて?

Ban 2009/05/27(水) 09:13:27
# 書き込みミスった上に、内容かぶりました…すみませんorz

としや 2009/05/27(水) 14:25:37
replaceは使わずにinsertで自分で作りたいです。

ryo 2009/05/27(水) 14:34:11
では、うまくいかないとはどういう状態になってるのか?を説明して

Blue 2009/05/27(水) 14:39:19
テケトー

#include <iostream>
#include <string>

int main()
{
    std::string input;
    std::cout << "文字列を入力してください" << std::endl;
    std::getline(std::cin, input);

    std::string::size_type index = 0;
    while (index != std::string::npos)
    {
        index = input.find_first_of("!", index);
        if (index != std::string::npos)
        {
            ++index;
            input.insert(index, "?");
        }
    }
    std::cout << input.c_str() << std::endl;

    return 0;
}

としや 2009/05/27(水) 15:31:07
>>ryo

今は、コンパイルは通って表示できるのですが、?を表示するときにループを抜け切れ
てなく、出力が止まらない状態です。

#include<iostream>
#include<string>
#include<cstdlib>
using namespace std;

int main(void) {

    string a,s;

    cout <<"文字列を入力してください"<<endl;
    getline(cin,s);

    int i,j=0;

    while( j!= s.npos) {
        i=s.find_first_of("!",j);

        if(i==s.npos){
 
            cout << s.substr(j) << endl; 
            break;
        }
        if( i>0) {
            cout << s.substr(j, i-j);
            j=i;
            
        }            
        s.insert(i,"?");    
        cout<<s.c_str()<<endl;
    }    
    
        return 0;
}

tetrapod 2009/05/27(水) 16:36:32
今回の要望に対しては find_first_of より find のほうが適切。
find : 与えられたオペランドシーケンスに一致する位置
find_first_of : 与えられたオペランドの要素のどれかに一致する位置

で、なにか難しく考えすぎなような気がする。
・文字列の終わりまでループする
・ ! をみつけたら、その直後に ? を挿入する
だけでいいわけで npos との判定を何度も行ったり substr 取ったりする必要はない。

挿入文字が1文字であり、挿入前文字と同じ文字を含まない前提で単純化したら
int main() {
  string s("WoW!! This!is a Text!");
  for (string::size_type p=0; (p=s.find('!', p))!=string::npos;) {
    ++p;
    s.insert(p, "?");
    ++p;
  }
  cout << s << endl;
  return 0;
}
挿入文字数が1文字より多い場合などは宿題にしておこう。

ryo 2009/05/27(水) 20:31:26
自作したいというので、質問者さんのソースについて

無限ループになってるのは

>i=s.find_first_of("!",j);
ここでみつけた!の位置そのままに?を挿入してるためです。
たとえば

t!t

この例から、!を見つけた場所に挿入すると文字列は

t?!t

となります。

次に
 j=i;
をしてから、j(=i)の位置から検索するということは
?を挿入したところから検索するということなので、
右にずれた「!」を再度検索することになります。

以降、これがずーっと繰り返されてしまいます。

ですので、
「見つけた場所」から「挿入すべき場所」に変えないといけません

multi 2009/05/28(木) 09:59:16
http://oshiete1.goo.ne.jp/qa4990874.html

>発言される前に「使用上の注意」を必ずお読み下さい。
> マルチポストとは、「同じ内容の質問などを複数の掲示板等に書き込むこと」です。
この行為は
> マナー違反として嫌われています。マルチポストは行わないで下さい。

古いスレッドには追加発言できません。