1 名前:静的領域の名無しさん mailto:sage [2008/08/12(火) 18:23:10 ] C言語の入門者向け解説スレです。 教えて欲しいのではなく宿題を丸投げしたいだけなら ↓宿題スレ↓へ行ってください。 C/C++の宿題を片付けます 114代目 pc11.2ch.net/test/read.cgi/tech/1216746971/ ・C++言語はスレ違いです。 ・分からない事をなるべく詳しく書いて下さい。 ・ソースコードを晒すと答えやすくなるかもしれません。 # 抜粋/整形厳禁、コンパイラに渡したソースをそのまま貼ること # サイズが大きい場合は宿題スレのアップローダ等を利用してください ・開発環境や動作環境も晒すと答えが早いかもしれません。 ・質問者は最初にその質問をした時のレス番号を名前欄に書いて下さい。 前スレ C言語なら俺に聞け(入門篇) Part 33 pc11.2ch.net/test/read.cgi/tech/1217073697/ 過去スレ makimo.to:8000/cgi-bin/search/search.cgi?q=%82b%8C%BE%8C%EA%82%C8%82%E7%89%B4%82%C9%95%B7%82%AF&andor=AND&sf=0&H=&view=table&D=tech&shw=5000
445 名前:デフォルトの名無しさん mailto:sage [2008/08/19(火) 21:48:34 ] 計算結果がオーバーフローorアンダーフローしてるかどうかを調べることってできる?
446 名前:デフォルトの名無しさん mailto:sage [2008/08/19(火) 21:50:30 ] >>445 標準Cの範囲内では無理じゃないかな?
447 名前:デフォルトの名無しさん mailto:sage [2008/08/19(火) 22:11:52 ] >>440 ちょw 条件後付
448 名前:440 mailto:sage [2008/08/19(火) 22:38:10 ] >>447 私に言うな。
449 名前:デフォルトの名無しさん mailto:sage [2008/08/19(火) 22:53:17 ] ふつうに計算じゃなくてビット演算組み合わせればオーバーフローもチェックできるんじゃね?って思った
450 名前:デフォルトの名無しさん mailto:sage [2008/08/19(火) 23:01:45 ] >>445 ,446,449 できるよ。 符号付きとなしとで微妙に変わるけど、加減算なら二つの数値の 最上位ビット見ればいい。 乗除算もちょっと手間かかるけどできなくはない。
451 名前:デフォルトの名無しさん mailto:sage [2008/08/19(火) 23:09:23 ] 具体的にどうやんの 加算でもいいから教えてくだちい
452 名前:デフォルトの名無しさん mailto:sage [2008/08/19(火) 23:16:07 ] 符号付での二つでの足し算で言うと 負と負なら答えは負なので最上位ビットは普通はずっと1、 オーバー フローすると0になる 負と正ならそもそもオーバーフローしない 正と正ならオーバーフローすると最上位は1になる そんな感じ
453 名前:デフォルトの名無しさん mailto:sage [2008/08/19(火) 23:17:01 ] 桁あふれか 加算なら結果からもう一回引いてみればいいんじゃね? 元の数字に復元できれば桁あふれ無し。 元の数字にもどら無ければ桁あふれあり
454 名前:デフォルトの名無しさん mailto:sage [2008/08/19(火) 23:26:06 ] オーバーフローした結果から引いたらアンダーフローして元に戻ると思うよ ・・・アンダーフローって意味違うような気がした
455 名前:デフォルトの名無しさん mailto:sage [2008/08/19(火) 23:27:45 ] 半分のビット数ごとに分けて計算する
456 名前:デフォルトの名無しさん [2008/08/19(火) 23:31:35 ] >>453 お戯れを。
457 名前:デフォルトの名無しさん mailto:sage [2008/08/19(火) 23:33:35 ] logで計算する
458 名前:デフォルトの名無しさん mailto:sage [2008/08/19(火) 23:38:17 ] logで足し算できるものなら教えて欲しい。
459 名前:デフォルトの名無しさん mailto:sage [2008/08/19(火) 23:39:47 ] 指でも折って数えるんだ 足りなくなったら隣の人の借りろ マイナスなど知らん
460 名前:デフォルトの名無しさん mailto:sage [2008/08/19(火) 23:44:17 ] >>445 そもそも、どんなデータなんだよ。 そのオーバーフローやアンダーフローを気にしなくてはいけないデータというのは。
461 名前:デフォルトの名無しさん mailto:sage [2008/08/19(火) 23:51:07 ] int add(int a, int b, int *p_is_overflow){ int chk_type, result, is_over_flow=0; chk_type=(a<0)*2+(b<0); result=a+b; switch(chk_type){ case 0: if(result>0) is_over_flow=1; break; // a, b ともに 0 以上なので解も 0 以上になるべき case 3: if(result<0) is_over_flow=1; break; // a, b ともに 0 未満なので解も 0 未満になるべき } if(p_is_over_flow) *p_is_over_flow=is_over_flow; return result; }
462 名前:デフォルトの名無しさん mailto:sage [2008/08/19(火) 23:52:00 ] >>461 case の 0 と 3 間違えた
463 名前:デフォルトの名無しさん mailto:sage [2008/08/20(水) 01:01:39 ] >>460 ちょっとした計算を代わりにやってもらうのプログラムなんですが 計算過程を式としては理解しているのですが、 計算途中の値がどの程度の大きさになっているのは知りません 知らないうちにオーバーフローしてるんじゃないかと少し不安なんです もちろん値が狂ったら答えも大抵はおかしくなるでしょうからそうそう困ることはないのですが
464 名前:デフォルトの名無しさん mailto:sage [2008/08/20(水) 01:04:47 ] 出た答えが正常かおかしいかは判断できるのか? 方程式の解とかで元の式に代入して検算とかできるのなら困らないけど
465 名前:デフォルトの名無しさん mailto:sage [2008/08/20(水) 01:37:58 ] >>461 の修正版 int add(int a, int b, int *p_is_overflow){ int chk_type, result, is_overflow=0; chk_type=(a<0)*2+(b<0); result=a+b; switch(chk_type){ case 0: if(result<0) is_overflow=1; break; // a, b ともに 0 以上なので解も 0 以上になるべき case 3: if(result>=0) is_overflow=1; break; // a, b ともに 0 未満なので解も 0 未満になるべき } if(p_is_overflow) *p_is_overflow=is_overflow; return result; } 掛け算は a*b/b==a をチェックすればいい 整数同士の除算は一つの例外を除いてオーバーフローしない (0div はあるけど)
466 名前:デフォルトの名無しさん mailto:sage [2008/08/20(水) 01:57:37 ] その例外は・・・?
467 名前:デフォルトの名無しさん mailto:sage [2008/08/20(水) 02:00:18 ] ヒント・大抵正の最大値より負の最少値のほうが絶対値が大きい
468 名前:デフォルトの名無しさん mailto:sage [2008/08/20(水) 02:02:27 ] >>466 読みたくば●を買え C言語なら俺に聞け(入門篇) Part 12 pc11.2ch.net/test/read.cgi/tech/1178620766/951-952
469 名前:デフォルトの名無しさん mailto:sage [2008/08/20(水) 02:04:57 ] 951 名前:デフォルトの名無しさん[sage] 投稿日:2007/05/15(火) 14:28:25 これでダメな場合って lop==0 の時以外にあるかな? result=lop*rop; if(result/lop!=rop) オーバーフロー 952 名前:デフォルトの名無しさん[sage] 投稿日:2007/05/15(火) 14:54:12 >>951 っ lop=-1 rop=INT_MIN
470 名前:402 mailto:sage [2008/08/20(水) 09:34:26 ] >>440 ありがとうございます。 今作っている物は1秒ごとの判断で良かったので最終的にtime()関数を使うことにしました。 gettymeofday();も今度試してみます。
471 名前:デフォルトの名無しさん mailto:sage [2008/08/20(水) 10:39:41 ] このプログラムなら正常に動くんですが、main関数内のnibai関数を scanf("%d",&a); nibai(a); printf("二倍した数値は%d\n",a); と書くと2倍してくれないんですが、何故でしょうか? ----------------------------------------------------------- #include<stdio.h> int nibai(int x); int main(void){ int a; printf("数値を入力してください:"); scanf("%d",&a); printf("二倍した数値は%d\n",nibai(a)); return 0;} int nibai(int x){ int wk; wk=x*2; return wk;}
472 名前:デフォルトの名無しさん mailto:sage [2008/08/20(水) 10:59:39 ] a = nibai(a);
473 名前:デフォルトの名無しさん mailto:sage [2008/08/20(水) 11:00:37 ] あーなるほど!! ありがとうございます。
474 名前:ym [2008/08/20(水) 13:43:00 ] 受け渡された文字列が'0000'〜'2359'の時刻範囲内かをチェックする プログラムを教えてください。お願いします。 チェック内容は以下の通りです。 1. 受け渡された文字列が全て数値であること。 2. 受け渡された文字列の先頭2文字が'00'〜'23'の範囲であること。 3. 受け渡された文字列の3文字目〜4文字目が'00'〜'59'の範囲であること。 正常終了時:return 0 異常終了時:return -1(時刻範囲外)
475 名前:デフォルトの名無しさん mailto:sage [2008/08/20(水) 13:45:10 ] 教えて欲しいのではなく宿題を丸投げしたいだけなら 宿題スレへ行ってください。
476 名前:デフォルトの名無しさん mailto:sage [2008/08/20(水) 13:48:49 ] なんか最近範囲内チェックの質問多いな。全部同じやつか?
477 名前:ym [2008/08/20(水) 13:57:04 ] char hh[3]; char mm[3]; int h; int m; hh[0]=pstime[0]; hh[1]=pstime[1]; hh[2]='\0'; mm[0]=pstime[2]; mm[1]=pstime[3]; mm[2]='\0'; h=atoi(hh); m=atoi(mm); if((h >= 0 && h <= 23)&& (m >= 0 && m <= 59)){ return RET_OK; }else{ return RET_NG; } } int main(void) { char str[256]; int chk; gets(str); chk = N60901D04(str); printf("\nreturn=%d\n",chk); } 受け渡された文字列が'0000'〜'2359'の時刻範囲内かをチェックするプログラムなんですけど、コンパイルをしたら、 アルファベット4文字を入力してもreturn 0(正常)で判定されてしまったん ですけど、プログラムの中のどこが悪かったのか、教えてください。お願いします。
478 名前:デフォルトの名無しさん mailto:sage [2008/08/20(水) 13:59:57 ] たぶん、数字以外で数値に変更できなかったから0になって0時0分は有効だから、じゃない? isdigit とかで先にチェックするとか。
479 名前:デフォルトの名無しさん mailto:sage [2008/08/20(水) 14:00:28 ] >>474 int main(int argc, char *argv[]) { char *p; int n; for(p=argv[1] ; *p ; p++) switch(*p) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': break; default: return -1; } switch(argv[1][0]) { case '0': case '1': break; case '2': switch(argv[1][1]) { case '0': case '1': case '2': case '3': break; } default: return -1; } switch(argv[1][2]) { case '0': case '1': case '2': case '3': case '4': case '5': break; default: return -1; } return 0; }
480 名前:デフォルトの名無しさん [2008/08/20(水) 14:01:42 ] >>477 atoiで変換は失敗すると0を返すからじゃね
481 名前:デフォルトの名無しさん mailto:sage [2008/08/20(水) 14:02:11 ] あ、n消し忘れた
482 名前:デフォルトの名無しさん mailto:sage [2008/08/20(水) 14:03:47 ] >>479 4桁目のチェックが抜けてないか?
483 名前:デフォルトの名無しさん mailto:sage [2008/08/20(水) 14:05:20 ] >>482 必要あるか?
484 名前:デフォルトの名無しさん mailto:sage [2008/08/20(水) 14:05:42 ] >>482 あーそうだね switch(argv[1][2]) { case '0': case '1': case '2': case '3': case '4': case '5': if(argv[1][3]) break; default: return -1; } こうか
485 名前:デフォルトの名無しさん mailto:sage [2008/08/20(水) 14:07:05 ] >>483 ある [3]が\0のときも無視して通してしまう
486 名前:デフォルトの名無しさん mailto:sage [2008/08/20(水) 14:09:08 ] 2桁目も switch(argv[1][0]) { case '0': case '1': if(argv[1][1]) break; だな
487 名前:デフォルトの名無しさん mailto:sage [2008/08/20(水) 14:22:21 ] int check_time(const char *hhss) { int i, hour, second; if (strlen(hhss) != 4) return -1; for (i = 0; i < 4; i++) if (!isdigit(hhss[i])) return -1; hour = (hhss[0] - '0') * 10 + (hhss[1] - '0'); second = (hhss[2] - '0') * 10 + (hhss[3] - '0'); return (0 <= hour && hour < 24 && 0 <= second && second < 60) ? 0 : -1; }
488 名前:デフォルトの名無しさん mailto:sage [2008/08/20(水) 14:29:42 ] 教えてください int型の2次元配列の先頭のポインターだけをもらってくる関数があります。 配列のサイズはわかっているんですが関数内で見る際にはどう記述すればいいでしょうか? これを関数内でいじりたい unsigned int hoge2div[100][200]; 関数を呼ぶ前に連絡用構造体の所定のエリアに2次元配列のポインターを格納してます。 (unsigned int* )hoge->ptr = hoge2div; 関数内の定義(ここを直したい。) unsigned int* 2div = (unsigned int* )2div->ptr;
489 名前:デフォルトの名無しさん mailto:sage [2008/08/20(水) 14:30:40 ] >関数を呼ぶ前に連絡用構造体の所定のエリアに2次元配列のポインターを格納してます。 >(unsigned int* )hoge->ptr = hoge2div; こっちが正解です hoge->ptr = hoge2div;
490 名前:デフォルトの名無しさん mailto:sage [2008/08/20(水) 14:36:52 ] unsigned int (*p)[DIV1_SIZE]=(unsigned int (*)[DIV1_SIZE])hoge->ptr;