08/12/04 10:19:18
>>259
引っかけ問題に引っかかったね。
「小数点1ケタまで等しい」→「小数点1ケタ目までの数字が同じ」
だから、丸めたら不正解。
263:名無しさん@お腹いっぱい。
08/12/04 10:24:13
if (fabs(a - b) < 0.1)
264:名無しさん@お腹いっぱい。
08/12/04 10:27:49
>>263
それだと 1.09 と 1.1 でも一致とみなされる
>>262 参照
265:名無しさん@お腹いっぱい。
08/12/04 10:31:23
>>262 は抜きして、丸める方式でOKだとしても、
>>263 だと 1.11 と 1.02 が一致と判定されるから駄目だな
266:名無しさん@お腹いっぱい。
08/12/04 10:42:06
1.11と1.02は偽
1.00と1.09は真
実際はこんな比較を行いたいわけがない。
267:名無しさん@お腹いっぱい。
08/12/04 10:48:37
>>266
数値符号の生成処理なんかだと、
文字通りの数字の一致を判定したいことがあるよ。
1.11と1.02は偽
1.00と1.09は真
そういう比較を行ないたい。
268:名無しさん@お腹いっぱい。
08/12/04 11:08:11
文字列化シロ
269:名無しさん@お腹いっぱい。
08/12/04 11:13:46
なんで誰も10倍してfloorしろとアドバイスしてやらないんだ
270:名無しさん@お腹いっぱい。
08/12/04 11:57:36
オーバーフローするかもしれんじゃん。
271:名無しさん@お腹いっぱい。
08/12/04 14:18:50
そんなでかいdoubleなら、小数点以下は0だから、別チェックを前に入れるだけ
272:名無しさん@お腹いっぱい。
08/12/04 20:04:28
>>269にツッコミを入れるなら floorでなくてIntだろ。
floorだと-2.0と-2.3が違う値になる。
だから不正解
それと実数は10倍してintだと化けることがあることを忘れるな。
整数部と小数部を分離して
整数部チェックの後
小数部の判定をすればいい
273:名無しさん@お腹いっぱい。
08/12/04 20:09:49
そろそろ正しいコード書いて見せろよ
274:名無しさん@お腹いっぱい。
08/12/04 22:02:12
珍しいスレが上がってると思ったら
なんだ、釣りか……
275:名無しさん@お腹いっぱい。
08/12/04 22:10:07
んじゃ、俺が。
int compare(double a, double b)
{
char s1[512], s2[512], p;
snprintf(s1, sizeof(s1), "%f", a);
if ((p = strchr(s1, '.')) && p[1])
p[2] = 0;
snprintf(s2, sizeof(s2), "%f", b);
if ((p = strchr(s2, '.')) && p[1])
p[2] = 0;
return !strcmp(s1, s2);
}
276:名無しさん@お腹いっぱい。
08/12/05 07:10:19
>>275
そんなことしなくても、
sprintf() で "%.1f" のフォーマットで文字列化すれば
最初から小数点以下第1位までで文字列カットできる。
277:名無しさん@お腹いっぱい。
08/12/05 07:16:16
>>276
アフォか。"%.1f" だと丸められてしまうだろ。
278:名無しさん@お腹いっぱい。
08/12/05 08:58:20
指摘される前になおしておこう。
int compare(double a, double b)
{
char s1[512], s2[512], *p;
snprintf(s1, sizeof(s1), "%f", a);
if ((p = strchr(s1, '.')) && p[1])
p[2] = 0;
snprintf(s2, sizeof(s2), "%f", b);
if ((p = strchr(s2, '.')) && p[1])
p[2] = 0;
return !strcmp(s1, s2);
}
279:名無しさん@お腹いっぱい。
08/12/05 09:27:12
>>278
別の指摘するよ。
"%f" は、デフォで小数以下6桁精度に丸められる。("%.6f"と同じ)
なので、1.9999999 が、2.0 に丸められてしまう。
280:名無しさん@お腹いっぱい。
08/12/05 10:44:50
ふむ、10倍するのも計算誤差で小数点第1位が変わる可能性があるな。
そもそも、外部表現から浮動小数点に変換した時点で誤差が発生するから、
BCD使えという結論か。
281:名無しさん@お腹いっぱい。
08/12/05 11:20:41
丸め方式はFPUに指定コードを与えれば変えることができる。
そもそも精度を取り違えている。6桁の精度に対して10桁の演算精度があるなら
最下位2桁部分の丸めで精度が狂うことはない。
それは最初の質問者が「文字」で質問していたことでも分かる。
今回の場合無理に比較するのではなくて
二つの引き算した結果の符号をとって(絶対値化)
その値から0.1引いた値が正ならfalse
というのが一番無難。
282:名無しさん@お腹いっぱい。
08/12/05 11:39:11
>>281
それ、>>263 と同じ。
263は、>>264-265 で否決。
283:名無しさん@お腹いっぱい。
08/12/05 12:04:28
IEEE 754 として、10倍して整数部をとったんじゃだめな具体例を誰かプリーズ。
284:名無しさん@お腹いっぱい。
08/12/05 13:03:09
>>283 仮数部フルにつかってたらだめだろ。
せめて整数化して小数部だけにしてからからという前提にシロ
285:名無しさん@お腹いっぱい。
08/12/05 13:15:16
だから、具体例を。
double f = 0.1;
f = floor(f*10.0);
printf("%d\n",f==1.0);
=> 1
だよ。
286:名無しさん@お腹いっぱい。
08/12/05 14:38:49
a = 300000000000000.3125;
b = 300000000000000.3750;
printf("%f %f %d\n", a, b, floor(a * 10) == floor(b * 10));
287:名無しさん@お腹いっぱい。
08/12/05 17:36:14
なるほど。わかったよ。
正に限ると、
floor(a) == floor(b) && floor((a-floor(a))*10) == floor((b-floor(b))*10)
でおけ?
288:258
08/12/05 23:03:41
ちなみに実数は0より小さいです。それで小数点2桁目を四捨五入したいです。
一応自分で作ったんですが
double x=0.15;
int a;
x+=0.05;
a=x*10;
x=(double)a/10.0;
これで大丈夫ですかね?
289:258
08/12/05 23:04:35
↑間違えました。0でなく1より小さいです。
290:名無しさん@お腹いっぱい。
08/12/05 23:05:41
>>267
お前らあほだな。
sprintfとstrncmpで解決だろ。
291:名無しさん@お腹いっぱい。
08/12/05 23:24:56
覆面算をマクロで解きたいのですが教えてください
B、C、Dは0を除外
C A B
+) B A C
----------------------
D A B A
292:名無しさん@お腹いっぱい。
08/12/05 23:29:42
マクロってm4あたり?
293:名無しさん@お腹いっぱい。
08/12/05 23:31:33
>>292
エクセルのマクロです
294:名無しさん@お腹いっぱい。
08/12/05 23:42:27
まったく板ちがいです。おひきとりください。
295:名無しさん@お腹いっぱい。
08/12/05 23:44:00
失礼しました
296:名無しさん@お腹いっぱい。
08/12/06 00:29:52
>>288
0より小さい実数は負なのだが…
中学数学をやり直せ。
297:名無しさん@お腹いっぱい。
08/12/06 10:16:03
>>296
0より小くて負よりも大きい数oがあるとしたら?
298:名無しさん@お腹いっぱい。
08/12/06 10:40:46
>>290
sprintf()する時に、"%f"の変換で勝手に四捨五入されるから不可。
299:名無しさん@お腹いっぱい。
08/12/06 10:48:11
>>297
そんな実数があるのか?
300:名無しさん@お腹いっぱい。
08/12/06 11:37:11
1.0以下なら
10倍説でいいけれど >>287はかっこが足りないだろ
それに正が前提と言うならfabsなりabsなりいれればいいじゃないか。
あとsprintf関連のつっこみは四捨五入(rint)じやなくてroundだろ。
もちょっと「道具の仕様」はしっておこうよ
double演算でも特定のライブラリーを使っていると高速化のため「singleモード」に設定していて
丸め誤差も出やすくなったりしていることもある。もっぱらWinに多いけど
逆にlong doubleにしておけば丸め精度はでにくい。
今回の場合しょっぱなの「見た目の数字」なんだからsprintfでの誤差は
最初に認識した文字列にも反映されているはず
1以下限定なら文字列の段階で整数として入力するか
文字列できるほうがいい
しかしネタとして考えるならばbit比較とかマニアックな関数とか
論理的に完璧なものとかそういうものの方がおもしろい。
というかUNIX板なんだからネタとして解を求めるならbc前提にするとか
仮数部のビット比較してみるとか特定ツールにしぼるか
FreeBSDでのextendedというかlong doubleでの精度アップとか
もうちょい下のほうにするとかにシチクリ
301:名無しさん@お腹いっぱい。
08/12/06 11:47:11
使えるツール、足りないツールを作る。それがプログラミング
できない人は覚えたい。できる人でも穴はある。
UNIXはツールが多いようでつなぎも情報もすくないんだから
貴重なスレをあんまり算数の遊びみたいなんでスレを消費するない。
やるならせめてbcとかシェルとか局所的なものにしちくれ
302:名無しさん@お腹いっぱい。
08/12/06 11:50:30
>>300
> >>287はかっこが足りないだろ
どこが?
> それに正が前提と言うならfabsなりabsなりいれればいいじゃないか。
単純に入れたら、正=負とかいう馬鹿な結果が出るから、めんどうだっただけ。
303:名無しさん@お腹いっぱい。
08/12/06 12:27:28
貴重なスレって、長寿スレでも狙ってるのか? w
実数演算の話題はあまりないので結構楽しかったぞ。
304:名無しさん@お腹いっぱい。
08/12/06 12:45:32
板違いと思っていたから参戦しなかったが、
その辺のことはアメリカ人が詳しくまとめてるよ。
やつらは実数部でドル、小数部でセントを表すことをよくやるから。
いろいろな言語にBCD演算を入れる提案がつきないのもそのため。
exact calculation floating point number あたりでググってくれ。
IEEE 754を仮定して近似計算で、BCD相当の結果を出すものがたくさんある。
中にはbit演算で正規化されたIEEE 754表現を扱うものまである。
現代のCOBOL、Javaのページにもこんなんがあるしな。(単純なものだけ)
URLリンク(java.sun.com)
305:名無しさん@お腹いっぱい。
08/12/06 12:46:37
今のペースだと、Part1なのに10年以上あるスレってか
306:名無しさん@お腹いっぱい。
08/12/06 12:51:59
>>304
それは、内部表現を固定小数というか、
全部セントに統一しなかったアメリカ人が馬鹿なだけのような
307:名無しさん@お腹いっぱい。
08/12/06 12:58:41
金利計算とかあるからセントが最小単位じゃダメだろ。
308:名無しさん@お腹いっぱい。
08/12/06 13:04:25
>>300
お前は roundのことは四捨五入と言わないのか?
あと、>>287 に括弧が足りないところなんてないし。
もうちょっと「日本語」と「道具の仕様」は知っておこうよ
309:名無しさん@お腹いっぱい。
08/12/06 13:17:07
>>307
じゃあやっぱりBCD一択。
310:名無しさん@お腹いっぱい。
08/12/06 13:19:59
>>300
おいおい、(s)printfの "%f" 変換は、round() じゃなくて rint() 方式だよ。
(確認済み)
311:名無しさん@お腹いっぱい。
08/12/06 13:21:18
ジンバブエ・ドルも計算できる桁数無いといかんな。
312:名無しさん@お腹いっぱい。
08/12/06 16:30:25
インストールしたプリンタの一覧ってどうやって
取得できるのですか?
313:名無しさん@お腹いっぱい。
08/12/07 00:33:16
>>309
組み込みでBCDがないなら、
オペレーター多重化がないとプログラム書きづらいな。
314:名無しさん@お腹いっぱい。
08/12/07 07:34:44
無知晒した >>300 の釈明まだぁ?
315:名無しさん@お腹いっぱい。
08/12/07 10:39:11
sprintfで少数第2位まで出しておいて、strncmpで小数点1桁の文字列と比べれば丸めも減ったくれもどうでもいいだろ。
316:名無しさん@お腹いっぱい。
08/12/07 11:47:04
>>315
だから、sprintf()で小数第2位まで出す際に、sprintf()自体で丸めが起きるんだよ。
printf("%.2f", 1.099) → 1.10 と表示
あと、×少数 ○小数な、日本語くらい正確に使おうよ。
317:名無しさん@お腹いっぱい。
08/12/07 11:51:42
>>315
sprintfで小数第2位まで出す際に、
小数第3位が丸められるから、
その結果、小数第1位に繰り上がってしまうことがある。
よって、>>315 の言ってることは不正解。
318:名無しさん@お腹いっぱい。
08/12/07 12:41:31
doubleの有効桁は15~16なので>>278を改造して17桁とれば良い。
int compare(double a, double b)
{
char s1[512], s2[512], *p;
snprintf(s1, sizeof(s1), "%.17f", a);
if ((p = strchr(s1, '.')) && p[1])
p[2] = 0;
snprintf(s2, sizeof(s2), "%.17f", b);
if ((p = strchr(s2, '.')) && p[1])
p[2] = 0;
return !strcmp(s1, s2);
}
319:名無しさん@お腹いっぱい。
08/12/07 12:46:13
>>318
…ネタだよな?
320:名無しさん@お腹いっぱい。
08/12/07 22:48:58
>>317
じゃあ4位まで出すか。
321:名無しさん@お腹いっぱい。
08/12/07 23:05:57
>>320
sprintfで小数第4位まで出す際に、
小数第5位が丸められるから、
その結果、小数第1位に繰り上がってしまうことがある。
よって、>>320 の言ってることは不正解。
322:名無しさん@お腹いっぱい。
08/12/07 23:51:11
小数点指定なしでいいな。
323:名無しさん@お腹いっぱい。
08/12/08 16:56:18
>>303 UNIX関連のプログラミングの情報源として密度が薄まる
別にスレが長寿になる必要はない。
>>302 のは結果として役立たずなわけだから「~れば」とかいうのはいいわけでしかない。
できたような気になっているだけだ。
>>308 roundが四捨五入なんてプログラミング言語はない。
知らないなら覚えろ。常識
四捨五入は意図的にコンパイラが切り捨てコード使ってで作るものだ。
カッコなしで複数の条件列挙は
は言語によりなければエラーになるものがある。
イコールでの条件列挙は適切とは言えない。
速いからdoubleなんだしdoubleのデータの問題で
「初めからBCDで」とか論外
324:名無しさん@お腹いっぱい。
08/12/08 17:16:43
>>323
roundは普通の意味での四捨五入。(2進だから0捨1入)
rintは四捨五入ではなく、偶数への丸め。常識。知らないなら覚えろ。
おまえ、sprintfの件で、roundとrintを混同して指摘してただろ。>>300 で。
> カッコなしで複数の条件列挙は
> は言語によりなければエラーになるものがある。
「言語により」って、最初から C言語の話してるんだろ。
演算子の優先順位も知らなかったくせに、見苦しい言い訳するなw
結論:
>>300 = >>323 は自意識過剰のものすごい知ったか。
お前の言葉をそのまま返す、
「もうちょっと『道具の仕様』は知っておこうよ」
325:名無しさん@お腹いっぱい。
08/12/08 17:46:18
「~れば」とか「初めからBCDで」とか「」使って引用してるふりしながら、
どれも正確じゃないんだよな。
自分独自の解釈を随所におりまぜてそう。
326:名無しさん@お腹いっぱい。
08/12/08 20:12:00
はいはい逆にしてましたよ。間違えてました。RINTとROUND
恥ずかしくも「正しい解説のメモ」とかアップしているていたらく
どうせアタシャ低レベルなアセンブラプログラマーですよ。
でも今回いつCが前提になったんですか?
JavaScriptとかPerlもありだとみてたんですがね、
独自解釈でもなんでもちゃんと動くものを仕様書こみでつくれるからいいんです。
でも今回の件は
long doubleにキャストして
i386 FreeBSDに関して言えば
fpsetprec(FP_PE)
を使って10倍して差をとり整数化すればいいんですよね、
仮数部が内部で64bitになるので丸め誤差でません。
最初から10byteモードっていってましたよね。
理解できなかった?
どうして型キャストとかできないんですか?
floorとかsprintとか無駄過ぎ
机上の論議過ぎて実用性ゼロ
その点を言っているんです。
道具としてのUNIXでなくて
UNIXのためのプログラミングノーハウの話をしないなら
板違いだっていっているんだ。
327:名無しさん@お腹いっぱい。
08/12/08 20:26:33
>>326
> でも今回いつCが前提になったんですか?
>>258の1行目
328:名無しさん@お腹いっぱい。
08/12/08 20:40:08
今回いつ、「実数」がdouble以下で、かつ、
long double が double より精度高いプラットフォームが前提になったんですか?
329:名無しさん@お腹いっぱい。
08/12/08 20:41:01
こういうバカがチームにいると大変だな。お前、向いてない転職しろ。
330:名無しさん@お腹いっぱい。
08/12/08 21:17:38
たしか、JavaScriptもPerlも&&より==の方が強いよなぁ。
しかもこいつらってlong double的なの明示的に使えたっけ?
331:名無しさん@お腹いっぱい。
08/12/08 21:35:22
使えないな。
しかも、FPU使うコードなんて今時見ないぞ。
332:名無しさん@お腹いっぱい。
08/12/08 23:37:10
>>329
普通はこんなしょうもない問題にぶち当たらないようにコーディングするもんだ。
お前の卓越した知能wがチームの効率下げてるんじゃね?
333:名無しさん@お腹いっぱい。
08/12/08 23:55:42
自信満々で「仕様書込みで動くものをつくれるからいい」とか豪語しながら
仕様を逆に覚えてヘッポコなバグを作りこむクズはいらない。
334:名無しさん@お腹いっぱい。
08/12/09 00:00:34
>>332
つっこみどころはそこだけなんかよ
技術的なことにつっこんでくれよ
335:名無しさん@お腹いっぱい。
08/12/09 11:02:08
>>326
> 10倍して差をとり整数化すればいいんですよね、
ここ意味わからんかった。
これじゃ差が0.1以下であるという判定しかできないんじゃないの?
やっぱりfloor的なものがどこかにいるんでは?
336:名無しさん@お腹いっぱい。
08/12/09 13:32:00
彼の完璧な仕様に文句をつけてはいけない。
337:名無しさん@お腹いっぱい。
09/01/14 17:04:18
この問題なんですが、解答あってるでしょうか?
msgbox "変数aの値は" & a & " , 変数bの値は" & b
この文を先頭から2つ目の&までとその後の部分に分け、正しく2行で記述しなさい。
また、変数a,bの値がそれぞれ10,20である場合に、実行したときに表示される
メッセージボックスの中の記述内容を書きなさい。
解答。
msgbox"変数aの値は" & a &
msgbox"変数bの値は" &b
変数aの値は 10
変数bの値は 20
338:名無しさん@お腹いっぱい。
09/01/14 17:31:14
UNIX無関係なので板違い
339:名無しさん@お腹いっぱい。
09/01/14 22:36:54
金をdoubeで扱う勘定系プロジェクトに配属になったけど
ソッコーで抜けさせてもらったことがある
「おかしい計算が合わない…」とかいうつぶやきが遠くで聞こえてるうちに逃げてきた
340:名無しさん@お腹いっぱい。
09/01/14 22:39:50
あはははははは
341:名無しさん@お腹いっぱい。
09/01/14 23:40:05
>>326
> 仮数部が内部で64bitになるので丸め誤差でません。
何も理解してないw
342:名無しさん@お腹いっぱい。
09/01/14 23:53:11
仮数部を増やす方向にキャストしてから10倍すれば問題起きないよ。
それができるという前提がなかったからあの話がおかしかっただけで。
それよりおまえは1ヶ月以上前の話につっこんでも意味がないことを理解していない。
343:名無しさん@お腹いっぱい。
09/01/17 12:00:35
>>342 プログラミングという机上の空論で遊んでいるやつらに
現実的なプログラミングのノーハウをちらみさせても意味ない事に気づけ
ダメ系の算数野郎さんはとりあえずgccでπでも1万桁求めるにはどうしたらいいかとか
まっとうなプログラミングの道でもしめせばいいよ。
UNIXの場合必要なライブラリーはデスクトップを入れるとついてきたりしている。
あえて名称はかかんけどね、
だいたい元々の話がリアルな精度ではなくて「10進化された文字列」での話なんだから二進演算の精度うんぬんなんて実は関係ない。
どっちかというと「.」がらみの正規表現のプログラミングの方が正解で
それは最初に「文字列で」と書いているレスでおわっているわけだ。
344:名無しさん@お腹いっぱい。
09/01/30 14:26:14
コンパイル結果のファイル名ににタイムスタンプをつけたくて
Makefile中に以下のようにして
TIMESTAMP=`ls -l --time-style=long-iso $(OBJNAME).hex | awk '{print $6}' | sed 's/-//g'`
時間をとりだしているのですが、結果的にTIMESTAMPには
TIMESTAMP=rwrr 1 user user 601847 20090130 14:19 objname.hex
という値が格納されてしまいます。
実際にシェルから実行したら
20090130
という結果が表示されるのですが、なぜでしょうか?
ちなみに
TIMESTAMP=$(ls -l --time-style=long-iso $(OBJNAME).hex | awk '{print $6}' | sed 's/-//g')
でも結果は同じです。
アドバイスよろしくお願いします。
345:名無しさん@お腹いっぱい。
09/01/30 14:28:13
失礼しました。
TIMESTAMP=$(ls -l --time-style=long-iso $(OBJNAME).hex | awk '{print $6}' | sed 's/-//g')
ではなく
TIMESTAMP=$(shell ls -l --time-style=long-iso $(OBJNAME).hex | awk '{print $6}' | sed 's/-//g')
でした。
346:名無しさん@お腹いっぱい。
09/01/30 14:42:44
TIMESTAMP=`ls -l --time-style=long-iso $(OBJNAME).hex | awk '{print $6}' | sed 's/-//g'`
awkのprintの引数を$$6にしたらいけました。
何故でしょうか。
よく分かりません。
347:名無しさん@お腹いっぱい。
09/01/30 15:10:55
Makefile中では$に特別な意味があるから。
348:名無しさん@お腹いっぱい。
09/01/31 00:25:38
makeの変数展開
↓
shの変数展開
↓
awkの変数展開
349:名無しさん@お腹いっぱい。
09/02/05 21:48:12
ポインタじゃなくて、structの実体渡しで呼び出す関数を、
structの即値の引数で呼び出すことってできませんか?
どういうことかというと、
struct hoge {
int hoge_a;
char *hoge_b;
};
void func(struct hoge);
と宣言されてる時、
struct hoge hh = {123, "boke"};
func(hh);
で呼び出すと、呼び出しのためだけにstruct hoge hhを宣言するのが無駄なので、
func({123, "boke"});
みたいな形で、引数を即値にして一発で呼び出したいんですが。
350:名無しさん@お腹いっぱい。
09/02/05 22:22:28
>>349
たぶんC99限定だけど、複合リテラル
func((struct hoge){123, "boke"});
351:名無しさん@お腹いっぱい。
09/02/05 22:36:02
>>350
ありがとうございます。(struct hoge)を頭につけるだけで良かったんですね。
ちなみに、実体渡しじゃなくて、普通のポインタ渡しの場合でも、
func(&(struct hoge){123, "boke"});
で行けることを確認しました。
352:名無しさん@お腹いっぱい。
09/02/06 08:18:47
えっと自分でなんちゃってダウンローダを作っていて、いくつかの Unix 上で
(いまんとこ Linux と Mac OS X)で同じコードを使いたいと思ってます。
で、整数型の移植性がちょっと気になってます。
4GB以上のファイルを扱うために32bitより大きい整数でファイルの大きさを表現しない
といけないのですが、これってどんな型を使うのが正解ですかね?
必要なのは 1) 4GB以上のサイズを表現可能(http とかにファイルサイズを埋め込む)
2) printfとかで簡単に表示可能 です。
とりあえず off_t かな? と思ったんですが、ビット数とかよくわからないし、printfの指定も
よくわからないし、もしかしてとりあず long long にでもした方が楽なのかなあ、とか...
353:名無しさん@お腹いっぱい。
09/02/06 08:31:56
もちろんoff_t
URLリンク(www.suse.de)
これも参考になる。
URLリンク(jp.sun.com)
Macは知らない。
354:名無しさん@お腹いっぱい。
09/02/06 09:05:26
便乗質問ですが、
off_t を printf する時、書式指定はどうすればいいの?
off_tは、64bitの場合も32bitの場合もあって、OSによって違うけど、
ソースは共通にしたいという場合の話です。
355:名無しさん@お腹いっぱい。
09/02/06 09:36:01
>>354
書式は固定して、32bitの場合でも(long long)にキャストして表示。
356:名無しさん@お腹いっぱい。
09/02/06 09:42:02
URLリンク(jp.sun.com)
357:名無しさん@お腹いっぱい。
09/02/27 18:41:03
はて? 何が悪い?
$ cat file1.c
char s[] = "hoge\n";
$ cat file2.c
extern char *s;
int main(){printf(s);}
$ gcc file1.c file2.c
$ ./a.out
Segmentation fault
358:名無しさん@お腹いっぱい。
09/02/27 18:59:12
あたりまえだ。
$ cat file2.c
extern char s[];
int main(){printf(s);}
359:名無しさん@お腹いっぱい。
09/02/27 19:00:51
file1 では、s という名前の箱には、直接 char[] が入っている。
file2 では、s という名前の箱には、char を指すポインタが入っている、と宣言している。
ポインタと配列は混同してはいけない。
「エキスパートCプログラミング」の4章を嫁
360:名無しさん@お腹いっぱい。
09/02/27 19:00:54
>>357
C FAQ一読しとけ
URLリンク(www.kouno.jp)
361:名無しさん@お腹いっぱい。
09/02/27 19:06:18
じゃあなんでこれは動くんだよ
func(char *s){printf(s);}
int main(){char s[] = "hoge\n"; func(s);}
362:名無しさん@お腹いっぱい。
09/02/27 19:08:05
>>357
main()で、int宣言してるのに値を帰してないからじゃないの?
未定義の値が帰ってSegmentation faulするのでは?
363:名無しさん@お腹いっぱい。
09/02/27 19:26:00
>>361
いいから>>360を読め。
>>362
釣れるかい?
364:名無しさん@お腹いっぱい。
09/02/27 19:27:42
ていうか>>360内の
URLリンク(www.kouno.jp)
一番最初に出てる。
365:名無しさん@お腹いっぱい。
09/02/27 19:40:51
>>362
return(1)を足したら動きました。返り値は無視できませんね。勉強になりました。
366:名無しさん@お腹いっぱい。
09/02/27 20:05:19
配列の値がアドレスなのがいけないんだろう。
だからポインタと同じに見える。
367:名無しさん@お腹いっぱい。
09/02/27 20:07:58
× 配列の値 (それはchar)
○ 配列名の値
368:名無しさん@お腹いっぱい。
09/02/27 21:29:31
去年の秀逸な記事
URLリンク(s03.megalodon.jp)
369:名無しさん@お腹いっぱい。
09/02/28 01:27:00
>>368
おお、恐ろしい。恐ろしい。
370:名無しさん@お腹いっぱい。
09/02/28 12:17:44
ダメ初心者が初心者に教えてるのか…
> int main( void ) {
> int *n;
> *n = 5; /* ポインタ変数nに値5を代入 */
371:名無しさん@お腹いっぱい。
09/02/28 13:31:28
コード例だけ見ると typoっぽいけど、地の説明文からして
どうもポインタを勘違いして理解してるっぽい。
この沖林正紀って人は、なんでこの程度の知識で原稿書いたんだろう
初心者レベルの駄文より、嘘を教える方が性質が悪い。
372:名無しさん@お腹いっぱい。
09/02/28 13:50:40
>>370は初心者が陥りやすい間違いなので、ポインタの解説記事ならば間違えてはいけない個所。
記事の題名が「C/C++のポインタの機能--参照渡しのような処理」なので、JavaやLLから入って
来た人なのだろう。参照渡しでは初期化は不要だからね。
傍証
URLリンク(bookweb.kinokuniya.co.jp)懼ィ�%B3%8BI/list.html
373:名無しさん@お腹いっぱい。
09/02/28 14:27:55
参照渡しでも値渡しでも、callee は初期化不要では?
374:名無しさん@お腹いっぱい。
09/02/28 17:53:21
>>373
372は、参照渡しということはcalleeの話だから初期化は不要と言ってるのであって、
参照渡し以外で呼び出されたcalleeが初期化が必要とは一言も言ってないよ。
375:名無しさん@お腹いっぱい。
09/02/28 19:28:41
glib-2.0のgstringってCで使う場合使い勝手とか負荷とかどんなもんなんでしょう
ポインタ配列とかリストとかもあるんなら使いたいのだけれど
仕様が微妙なのでばきばき使っている人の使用感が聞きたい
376:名無しさん@お腹いっぱい。
09/03/01 06:43:15
以下をコンパイルしたのですが何も表示されません。
どうしてですか?
#include <iostream>
class H{public:H(){std::cout<<"hoge\n";}};
int main(){H h();}
377:名無しさん@お腹いっぱい。
09/03/01 08:19:51
関数の宣言だから
378:名無しさん@お腹いっぱい。
09/03/01 08:55:08
>>376
iostream.h じゃないの?
ヘッダーの拡張子 .h がなくて正常コンパイルできてないに1票。
379:名無しさん@お腹いっぱい。
09/03/01 09:07:01
>>376
"\n" なんて使えたっけ? << std::endl でしょ?
改行が出力されず、行バッファがフラッシュされなかったから
表示されていないように思っただけでは?
380:名無しさん@お腹いっぱい。
09/03/01 09:13:46
>>378-379
だから、「関数の宣言だ」と言ってるだろ。
int main() {
int printf(...);
}
と書いてあるのと同じだよ。
381:名無しさん@お腹いっぱい。
09/03/01 09:15:46
>>380
もちろん、main()関数は宣言してます。そういう問題じゃないでしょw
382:名無しさん@お腹いっぱい。
09/03/01 09:34:33
おまえ、本当にバカだな。
printf()関数の宣言をしているのが見えないのか。
ホント、初心者の知ったかぶりって迷惑だよな。
383:名無しさん@お腹いっぱい。
09/03/01 09:36:10
>>382
ワーニングを無視すれば printf() は宣言なしでもつかえますよ。
あと、質問はprintf()じゃないしw
384:名無しさん@お腹いっぱい。
09/03/01 09:36:34
Hを返す引数の無い関数h()をmainの内部で宣言してる、と言われてるのに
知ったか初心者の癖に理解力ゼロだから困る。
385:376
09/03/01 09:38:23
>>378-379
.h付けて、endlに直したら表示が出ました。
ありがとうございました。
386:名無しさん@お腹いっぱい。
09/03/01 09:38:31
頭悪すぎだね。
387:名無しさん@お腹いっぱい。
09/03/01 09:41:43
>>383
あなたC++って言語、知ってる?
388:名無しさん@お腹いっぱい。
09/03/01 09:44:01
どこぞの独自拡張拡大解釈コンパイラしか知りません
389:名無しさん@お腹いっぱい。
09/03/01 09:47:40
>>387
printf()が出た時点で C++の可能性はゼロでしょ。
C++ではprintf()の使用は禁止だし。
390:名無しさん@お腹いっぱい。
09/03/01 09:59:28
ネタだよな?
まさかとは思うけど、本気で言ってるんじゃないよな?
これが初心者?
それとも老害?
391:名無しさん@お腹いっぱい。
09/03/01 10:00:33
>>389
幾らなんでも、それじゃ釣れないだろ。
392:名無しさん@お腹いっぱい。
09/03/01 10:04:56
main()がint型でありながら戻り値が省略可能な時点で、C++確定ですけど。
393:名無しさん@お腹いっぱい。
09/03/01 10:09:06
>>392
つC99
394:名無しさん@お腹いっぱい。
09/03/01 10:13:41
>>392
main()に限らず、何のint関数でも戻り値は省略可能。
ワーニングを無視するなら。
395:名無しさん@お腹いっぱい。
09/03/01 10:21:07
>>394
えーとね、main()は警告なしで省略可能なんだよ。
言語仕様として決まってるから。
もちろんあなたはは知らなかったでしょうけどね。
あ、もちろんprintf()も言語(のライブラリ)に含まれてますよ。
当然ながら、宣言なしで使うことは出来ませんがね。
396:名無しさん@お腹いっぱい。
09/03/01 10:22:48
>>395
つC89
397:名無しさん@お腹いっぱい。
09/03/01 10:23:30
警告をワーニングって言うのもちょっと恥ずかしい。
別にウォーニングと言えってことじゃないけどね。
単に「警告」で済むんだから。
ま、恥はいくつかいても恥で一緒だけどね。
398:名無しさん@お腹いっぱい。
09/03/01 10:28:04
>>396
つ 話の流れ
つ 空気
>>394
別にintに限りませんけど?
C(でかつ警告を無視する)なら。
399:名無しさん@お腹いっぱい。
09/03/01 10:32:21
そもそも>>376でclassが使われていて明らかにC++の話なのに
何故か「printfが使われてるからC++の可能性はゼロ」となって
Cでの話にすり替えられちゃってるんだよな。
不思議。
400:名無しさん@お腹いっぱい。
09/03/01 10:38:02
>>395
printf()は宣言なしで使えるよ。
実際にコンパイルしてみればわかるよ。
即席で書き捨てソースを書く時によくやる。
宣言なしでは使えないのはputs()とかputchar()とか。
401:名無しさん@お腹いっぱい。
09/03/01 10:44:48
>>395
仕様としてそう決まっていようが、現実はそうじゃない。
$ echo 'main(){}' | gcc -xc -; ./a.out; echo $?
148
$ echo 'main(){}' | gcc -xc -; ./a.out; echo $?
84
$ echo 'main(){}' | gcc -xc -; ./a.out; echo $?
101
毎回未定義。
402:名無しさん@お腹いっぱい。
09/03/01 10:44:57
>>400
つかえましたよ。
int main()
{
puts("xxx");
}
つーか、linkとごっちゃになってね。
403:名無しさん@お腹いっぱい。
09/03/01 10:49:17
>>402
>>395 に言ってくれ。
404:名無しさん@お腹いっぱい。
09/03/01 10:51:45
>>401
↓これじゃない
int main()
return 0; の話だろ
↓こっちは省略禁止
int main()
405:400
09/03/01 10:57:24
ああ、ごめん。
>>395 は論外としてputs云々が気になったので....
でだ。
ばかも ん。
昔のcompilerはなぁ、昔のcompilerはなぁ、
まともなwarning吐かないので、lint使ってたんだぞぉ。
406:名無しさん@お腹いっぱい。
09/03/01 10:57:31
>>400
だから、話の流れ的に「C++では」なの(>>395>>394>>392)。
C++では「宣言の無い関数は呼び出せない」の。
某コンパイラを除いてね。
407:名無しさん@お腹いっぱい。
09/03/01 11:00:40
>>401
あなたが省略してるのは「戻り値」ではなく「戻り値の型」。
話の流れとは全然関係ないから。
CでもC++でも
f() { return 0; }
という「戻り値の型の省略」は完全に合法ですから。
もちろんintと仮定されます。
そして、何もreturnしない場合、まっとうなコンパイラなら警告が出ます。
408:名無しさん@お腹いっぱい。
09/03/01 11:11:43
>>404 >>407
int付けても同じだよw そこが論点じゃないしww
$ echo 'int main(){}' | gcc -xc -; ./a.out; echo $?
41
$ echo 'int main(){}' | gcc -xc -; ./a.out; echo $?
116
$ echo 'int main(){}' | gcc -xc -; ./a.out; echo $?
32
毎回未定義。
409:名無しさん@お腹いっぱい。
09/03/01 11:12:13
>>395がCの話だと思ってる人って
わざわざ「printfが言語仕様に含まれる」と触れてる事を疑問に思わないのかな。
少し前に>>389があるのに。
410:名無しさん@お腹いっぱい。
09/03/01 11:19:51
>>408
>>406や>>393を無視して、何故わざわざ「省略可能なことが言語仕様で保証されていないC89」でコンパイルするわけ?
411:名無しさん@お腹いっぱい。
09/03/01 11:25:23
「C++では言語仕様で保証されている、だからC++のコードだ」という話(それが妥当かはともかく)なのに
わざわざ「言語仕様で保証されてない言語(C89)」での結果を何度も貼りつけて何がしたいのかな。
412:名無しさん@お腹いっぱい。
09/03/01 11:26:39
あ、違った。
「言語仕様で「不定」となることが決まっている言語」だな。
413:名無しさん@お腹いっぱい。
09/03/01 11:30:14
>>404 の書き方では、「intさえ付ければ戻り値は固定される」と
言ってるように見える。
>>408 はそれに対する反論かと。
414:名無しさん@お腹いっぱい。
09/03/01 11:32:03
>>404
で言ってるのは
>>401に対して仕様で省略が認められてるのはreturnの方だけだよということだろう
415:名無しさん@お腹いっぱい。
09/03/01 11:33:39
>>414
でも結局省略したら値が不定んなったんだから省略できないじゃんw
416:名無しさん@お腹いっぱい。
09/03/01 11:36:35
>>415
だからC99規格対応なら、省略できて
C89規格ではそうではないって話だろ
417:名無しさん@お腹いっぱい。
09/03/01 11:39:25
>>416
結局省略できないじゃんw
418:名無しさん@お腹いっぱい。
09/03/01 11:45:48
省略できる言語の話をしてるんだろ?
何で別の言語の話をする?
419:名無しさん@お腹いっぱい。
09/03/01 11:48:28
省略できるって主張してる奴は、
「仕様上は省略できるはずです」って言って、
不定値を返すままのソフトを納品すればいいさ。
420:名無しさん@お腹いっぱい。
09/03/01 11:56:21
>>419
実装がとにかく正しいとか言って、コンパイラ依存のプログラムでも作ってろ
421:名無しさん@お腹いっぱい。
09/03/01 11:59:15
だったらせめて -xc をやめて
-xc++ や -std=c99 をつけた結果を貼れよ。
C89で保証されてないことなんか、知らない奴殆ど居ないんだから。
>>376からの流れなのに>>380がC++の話じゃないと思い込むバカは居るかもしれないけど。
422:名無しさん@お腹いっぱい。
09/03/01 12:02:08
>>419
どこに、「C89で省略できる」って主張してる奴がいる?
あ、いるのかな。
戻り値が保証されてるとは誰も書いていない、ってだけで。
423:名無しさん@お腹いっぱい。
09/03/01 12:12:12
×戻り値が保証されてるとは誰も書いていない
○戻り値が保証されると脳内で勝手に決め付けて特定の実装の結果を張り続けるバカもいる
424:名無しさん@お腹いっぱい。
09/03/02 10:17:57
linuxだとsearch.hのハッシュがやけに遅いのでGhashTableのが性能いらしいんだけど
FreeBSDの場合ハッシュの実装をするのにGhashTableとsearch.hと
どっちのがおすすめ?
425:名無しさん@お腹いっぱい。
09/03/02 12:38:43
ほとんどの人には不要だと思うけど、一応張っとく。
C++とC98は、main関数は暗黙のreturn 0。C89とその前はそうではなかった。
$ echo 'int main(){}' | gcc -std=c99 -xc - && ./a.out; echo $?
0
$ echo 'main(){}' | gcc -std=c99 -xc - && ./a.out; echo $?
<stdin>:1: 警告: return type defaults to ‘int’
0
$ echo 'int main(){}' | gcc -Wall -std=c++98 -xc++ - && ./a.out; echo $?
0
$ echo 'main(){}' | gcc -Wall -std=c++98 -xc++ - && ./a.out; echo $?
<stdin>:1: 警告: ISO C++ forbids declaration of ‘main’ with no type
0 # 禁止されてるけどエラーにならない
$ echo 'int main(){}' | gcc -Wall -std=c89 -xc - && ./a.out; echo $?
<stdin>: In function ‘main’:
<stdin>:1: 警告: control reaches end of non-void function
196
426:名無しさん@お腹いっぱい。
09/03/02 12:48:53
>>424
基本どっちもクヌース本のアルゴリズム。
427:名無しさん@お腹いっぱい。
09/03/02 12:52:43
C98という新規格まで登場したか。
428:名無しさん@お腹いっぱい。
09/03/02 13:32:40
>>425
おまえがC++とCごっちゃになってどうする
429:名無しさん@お腹いっぱい。
09/03/03 09:27:07
Cのコード中でディレクトリの内容を比較するのはどうしたらいいか悩んでいます。
動作的には "diff -r dirA dirB" を実行した場合の結果と同じ処理をしたいのですが、
毎回 diff コマンドを呼ぶオーバーヘッドを避け、出来ればCのコードで実現したいと
思ってます。どうすべきでしょう?
1. UNIX の API にこの目的にふさわしいものがあり(何という名前?)、それを使う
2. 違うファイルかディレクトリに遭遇するまで地道に両者のディレクトリを辿るような
コードを自分で書く
3. diff のソースコードを入手し、自分のプログラムにリンクして使う
4. その他
430:名無しさん@お腹いっぱい。
09/03/03 09:57:03
お前の書くコードがdiffよりオーバーヘッドが少ないわけがない。
431:名無しさん@お腹いっぱい。
09/03/03 10:09:27
>>429
普通のdiffコマンドは高速でないアルゴリズム( O(ND) )を使ってるから、
gitとかpythonのライブラリに使われてるやつのが速い
ってわけで、速度を追い求めるなら差分取得のアルゴリズムについて調べてがんばれ
432:名無しさん@お腹いっぱい。
09/03/03 10:12:30
いや高速でないってこたないんですよ、それより速いのがあるだけで
433:429
09/03/03 10:29:38
あー書き方が悪かったかな。
もし diff ということで LCS とかそこらへんに脊髄反射されてたらごめんなさい。
自分が知りたいのは dirA と dirB の内容が違うか同じかだけなんです。
この場合むしろディレクトリの階層に効率よくアクセスできることが重要なんじゃないかと
思ったんですが、違います? fts とかですかね?
それにファイルを処理するようなソフトならありがちな処理のような気がするので、
どこかに適切なコードのサンプルがあればと思って...
434:名無しさん@お腹いっぱい。
09/03/03 10:37:16
>>433
> 自分が知りたいのは dirA と dirB の内容が違うか同じかだけなんです。
内容の比較は必要か
タイムスタンプの比較だけでいいか
同じファイル名が存在するだけでいいのか
rsync --dry-runの出力結果を使うとか。
435:429
09/03/03 10:50:52
>>434
「同じ」とはディレクトリ構造が同じで、その中に存在するファイルの名前&内容が同じ
という積もりです。
タイムスタンプは比較しません。
>rsync --dry-runの出力結果を使うとか。
はい、確かにそれも速そうですが、自分のプログラムだと比較的浅いディレクトリに
対してそれを何度も呼ぶことになりそうなので、C の何かの API で書いた方がいいのか
なあと。
ある意味 rsync みたいなプログラムなんですが、syncするときにいろいろカスタムな
ロジックを入れたいので、コードを書いているといいますか....
436:名無しさん@お腹いっぱい。
09/03/03 11:32:23
内容比較がcmp -sレベルでいいなら、
readdir/lstatで自分で書けばいいんじゃない?
質問せずに書けば、今頃書き終わっている頃かと。
437:名無しさん@お腹いっぱい。
09/03/03 13:31:30
ファイルとディレクトリの equality は適当に定義出来
るとして、↓みたいになるかな。
for (File src = each of srcDir) {
File dst = dstDir.Find(src);
if (dst == null) {
// src にしかない
} else if (src != dst) {
// 違う
}
}
for (File dst = rest of dstDir) {
// dst にしかない
}
each of …は都度 readdir して、Find は保持してるプー
ルから探して、無ければ見つかるまで readdir、してプー
ルに入れていく感じ。見つかったらプールから削除して
おいて rest of …でそれを得る。
438:名無しさん@お腹いっぱい。
09/03/03 14:07:34
両方コレクションにいれて、ソートして、
先頭二つ、計四つを比較しながら取り出せばいい。
四つになるのはどちらが欠けているかわからないから。
どれも違う場合、四つの中で小さいの二つを捨てればいい。
AB
AB
AB
BC
BC
AB
-
AB
CD
AC
BD
439:名無しさん@お腹いっぱい。
09/03/03 14:16:00
>>438
ファイル/ディレクトリの equality と同様に順序付け
も定義出来るなら(ソートするからには出来るはずだ)、
先読みする必要はない。マージソートの要領だ。
440:名無しさん@お腹いっぱい。
09/03/12 19:41:22
dirp=opendir(".");
printf("1 :%d;\n",telldir(dirp));
printf("2 :%d;\n",telldir(dirp));
printf("3 :%d;\n",telldir(dirp));
closedir(dirp);
とすると返す値は1,2,3とどんどんインクリメントしていくだけだし
seekdirは無反応rewinddirは巻き戻すばかりかtelldirをひとつ進めるだけ
readdirとかはちゃんとできているんだけれど
何か呪文とかいるのかダメダメな関数なのか情報please
441:名無しさん@お腹いっぱい。
09/03/12 19:51:28
>>440 OSはFreeBSDです。
442:名無しさん@お腹いっぱい。
09/03/12 20:15:55
たぶん実装がおかしいんだろう。MacOS Xも同様らしい。
URLリンク(idm.s9.xrea.com)
dirent読むのにtelldirやseekdir使うようなやつはいないから放置されてると想像。
443:名無しさん@お腹いっぱい。
09/03/12 20:24:17
追加。このへん関係あるかも。
URLリンク(www.freebsd.org)
444:名無しさん@お腹いっぱい。
09/03/12 20:32:49
>>440です。rewinddirの記述は間違っていました。
rewinddirとreaddirだけが使えます。
で調べたらscandirというのがありました。
mallocしてくれて配列に入れて関数指定すればsortもしてくれるようなので
コールバックもsort関数に入れます。
>>435もscandir+lstatでいいのでは?
しかしひどすぎるなtelldir+seekdir
ファイルの多いディレクトリーでちょろちょろよむもん作りたかったんだけど
一気読みが基本ですか?
445:名無しさん@お腹いっぱい。
09/03/12 20:38:50
とりあえずコールバック抜きのアルファソートやってみた。
c = scandir(dirname, &namelist, NULL, alphasort);
if(c == -1) {
puts("not opendir");
return(1);
}
printf ("%d\n", c);
for (i = 0; i < c; ++i) {
printf ("%s\n", namelist[i]->d_name);
free(namelist[i]);
}
free(namelist);
opendirの苦労は一体....orz
446:名無しさん@お腹いっぱい。
09/03/12 20:40:17
>>435
opendir -> ディレクトリをファイルとして開く
readdir -> ディレクトリのエントリを一つ読み込む(ポインタ一個進む)
seekdir -> ディレクトリのエントリを x 番目にセットする
telldir -> 今いるエントリ位置を報告する
を組み合わせて, 双方のエントリを比較して
1. 対象物の inode が同じなら処理スキップ
2. 対象物が ディレクトリなら, 自分自身を再帰的に呼び出す
3. 対象物がファイルなら中身を比較
すればええんちゃう?
447:名無しさん@お腹いっぱい。
09/03/12 20:46:16
既に読んだエントリに戻って読み直すシチュエーションがわからん。
仮にtelldir/seekdirの動作がまともでも、
いちいち物理的にディレクトリ読みに行くような実装だったりしたら、
遅いし最中に誰かがいじらんとも限らんし、いいことなしでは?
キャッシュしてるんだとすれば一気読みと何も変わらんし。
というわけで、telldir/seekdirは価値なしなんじゃないかと。
448:名無しさん@お腹いっぱい。
09/03/12 21:00:32
>>447
再帰して必要物がなくって、バックトラックするときに
変わってしまった状態を元に戻すために必要
recur_dir(...
here = telldir(...
if (このエントリが dir && 比較対象と違う)
if (recur_dir(...) == succeed)
return なんとか
ここに戻ってきた場合何がどうなってるか保証できない
seekdir(here)
続きの処理
449:名無しさん@お腹いっぱい。
09/03/12 21:56:26
何がどうなってるか保証できない状態なら
telldirしたところにseekdirしても保証できないだろう
450:名無しさん@お腹いっぱい。
09/03/15 11:44:20
ストリームとしてファイルリストをチェックしていくならseekとかは必須だと思うけれど
telldirもseekdirも機能しないんだから必要でも存在しない事実をどうする。
一旦readdirだかscandirでざっくりと読み込んで
それに対して操作するしか方法が無いのが現実。
バックアップとかで完全一致を目指す場合
「ほぼあっている」前提ならば結局ファイル自体の完全マッチをするしかないと思うが
事前にMD5とかSHA1とかとったリストをディレクトリーに入れとけばそれで済む気はする。