[表示 : 全て 最新50 1-99 101- 201- 301- 401- 501- 601- 701- 801- 901- 2chのread.cgiへ]
Update time : 01/29 10:31 / Filesize : 249 KB / Number-of Response : 964
[このスレッドの書き込みを削除する]
[+板 最近立ったスレ&熱いスレ一覧 : +板 最近立ったスレ/記者別一覧] [類似スレッド一覧]


↑キャッシュ検索、類似スレ動作を修正しました、ご迷惑をお掛けしました

はきだめC/C++下級者の質問箱 2



1 名前:デフォルトの名無しさん [2006/08/22(火) 09:21:31 ]
はきだめのスレへようこそ

ここは、C/C++に挫折し、それにもかかわらず、C/C++やらなければならない者達がたむろするスレです。
なお、質問する人は回答はあまり期待しないでください。


前スレ:はきだめC/C++下級者の質問箱
pc8.2ch.net/test/read.cgi/tech/1124256027/

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

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)するのと
どう違うのかと疑問に思ってました。例外処理のメリットというか。。
上記のような問題を解決する機構が例外というのはどういうことなんでしょうか。

何かキーワードだけでも教えていただけたらできるだけ自分で調べてみます。。






[ 続きを読む ] / [ 携帯版 ]

前100 次100 最新50 [ このスレをブックマーク! 携帯に送る ] 2chのread.cgiへ
[+板 最近立ったスレ&熱いスレ一覧 : +板 最近立ったスレ/記者別一覧]( ´∀`)<249KB

read.cgi ver5.27 [feat.BBS2 +1.6] / e.0.2 (02/09/03) / eucaly.net products.
担当:undef