タイトルの付け方が下手でごめんなさい。
C++の入力処理で、回数を指定しない文字列の入力処理はどのように実装すればよいのでしょうか。例えば、
cpp
1int n; 2char str[10]; 3cin >> n; 4for(int i=0; i<n; i++){ 5 cin >> str[i]; 6}
のような処理では、範囲を決めてfor文を扱うことができますが、nの値が決まっていない文字列の入力の場合はどういったものを作ればよいのでしょう。nの入力がなく、改行が入るまでの範囲を文字列として扱いたいときなどです。stringを使えば解決できるのでしょうが、char配列として文字列を扱う場合についての回答をいただきたいです。
よろしくお願いします。
※追記
文章が足らず、申し訳ありません。
経緯としては、一行で与えられる文字列の中で特定の文字を数字に置き換えて出力する、という問題を解くにあたって、char配列を使おうと思いました。しかし、この問題では上記の例でいうnが与えられません。一行を読み取って一文字ずつ配列に格納する方法を知らなかったため、このような質問をさせていただきました。
そのため、「char配列縛り」というわけではなく、stringなどを用いて、結果として配列として処理ができるような方法を教えていただきたいのです。宜しくお願いします。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。

回答7件
0
ベストアンサー
単純にstring
で受けた後にchar配列を生成してはいかがでしょうか?
以下ではchar配列str
は通常の(\0終端)文字列として扱うようにしています。
C++
1#include <iostream> 2#include <cstring> 3int main() { 4 char *str(nullptr); 5 std::string s; 6 if( std::getline(std::cin,s)){ 7 str = new char[s.length()+1]; 8 strcpy( str, s.c_str()); 9 } 10 11 if( str){ 12 // 何らかの処理 13 std::cout << str << std::endl; 14 delete [] str; 15 } 16 return 0; 17}
追記を受けて。std::replace
を使えば楽ですね。
なお、以下コードでは複数個の文字を置換していますが、英字→数字など、置換元先の文字がかぶらない前提です。
複数個の任意の文字について置換する場合は、処理を見直す(一度置換した文字は再置換しないようにする)必要があります。
C++
1#include <iostream> 2#include <algorithm> 3int main() { 4 std::string s = "abcabcde"; 5 std::string rep("ac"), num("12"); // a->1, c->2 6 for( int i = 0; i < rep.length(); i++){ 7 std::replace(s.begin(), s.end(), rep[i], num[i]); 8 } 9 std::cout << s << std::endl; // 1b21b2de 10 return 0; 11}
上の回答だとアレなのでepisteme
さんの回答をパクリ参考に平易に書いてみました。
C++
1#include <iostream> 2#include <map> 3int main() { 4 std::string src("abcabcde"); 5 std::string repFrom("ac"), repTo("12"); // a->1, c->2 6 7 // 置換マップ作成 8 std::map<char,char> mRep; 9 for( int i = 0; i < repFrom.length(); i++){ 10 mRep[repFrom[i]] = repTo[i]; 11 } 12 13 // 置換 14 std::string dst; 15 for( int i = 0; i < src.length(); i++){ 16 char c(src[i]); 17 auto it = mRep.find(c); 18 if (it != mRep.end() ) { 19 c = it->second; 20 } 21 dst += c; 22 } 23 std::cout << dst << std::endl; // 1b21b2de 24 return 0; 25}
投稿2018/03/01 02:40
編集2018/03/01 08:35総合スコア38352
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/03/01 02:46
2018/03/01 03:09
2018/03/01 04:29
2018/03/01 05:05
2018/03/01 07:45

0
char配列として文字列を扱う場合
配列は固定長でないとならないので、ちょっとしたテクニックがいります。
Cならmalloc()とrealloc(),free()を組み合わせるんでしょうが・・・
下記サイトにクラスを使ったサンプルが有ります。
Resizing arrays
文字を格納するのに、最初に確保した領域に入りきれない場合、領域を倍々にしていく方法です。
このクラスに、char operatorでも追加すれば文字列として扱えると思います。
投稿2018/02/28 12:59
編集2018/02/28 13:03総合スコア6851
0
改行が入るまで
stringを使えば解決できるのでしょうが
あっさり解決しますから、使いましょう。
など
https://github.com/hoxnox/cro2sql/blob/master/src/freader.cpp#L88
こんな感じに頑張れば。こう考えるとget_unill
みたいな処理はRustのほうが簡単にかけるなぁ。
投稿2018/02/28 12:27
編集2018/02/28 12:29総合スコア5852
0
一行で与えられる文字列の中で特定の文字を数字に置き換えて出力する
まかしとき。
C++
1 2#include <iostream> 3#include <iterator> 4#include <map> 5#include <string> 6#include <algorithm> 7 8int main() { 9 using namespace std; 10 // 変換表 11 map<char,char> conv = { 12 { 'a', '0' }, // a を 0 に 13 { 'b', '1' }, // b を 1 に 14 { 'c', '2' }, // 以下同文 15 { 'd', '3' }, 16 { 'e', '4' }, 17 }; 18 string input = "apple cherry banana"; 19 string result; 20 transform(input.begin(), input.end(), 21 back_inserter(result), 22 [&](char ch) -> char { 23 auto i = conv.find(ch); 24 return ( i == conv.end() ) ? ch : i->second; 25 }); 26 cout << input << " -> " << result << endl; 27} 28 29/* 実行結果 30apple cherry banana -> 0ppl4 2h4rry 10n0n0 31*/
stringなどを用いて、結果として配列として処理ができるような...
stringはcharの配列とみなしていいよね? それとも char[] じゃなきゃ却下?
[追記] 変換対象はイッコだけ? だったらもっと簡単
C++
1#include <iostream> 2#include <string> 3#include <algorithm> 4 5int main() { 6 using namespace std; 7 string str = "apple cherry banana"; 8 replace(str.begin(), str.end(), 'a', '?'); 9 cout << str << endl; 10} 11 12/* 実行結果 13?pple cherry b?n?n? 14*/
投稿2018/03/01 03:38
編集2018/03/01 03:49総合スコア16612
0
一行で与えられる文字列の中で特定の文字を数字に置き換えて出力する
これなら std::stringで十分です。
私なら、特定の文字を 例えば 'a' だとして、その特定文字'a' をstd::string::findで検索する。
で、その位置をstd::string::replace ( std::string::substrだったか? ) で 書き換える。
これでやると思う。
[追記1]
確か、ネットでもリファレンスっていうの?関数辞典みたいなのがあったはず。
C言語版:
C言語関数辞典
C++版:
cpprefjp
あと一個あった気がしますが...
こういうのでそれぞれのクラスが持つメンバを確認したり、引数,戻り値を確認したりといろいろ調べてみてください。
投稿2018/03/01 03:17
編集2018/03/01 03:55総合スコア4962
0
シバリがキツい...vectorだけでも使わせてくださいぃ
C++
1#include <iostream> 2#include <iterator> 3#include <vector> 4#include <algorithm> 5 6int main() { 7 using namespace std; 8 vector<char> buffer; 9 const char delim = '\n'; 10 cout << "enter CR-terminated string :" << flush; 11 12 istreambuf_iterator<char> first(cin), last; 13 find_if(first, last, 14 [&](char ch) { 15 bool eol = ch == '\n'; 16 buffer.push_back(eol ? '\0':ch); 17 return eol; 18 }); 19 const char* result = buffer.data(); 20 21 cout << '[' << result << ']' << endl; 22} 23 24/* 実行結果 25enter CR-terminated string :hogehoge payopayo 26[hogehoge payopayo] 27*/
投稿2018/03/01 01:18
総合スコア16612
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
先の回答者がおられるので別の視点から。
一応、ソフトウェア上は「無限」とか「可変」といった概念を扱うことができるとされています。が、当然ですけれど、ハードウェア上の制約がある以上、無限のメモリを確保することは現実には不可能です。
どこまでいっても、イレギュラーな運用をするユーザがおられますので、あまり「無限」のものを使うというのは望ましくはありません。バグとかセキュリティホールになります。ルールを取り決めたうえで、有限の資源の中で処理をするということも必要になります。
投稿2018/02/28 13:23
総合スコア4853
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。