0からの、超初心者C++相談室

■ このスレッドは過去ログ倉庫に格納されています
1デフォルトの名無しさん
垢版 |
2018/11/12(月) 14:55:13.35ID:Tf74ZWQr
何にも知らない0からの出発、超初心者のためのC++相談室
2021/05/19(水) 13:29:25.47ID:G7N6xM6g
ちなみに、rand()は、出力範囲内の整数を全て出力し終わってから元の値に
戻る様になっているので周期も RAND_MAX + 1 に等しく、出力値は
均等確率で生じる。
>>226だと10で割った時の余りが必ず8になっておりそれは、出力が
10n + 8 になっているということ。これだと、今言った法則に当てはまって
ないので矛盾し、何かがおかしい。
243デフォルトの名無しさん
垢版 |
2021/05/19(水) 15:03:30.63ID:SQApMI36
C言語でのサーバー構築のやり方わかる方いますか?
2021/05/19(水) 15:05:53.17ID:G7N6xM6g
>>243
HTTP サーバーのことかな?
2021/05/19(水) 19:58:38.12ID:Y2/6iGxL
>>243
バークレーソケットをオープンしてリスンして、接続してきたのなら fork() だのスレッドで処理だの、というのを昔したことがありますが、すっかりわすれてしまいました…
どんなサーバーが欲しいのですか?簡単なサーバーならご要望に応えてテキトーに書く準備はありますよ
2021/05/19(水) 23:06:46.13ID:ONEwpJm5
>>241
それはよくある勘違い。 >>227 の方式では均等にならない。 櫛状にばらける。

0〜32767 の乱数から 0〜99 の乱数を得るには
32700 以上の値が出たときにそれを捨てて
そうでない値のときに 100 の余りをとればいい。

少なくとも私の手元の環境にある std::uniform_int_distribution はそのように実装されている。
2021/05/19(水) 23:56:26.10ID:l+JWTKLH
>>241はアホと思ったけど、
こんな勘違いをするアホがよくいるって?
そんなアホな
2021/05/20(木) 00:27:22.67ID:qlUu+R49
>>246
uniform_real_distributionの時は?
2021/05/20(木) 02:25:38.74ID:Dz+v3/+O
>>226
の結果は予想と外れていると思う。
rand()は均等確率のはずなのに、100で割って下一桁に9ばかり出るはずはない。
2021/05/20(木) 02:28:22.34ID:UJvm/t/I
>>246
なるほど。言われてみればそうだわ。
32767はもともと100で割り切れないから、一部を捨ててやらないと
均等にはならないな。
2021/05/20(木) 02:52:09.51ID:onv6EMq1
しかし、昔実験してみた限り、rand()の周期は、通常、RAND_MAX + 1
であり、rand()自体は均等確率のはずだ。
それはべつに、>>246ではちみつが言っていることと矛盾するわけではない。
RAND_MAXが32767のように100で割り切れない値だから、>>227
のようにすると、端数の様な部分でわずかに均等確率からずれてしまう。
ただし、ずれる範囲は、32767/100 = 327.67 なので、確率にして
0.67/327 程度以下の小さなずれではあるが。
2021/05/20(木) 22:00:26.21ID:+zMkmbAL
>>246
剰余を取って特定範囲の乱数を生成することができるのは、元の乱数が MT 並に性質がよいときだけかと、つまり >>246 はちみつ氏のやりかたは、元の乱数が優れたものだからできる方法
MT が発明されるまでは、最悪の方法「線形合同法」でもなんとか我慢できる部分範囲の乱酔生成法しか推奨されなかった

C FAQ をみてもそれがわかりますね
http://www.kouno.jp/home/c_faq/c13.html#16

13.16:
A:ある範囲の整数からなる乱数はどうやったら生成することができるか。

Q:すぐに思い付く、
rand() % N
(これは0からN-1までの数を返そうとする)は乱数の質が低い。なぜな ら乱数発生器の多くで下位のビットは悲惨なほどランダムでない。よりよい方法は以下のようなものである。
(int)((double)rand() / ((double)RAND_MAX + 1) * N)
2021/05/20(木) 23:50:59.51ID:qkpZwp6c
>>252
乱数ソースの性質の悪い部分を分布関数で修正するのはレイヤの分離がきちんと出来ていない感じがして嫌だな。
下位ビットを捨てるなら捨てるでそれが明示的であるほうが好ましいと思う。
2021/05/21(金) 00:17:02.51ID:Q+lecBxK
QZからはキムチの匂いがする
2021/05/21(金) 10:19:44.69ID:pMLUvwAV
いずれにせよ >>226 は、まともな標準ライブラリで試すと 226 のような結果に
はならないはず。理由:
226では、rand()%100の下一桁が常に9だが、それだとrand()は常に奇数という
ことになるが、実際のrand()は全て奇数ということはないから。
現象的には、偶数と奇数が交互に来るという不具合が知られていたりするが、
全部奇数ということはない。
2021/05/21(金) 10:27:54.72ID:b4MjZLXj
超初心者スレであることを考えると >>226 の srand() がプログラム起動時一度だけとも限らないのでは。
2021/05/21(金) 13:18:40.70ID:JT5uzYpW
Windows の (msvcrt の) rand は線形合同法だが下位バイトを豪快に捨ててる。
そのせいか (下位バイトを捨てない線形合同法よりは) 乱数としての質は多少良いが
初期値の違いに鈍感で、初期値が似ていれば最初の乱数も近いということが起こる。

>>256 の指摘は妥当かもしれない。
2021/05/21(金) 17:16:26.14ID:qriMwFf7
>>256
つまり、rand()だけを繰り返しているのではなく、srand()とrand()の組を
ひっくるめて繰り返しているようなことなのかな。
なるほど、それなら問題の焦点はsrand()と時刻の関係性になるので
>>226のような結果になったとしてもおかしくはないな。
2021/05/21(金) 17:24:43.18ID:qriMwFf7
なるほど。
質問者は、だから>>227でも快い返事をしてくれなかったのか。
彼は例えば、以下の様に書いていたようだね:
(1)
for ( int i = 0; i < 20; i++ ) {
 srand((unsigned)time(0UL));
 int r=rand()%100-1;
 printf( "r=%d, ", r );
}
本来は、こう書くか、
(2)
srand((unsigned)time(0UL));
for ( int i = 0; i < 20; i++ ) {
 int r=rand()%100-1;
 printf( "r=%d, ", r );
}
こう書く:
(3)
srand((unsigned)time(0UL));
for ( int i = 0; i < 20; i++ ) {
  int r = (int) ( ((double)rand()) / ((double)RAND_MAX + 1.0)) * 100.0 );
  printf( "r=%d, ", r );
}
この中で(1)はダメ。(2)も余り良くない。(3)はplain Cでの簡単な書き方では
標準。しかし、わずかに均等確率からはズれる。
2021/05/21(金) 18:35:20.74ID:ojw3YA/u
>>255
>>226を見れば乱数になってないことは一目でわかると思うのだけど

>>255の時点で毎回srandを呼んでるのかとも思ったけど、
それにしても値が綺麗すぎる。
2021/05/21(金) 19:25:04.91ID:UZ6lwfzX
Cはよくわからんのだけど(3)のやつわざわざdoubleにキャストする必要あるの?
2021/05/21(金) 20:07:22.28ID:ojw3YA/u
RAND_MAX + 1 でオーバーフローするとか
2021/05/21(金) 20:19:47.95ID:UZ6lwfzX
最低でも32767以上だからINT_MAXのときもあるのか…
ありがとうございます。
2021/05/21(金) 20:22:18.98ID:UZ6lwfzX
と思ったけどRAND_MAX+1.0した時点でdoubleになるんじゃ?
2021/05/21(金) 20:30:15.34ID:ojw3YA/u
>>264
なるけど

書かなくても動作が同じであれば書かない主義?
カッコとかコメントとか
1.0 も 1. で良いんだよ

まあそれ以前に (3) はカッコの対応がおかしいな
2021/05/21(金) 20:40:21.60ID:XRGlJQOp
>>253
確かに今となっては MT が開発されてしまったので、その感覚は理解できます
しかし、我々は MT がなかった頃の好き古き時代についても考慮するべきでしょう、過去の方法を評価するのに、その当時の技術的制約を考慮せずに「今の価値観」で裁断するのはフェアではない、と私はつくづく考えているのです
2021/05/21(金) 20:47:24.81ID:XRGlJQOp
>>256-257
なるほど、従って >>226 に対する適切なアドバイスは次のとおりだと私は提案します

>>226
MT = メルセンヌ・ツイスタを使いなさい
srand() とか rand() は忘れなさい、これらは化石時代の乱数生成法だから、今となっては srand() とか rand() をあえて使う合理的理由は存在しません
MT の導入方法や使い方は、次の私のソースを参考にしてください

https://ideone.com/M2SRcE
https://mevius.5ch.net/test/read.cgi/tech/1434079972/60
2021/05/21(金) 21:29:08.32ID:ojw3YA/u
どう見ても乱数生成法の質の問題じゃない
使い方が間違ってる

乱数の質を求めるならハードウェアの乱数生成命令を使うのが一番だが
>>226はそういうレベルじゃない
2021/05/21(金) 21:33:53.10ID:ojw3YA/u
Visual Studioで以下をやったら>>226みたいな値になった
3秒ごとにsrand/rand をコールしてるんでしょう

for (int i = 0; i < 100; i++) {
srand(i*3);
printf("%d\n", rand() % 100);
}
2021/05/21(金) 23:18:48.19ID:XRGlJQOp
え? >>226 って srand() を複数回呼んでいるんですか?確かにそれは間違っていますね…
srand() は普通、アプリ起動直後に一回だけ呼べば十分ですよ…
2021/05/22(土) 02:03:33.66ID:8I9NK3Yz
>>269
洞察すれば、こんな風だろうか?
(端末で確認しながら三秒間隔でEnterキーを押している) :
for ( int i = 0; i < 20; i++ ) {
 srand((unsigned)time(0UL));
 int r=rand()%100;
 printf( "r=%d\n", r );
 getche(); // 3 秒間隔で人間が Enter キーを押す。
}
2021/05/22(土) 02:04:35.75ID:MF6mf+kw
>>269
洞察すれば、こんな風だろうか?
(端末で確認しながら三秒間隔でEnterキーを押している) :
for ( int i = 0; i < 20; i++ ) {
 srand((unsigned)time(0UL));
 int r=rand()%100;
 printf( "r=%d\n", r );
 getche(); // 3 秒間隔で人間が Enter キーを押す。
}
2021/06/02(水) 11:54:46.08ID:QfG+Xq1u
書籍の意味が分からないので教えてほしいのですが
それ以外のって部分から何を言ってるのか全く分かりません

”signed char a;である時は、aには−128〜127の数値しか入れられません。それ以外の数値を入れようとすると、普通は一番下の1バイト、つまり2進数での下8桁だけになり、上の方の桁は全て切り捨てられてしまいます。
最大値より大きい値になった時をオーバーフロー…略”
2021/06/02(水) 12:23:21.09ID:A2GTbdiP
何を教えてほしいのかわからない。
275デフォルトの名無しさん
垢版 |
2021/06/02(水) 12:37:39.80ID:QfG+Xq1u
>>274
ロベールの107ページの

”signed char a;である時は、aには−128〜127の数値しか入れられません。それ以外の数値を入れようとすると、普通は一番下の1バイト、つまり2進数での下8桁だけになり、上の方の桁は全て切り捨てられてしまいます。”

↑この文が意味不明なので簡単に教えてほしいです
”signed char a;である時は、aには−128〜127の数値しか入れられません” ここまではなんとなく理解できたのですが…
2021/06/02(水) 12:45:51.56ID:1WJ2HfQ7
>>275
そもそもビットとかバイトとかわかるの?
わからないなら、基本情報から勉強しないといけない。
2021/06/02(水) 12:56:19.74ID:QfG+Xq1u
>>276
この前のページに2進数 1ビット 1バイトなどの単位と各型のバイト数について触れられてるので
そこは何となく理解できてるのですが
2021/06/02(水) 13:18:03.17ID:1WJ2HfQ7
>>277
1ビットは、2進数一桁で、ゼロかイチ。
2ビットは、2進数二桁で、00、01、10、11の2**2==4通り。これらは10進数で表すと0、1、2、3となる。
3ビットは、2進数3桁で、000、001、010、011、100、101、110、111の2**3==8通り。これらは10進数では、0、1、2、3、4、5、6、7となる。
……
8ビットは、2進数8桁で2**8==256通り。10進では0〜255となる。現代では8ビットは1バイトに相当する。1バイトは16進二桁で表せる(2**8==16**2)。

以上は符号なしの場合。

符号付きの場合は最上位ビットがマイナス符号の有無を表し、正の場合は符号なしと同じで、負の場合は2の補数表現になる。
2021/06/02(水) 13:32:39.22ID:1WJ2HfQ7
2の補数表現というのがくせ者だが、まあ、Wikipediaの説明を見てもらいたい。

https://ja.m.wikipedia.org/wiki/2%E3%81%AE%E8%A3%9C%E6%95%B0

符号付き8ビットの場合はx+y==2**8となるyがxの2の補数となる。補数を使えば足し算で引き算を表せる。

まあ、例えば10進数4桁1234の10の補数表現は8766となる。1234+8766==10000となるが有効4桁からオーバーフロー(桁あふれ)してゼロになる。8767の場合は1234+8767==10001、
オーバーフローしてイチになる。このようにオーバーフローを前提とすれば、大きな数で引き算を表せる。
2021/06/02(水) 14:31:54.50ID:CzhBAh+2
お、優しい先生が現れたぞ。嘘ばかりの5ちゃんの中で珍しい。
2021/06/02(水) 14:44:42.56ID:QfG+Xq1u
>>279
すいません詳しくありがとうございます
補数って概念全く理解してなかったので、それが原因だと分かりました。
コンピュータは足し算しかできないのですね…
そこら辺知識固めてからもう一度読み直してみようと思います。
2021/06/02(水) 16:48:03.08ID:1WJ2HfQ7
10進4桁の場合、9999に1を足すと10000、オーバーフローしてゼロになる。よって、このオーバーフローするシステムの場合、9999はマイナスイチを表していると考えることができる。
同様に9998は-2であり、9997は-3である。
2021/06/02(水) 16:54:31.73ID:1WJ2HfQ7
符号付き8ビットの場合、2進数11111111、つまり16進でFFがマイナスイチを表す。同様に11111110(FE)はマイナス2であり、11111101(FD)がマイナス3である。

規則性が分かると思うけど、ビットを反転して、符号なし整数と見なしてイチを足すとマイナス符号の追加と同じ効果がある。証明略。
2021/06/02(水) 17:04:16.45ID:Bcy6nIKX
一応補足しておくけど負の数の表現が二の補数であることは C/C++ の言語仕様としては保証してないし、
(C++20 からは二の補数であることが保証されるようになった)
1バイトが8ビットであることも保証してない。
signed char に型変換したときに上位ビットを切り捨てることも保証されない。
(変換後の型が unsigned のときには実質的に保証される。)

言語仕様として保証しないからといって間違っているというわけではなくて、
一般的なコンピュータのアーキテクチャではおおよそそうなってるのが普通というのも事実。

C++ の言語仕様の一部は機械の都合 (どのような機械語を生成するのが効率的か) でいくつかの選択肢
をとれるように言語仕様の側では意図的に決めてない部分がある。
「C++ の説明」として見たら >>275 で引用されている説明はちょっと微妙かもしれん。
あまり踏み込んで説明するのがめんどいから「普通は」という言葉でごまかしているんだと思う。
285デフォルトの名無しさん
垢版 |
2021/06/02(水) 23:13:21.37ID:ZuDsQZsq
float/doubleは
2021/06/03(木) 02:59:14.77ID:Ers5yK+g
char は環境依存なので使わないようにする。
unsigned・signed のどちらなのか、分からないため

unsigned char は、0〜256
signed char は、-128〜127

0〜127、7ビットの範囲では、この2つは共通している

signed charは、先頭ビットが1なら、負数となる。
2の補数を調べて

1111_1111・0xFF なら、256か、-1
287286
垢版 |
2021/06/03(木) 03:03:09.44ID:Ers5yK+g
>>286
修正

256 ではなく、255 です

unsigned char は、0〜255

1111_1111・0xFF なら、255か、-1

だから、環境依存のchar 型を使っていると、
エラーに、-1を使っていたが、他の環境では255と表示されたりする
288デフォルトの名無しさん
垢版 |
2021/06/03(木) 10:13:20.76ID:oKNqyVQK
むしろ int を期待してる引数に char 渡す時が危険
2021/06/03(木) 13:38:18.86ID:ivgy5ZU8
char 同士なら符号の有無が違ってもビットパターンは維持された
ままで型を読み替えることが期待できる (言語仕様として保証しているわけではない)
けど、大きな型に変換するときは符号拡張が起こることがあるからだね。
2021/06/05(土) 22:29:47.19ID:UR0LV/yo
ハーバートシルト『STL標準講座』翔泳社, 1999, p.156-157
のサンプルプログラムで、そのままだとコンパイルが通らないものがあるのですが、
適当にconstをつけていたらコンパイルできるようになりました
しかし、理由がわかりません
どなたかご教示いただけませんか?
https://ideone.com/LGnjXo
2021/06/06(日) 01:24:02.19ID:Lz5dZs8J
operator <<のとこでoがconst参照だから、そのoからはconstなメンバ関数しか呼べない。のでそれで合ってる
元のソースが間違ってるか何かだと思う、この仕様は最初からのはずなので
2021/06/06(日) 01:44:38.27ID:xlnMgrm3
>>290
set<>::iterator は const をつけていなくても set<>::const_iterator と同じくイテレータ≒ポインタに const 属性がつきます。
だから set<>::iterator p; …@、と宣言した場合の p には「終生」 const 属性がつきまとうことになります。
例えば@の p にポインタ演算子 * を適用して出来た表現「*p」が参照に読み替えることがあれば、その参照は const 参照でなければなりません。

もともと const 属性はポインタにつけて、const 属性のついたポインタに -> 演算子を使って出来たメンバ変数の値を変更しないようにコンパイル時に厳密にチェックする縛りです
c++ における参照は「機械的にポインタを使った書き方に書き直すこと」が可能(…A※)ですから、const なイテレータ(≒ポインタ)から生成した参照は const な参照にならざるを得ないのです
※Aは私の持論で、今回のお題でも参照をポインタに全部書き換えてやろうと試行錯誤していましたが、さすがに iostream や set で先に参照として宣言されているものを後からポインタにするのは不可能でした
頑張ってみたけれども、かえって意味不明な https://ideone.com/Yc0YvT ぐらいにしかならなかった、持論は修正しなくてはいけないなあ…

set は重複要素を許さない二分木構造です。二分木構造 set に要素を挿入するときに、要素の大小関係にしたがって二分木の形をくみ上げていきます。
だからすでに二分木に組み込まれてしまった要素が、後からほいほいと要素の内容を変えられてしまっては二分木構造に矛盾をきたし、役に立たなくなってしまう…
だから set にすでに組み込まれている要素をイテレータで走査するときは、そのイテレータ≒ポインタは、メンバの書き換えが不可能なイテレータとするしかないか、と私は考えます

提示していただいたソースを、上に述べた原則にしたがって、この原則に関係ない余分な部分を削り落として書く(あと、ちょっと簡略化もしています)と次のような感じでしょうか。
https://ideone.com/Zr1qIH
friend 略 operator<<(略 C const &obj) { ... }
にならなくてはならないのは set<C>::iterator は set<C>::const_iterator と同じだからです
friend bool operator<(C const &a, C const &b) は set への要素の挿入のときに使う比較関数ですが、比較作業以外に要素のメンバを変えるとか余計なことをさせないために、最初から const 参照で宣言するべきでしょうし、そうなっているみたいですね

しかし、この const 属性はプログラミング 3 年生くらいまでは、かなり分かりにくい縛りであることは、私の経験からもとても理解できます。
ポインタや参照をしっかり理解しないことには、わざわざ自分を縛る const のありがたみもよく理解できないだろうと、私も同情するのです。そういうときは、const_iterator p から作った表現 *p が展開された先の実際の表現を、「*p のコピー・オブジェクトのコピー」にするのがいいでしょう
上記のお題をこの方針で書くとこうなります。
https://ideone.com/G42gUs

いろいろ書きすぎたかもしれませんが、上に示した三つのソースコードを研究してみてください
2021/06/06(日) 01:58:54.60ID:xlnMgrm3
>>290
>>292

https://mevius.5ch.net/test/read.cgi/tech/1594615908/593
593 名前:◆QZaw55cn4c [] 投稿日:2021/03/14(日) 20:13:24.03 ID:uaeFGveg [3/6]
>>590
>C++は未だ*や&、&&、で頭の中がグルグル回ってしまう
これらの「記号」は習得に順序があります。
まず * をしっかり理解します。C/C++ はなんといってもポインタが基本です。
次に参照 & を理解します。参照& を使う場面が出てきたら、これを * を使った書き方に書き直す、という機械的な訓練がいい練習になるでしょう
参照 で返す、という場面でも、@参照返しが出来る場合と、A参照返しはできずせいぜい RVO に期待するしかない場合、の@A二つの違いを明確に即答できるようになるべきでしょう(最近まで私はそれができなかった……)参照& の表現は新しい表現( ranged-for とか) でよく目にしますし、@Aは結構重要だと思います

&& は多分最後でしょうね、私も && は良く分かっておらず、というか、分からないから使わないという態度に留まっていますが、まあそれでもなんとかなる気がします
2021/06/06(日) 02:07:24.75ID:xlnMgrm3
>>291
operator<<() のストリームじゃないほうの引数は、const 参照ではなくてもいいと思います
今回のは const 参照が要求されたのは、 set のイテレータだから
https://ideone.com/j6CV0s
2021/06/06(日) 02:32:48.87ID:xlnMgrm3
>>292
ソースを貼り付けた一行目がミスっていましたね、修正します。

>しかし、この const 属性はプログラミング 3 年生くらいまでは、かなり分かりにくい縛りであることは、私の経験からもとても理解できます。
>ポインタや参照をしっかり理解しないことには、わざわざ自分を縛る const のありがたみもよく理解できないだろうと、私も同情するのです。
>そういうときは、const_iterator p から作った表現 *p が展開された先の実際の表現を、「*p のコピー・オブジェクトのコピー」にするのがいいでしょう
>上記のお題をこの方針で書くとこうなります。

https://ideone.com/Ivx0JY
2021/06/06(日) 02:41:34.70ID:Lz5dZs8J
ああ、operator <<のconstも最初付いてなかったのか
それならsetの仕様変更のせいだね

というか昔のままの非constの方が良かったんだけどなぁ
比較演算子自分で書いてるような構造体だと順序変わらない場合もあるんだし・・正直押し付けがましい
2021/06/06(日) 03:22:16.34ID:xlnMgrm3
>>296
自分で一から書く分には const に一貫性を持たせて、結果、const が有用に働くように書いていけるかもしれない、とか思うのですが、
他の人の分を取り込むときは、最悪 const_cast を >>290 の言うように「適当にconst_cast をつけていたらコンパイルできるようになりました」とか私も言っているわけでして、私は >>290 を笑うことができません……
2021/06/06(日) 08:29:50.46ID:KyPgEn9X
一から書いている私ですが、
全てのフォルダ・ファイル・プログラムに一貫して
*と何か名前を付けてプログラミングをしています。
2021/06/06(日) 08:34:21.45ID:8VTCuGWY
QZ・・・・
C++をちゃんと理解できてないのに無理すんなw
2021/06/06(日) 09:27:07.17ID:xlnMgrm3
>>299
>C++をちゃんと理解できてないのに無理すんなw

うん。すっごく認めます!

でもちゃんと理解できていないからこそ、アウトプットもきちんと書くようにして定着させたい、というのもあるんですよ
「教えることは教わること」

>>290 に対する回答としての >>292, >>294 に間違いはないですよね?
2021/06/06(日) 09:44:11.48ID:WkbXnMOk
意味分からん理屈だな
ずっと前からC++分からないって言ってるよね?
もしかして理解できる頭を持ってないのかな?
2021/06/06(日) 13:37:50.42ID:xlnMgrm3
>>301
自己申告なんて当てにしてはいけないのでは?
2021/06/06(日) 15:27:30.95ID:fMmzH2Jl
文面から必死な感じがヒシヒシと伝わってくるのに
皮肉も理解できないとはさすが厚顔無恥の代表格
誰も認めてくれないから自画自賛するしかないんですね
2021/06/06(日) 16:22:05.09ID:xlnMgrm3
>>303
え?必死?思いがけない反応ですね
まあ >>290 の方が提示したソースはハーバードシルトにしては冗長だと思って無駄丁寧っぽく説明したほうがいいかと >>292 をワサワサ書きましたが、それが必死だとは…
よく分かっている方 >>291 に対しては簡潔に私の意見 >>294 を送ってもう十分、仕様変更があったという情報 >>296 をいただいて感謝、というところでしょうか
305290
垢版 |
2021/06/06(日) 22:29:30.82ID:DvMt5hdj
>>291
>>292
どうもありがとうございます

constメンバ関数の理解が不十分だったようです
constメンバ関数はメンバ変数を変更しないという理解だけで、
constオブジェクトはconstメンバ関数しか呼べないことへの
理解が足りなかっため私自身混乱していました

ご説明いただいた内容を足掛かりに理解を深めたいと思います
3061
垢版 |
2021/06/07(月) 07:01:58.64ID:pWKPTo4/
まぁ、いいじゃねぇか、プログラミングなんて何にも知らないってのスレだし。
2021/06/07(月) 07:48:28.30ID:c29T7zKX
const char* const str[] は文字列アドレスを格納するポインタの配列って意味であってますか?
const char* strは文字列を格納するポインタ?
char str[] は文字配列?

一気に出てきてよくわからなくなって来たので間違えてたら教えて欲しいです。
2021/06/07(月) 08:39:52.02ID:xFpLHEPr
>>307
だいたいあってる
2021/06/07(月) 11:12:06.49ID:BLDePS2Q
ちゃんとメモリ確保してから使えよ
2021/06/07(月) 22:09:28.76ID:JY7FyEcf
>>308
ありがとうございます。
2021/06/08(火) 23:28:22.97ID:kZSYpF+Y
https://ideone.com/2fyV5M

103 と115で確保された動的配列のアドレスは別物なんでしょうか?
コピーコンストラクタの動きがよくわからないです
2021/06/09(水) 02:24:41.44ID:ZtayyY2i
103のarrayはコピーされたものだから別物だよ
てか初っ端から手直しが必要なソースを貼るのはやめろ
2021/06/09(水) 02:39:16.49ID:Ih94CWHU
スレの主旨的に初心者が初歩的な質問をするのは別に構わんとは思うんだが、
入門書にでも書いてあるようなことはよく読んで勉強したほうがいいと思うぞ。
素人が1レスで答えるよりはちゃんと体系だった解説のほうがわかりやすいよ、常識的に考えて。
2021/06/09(水) 04:24:03.76ID:BGdtXEJj
>>312
すいません、ヘッダーとかcpp分けてるのどうアップロードすればいいのか分からなかったです

後65行目にcopy(other.m_array, other.m_array + m_size, m_array);とあるのですが何をしてるのか分かりません
本には”第1引数以上第2引数未満のアドレスにあるデータを第3引数の指すアドレス以降にコピーする関数で…とあるのですが
具体的に何をしてる関数なのでしょうか?第2引数の足し算も何なのかよく分かりません。
2021/06/09(水) 04:43:32.09ID:ZtayyY2i
https://ideone.com/EScxwq
こうしたらそのままコンパイル通るやろ
自分のヘッダincludeしてるとこにヘッダの内容貼り付けるだけ

https://cpprefjp.github.io/reference/algorithm/copy.html
memcpyと似たようなもん(コピーの仕方は違うけど
other.m_arrayの指すアドレスから+m_size分のアドレスまで(未満)をm_arrayの指すアドレスから同じく+m_size未満までコピーしとるだけ
これで分からんならポインタの理解が出来てない
上記のとこだとイテレータとか出てるけどこの場合ポインタなので全部ポインタに読み替えていい
2021/06/09(水) 04:53:28.23ID:ZtayyY2i
ちょっと誤解招きそうなので補足
m_sizeは個数なのでアドレス値ではないがintのm_size個分アドレスが加算される
このへんは>>313の言う通り入門書嫁
317デフォルトの名無しさん
垢版 |
2021/06/09(水) 14:16:25.82ID:3Qpbsqp/
cpp で socket を読み書きする stream 系の class ってありますか?
boost にはあったと思いますが
標準のはあるんですか?無いですか?
2021/06/09(水) 16:06:33.34ID:Ih94CWHU
>>317
標準には無い。
が、ソケットに stream のインターフェイスをかぶせることはそれほど難しくはない。
2021/06/09(水) 22:30:15.61ID:BwbEIJxn
>>315
1引数から2引数で足したアドレスまでを第三引数にコピーしてるのですね
やっと分かりました。ありがとうございます。
頭硬い人はロベール向いてないのかな…
2021/06/09(水) 23:57:13.88ID:ZtayyY2i
それは良かった
まぁ最初は理解に時間かかるもんだ
321デフォルトの名無しさん
垢版 |
2021/06/10(木) 10:45:51.80ID:ZbfFyHii
>>318
thx

cpp の std にある関数で glibc の様な getpass ってありますか?
標準のは無いですか?
2021/06/10(木) 14:24:18.43ID:MOYAWABe
>>321
無いよ。
323デフォルトの名無しさん
垢版 |
2021/06/11(金) 14:28:13.59ID:tB3/M6ll
FILE *fp = fopen() で取得した fp を使って
stringstream としてアクセスすることは出来ますか?
2021/06/11(金) 17:27:01.32ID:DsaVPusD
>>323
直接的に一発で FILE* に stream をかぶせる手軽な方法はないと思うけど、
std::basic_streambuf を継承して setbuf, overflow, sync などをオーバーライドしたクラスを作ればストリームバッファになる。
(普通は std::basic_filebuf も内部的にはそう実装されているはず。)
それをストリームに結び付ければストリームに出来ることは何でもできるよ。

仕様を調べるのがすごくしんどいだろうけど、
実装は (細かいエラーチェックとかを抜きにすれば) 百行も要らないくらいの簡単なものでいけるんじゃないかな。
2021/06/16(水) 00:59:39.17ID:QFUk0bjY
>>323
fstreamを使えば?
#include <fstream>
#include <sstream>

std::ifstream fs("hoge.txt");
std::stringstream ss;
ss << fs.rdbuf();
fs.close();

それともfstream使えない特殊な環境?
2021/06/16(水) 16:36:23.72ID:uJQ6HHCX
FILE *fp = fopen(...);
std::ifstream fs(fp);
出来たらいいな
2021/06/17(木) 21:31:03.90ID:OB6uOiq6
関数へ渡す引数の型を限定したいときどう書くのが一般的ですか?
具体的に言うと符号なしのintだけ受けつけたいんですけど
2021/06/17(木) 23:54:09.39ID:Gi/wqrqm
>>327
暗黙の型変換を許さないということかな?
それならテンプレートにした上で型に制約を付ければいい。
ここでは C++11 でも通るように書いてみたけど C++20 以降なら
コンセプトが使えるのでもう少し簡単に書ける。

#include <type_traits>

template<class T>
typename std::enable_if<std::is_same<T, unsigned int>::value>::type foo(T) {
}

int main(void) {
int a = 1;
unsigned int b = 2;
foo(a); // これはエラーになる
foo(b); // これは通る
}
2021/06/18(金) 08:42:03.67ID:kejK9s3z
なんで戻り値voidに限定してんだよボケ餃子
2021/06/18(金) 11:49:14.92ID:AVf6Ht59
確かにそれで可能だけど、回答が超初心者スレのレベルを逸脱していると思うのですが
2021/06/18(金) 18:30:00.74ID:JA4mPV9U
>>329
単なるサンプルだからだよ。

>>330
超初心者が相談するという主旨のスレではあるけど、
超初心者には理解できないという結果になることもあるだろうし、
可能であれば相談した結果として初心者から脱したらそれに越したことは無いでしょ。

これで相談がクローズってわけでもないから
もっと深く知りたいってのならわからないところを続けて質問してもらってもいいわけで。

もっと簡単な方法があるならそれを提示するんだけども、なくなくなくない?
2021/06/18(金) 19:23:19.39ID:kejK9s3z
>>331
アホか
普通のenable_ifの使い方と全く違うお前だけのオナニーコード押し付けて何がサンプルだ
何不必要な制限勝手につけてドヤってんだボケ
2021/06/18(金) 19:32:07.35ID:JA4mPV9U
>>332
返却値 (または enabler) で制限するのは普通だろ。
むしろ他にどう使えるんだ?
2021/06/18(金) 19:35:45.29ID:kejK9s3z
>>333
マジで言ってんのか?

#include <type_traits>
template <class T, typename std::enable_if<std::is_same<T, unsigned int>::value>::type* = nullptr>
void foo(T)
{
}

int main()
{
// foo((int)1);
  foo((unsigned int)1);
}

enablerってこれのことか知らんが、お前のコードだと戻り値voidにしか出来んだろってこと
2021/06/18(金) 19:42:19.79ID:kejK9s3z
>>327
ちなコンセプト版(C++20対応コンパイラが必要)

#include <type_traits>

template <class T>
concept UnsignedInt = std::is_same_v<T, unsigned int>;

template <UnsignedInt T>
void foo(T value)
{
}

int main()
{
// foo((int)1);
  foo((unsigned int)1);
}
(インデントは全角なので注意)
まぁどっちも難しいと思うけど無理に理解せず流した方がいいと思う(それか制限あきらめるか
2021/06/18(金) 19:43:08.40ID:AVf6Ht59
>>331
いや、お前の言いたいことは分かるよ
ただテンプレートメタプロコードを超初心者にいきなり例示して、「わからないところを続けて質問」して回答を繰り返して、結果的に理解に至るのは何ヵ月後になるんですかと
テンプレートに関する高度な質問が飛び交う中、ここは超初心者スレとして機能するんですかと

この場合>>327が求めているのはドリルじゃなくて穴だと思うよ俺は
どういう背景があってunsigned int以外を受け付けたくないか、を聞くべきなのでは?
2021/06/18(金) 19:57:29.32ID:kejK9s3z
確かにそうだね
というか自分もテンプレート以外思いつかんかった・・

>>333
なんか変な癖あるから標準的な使い方がすっぽ抜けてたのかね
ボロカス言って悪かった
2021/06/18(金) 20:01:53.90ID:zIhiG+wy
あんまり詳しくない俺にはこういうのしか思いつかん。
__my_func() は直接呼ばないお約束にしておいて、static_assert で。
template のところは、書き換えは雰囲気でできると思うけど・・・

#include <type_traits>
#include <iostream>

unsigned int __my_func(unsigned int a) { return a * 2; }

template <class T> unsigned int my_func (T a) {
static_assert(std::is_same<T, unsigned int>::value == true, "is not uint.");
return __my_func(a);
}

int main() {
int a = 2;
unsigned int b = 2;

//std::cout << my_func(1) << std::endl; // assert
//std::cout << my_func(a) << std::endl; // assert
std::cout << my_func(1U) << std::endl;
std::cout << my_func(b) << std::endl;
}
2021/06/18(金) 20:30:53.23ID:JA4mPV9U
>>334
> お前のコードだと戻り値voidにしか出来んだろ

なんか変なこといってると思ったらそこがすれ違いか。
std::enable_if のテンプレート引数の二個目を省略しなければ何にでも出来るよ。
(std::enable_if の type は void に固定されているわけではない。)
クラスやコンストラクタは返却値がないから enabler を使うんであって、
普通の関数のときは返却値のほうで制御するのが普通だと思うぞ。
2021/06/18(金) 20:33:26.89ID:JA4mPV9U
>>336
まあそうなったら他に誘導してもいいし、資料を提示するだけで十分だと思った。
ただ背景をもうちょっと引き出すべきというのも確かに必要なことではあったな。
2021/06/18(金) 20:39:10.69ID:kejK9s3z
そうなんか、そういえばいつも自作alias使ってたから気付かんかったわ

>普通の関数のときは返却値のほうで制御するのが普通
別に戻り値でも引数でもいいが、クッソ読みづらいと思うけどな
あとそれならこういうスレで第2引数省略すんなよ、初心者惑わしたいのか?
■ このスレッドは過去ログ倉庫に格納されています
5ちゃんねるの広告が気に入らない場合は、こちらをクリックしてください。

ニューススポーツなんでも実況