1 名前:デフォルトの名無しさん [2006/08/22(火) 09:21:31 ] はきだめのスレへようこそ ここは、C/C++に挫折し、それにもかかわらず、C/C++やらなければならない者達がたむろするスレです。 なお、質問する人は回答はあまり期待しないでください。 前スレ:はきだめC/C++下級者の質問箱 pc8.2ch.net/test/read.cgi/tech/1124256027/
152 名前:デフォルトの名無しさん mailto:sage [2006/10/07(土) 18:14:19 ] PXOR
153 名前:デフォルトの名無しさん mailto:sage [2006/10/08(日) 12:42:50 ] ( a < 0 ) == ( b < 0 ) 何に使うのか知らないけど、これじゃ、ちゃんと動かない可能性ある罠。 a<0が、1返して、b<0が2返したら、!=になるし。 また、aかbのどちらかがゼロだったらどうする?(プラス扱いするならいいけど) おいらなら、signって関数(符号に応じて-1,0,1を返す)を作って、 sign(a)==sign(b)って書く。 おそらく関数の中でif文使うから、実行効率は最悪だけど、 実行効率より、バグ鳥する時のコードの読みやすさ考えないと。 あと、どうしても効率最優先でも、何に使うのかが分からないと、最適な判別式は決められない。
154 名前:デフォルトの名無しさん mailto:sage [2006/10/08(日) 12:47:33 ] pugya-
155 名前:デフォルトの名無しさん mailto:sage [2006/10/08(日) 13:15:16 ] >>153 a < 0 が0か1であることは保証されている。
156 名前:デフォルトの名無しさん mailto:sage [2006/10/08(日) 13:30:28 ] >>153 Cの比較演算の仕様を勉強しなおしてからお越しください。
157 名前:デフォルトの名無しさん mailto:sage [2006/10/08(日) 14:36:37 ] 0 か 1 になるのは C.質問者は C++ で聞いている.まあそれでも The operands shall have arithmetic, enumeration or pointer type. The operators < (less than), > (greater than), <= (less than or equal to), and >= (greater than or equal to) all yield false or true. The type of the result is bool. であって,bool 同士の == が正常に動くことも保証されてるから >>153 はアホ.
158 名前:デフォルトの名無しさん mailto:sage [2006/10/08(日) 23:56:38 ] #include <string> using std;;string; struct A { string a; }; struct B { string b; B &operator=(const string &s){ b = s; } }; int main(void){ A a; A aa = a; // xxx B b; B bb = b; return 0; } --- 質問なのですが、main()のxxxのところってまずいですよね?
159 名前:デフォルトの名無しさん mailto:sage [2006/10/08(日) 23:59:42 ] 別に。
160 名前:デフォルトの名無しさん mailto:sage [2006/10/09(月) 00:00:15 ] 間違えた。 B &operator=(const B &b0){ b = b0.b; }
161 名前:デフォルトの名無しさん mailto:sage [2006/10/09(月) 00:02:14 ] >>159 stringのメンバにポインタがないことは保障されているのですか?
162 名前:デフォルトの名無しさん mailto:sage [2006/10/09(月) 00:09:21 ] >>161 stringはコピーコンストラクト可能かつ代入可能。 ポインタは含まれているが、コピー時は生ポインタを明け渡すわけじゃなくって ポインタが指し示す内容をコピーする様に作られてる。 よって何の問題も無い。
163 名前:デフォルトの名無しさん mailto:sage [2006/10/09(月) 00:15:33 ] A のデフォ代入演算子がmemcpy() だとまずいと思ったのですが。 つまり、デフォの実装が A A::operator=(const A &a0){ memcpy(this, &a0, sizeof(A)); }
164 名前:デフォルトの名無しさん mailto:sage [2006/10/09(月) 00:17:34 ] 送信失敗、すみません。 デフォの実装が A A::operator=(const A &a0){ memcpy(this, &a0, sizeof(A)); return *this; } これだと、メモリ二重開放にならないかと心配したわけです。
165 名前:デフォルトの名無しさん mailto:sage [2006/10/09(月) 00:21:22 ] C++のクラス(=構造体)の代入処理は、各メンバの代入処理を行なう形になる。 たまたまPODメンバがまとまっていれば、memcpy()相当の実装をするかもしれない。
166 名前:デフォルトの名無しさん mailto:sage [2006/10/09(月) 00:21:48 ] なるよ。 つーかそんな馬鹿な実装はしちゃいかん。 C++におけるmemcpyは純粋に生のバイナリデータ転送用で、メンバのコピー用じゃない。 余談だけど、thisがポインタなのはthis登場時にC++がまだ参照をサポートしてなかったからで、 thisがポインタであることを副作用的に使うコード(memcpyの引数にする、this[2]とか書く、エトセトラ)は 総じて何か勘違いしている傾向。 忌避したくらいで丁度いいぞ。
167 名前:デフォルトの名無しさん mailto:sage [2006/10/09(月) 00:22:32 ] >>159 ,>>162 は間違い。自前で代入演算子をちゃんと定義してやらないと >>163-164 で心配している通り memcpy な実装になってメモリリークする。
168 名前:デフォルトの名無しさん mailto:sage [2006/10/09(月) 00:27:03 ] >memcpy な実装になってメモリリークする。 服脱いで正座してbasic_stringのコード読んで来い。 そんなになってたまるか。アホらしい。
169 名前:デフォルトの名無しさん mailto:sage [2006/10/09(月) 00:29:57 ] >>168 コンパイラが A A::operator=(const A &a0){ a = a0.a; } と解釈してくれるものなのでしょうか?
170 名前:デフォルトの名無しさん mailto:sage [2006/10/09(月) 00:36:15 ] >>169 >165
171 名前:デフォルトの名無しさん mailto:sage [2006/10/09(月) 00:37:51 ] 158の場合では代入演算子ではなく、コピーコンストラクタが使われる。まあ話は変わらないが。 operator =が定義されていないときのデフォルトの実装は、 各メンバと基底クラスに代入演算子を使用したのと同じ動作をするということになっている。 また、コピーコンストラクタにも同じような規定が存在する。 162の言うとおりstd::stringが適切なコピーコンストラクタやoperator =を持っているため、 158/164の心配は杞憂だということになる。
172 名前:デフォルトの名無しさん mailto:sage [2006/10/09(月) 00:38:56 ] ああ、ごめんみんなもう書いていたね。
173 名前:デフォルトの名無しさん mailto:sage [2006/10/09(月) 00:41:26 ] >>168 それ全然問題の本質じゃないから。
174 名前:デフォルトの名無しさん mailto:sage [2006/10/09(月) 00:43:06 ] >>171 >158の場合では代入演算子ではなく、コピーコンストラクタが使われる。 例が悪くてすみません、全くもってその通りでした。 >>165 これがFAでしたか。 皆様ありがとうございました。
175 名前:153 mailto:sage [2006/10/09(月) 00:44:02 ] >>155-157 そうだったのか。申し訳ない。
176 名前:デフォルトの名無しさん mailto:sage [2006/10/09(月) 01:56:06 ] 質問させてください。 ちょっと説明が下手でわかりにくいかもしれませんが、 ある関数の中で、引数の配列の長さを知ることはできるでしょうか? 例えば配列の平均を求める関数averageを作りたいとき main関数内でa[100]とかb[80]とかを定義して、average関数に引き渡すとします。 (average(a)みたいな感じで) このとき平均を求めるには当然、配列の要素の数が必要になるわけですが、 これをaverage関数内で求めることはできるのか?という質問です。 今は配列とともに要素の数もaverage関数に渡しているのですが、他に良い方法があったらご教授ください。
177 名前:デフォルトの名無しさん mailto:sage [2006/10/09(月) 02:01:26 ] >>176 C++なら関数テンプレートにすればできんことはないよ。 多分↓こんな感じにすればおk template<int array_size> int average(const int array[array_size]) { ... }
178 名前:デフォルトの名無しさん mailto:sage [2006/10/09(月) 02:15:52 ] template <int N> int average(int (&array)[N])
179 名前:デフォルトの名無しさん mailto:sage [2006/10/09(月) 02:16:34 ] で、後は要素の数は sizeof(array) / sizeof(array[0])
180 名前:デフォルトの名無しさん mailto:sage [2006/10/09(月) 02:17:14 ] Nでもいいかもしれん。
181 名前:デフォルトの名無しさん mailto:sage [2006/10/09(月) 02:22:05 ] Cなら要素数を別の引数で渡すこと以上の方法はないし、それが最も一般的だと思う。 C++なら177-178のように直接要素数をテンプレート引数にして配列への参照を引数にするのもいいが、 Boost.Rangeを使えばついでにstd::vectorなんかも渡せるようになってお得かもしれない。 ただしコードが難解になりやすいきらいがある。 #include <iostream> #include <numeric> #include <boost/range.hpp> template<typename RandomAccessReadableRange> typename boost::range_value<RandomAccessReadableRange>::type average(RandomAccessReadableRange& r) { typedef typename boost::range_value<RandomAccessReadableRange>::type value_type; return std::accumulate(boost::begin(r), boost::end(r), value_type()) / boost::size(r); } int main() { int arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9}; std::cout << average(arr) << std::endl; }
182 名前:176 mailto:sage [2006/10/09(月) 12:05:08 ] なるほど…Cでは引数として渡すしかないんですね。 実はC++はまだ勉強してないんですが、これを機に勉強してみようと思います。 みなさんご丁寧にありがとうございました!
183 名前:デフォルトの名無しさん mailto:sage [2006/10/10(火) 17:29:20 ] >>182 Cなら配列と要素数を構造体にまとめる方法もある。 配列の要素数を知りたいという問題の解決には全くなっていないが、多少管理が楽になる?
184 名前:デフォルトの名無しさん mailto:sage [2006/10/11(水) 03:17:22 ] >>151 がいいこといった。みんあ、よく聞いておけよ!
185 名前:デフォルトの名無しさん mailto:sage [2006/10/11(水) 22:40:17 ] 連想配列みたいなことをしたいのですが質問です。 以下コードです。 #include <stdio.h> #include <string> #include <vector> int main(){ std::vector<std::string> data;//連想配列を想定 enum key_type {name,street,tel} _key; //name=val_name&street=val_street&tel=val_tel //この文字列を分割して、一番目のkeyとvalueを取り出す std::string key="name"; std::string value="val_name"; //連想配列と仮定して代入したいのですが、 //'_STL::string' から 'key_type' へのキャストはできないというエラーがでます data[(key_type)key]=val_name; printf("%s",data[(type)key].c_str()); return 0; } 文字列を分割して取り出した、key値を列挙型の値にできれば うまく連想配列に代入できるんですが、上のようなコードで 動くようにできないでしょうか。 よろしくお願いします。
186 名前:デフォルトの名無しさん mailto:sage [2006/10/11(水) 22:47:07 ] 訂正お願いします。 ×data[(key_type)key]=val_name; ○data[(key_type)key]=value; もうちょっとはっきり違う名前にすればよかったですが、 _keyは列挙型で、keyはstd::string型です。 よろしくお願いします。
187 名前:デフォルトの名無しさん mailto:sage [2006/10/11(水) 22:55:28 ] >>185 key_typeのname, street, telなどといった列挙子は、 コンパイル時定数で、基本的に実行時に参照する方法はない。 C++は、どちらかというと何でも静的(コンパイル時)に解決するのが特徴。 どうしても実行時に文字列から列挙子を取り出したければ、 std::map<std::string, key_type>を使えば何とかなるだろうが、 だったら、初めからそのdataをstd::map<std::string, std::string>にすればいいだろということになるわけで。
188 名前:デフォルトの名無しさん mailto:sage [2006/10/11(水) 22:57:01 ] std::map<std::string, std::string>
189 名前:デフォルトの名無しさん mailto:sage [2006/10/11(水) 23:07:25 ] >>187 >>188 std::map検索してみました。 連想配列みたいなことができそうですね。 ありがとうございました。
190 名前:デフォルトの名無しさん mailto:sage [2006/10/11(水) 23:11:07 ] まあvectorでも大きめに取っておいて、push_heap()などのアルゴリズムを 使って、中にはstd::pair<std::string, std::string>を入れておけばそこそこの 速度は出るが。
191 名前:デフォルトの名無しさん mailto:sage [2006/10/11(水) 23:34:12 ] >>189 みたいな事じゃなくてそのまんま。
192 名前:デフォルトの名無しさん mailto:sage [2006/10/11(水) 23:35:36 ] うわっごめん std::search_heap()ってalgorithmにはないのね。 素直にstd::sort掛けてからstd::binary_search()使うしかないか。
193 名前:デフォルトの名無しさん mailto:sage [2006/10/11(水) 23:40:22 ] Loki::AssocVectorという手もある。
194 名前:デフォルトの名無しさん mailto:sage [2006/10/12(木) 00:11:20 ] >>193 それ良さそうだね。今std::mapと、std::pairをぶち込んだstd::vectorを 作って比較したら、std::mapの方がstd::vectorのstd::lowerbound()を 使ったバージョンより2倍速かった。自分の環境でですが。
195 名前:デフォルトの名無しさん mailto:sage [2006/10/12(木) 07:01:35 ] for(double t=0;t<100;t+=0.1) { ///// } このようなforループで、変数tを増加させているのですが、 途中でtの値を出力すると、 10.000000000018849 のように、小さな誤差が蓄積しています。 割り算とかはではなく、単純な足し算のみしかしていないのですが、 このような誤差はどこから来るのでしょうか?
196 名前:デフォルトの名無しさん mailto:sage [2006/10/12(木) 07:15:11 ] 0.1 を有限桁数の二進数で厳密に表現することができないから。 それにしても誤差が大きいな。こっちだと 10 に対応するのは 9.9999999999999805。 理論的には 0.1 を有限桁数の二進数で表したときの誤差が 1e-16 くらいで、 これを 10/0.1 = 100 回くらい足すから 1e-14 くらいの誤差になるはずだけど。 こっちの結果はそれに適合してるんだけどなあ。
197 名前:デフォルトの名無しさん mailto:sage [2006/10/12(木) 13:15:49 ] なにか誤差を蓄積しない方法はないでしょうか? for(double t=0;t<1000;t+=1) { ///// } とかなら、誤差が蓄積しないのでしょうか?
198 名前:デフォルトの名無しさん mailto:sage [2006/10/12(木) 15:13:38 ] >>197 基本的に浮動小数は誤差が入ると思え。 ループ回数が重要ならループ変数は必ず整数にするのが原則。 ただし、 >>197 の例だと(おそらく)誤差は全く出ない。 詳しくは浮動小数の表現(IEEE754方式)を調べるべし。
199 名前:デフォルトの名無しさん mailto:sage [2006/10/15(日) 17:42:36 ] windowsのマルチスレッド、排他制御についてなのですが、 こちらでも良かったでしょうか。 スレッドA,B,Cがあるとします。 このA,B,CをCriticalSectionクリティカルセッションを使うと 他のスレッドが処理していたらお互いに待つことになると思います。 そうじゃなくって、 Aが処理しているときはB,Cはストップ Bが処理しているときは他のスレッドは待たない Cが処理しているときは他のスレッドは待たない ということがしたいです。 クリティカルセッション使うと、B,Cが処理しているときも 他のスレッドが待つことになってしまいます。 Aの排他制御する区間に入るまでに、B,Cは区切りのいいところまで処理して(ループの最後など) 待機をさせるというイメージです。 Aのスレッドだけコードのイメージです。 void thread_A(void){ //いろんな処理 //B,Cを区切りのいいところで、待機させる命令 EnterCriticalSection(§ion); //排他制御 LeaveCriticalSection(§ion); //いろんな処理 } 説明がくどくてすみません。 そもそもクリティカルセッションの話じゃないんでしょうか。 よろしくお願いします。
200 名前:デフォルトの名無しさん mailto:sage [2006/10/15(日) 18:03:24 ] 1.マルチスレッドプログラミング相談室に行く 2.Win32API質問箱に行く 3.最高にド低脳な発言してください in ム板に行く
201 名前:デフォルトの名無しさん mailto:sage [2006/10/15(日) 18:24:04 ] クリティカルセクションだし
202 名前:デフォルトの名無しさん mailto:sage [2006/10/15(日) 18:25:50 ] セマフォでも使えば?
203 名前:デフォルトの名無しさん mailto:sage [2006/10/15(日) 22:09:46 ] >>200 スレッドご紹介ありがとうございます。 前に専門スレいったことあるのですが、初心者スレ行けって いわれたこがあったりしたので難しいです。(汗 移動しようと思いましたが回答いただけたので、 今回はすみませんがよろしくお願いします。
204 名前:デフォルトの名無しさん mailto:sage [2006/10/15(日) 22:10:38 ] >>201 ,202 クリティカルセッションじゃダメですか。 セマフォじゃないのですが考えてみました。 グローバル変数flagを使います。 flagが1の時、スレッドAは実行、他B,Cは待機(Sleep) flagが0の時、スレッドB,Cは実行、Aは実行しない(待機もしない) void thread_A(void){ while(1){ //はじめにflagを立てる flag=1; //いろんな処理 //Aの処理が終わるので寝てたB,Cを起こすためflag=0 flag=0; } } void thread_B(void){ while(1){ //はじめにflagをチェックして、値が1ならSleep while(flag==1){Sleep(1000);} //いろんな処理 } } //thread_Cも同様の内容です これで実現できそうです。 セマフォについてですが、今回の処理に当てはめて考えるのが難しいのですが、 スレッドA,B,Cそれぞれ、どのような処理が必要かヒントいただけないでしょうか。
205 名前:デフォルトの名無しさん mailto:sage [2006/10/15(日) 22:44:59 ] セマフォが難しいなら、ミューテックスを使えばいいじゃない
206 名前:デフォルトの名無しさん mailto:sage [2006/10/15(日) 23:49:50 ] >>204 Section ↑これなんて発音するか知ってる?
207 名前:デフォルトの名無しさん mailto:sage [2006/10/16(月) 00:26:09 ] セッション
208 名前:デフォルトの名無しさん mailto:sage [2006/10/16(月) 00:45:41 ] セシーチオン
209 名前:デフォルトの名無しさん mailto:sage [2006/10/16(月) 03:01:03 ] あれれ、 クリティカルセッション × クリティカルセクション ○ でしたか。はずかしい。 ネットで検索してるときに、脳内で変換して クリティカルセッションでもひっかかるので、 ごちゃごちゃにしてました。 >>205 お互いに排除する相互排除するサンプルとか見かけるんですが、 今回みたいにAが一方的に他を排除するっていうのが、どうなんでしょうか。 ミューテックスも勉強して考えて見ますが、掃き溜めレベルの僕としては Sleepを使うのに気づいたのは奇跡でした。
210 名前:デフォルトの名無しさん mailto:sage [2006/10/16(月) 06:04:09 ] >>202 ミューテックス調べてみました。 一度にひとつのスレッドしか動かせないみたいなんですが、 今回の場合Aのときはひとつで動かしたいのですが、B,Cは同時に動くのちょっと 違うでしょうか。
211 名前:デフォルトの名無しさん mailto:sage [2006/10/16(月) 11:29:58 ] 違います
212 名前:デフォルトの名無しさん mailto:sage [2006/10/16(月) 11:46:21 ] 取ってすぐ戻せ
213 名前:デフォルトの名無しさん mailto:sage [2006/10/16(月) 17:03:36 ] void thread_A(void){ WaitForSingleObject(hMutex,INFINITE); while(1){ //いろんな処理 } ReleaseMutex(hMutex); } void thread_B(void){ //取ってすぐ戻す WaitForSingleObject(hMutex,INFINITE); ReleaseMutex(hMutex); while(1){ //いろんな処理 } } //スレッドCも同様 これで大丈夫と思うのですが、きちんと処理できてますでしょうか? linuxでいうlock,unlockでもできそうな気がしますが、同じようなものでしょうか。
214 名前:デフォルトの名無しさん mailto:sage [2006/10/16(月) 17:13:38 ] OS限定されるけど、 A は EntrerCriticalSection() / LeaveCriticalSection() して B,C は TryEnterCriticalSection() しちゃダメ?
215 名前:デフォルトの名無しさん mailto:sage [2006/10/16(月) 20:17:33 ] ひどいなそりゃ
216 名前:デフォルトの名無しさん mailto:sage [2006/10/16(月) 22:01:39 ] >>204 ヒント。 最大カウント2のセマフォを作る。 A は2回待ってすることしたら2つ手放す。 B と C は1回待ってすることしたら1つ手放す。
217 名前:デフォルトの名無しさん mailto:sage [2006/10/16(月) 23:44:13 ] >>216 それだとAも待ち状態になっちゃうよ。
218 名前:デフォルトの名無しさん mailto:sage [2006/10/16(月) 23:58:59 ] JavaやってからC++やると C++ってオブジェクト変数の宣言だけでインスタンス化されるのが気持ち悪い。
219 名前:デフォルトの名無しさん mailto:sage [2006/10/17(火) 00:35:31 ] 199 の条件に A が待ち状態になってはならないという制約はない。 というか A が仕事している間 B、C を停止させる必要がある以上それは必須だろ。
220 名前:デフォルトの名無しさん mailto:sage [2006/10/17(火) 00:46:14 ] >>219 君、大丈夫?
221 名前:デフォルトの名無しさん mailto:sage [2006/10/17(火) 01:05:55 ] >>214 ありがとうございます。 なるほどです。EntrerCriticalSectionでも大丈夫な可能性があるんですか。 ただいま、セマフォでいっぱいいっぱいなのであとで必ず調べてみます。 >>216 ヒントありがとうございます。 コードはアドバイスいただいた通り、下のようにしてみました。 void thread_A(void){ //2回待つ WaitForSingleObject;@ WaitForSingleObject;A while(1){ //いろんな処理 } //セマフォ2つ開放 ReleaseSemaphore; } void thread_B(void){ //1回待つ WaitForSingleObject; while(1){ //いろんな処理 } //セマフォ1つ開放 ReleaseSemaphore; } //スレッドCも同様 処理の順番ですが、下記で当たってますでしょうか。(続く)
222 名前:デフォルトの名無しさん mailto:sage [2006/10/17(火) 01:07:34 ] ・セマフォは2あるので、@、Aを通ってスレッドAが実行->セマフォ2開放されます ・セマフォ2あるので、スレッドB,Cが実行 2順目なんですが、 ・スレッドB,Cのどちらかの処理が終わって、ひとつセマフォが開放されて@を通過。 ・次に処理が遅れているB,Cのどちらかの処理が終わって、ひとつセマフォが開放されてAを通過。 ・スレッドAが実行される。 っていうループになりますでしょうか。 セマフォの基本がまだわかっていないので、スレッドBがReleaseSemaphoreしたと セマフォが1残っているので、またスレッドBが実行されないかとか変なこと考えてしまいます。 この辺はwaitがキューで入っているとかそういうことなのかと思って調べてみます。 >>220 違う方法もあるんでしょうか。 よかったら、アドバイスよろしくお願いします。
223 名前:デフォルトの名無しさん mailto:sage [2006/10/17(火) 01:08:14 ] 処理の順番が「当たってる」とかいう発想が信じらられん。当てずっぽうかよ。
224 名前:デフォルトの名無しさん mailto:sage [2006/10/17(火) 01:14:53 ] >>222 たしかに、動いているの確認すればいいですが、 理解力に自身がないので、これであっているのか心配でして。。。
225 名前:デフォルトの名無しさん mailto:sage [2006/10/17(火) 01:38:01 ] 223のようなやつが、初心者にどんどん抜かれていくんだよな。 かわいそう。
226 名前:デフォルトの名無しさん mailto:sage [2006/10/17(火) 04:07:42 ] つーか、そもそも>>204 でOK。 1sec(あるいはいくらか)のループが気に入らなければ>>213 でOK。 何が気に入らんの?
227 名前:デフォルトの名無しさん mailto:sage [2006/10/17(火) 05:34:19 ] >>226 初心者なので、せっかくヒントもいただいたので、 セマフォも勉強したいと思いまして。 現状ですが悪戦苦闘中でして、下記のコードになりました。 void thread_A(){ while(1){ WaitForSingleObject(hSemaphore,INFINITE); printf("AのWaitForSingleObject1を通過\n"); WaitForSingleObject(hSemaphore,INFINITE); printf("AのWaitForSingleObject2を通過\n"); for(int i=0;i<5;i++){ printf("Aの処理中なのでB,C割り込んじゃダメ\n"); //Sleep(1000); } ReleaseSemaphore(hSemaphore,2,NULL); } } void thread_B(){ while(1){ //1回待つ WaitForSingleObject(hSemaphore,INFINITE); printf("BのWaitForSingleObjectを通過\n"); //セマフォ1つ開放 ReleaseSemaphore(hSemaphore,1,NULL); printf("Bのセマフォ1つ開放しました\n"); //Sleep(1000); } } //Cも同様
228 名前:デフォルトの名無しさん mailto:sage [2006/10/17(火) 05:35:48 ] >>227 の続きです。 Sleep入れると大丈夫ですが、Sleep入れないと割り込み入ります。 できているようないないような。プログラミングがだめなので、わかりにくいです。 Sleep無いとだめということは、たぶん、だめってことですよね。 Sleepありは、出力下記のようになります。 AのWaitForSingleObject1を通過 AのWaitForSingleObject2を通過 Aの処理中なのでB,C割り込んじゃダメ Aの処理中なのでB,C割り込んじゃダメ Aの処理中なのでB,C割り込んじゃダメ Aの処理中なのでB,C割り込んじゃダメ Aの処理中なのでB,C割り込んじゃダメ Aのセマフォ2つ開放しました BのWaitForSingleObjectを通過 Bのセマフォ1つ開放しました CのWaitForSingleObjectを通過 Cのセマフォ1つ開放しました <繰り返しです。>
229 名前:デフォルトの名無しさん mailto:sage [2006/10/17(火) 05:47:55 ] すみません。コード改行入れているときに消してしまったところあります。 ごちゃごちゃしてすみません。 printf("Aのセマフォ2つ開放しました\n"); がなたったようです。 void thread_A(){ while(1){ WaitForSingleObject(hSemaphore,INFINITE); printf("AのWaitForSingleObject1を通過\n"); WaitForSingleObject(hSemaphore,INFINITE); printf("AのWaitForSingleObject2を通過\n"); for(int i=0;i<5;i++){ printf("Aの処理中なのでB,C割り込んじゃダメ\n"); //Sleep(1000); } printf("Aのセマフォ2つ開放しました\n"); ReleaseSemaphore(hSemaphore,2,NULL); } } void thread_B(){ while(1){ //1回待つ WaitForSingleObject(hSemaphore,INFINITE); printf("BのWaitForSingleObjectを通過\n"); //セマフォ1つ開放 printf("Bのセマフォ1つ開放しました\n"); ReleaseSemaphore(hSemaphore,1,NULL); //Sleep(1000); } } //Cも同様
230 名前:デフォルトの名無しさん mailto:sage [2006/10/17(火) 06:16:11 ] thread_B()のSleepの位置が違うし、 眠くてもう脳がだめみたいです。ほんとごめんなさい。 あと、割り込んでなかったみたいです。 Sleep無しの一部を切り取りましたが、 AのWaitForSingleObject1を通過後は、B,C割り込んでいいんでした。 AのWaitForSingleObject2を通過後は、B,C割り込めなければいいんですね。 ほんと、お騒がせしました。 あと<<217さんのご指摘が気になるのですが。 AのWaitForSingleObject1を通過 CのWaitForSingleObjectを通過 Cのセマフォ1つ開放しました BのWaitForSingleObjectを通過 Bのセマフォ1つ開放しました AのWaitForSingleObject2を通過 Aの処理中なのでB,C割り込んじゃダメ Aの処理中なのでB,C割り込んじゃダメ Aの処理中なのでB,C割り込んじゃダメ Aの処理中なのでB,C割り込んじゃダメ Aの処理中なのでB,C割り込んじゃダメ Aのセマフォ2つ開放しました
231 名前:デフォルトの名無しさん mailto:sage [2006/10/17(火) 06:21:24 ] >>217
232 名前:デフォルトの名無しさん mailto:sage [2006/10/17(火) 08:55:09 ] >>230 きみは 216 のヒントを理解する能力があった。 217 は 216 のヒントを理解する能力がなかった。 ただそれだけのことなんで気にしなくてもいい。
233 名前:デフォルトの名無しさん mailto:sage [2006/10/17(火) 16:43:48 ] カウント2のセマフォを使う必然性なんてどこにもないよ。
234 名前:デフォルトの名無しさん mailto:sage [2006/10/17(火) 16:54:36 ] やりたいことをまとめると、 ・スレッドAが実行中は、B・Cは待機する ・スレッドBあるいはCが実行中は、Aは待機する ・スレッドB・Cは同時に実行できる ってことか? だったらカウント2のセマフォが必要だね。
235 名前:デフォルトの名無しさん mailto:sage [2006/10/18(水) 01:22:24 ] >>232 ありがとうございます。 >>233 セマフォっぽくないですが、ミューテックスのときみたいに、 取ってすぐ戻すと同じ動きになりそうですね。 って実はネットに書いてありました。 >>234 はい、やりたいことそれです。 いろんな方法一気に覚えられてよかったです。 ありがとうございました。
236 名前:デフォルトの名無しさん mailto:sage [2006/10/18(水) 04:27:33 ] >>235 >>234 の仕様だとすると、>>229 のコードでは駄目だよ。 Aが連続してセマフォを獲得する保証は無く、Aがひとつ、Bがひとつ獲得した状態で Cが待ち状態になる場合もある。それでいいならいいんだけど・・・。
237 名前:デフォルトの名無しさん mailto:sage [2006/10/18(水) 07:54:55 ] >>236 Sleep無しで実行したときなのですが、 >>230 の結果を見ると Aがひとつ、Cがひとつ獲得した状態で Bが待ち状態になっているようなんですが。 Aがひとつ、Bがひとつ、Cが待ちというのもあると思います。 >Aが連続してセマフォを獲得する保証は無く Aが連続してセマフォを獲得する保証は、 どのようにすればよいでしょうか。 Aが連続で取れるように、B,CにSleepなど何か 処理をするということでしょうか?
238 名前:デフォルトの名無しさん mailto:sage [2006/10/18(水) 14:59:52 ] >>237 Windowsに詳しくないのでこれだという解決策は示せませんが、この問題は 「read write lock問題」として有名です。 ・誰も読んでないときは書ける ・誰かが書いてるときは書き終わるまで読めない ・誰かが読んでいるときは読み終わるまで書けない ・誰かが読んでいても読める 今回の例ではAが書き込みスレッド、B,Cが読み取りスレッドとして対応させると わかると思います。 windows read write lock windows read write synchronization などのkeywordで検索すれば、根本的な解決策が見つかるはずです。
239 名前:デフォルトの名無しさん mailto:sage [2006/10/18(水) 18:56:53 ] >>238 そういうことでしたか。 「Aがひとつ、Bがひとつ獲得した状態で Cが待ち状態になる場合」 はAがひとつ取っても、まだ待機している状態なので、 A,C待機、Bが実行という場合もありますね。 ただ、>>234 には矛盾して無いので、 今回は、これもあって大丈夫ということにしたいと思います。 まとめますと、変更無いですが、 ・スレッドAが実行中は、B・Cは待機する ・スレッドBあるいはCが実行中は、Aは待機する ・スレッドB・Cは同時に実行できる(片方だけのときもある) ということになると思います。 「read write lock問題」さっそく勉強してみます。 ありがとうございました。
240 名前:デフォルトの名無しさん [2006/10/19(木) 20:22:09 ] 以下のプログラムをコンパイルする時点ではエラーはでません。 しかし、できたexeを実行するとエラーがでます。 どうしてでしょうか?おしえてください。 ちなみにコンパイラはBCC5.5.1です。 #include <stdio.h> #include <string.h> struct a { int no; char name[64]; }; int main(void) { struct a data[2]; data[1].no = 1; strcpy(data[1].name,"name1"); data[2].no = 2; strcpy(data[2].name,"name2"); printf("No.%d\n", data[1].no); printf("%s\n", data[1].name); printf("No.%d\n", data[2].no); printf("%s\n", data[2].name); return(0); }
241 名前:デフォルトの名無しさん mailto:sage [2006/10/19(木) 20:35:09 ] struct a data[3];
242 名前:240 [2006/10/19(木) 21:13:34 ] あ、できました。ありがとうございます。 でも何でですか?
243 名前:デフォルトの名無しさん [2006/10/19(木) 21:22:51 ] >>240 struct a data[2]; data[0]: 先頭の構造体a data[1]: 二番目の構造体a data[2]: 三番目の構造体a <-定義されていない
244 名前:デフォルトの名無しさん mailto:sage [2006/10/19(木) 21:23:28 ] 配列の章をまた初めから読み返してみろ
245 名前:240 mailto:sage [2006/10/19(木) 21:28:02 ] ああ、わかりました。0から始まるんですね。 すいません。おさわがせしました。
246 名前:デフォルトの名無しさん [2006/10/19(木) 21:33:29 ] 質問です。 エラー E2209 test.cpp 1: インクルードファイル 'vcl.h' をオープンできない エラー E2303 test.cpp 3: 型名が必要 エラー E2034 test.cpp 3: 'char *' 型は 'int' 型に変換できない エラー E2303 test.cpp 4: 型名が必要 エラー E2034 test.cpp 4: 'char *' 型は 'int' 型に変換できない エラー E2293 test.cpp 4: ) が必要 エラー E2141 test.cpp 6: 宣言の構文エラー とでてコンパイルできません…
247 名前:デフォルトの名無しさん [2006/10/19(木) 21:40:33 ] >>246 ソースを見せてみ
248 名前:デフォルトの名無しさん [2006/10/19(木) 21:46:38 ] こちらです #include <vcl.h> #pragma hdrstop USERES("test.res"); USEFORM("Unit1.cpp", Form1); //--------------------------------------------------------------------------- WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) { try { Application->Initialize(); Application->Title = "test"; Application->CreateForm(__classid(TForm1), &Form1); Application->Run(); } catch (Exception &exception) { Application->ShowException(&exception); } return 0; }
249 名前:デフォルトの名無しさん mailto:sage [2006/10/19(木) 22:35:31 ] 君はVCLをもっているのか?
250 名前:デフォルトの名無しさん [2006/10/20(金) 00:00:25 ] 2時間前くらいからCを勉強し始めたんですが、うまくいきません。 半径を入力して球の体積と面積を求めるってやつなんですけど、 入力が反映されなくて。 #include <stdio.h> #include <math.h> void main() { double rad, surface, volume; printf("\nPlease input a radius. "); scanf("%f",&rad); printf("Radius = %f \n",rad); surface = 4 * M_PI * rad * rad; volume = 4 / 3 * M_PI * rad * rad * rad; printf("S = %f V = %f \n",surface,volume); }
251 名前:デフォルトの名無しさん mailto:sage [2006/10/20(金) 00:08:38 ] >>250 そのプログラムを動かし、たとえば1と入力するとどうなる?
252 名前:デフォルトの名無しさん mailto:sage [2006/10/20(金) 00:34:47 ] 4/3=1