【初心者歓迎】C/C++室 Ver.100【環境依存OK】 [無断転載禁止]©2ch.net
■ このスレッドは過去ログ倉庫に格納されています
エスケープシーケンスやWin32APIなどの環境依存なものでもOK。 ただしその場合、質問者は必ず環境を書きましょう。 ◆ソースのインデントについて 半角空白やTABでのインデントはスレに貼ると無くなります。 そのため、アップローダーに上げるのも手ですが直接貼る場合は、 全角空白か に置換すると見栄えだけはよくなります。 【アップローダー】(質問が長い時はココ使うと便利) http://codepad.org/ (コンパイルもできるし出力結果も得られる[]privateをチェック) http://ideone.com/ (時間帯によってはcodepadが重い事があるのでここも利用) 前スレ 【初心者歓迎】C/C++室 Ver.99【環境依存OK】 http://echo.2ch.net/test/read.cgi/tech/1469177649/ >>2 訂正しときます 次スレの>>3-100 0が射精魔 前スレ>>999 再掲 class A{ int a[2]; A(int b[]) :a(b) //error {} }; この:a(b)ってなにか書き方ありますか? 前スレ>>100 0 無理でした・・・ 引数の int b[] って int* b と同じやしなぁ C++11以降なら A(int (&b)[2]) : a{b[0], b[1]} {} >>4 C++11以降ならstd::initializer_listが使える #include <iostream> #include <initializer_list> #include <algorithm> class A { int a[6]; public: A(std::initializer_list<int> b) { std::copy(std::begin(b), std::end(b), a); } void print() const { for (int i : a) std::cout << i << std::endl; } }; int main() { A a({10, 4, 2, 8, 5, 66}); a.print(); } >>12 それinitializer_listに6っこ以上与えたら実行時のアクセス違反になる >>4 C++11以降ならstd::array使うべき そうすれば普通に書ける class A{ std::array<int,2> a; public: A(const std::array<int,2> &b):a(b) { } }; >>13 いやいくらでも動的に増やせるんだけど初心者スレだから省略した http://ideone.com/ryEwkt 要求は固定長の配列であって、動的に増やせるようにしろとは言ってないので それのコードは非効率にしかならないと思うよ >>11 ん? int b[2][3];をわたせんの? func(int a[][3]);以外で >>16 だからvector使ってないでしょう unique_ptrのパフォーマンス知らないの? ID:hOJqMng1 の主張の変遷 1.わざと大きい初期化子を与えると実行時にアクセス違反になると主張 →だから動的に対応できるようにした 2.すると今度は非効率的だからarrayを使えという →arrayが特に効率的なわけではないし、今度は「要求は固定長の配列だ」と言い出す どう考えても言ってることがコロコロ変わってるんだが A() : a{b[0], b[1]} {}がダメだった人にC++11を押しつけてどーすんだ >>12 に至ってはもとの質問と全然関係ねーし VC++で、マウスオーバーで色が少し変わって、クリックしたら沈んだみたいになる画像ボタンを作るにはどうしたらいいですか? >>19 まず効率は動的確保を行うnewとunique_ptrより確実にarrayのほうがいい そして>>4 の要求はコードから明らかに固定長でいいと言ってる これは私の勝手な主張ではなく元の要求がそうなってる 目的を達成するために非効率な動的確保は必要ない 私はアクセス違反になるといったが動的確保にしろとは言っておらず、動的確保にしたのはそっちが勝手にやったこと アクセス違反を回避するために動的確保にするのは全く割に合わない だったら長さチェックすればいいだけ >>21 で結論でてるじゃねえか C+11を押し付けてる時点でおまえら全員ダメだ! >アクセス違反を回避するために動的確保にするのは全く割に合わない こう書かれるべきものが >>16 で >それのコードは非効率にしかならないと思うよ と書かれたため>>19 が射精した 特に「非効率にしかならない」の「にしか」という表現が前後の繋がりを考えると最悪だ using std; int main() { int a; cout<< "数を入力してください" <<endl; cin>> a; cout<<a <<"ですね?" <<endl; } aを確実に入力させたくて困っています ご教授ねがいます まず確実ってなんやねん 数以外だったり未入力は弾くってか そうです 未入力で無限ループみたいに表示されて困っています >>28 http://ideone.com/dpolU5 一応単なる改行や数字で始まらない文字列は弾くようにした ただしコメントにも書いてあるけど 123def みたいな数字で始まる文字列を 入力したときは数字だけ返すんでそれが駄目なら自前で作るしかないね >>32 getline知りませんでしたが何とかできそうです ありがとうございます 独習C第4版 P197ページの再帰のプログラムなのですが、 #include <stdio.h> void recurse(int i); int main(void) { recurse(0); return 0; } void recurse(int i) { if(i < 10) { recurse(i + 1); printf("%d " , i); } } 実行結果は 9 8 7 6 5 4 3 2 1 0 の動作がわかりません。10になるまでprintfが実行されずに+1され続けるのはいいのですが、 なぜ10になったらiが戻り始めるのでしょうか? あまりに初心者な質問ですみません。 引数だけ書くと 0+1 1+1 ・・・ 9+1 ここまではprintfまで来ないまま再帰 9+1でifに入らないからrecurseからリターン printfがiを表示(9)してリターン printfがiを表示(8)してリターン の繰り返し >>35 早速のレスありがとうございます。 >9+1でifに入らないからrecurseからリターン ということはmain関数のreturn 0でプログラムは終了してしまうのではないですか? なぜprintfが呼ばれるのかわからんのですが。(iが減算される理由もわかりません) if(i < 10) { recurse(i + 1); printf("%d " , i); } で recurseとprintfは同じifブロックに入っているので、ifが偽なら両方共スキップされると思うのですが、 なぜprintfだけ呼ばれるのでしょうか? 丁度再帰打ち切り付近の挙動 i=8 で受けた recurse recurse(8+1) の呼び出し i=9 で受けた recurse recurse(9+1) の呼び出し i=10 で受けた recurse 条件合致せず戻る printf("%d", i) で 引数の 9 を書く i=9 で受けた recurse から戻る printf("%d", i) で 引数の 8 を書く i=8 で受けた recurse から戻る >>37 9+1で入って偽で抜けたら 8+1で入ってきたif内のrecurseから抜けて次のprintfが実行されて抜ける 8+1で抜けたら7+1で入ってきたif内のrecurseから抜けて次のprintfが実行される の繰り返し >>35-39 さん どうも再帰関数とforループがごっちゃになっていたようです。 何となくわかりました。 後は自分で考えてみます。 どうもありがとうございました。 再帰呼び出し後に書く recurse(i+1); printf("%d ", i); と 書いてから再帰呼び出し printf("%d ", i); recurse(i+1); の違いとか 呼び出しの出入りを整理する printf("in:%d\n", i); recurse(i+1); printf("out:%d\n", i); と見えてくると思うよ なんか遠回りな説明ばかりだな スタックフレームというキーワードを出してやれよ >>41 >再帰呼び出し後に書く recurse(i+1); printf("%d ", i); >と >書いてから再帰呼び出し printf("%d ", i); recurse(i+1); >の違いとか これはこの本の次のページにも書いてありました。 書いてから再帰呼び出しの場合は昇順(1,2,3,4,5,6~)になりますね。 相変わらず曖昧な理解なんですが、 どのiの場合もi=10に達するまではrecurse(i+9)までしか実行されていなくて、 printfは実行されていない待機中の状態だと考えればいいのでしょうか? それでi=10でif条件文を抜けて、i=9からi=0まで数字が大きい方から順番にまだ実行していなかった printfを降順で実行していくのでしょうか? この本(独習C)には > 引数の値が10に達すると、recurse()の再帰呼び出しから戻りはじめます。関数は、呼び出し元に戻る >ものなので、recurse()は直前の呼び出し元に戻り、そこでprinf()を文を実行して「9」と表示し、 >さらに前の呼び出し元に戻ります。こうしてrecurse()は、今度は「8」と表示します。 その後も同じ>プロセスが繰り返され、すべての呼び出しから戻った段階でプログラムが終了します。 実行される順番が、最初のi=0からではなく、直近のi=9からなのはなぜなのでしょうか? 再帰でどう動いてるか理解するのに スタックフレーム出されても困らないか? 値の保持の実装でそうなってるってだけだし この手の人は、具体的な実装例を見さえすれば、すぐさま疑問が解消されるんだよ >>43 でも「待機する」だとか なんで逆順になるのか分からないとか 言っているが スタックフレームさえ知れば全ての疑問は解決だし C/C++するのにスタックフレームさえ知らない状態だと このさき困難だろう 待機する、って言い方を見るに、何かキューのような物を連想しているようだし 実際、なんで逆順になるか分からないと発言しているわけだが 答えは関数呼び出しはキューではなくスタックだから、と言う他ない キューやスタックという言葉の意味が分からなかったとしても どのみちこれらも覚える必要のある最も基本的な事の一つだから 合わせて覚えればよいだろう コンピュータの基本動作もよくわからないままプログラムを書くということは 多言語ではあり得るのかもしれんが、とりわけここはC/C++スレだからね いや、俺は別に何も説明するつもりはないよ ただ、スタックフレームというキーワードをだね そうすれば後は本人が検索するなりなんなり、勝手に調べるだろう キーワードが分からなきゃ検索も出来ないから、キーワードを出してやれという話 スタックを知らずして再起呼び出しの動作を理解するのは非常に困難というか 質問者は関数呼び出しがキューのようなものであると考えている可能性が高いようだけど 実際にはスタック動作だよ、と ここを勘違いしていたら、答えにたどりつかないかなぁと スタックフレームで検索して見たところ、 ttp://brain.cc.kogakuin.ac.jp/~kanamaru/lecture/MP/final/part06/node9.html このページが一番わかりやすそうです。 LIFOなんで新しい関数と引数が上の方に積み上がっていくと考えれば良いのでしょうか? first outなんで実効は新しい順(つまり今回の例の場合はi=9)ということですね。 スタックフレームという言葉で検索したらおもしろそうなサイトがたくさん出てきました。 皆さん今回はありがとうございました。 >>43 まず大前提としてプログラムの流れは1本道で別れたりしないし、待機みたいなことも普通しない そして再帰関数という特別な関数があるわけではない、recurseは普通の関数と何も変わらない void recurse(int i) { if(i < 10) { recurse(i + 1); printf("%d " , i); } } この4行目はrecurseという関数を呼び出している つまり自分自身を呼ぶのでこの4行目の呼び出し後、recurse関数の最初に戻る ただし引数iは1大きい値で呼ぶ これを入れ子のように10回繰り返すことになる >>51 レスありがとうございます。 ttps://ipa-zone.info/page-2644/ このページに私が使っている独習Cの再帰の部分が丸ごと転載されているんですが(違法?)、 i=0~10と昇順で増加していく前半部分でも呼び出された関数(recurse(1)など)は終了した訳ではないですよね? 後半のi=10から降順で減少していくときにはじめてprintfが実行されて関数が終了すると思うんですが、 LIFOなんで最後に呼び出されたrecurse(9)からrecurese(0)まで降順で残ったprintfを実行していくということではないんですか? >実行は新しい順(つまり今回の例の場合はi=9)ということですね。 難しく考える必要は無い 関数を呼び出すとき、自分が今何をしていたかをそっくりそのまま保存した状態で 新たにスタックを確保して、呼び出した関数を実行する 関数の実行が終わると、使っていたスタックを開放して 呼び出される前に実行していた処理に復帰する ちょうど君が 1)ビデオを見ていた時に電話がかかってきたら、ビデオを一時停止して電話に出る 2)電話が終わると、ビデオを再生して続きを見る のと同じで、ビデオの一時停止機能がスタックに相当している で、君がこの日のことを日記を書くとき 1)のことを重視すれば、ビデオ→電話、って順になるし 2)のことを重視すれば、電話→ビデオ、って順になる 実際にはビデオ→電話→ビデオ、という順で物事は流れているんだが どこのタイミングを切り取ってくるかで順番が変わるのだ 下から順番に1,2,3,4,5と積み上げて、上から順番に5,4,3,2,1と取り出すとき 積み上げるとき(積み上げる前)に出力すると1,2,3,4,5だし 取り出すとき(取り出した後)に出力すると5,4,3,2,1になる 実際には1,2,3,4,5,4,3,2,1という順で処理は走っているが(積み上げる→取り出す) 前半に着目すれば1,2,3,4,5だし、後半に着目すれば5,4,3,2,1なのだ ポインタを返すラムダをstd::functionで取り扱いたくて調べてるのだが どうしてどの参考例もintやvoidの例しか示していないのだろう 参考例を示すまでもなく誰でも簡単に記述出来ているのだろうか >>53 レスありがとうございます。参考になりました。 >>55 特に難しくは無いと思う 例えばどんなことをしたいの? std::function<int*(const int)> create_array = [](const int n)->int*{ return new int[n]); }; でいいんじゃないの 誰かdeleteすんだよと思うけど >誰かdeleteすんだよと思うけど 自覚があるならそんな変な例を出さなければいいのに >>55 の回答はこんな感じでいいだろう using ptr_type = void *; std::function<ptr_type ()> f1{ []{ return ptr_type{}; } }; std::function<void *()> f2{ []{ return static_cast<void *>(nullptr); } }; >>62 散々煽ってたから聞くけど static_cast<void *>(nullptr) このキャスト無駄じゃない? これは変な例ではないの? う〜んどうだろうね よく見るとラムダの戻り値の型が省略されているし こういったことがどの段階のC++のバージョンで出来るようになったのか 俺は知らないが、実際の戻り値の型からラムダの型を推測してくれる便利機能 を使っていると思われる となれば、キャストなしのnullptrでは型がわからないから ラムダの戻り値の型の推測もできず、コンパイルエラーになるのではないだろうか もしくは、ひょっとしたらnullptrには何らかな特殊な型が与えられているのかもしれんが それはしらないが、ともかくvoid*型ではないのは確かなので その場合でもstd::function<void *()>への代入で問題を起こすんだろう nullptrに型が有るのか無いのか、俺は知らんし、興味もないんだけどね >>57 >>59>>62 vsで試してて std::function<void *()> のような書き方をするとテンプレートがエラーを出していたので 関数ポインタのような特殊な記述が必要になるのかと思って調べていたのですが 原因が分かりました 仮で書いていたラムダ式の中の返り値を return NULL; にしていたのでこれがintなためエラーが出ていたようです テンプレートの奥のほうで型の不一致を出していたので <>内の記述ばかり疑っていました というかNULLって今まで(void *)0だと思ってました・・・ まさかただの0だとは 普段はコンパイラが暗黙に変換してるんだね・・・ 自宅のvs2015communityで実験したところ std::function<void *(void)> f0 = [](void) { return NULL; }; std::function<void *(void)> f1 = [](void) { return (void *)NULL; }; std::function<void *(void)> f2 = [](void)->void * { return NULL; }; std::function<void *(void)> f3 = [](void) { return nullptr; }; だとf0のみエラーです gccとかでも同様なんですかね >>65 nullptrの型はnullptr_tだよ だからラムダの戻り値の型はnullptr_tと推論される ただ問題はvoid *を戻り値としたfunctionに代入できるか ぶっちゃけ俺も書いてからやっちまったかと思って調べた 規格を調べたところやはり要らなかった 戻り値が暗黙変換できれば代入できると書いてある つまりラムダの戻り値intでfunctionはdoubleとかもあり そして当然nullptrはvoid *型に暗黙変換できる なので要らない https://ideone.com/EwRvlU >>67 の結果とも一致する >>63 コンパイルが通るかどうか以前に55は『ポインタを返すラムダを』と言っているのだから、 無いとお題改変になってしまうだろう >>67 当然 int f() {return NULL;} void *関数() { return f();//エラー } と同じことなので >nullptrに型が有るのか無いのか この手の文法で型が無い落とし穴は初期化の { } ぐらいか int a = {0}; // 「{0}」は式でなく型も無い さすがにCは時代に取り残された感があるな 新規案件なら埋め込み系を除いて存在意義なし 組み込み系って英語ではembedded なんちゃら だし よくある間違いでしょ linuxのカーネルモジュールてC++で書けるようになったんだっけ? ドライバとかはサブシスは普通に書いてるぽい、コアな部分はメンテナがパニクルのでやっぱCかと 実際ひと目でいいからソース見てみ 一生C++なんか使わねーという主張がにじみ出てるよ C++使わなくていいならそれに越したことはないからね c++は個人差が大きすぎるようです。議論も出来ない。 方向がコンフリクトしたら大変なのは ここ見てればわかる。 C++初学者です。 既存のCのライブラリに次のような関数が有るんだけど bool SendData(uint32_t * txData, uint32_t * rxData, uint16_t length); ラッパーで引数をuint16_tのポインタに変更したもを作りたいと考えています。 bool SendData(uint16_t * txData, uint16_t * rxData, uint_16_t length); 単にラッパーの中でバッファを持って変換してやれば良いとも思ったけど、 組み込み用途なんで速度や消費メモリ的にそれは避けたいです。 newやdeleteは無しでスタックのみを使用できれば、なお良いのですが、 良い方法が思いつきません。 何かスマートな方法は有りませんか? 元関数の length が uint32_t 単位での個数という仮定 → uint32_t より小さい粒度は取り扱えない → uint16_t で取り扱える個数は偶数個に限定される → ポインタのキャストと length を /2 で渡すだけ uint16_tの方がラッパーなの? どちらにしろ元の関数をそのまま使うなら変換は必要だね。 スタックが使われるかどうかはしらないけどClangコンパイラなら 可変長配列(VLA)っていうのがC++でも使えたはず。 サイズが大きすぎるとオーバーフローするけど。newと兼用してみるのも手。 >>86 なるほど、 渡すデータを1つ置きにすれば良いわけですね。 渡すデータを組み立てるときにそうすれば良いですし変換のコストは少なそうです。 多少汚いとこが関数外に出ちゃいますが今回のケースでは現実的な方法だと思います。 >>87 残念ながら使用しているコンパイラはclangではないですし、 VLAは今回の用途には重そうですね。 便利そうなので、PC用のプログラムを作るときに使えるかもしれません。 ひとまず>>86 さんの方向で考えてみます。 お二人ともありがとうございました。 組み込みでスタックに可変長のデータ領域確保するとか頭大丈夫? >>89 組み込みのことは知らないんだけど、サイズチェックして分岐するのはどうなん? if (length * sizeof(uint32_t) < 32767) { uint32_t list[length]; Test(list, length); } else { uint32_t list = new uint32_t[length]; Test(list, length); } >>90 どうなのって言われても好きにしろよとしか言えないけど... 個人的には各々のテストも必要になるその手のコードは書かない ガチの初心者でプログラミング勉強したいと思ってるんですが プログラミング勉強するとなるとどんなものから作り始めればいいですかね? ちなみにCの基本的なこと(if,for文やファイル入出力)くらいしか知りません やっぱり画像が出たら楽しいから画像ビューアとかが良いんじゃないかな 画像が動いたらもっと楽しいって言うんならゲームもよいんじゃない? 音関係も楽しいんだが、サウンドプログラミングは結構専門知識がいるうえ デバッグが難しいから最初は手を出さないほうが良いよ ま、画像ビューアや動画プレイヤーが楽しいよ ちょっとした実用性もあるし Cであることに特に意味がないのなら別の言語の検討をすすめる >>92 プログラミングを習得した延長線上に何を作りたいか決まってる? >>92 作りたいプログラム(今ならアプリケーションというのかな)の イメージが先にないとアドバイスしにくい時代なのよ。 まずコンソールに hello, world を表示して、続いて標準入出力、 ソートやらリンクド・リストやらのアルゴリズムを習得して… という順序を踏んでも、「マウスをクリックすると何かしてくれる」ような 今様のプログラムには少しも近づかないんだな、これが。 >>96 ゆくゆくはカメラを使って画像処理的なものをしてみたいと思ってます 具体的にはまだ決まってませんが… >>97 なるほど 将来的にやりたいことをしっかり考えたうえで何を学ぶべきか考えたほうがいいんですね! ■ このスレッドは過去ログ倉庫に格納されています
read.cgi ver 07.5.5 2024/06/08 Walang Kapalit ★ | Donguri System Team 5ちゃんねる