- 1 名前:デフォルトの名無しさん [2006/08/22(火) 09:21:31 ]
- はきだめのスレへようこそ
ここは、C/C++に挫折し、それにもかかわらず、C/C++やらなければならない者達がたむろするスレです。 なお、質問する人は回答はあまり期待しないでください。 前スレ:はきだめC/C++下級者の質問箱 pc8.2ch.net/test/read.cgi/tech/1124256027/
- 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
- 253 名前:デフォルトの名無しさん [2006/10/20(金) 00:36:25 ]
- >>251
0.000000 です。
- 254 名前:デフォルトの名無しさん mailto:sage [2006/10/20(金) 00:38:37 ]
- >>253
S = とか V = とか表示されねーのか。そりゃ不思議だな。
- 255 名前:デフォルトの名無しさん mailto:sage [2006/10/20(金) 00:40:50 ]
- うまくいかない、じゃなくて、何を期待してどういう結果になったのか書くべし。
それ以前に、勉強開始たった2時間半程度で人に聞くのはどうかと。 その時点では分からないことだらけで当然だろう。 とりあえずは参考書などで基本事項を一通り勉強したら? %f → %lf
- 256 名前:デフォルトの名無しさん mailto:sage [2006/10/20(金) 00:57:06 ]
- >>255
どうもありがとうございます。 参考書の例題だったんですが、 書いてある通りやってもうまくいかなくて。
- 257 名前:デフォルトの名無しさん [2006/10/20(金) 01:02:34 ]
- 関数の中で関数別の関数呼んで、またそのなかで別の関数を…っていうふうに
階層が深くなってるとき、下のほうで起こったエラーはどこで処理するのがいいんですか。 一番下なのか…?はたまた上までエラーコード引っ張っていって一番上なのか…? また上まで引っ張っていった場合、その途中の関数で起こったエラーコードとかぶらないようにするために 考えると、エラーコードの種類がすごく肥大化してしまったんですけど、 こういうものなんでしょうか?
- 258 名前:デフォルトの名無しさん mailto:sage [2006/10/20(金) 01:08:04 ]
- >>257
C では、そういうもの。 そういう問題への対策が、最近の言語に備わっている例外処理機構。 C++ にもある。
- 259 名前:デフォルトの名無しさん mailto:sage [2006/10/20(金) 01:14:09 ]
- >>258
なるほど。そういうものなんですか。 ありがとうございます。 後例外処理なんですが、実はあまり理解していなくて、try catchする(c++)のと、戻り値判定(c)するのと どう違うのかと疑問に思ってました。例外処理のメリットというか。。 上記のような問題を解決する機構が例外というのはどういうことなんでしょうか。 何かキーワードだけでも教えていただけたらできるだけ自分で調べてみます。。
- 260 名前:デフォルトの名無しさん mailto:sage [2006/10/20(金) 01:23:15 ]
- >>259
C++ の例外処理機構を使えば、エラーは発生した その場所で迷わず throw すればいい。 エラーを処理する場所や方法は使用者が選べる。 ↓のスレに情報がいくらか貯まっている。 例外処理 pc8.2ch.net/test/read.cgi/tech/1142667446/
- 261 名前:デフォルトの名無しさん mailto:sage [2006/10/20(金) 01:23:54 ]
- try {
func1 +func2-1 +func3 --(A) +func2-2 --(B) } catch (...) { // エラーきた --(C) } のように奥の func3 で例外を発行すると、func1 の途中部分であっても きれいに脱出して(デストラクタの面倒は見て) (C) に到達できる。 この例の場合、(B) は実行されない
- 262 名前:デフォルトの名無しさん mailto:sage [2006/10/20(金) 01:33:57 ]
- >>260
上まで引っ張っていかなくてもいいってこと…ですよね? なるほどそれだとたしかにエラー処理が綺麗に書けそうな気がします。 スレのほうも熟読してみます!ありがとうございました。 >>270 なるほど!これはわかりやすいです。 これは便利なんですね… いままでせっかくc++のコンパイラ使ってたのに全部戻り値判定で引っ張っていたのが すごく時間と労力を無駄にしてたきがしてきました…大げさかもしれませんがw こんな機能ならぜひ例外処理を勉強してうまく使っていくようにしたいとおもいました。 どうもありがとうございました。
- 263 名前:デフォルトの名無しさん mailto:sage [2006/10/20(金) 02:06:14 ]
- 基本的に例外処理は便利で有意義なもの。
がんがん使え。 が、C++に限っては、性能を気にしだすと封印せざるを得なくなる諸刃の刃。 でもやっぱりがんがん使え。 使い慣れないとデストラクタ周りで戸惑ったりするので、経験値稼ぐためにもばんばん使え。 デメリットのことは後で考えればよい。
- 264 名前:デフォルトの名無しさん mailto:sage [2006/10/20(金) 02:19:37 ]
- はい。ガンガン使っていくようにしたいです。
何かのプログラムの本で、便利な機能は変なこだわりは捨ててどんどん使ったほうがいいって書いてたのを 読んだことがことがあります。 あとご指摘のデストラクタとの絡みのところもしっかり勉強したいと思います。
- 265 名前:デフォルトの名無しさん mailto:sage [2006/10/20(金) 02:29:18 ]
- へー、諸刃の刃なんて言葉も一応辞書に載ってるんだ。
普通は諸刃の剣だと思ってたけど。
- 266 名前:デフォルトの名無しさん mailto:sage [2006/10/20(金) 02:29:59 ]
- 指が滑ったんだ。
ケツの穴の小さいこというなよ。 刺さらないじゃないか。
- 267 名前:デフォルトの名無しさん mailto:sage [2006/10/20(金) 02:33:31 ]
- つーか、今まで「もろはのけん」だと思ってたよ。
ついでに正しい知識が身についてよかった。 ・・・・吉野家コピペくらいでしか使わないかもしれないが。
- 268 名前:デフォルトの名無しさん mailto:sage [2006/10/20(金) 10:57:54 ]
- うかつなこと書くなよ
剣がケツの穴に刺さったところ想像しちゃったじゃないか
- 269 名前:デフォルトの名無しさん mailto:sage [2006/10/20(金) 19:58:59 ]
- C++で例外と入ったら、性能よりも例外安全のほうがよっぽど心配になる。
- 270 名前:デフォルトの名無しさん mailto:sage [2006/10/21(土) 00:59:54 ]
- そいつもいちいちごもっとも。
- 271 名前:デフォルトの名無しさん mailto:sage [2006/10/21(土) 01:38:49 ]
- 質問失礼します。
stringに入っている文字列を char* に変換したいのですが 良い知恵はありますでしょうか。 const char* では無く char* にしたいのです。 今のところ思いつくのは、自前で char* の領域を確保して そこに c_str() の内容をコピーすれば問題は無いかと思うのですが せっかく便利なクラスがあるのに、何だか冗長な気がします。 一応調べた限りでは const_cast という物があるようですが const_castした文字列にアクセスした場合の動作は未定義という 記述がされていたりするのでそれはちょっと無いかな、と思います。
- 272 名前:デフォルトの名無しさん mailto:sage [2006/10/21(土) 01:54:43 ]
- >>271
std::vector<char>でも使えば?
- 273 名前:デフォルトの名無しさん mailto:sage [2006/10/21(土) 01:59:47 ]
- const_castは古いライブラリの機能を無理やり使いたい時とかのためだけに用意されてる様なもん。
基本的に使っちゃ駄目。 で、const_castを止めておきながら、こんなコードを薦めるのは激しくナニなんだが、 std::stringは添え字演算子が使える。 ので、一応 std::string str = "nullpo"; char* p = &str[0]; みたいな書き方はできないわけじゃない。 やっちゃ駄目よ? 問題起こしたところも見たことは無いけど。
- 274 名前:デフォルトの名無しさん mailto:sage [2006/10/21(土) 02:29:31 ]
- >>271
>stringに入っている文字列を char* に変換したいのですが これが何を言っているかはっきりしないんだけど、 char *型の引数を要求するけど実際には渡した領域を更新することはない、 という関数に渡すというような使い方なら、const_castで問題ないと思う。 >const_castした文字列にアクセスした場合の動作は未定義 参照するだけなら問題ないんじゃなかったっけ? 文字列を更新する目的で char*型にしたいといっているなら、 自分で更新可能な領域にコピーするしかない。
- 275 名前:271 mailto:sage [2006/10/21(土) 03:05:01 ]
- >272-274
参考になります。 今回の場合、実際は更新しない文字列だったので >274さんの言う通りconst_cast使っても問題はあまり無さそうです。 ただ、更新する文字列のことも考えると 自前で確保する方法も覚えて損はなさそうですね。 std::vector はまだ使った事がありませんが覚えておきます。 ありがとうございました。
|

|