1 名前:デフォルトの名無しさん mailto:sage [2007/10/15(月) 22:34:33 ] C言語の入門者向け解説スレです。 ・C++言語はスレ違いです。 ・分からない事をなるべく詳しく書いて下さい。 ・ソースコードを晒すと答えやすくなるかもしれません。 ・質問者は最初にその質問をした時のレス番号を名前欄に書いて下さい。 前スレ C言語なら俺に聞け(入門篇) Part 19 pc11.2ch.net/test/read.cgi/tech/1190342593/ 教えて欲しいのではなく丸投げしたいならこちらへ C/C++の宿題を片付けます 97代目 pc11.2ch.net/test/read.cgi/tech/1191937213/
828 名前:デフォルトの名無しさん mailto:sage [2007/11/03(土) 16:12:56 ] すみません。質問です。 struct AAA{ : : }; AAA* a = (AAA*)malloc(sizeof(AAA)*4); とコーディングしていたら客先の担当者からおこられました。 「一応サイズは保証されているけどそれはAAA a[4]ではない」、と。 C++では AAA* a = new AAA[4]で保証されていますの、といったら 「それはC++だからでしょ?」といわれました・・・・。 AAA* a = (AAA*)malloc(sizeof(AAA)*4);ってやっちゃいけないんですか?
829 名前:デフォルトの名無しさん mailto:sage [2007/11/03(土) 16:19:04 ] a[4]と宣言できる状態なら、客先の反応が正しいかな。
830 名前:デフォルトの名無しさん mailto:sage [2007/11/03(土) 16:24:50 ] >>828 べつに問題ないと思うけど。 固定長で、配列で済むところでmalloc()なんか使うなって意味かな? malloc()禁止だったら、可変長の配列はどうするんだろ。
831 名前:デフォルトの名無しさん mailto:sage [2007/11/03(土) 16:31:19 ] >>828 それはそもそもCではエラーなわけだが。そのコードが通るなら、C++なのだからvectorかnewを使うべきだし。
832 名前:デフォルトの名無しさん mailto:sage [2007/11/03(土) 16:32:26 ] 「AAA* a = new AAA[4]で保証されていますの」 口調に萌えた
833 名前:デフォルトの名無しさん mailto:sage [2007/11/03(土) 16:33:57 ] C99
834 名前:デフォルトの名無しさん mailto:sage [2007/11/03(土) 16:35:28 ] >>830 回答ありがとうございます。 言葉足らずでした。「構造体のmallocなんてありえない!」といわれたのを書くの忘れてました。 すみません。ついでに便乗質問なのですが (1) AAA aaa[30][30]; int x=...; int y=...; aaa[y][x]=...; (2) AAA aaa[30*30]; int x=...; int y=...; aaa[y*30+x]=...; で(2)の使い方をしていたらこれも理解しづらいということで怒られました。 2次元配列のほうが処理的にも良いのでしょうか。
835 名前:デフォルトの名無しさん [2007/11/03(土) 16:36:30 ] ここ見てると自分とのレベルの差が分かるんだが皆学生とかなのか? レベルの差ってのは自分よりすげーってことね
836 名前:デフォルトの名無しさん mailto:sage [2007/11/03(土) 16:37:20 ] (1)でいい状況でわざわざ(2)を選ぶ神経がわからない。
837 名前:デフォルトの名無しさん mailto:sage [2007/11/03(土) 16:38:02 ] そりゃ、特別な理由がないかぎりa[30][30]と書くべきだろう。
838 名前:デフォルトの名無しさん mailto:sage [2007/11/03(土) 16:39:57 ] >>834 (2)が明確に処理的に優れてることを示せないのに(2)を選んだ理由は?
839 名前:デフォルトの名無しさん [2007/11/03(土) 16:40:15 ] 「構造体のmallocなんてありえない!」 callocを使えということかな?
840 名前:デフォルトの名無しさん mailto:sage [2007/11/03(土) 16:40:49 ] >>834 いいえ、処理的にはどう考えても(2)の方が何かと都合がよいと思います。 私のところではパフォーマンスを要求する場合は(2)の形式でかつ、オフセット計算関数を用意することが多く、 そうでない場合には(1)の形式を配列の配列ではなく配列へのポインタ配列の形で使うことが多くなります。
841 名前:デフォルトの名無しさん mailto:sage [2007/11/03(土) 16:46:45 ] >>834 > 言葉足らずでした。「構造体のmallocなんてありえない!」といわれたのを書くの忘れてました。 その担当者は、プログラム知らなさすぎなんじゃね?
842 名前:834 mailto:sage [2007/11/03(土) 16:46:55 ] >>838 処理的には a[y]のアドレスにとんで、そこからsizeof(AAA)分移動になるかと思いそれなら最初から1次元で 計算したほうがよいのかなと思いまして。 >>839 担当者いわく、構造体の領域確保はできない、ない、ということらしいです。
843 名前:デフォルトの名無しさん mailto:sage [2007/11/03(土) 16:49:51 ] >>842 >841に同意。後学の為に、その担当者の所属企業をお教え願えませんか?w
844 名前:デフォルトの名無しさん mailto:sage [2007/11/03(土) 16:51:15 ] >>840 コードの可読性は(1)のほうがいいだろ。 パフォーマンスの問題なら、(2)のほうが何パーセント処理時間が短くなるとか、具体的な数字を見せて説得すれば いいんじゃね?
845 名前:デフォルトの名無しさん mailto:sage [2007/11/03(土) 16:51:51 ] >>842 >処理的には >a[y]のアドレスにとんで、そこからsizeof(AAA)分移動になるかと思いそれなら最初から1次元で >計算したほうがよいのかなと思いまして。 だからなんで「よい」と思うのか教えてくれ。
846 名前:デフォルトの名無しさん mailto:sage [2007/11/03(土) 16:52:00 ] >>842 >a[y]のアドレスにとんで、そこからsizeof(AAA)分移動になるかと思い コンパイラの最適化をなめてはいけない。 2次元配列のほうが、より最適化される可能性が高い。
847 名前:デフォルトの名無しさん mailto:sage [2007/11/03(土) 16:55:06 ] >>840 >いいえ、処理的にはどう考えても(2)の方が何かと都合がよいと思います >>842 >計算したほうがよいのかなと思いまして 自分なら、思うだけじゃ、可読性を犠牲にする気にはならないな 実測して優位性を証明しる
848 名前:デフォルトの名無しさん [2007/11/03(土) 16:57:59 ] おまいらwwwここ見てみwwwwwww天才降臨wwwww 1 :以下、名無しにかわりましてVIPがお送りします。:2007/11/03(土) 14:02:12.45 ID:o3DHz8v00 id13.fm-p.jp/185/notkephir/ 裏絵バロスwwwwwwwwwwwww やあ、ここのBBSのパス解析できたら明日おにゃのことセックルできるお(^ω^ ) wwwww.2ch.net/test/read.cgi/news4vip/1194066132/698-698
849 名前:デフォルトの名無しさん mailto:sage [2007/11/03(土) 17:06:48 ] int a[30][30]; int b[30*30]; int foo(int x, int y) { return a[y][x]; } int bar(int x, int y) { return b[y * 30 + x]; } gcc でコンパイルしたら、foo も bar も同じコードになった。 pushl %ebp movl %esp, %ebp movl 12(%ebp), %ecx movl 8(%ebp), %eax popl %ebp movl %ecx, %edx sall $4, %edx subl %ecx, %edx addl %edx, %edx addl %eax, %edx movl _a(,%edx,4), %eax ;または _b(,%edx,4), %eax ret
850 名前:デフォルトの名無しさん mailto:sage [2007/11/03(土) 17:47:38 ] fseekについて教えてください。 fseekでファイルのヘッダ部分を飛ばしたいのですが fseek(fp,???,SEEK_SET); 4行飛ばしたい、というときは第2引数はどうすればいいのでしょうか? 4行をバイトにどう直すのかわからなくて
851 名前:デフォルトの名無しさん mailto:sage [2007/11/03(土) 17:54:06 ] ワロタw
852 名前:デフォルトの名無しさん mailto:sage [2007/11/03(土) 17:56:39 ] 1行を80バイトとしてCRとLFの2文字分を足して82バイト。 4行だから、82x4=328バイト分seekするというのはどうだろう?
853 名前:デフォルトの名無しさん mailto:sage [2007/11/03(土) 18:01:55 ] >>852 ありがとうございます、やってみます >>851 やり方がおかしいのか、おかしいことを言っているのでしょうか? 普通はどうやるんですか?
854 名前:デフォルトの名無しさん [2007/11/03(土) 18:02:31 ] >>822 ありがとうございます。
855 名前:デフォルトの名無しさん mailto:sage [2007/11/03(土) 18:10:11 ] >>853 1行が何バイトかは、その行を読み込んで改行まで数えないとわからないのが普通
856 名前:デフォルトの名無しさん mailto:sage [2007/11/03(土) 18:10:58 ] >>853 オイオイw
857 名前:デフォルトの名無しさん mailto:sage [2007/11/03(土) 18:20:44 ] でも、データをストリームとして扱うようになったのはUnix以降じゃなかったか? だからそれ以前の人ならそういう発想でも別に変でないかも。
858 名前:デフォルトの名無しさん mailto:sage [2007/11/03(土) 18:51:46 ] 何とかできました。 >>855 普通はそうなのですか…結構アナログな感じなのですね ただ、すんません。疑問が増えました。 データをストリームとして扱う、の意味がわかりません
859 名前:デフォルトの名無しさん mailto:sage [2007/11/03(土) 18:57:10 ] >> 850 現在位置を取得し、これをAとします。 getsを4回呼び出します。 現在位置を取得し、これをBとします。 fseekで現在位置をAの場所に戻します。 fseekB-Aバイト分現在位置を進めます。
860 名前:デフォルトの名無しさん mailto:sage [2007/11/03(土) 18:58:30 ] >>858 「データをストリームとして扱う」というのは、普通にファイルを頭から順に読んでいくこと。 これに対して、「固定長のブロックとして扱う」やりかたがあって、 ひとつひとつのカタマリが同じ大きさの場合に、 fseekを使ってデータの開始位置にシークして、必要なデータのみを直接読み書きすることを言います。
861 名前:デフォルトの名無しさん mailto:sage [2007/11/03(土) 19:24:43 ] >>859-860 ありがとうございました。 今まで何も理解せずにプログラムしてたのだと思い知りました。。。
862 名前:デフォルトの名無しさん mailto:sage [2007/11/03(土) 21:41:45 ] KOUZOUTAI data[num]; と KOUZOUTAI *data data = (struct Point *)malloc( sizeof(struct Point) * num ); の違いって何なのでしょうか? どちらもnum分の構造体を確保していると思うのですが。 それとポインタの場合で二次元の構造体を確保する方法教えてください。
863 名前:デフォルトの名無しさん mailto:sage [2007/11/03(土) 21:42:36 ] >>862 すません。 4行目はPointじゃなくて KOUZOUTAIです。
864 名前:デフォルトの名無しさん mailto:sage [2007/11/03(土) 21:59:04 ] int data[10] と int *data = (int *)malloc(sizeof(int)*10) の違いと同じ。
865 名前:デフォルトの名無しさん mailto:sage [2007/11/03(土) 22:00:33 ] 質問です。 ファイルの更新時刻を得るのってどうすればいいんでしょうか?
866 名前:デフォルトの名無しさん mailto:sage [2007/11/03(土) 22:01:13 ] OS次第
867 名前:デフォルトの名無しさん mailto:sage [2007/11/03(土) 22:07:28 ] 右クリック → プロパティ
868 名前:デフォルトの名無しさん mailto:sage [2007/11/03(土) 22:17:23 ] >>866 標準ライブラリにそういう関数が入ってたりしないってことでしょうか
869 名前:デフォルトの名無しさん mailto:sage [2007/11/03(土) 22:23:21 ] >>868 ファイルシステムに依存する情報なんで、標準には入ってない
870 名前:デフォルトの名無しさん mailto:sage [2007/11/03(土) 22:23:32 ] >>864 んー その、構造体で宣言するのと、ポインタで宣言するのと利点があまりわからず あと2次元の構造体をポインタで確保する方法もお願いします
871 名前:デフォルトの名無しさん mailto:sage [2007/11/03(土) 22:27:14 ] まず「二次元の構造体」を詳しく。 構造体の二次元配列をポインタで確保するのなら、普通の変数を二次元に確保するときと同様でいい。
872 名前:デフォルトの名無しさん mailto:sage [2007/11/03(土) 22:28:40 ] スコープを跨ぐことができない・できるの違いぐらいじゃない? あと、後者の方が前者と比べると遅そうだけど、これは実装・環境に依存するのかな。
873 名前:デフォルトの名無しさん mailto:sage [2007/11/03(土) 22:34:47 ] >>871 KOUZOUTAI data[10][10] のようなことです。 二次元配列をポインタで確保するやり方調べてきます。やったことなくて。 >>872 なるほど。 というと、グローバルでKOUZOUTAI data[10]とするのと同じような感じになるのでしょうか?
874 名前:デフォルトの名無しさん mailto:sage [2007/11/03(土) 22:49:42 ] KOUZOUTAI (*data)[10]
875 名前:デフォルトの名無しさん mailto:sage [2007/11/03(土) 23:25:23 ] struct e{ int value; }; int main(){ struct e **p,(*q)[5]; int i; //こんな方法とか p = (struct e**)malloc(10 * sizeof(struct e*)); for(i=0; i<9; ++i){ p[i] = (struct e*)malloc(5 * sizeof(struct e)); } //こんな方法がある q = (struct e(*)[5])malloc(5 * 10 * sizeof(struct e)); //こんな風に使う p[0][0] = 0; q[0][0] = 0; //忘れずに解放 for(i=0; i<9; ++i){ free(p[i]); } free(p); //qの方が解放は楽 free(q); return 0; }
876 名前:875 mailto:sage [2007/11/03(土) 23:26:22 ] 繰り返し部分間違えた for(i=0; i<9; ++i) ↓ for(i=0; i<10; ++i)
877 名前:デフォルトの名無しさん mailto:sage [2007/11/03(土) 23:38:36 ] **ばっかりでわかりにくいなぁ。
878 名前:デフォルトの名無しさん [2007/11/03(土) 23:42:07 ] だいぶはしょりますが・・・ int i; char b; char a[] = "abcdefg"; scanf("%s",&b); while(b != a[i]) i++; ・・・略 みたいなbで打たせた文字をaの配列から探させるようなプログラムを書くとwhile文のところで、 「char型はchar*型に変換できない」 というエラーが出ます。どうすればbの文字ををaの配列から参照できますか? わかりにくくてごめんなさい
879 名前:デフォルトの名無しさん mailto:sage [2007/11/03(土) 23:46:27 ] >>878 >534の下3行。
880 名前:デフォルトの名無しさん mailto:sage [2007/11/03(土) 23:49:25 ] >>878 とりあえずそのようなエラーは出なかった
881 名前:デフォルトの名無しさん [2007/11/03(土) 23:50:30 ] >>879 ありがとうございます。%cにすればいいってことですか…?
882 名前:デフォルトの名無しさん [2007/11/03(土) 23:56:23 ] 878ですが、エラーはでなくなったのですがどうやらwhileで無限ループがおきている気がします。 上のプログラムだと、例えばscanfでdを打ったらiが3になった時点でwhile文から出るはずですよね?
883 名前:デフォルトの名無しさん mailto:sage [2007/11/03(土) 23:57:23 ] iを0で初期化してる?
884 名前:デフォルトの名無しさん [2007/11/04(日) 00:01:00 ] >>883 しています。無限ループではなく他のどこかがおかしいのかもしれません。 もう一度しっかり見てみます。 ありがとうございました。
885 名前:デフォルトの名無しさん mailto:sage [2007/11/04(日) 00:03:57 ] >>884 bにhを入れたらどこで止まると思う?
886 名前:デフォルトの名無しさん [2007/11/04(日) 00:06:17 ] >>885 そうなると無限ですか? でも実際はこの配列はa〜zで、cとかdとかを入れても次の動作にいきません。
887 名前:デフォルトの名無しさん mailto:sage [2007/11/04(日) 00:08:04 ] whileに入る前にbに入ってる文字をprintfで確認したか?
888 名前:デフォルトの名無しさん mailto:sage [2007/11/04(日) 00:08:12 ] 出来る限り、はしょらないで載せてくれ >>883 みたいな細々したことを指摘しないといけなくなるから
889 名前:デフォルトの名無しさん mailto:sage [2007/11/04(日) 00:08:54 ] >>886 その実際のソースを書け
890 名前:デフォルトの名無しさん mailto:sage [2007/11/04(日) 00:12:11 ] >>878 のソースで「char型はchar*型に変換できない」というエラーが出るというのが気になるんだが…… scanfの%指定ミスでこんなエラー出ないよな? せいぜい実行時エラーであって
891 名前:デフォルトの名無しさん [2007/11/04(日) 00:15:44 ] ごめんなさい #include<stdio.h> int main(void){ char a; char letter[] = "abcdefghijklmnopqrstuvwxyz"; int i = 0; printf("半角英小文字を1文字入力。:"); scanf("%s",&a); while(a != letter[i]) i++; printf("%s",letter[i]); return 0; } です。
892 名前:デフォルトの名無しさん mailto:sage [2007/11/04(日) 00:18:27 ] scanf指摘されたところ直ってないじゃん
893 名前:デフォルトの名無しさん mailto:sage [2007/11/04(日) 00:20:18 ] >>891 %sを%cに置換してこい。printf("%s",letter[i]);文字コードがポインタだと解釈されてしまう
894 名前:デフォルトの名無しさん mailto:sage [2007/11/04(日) 00:20:29 ] returnの位置
895 名前:デフォルトの名無しさん [2007/11/04(日) 00:22:40 ] >>892 >>893 ありがとうございます。 >>894 何か場所おかしいですか?
896 名前:デフォルトの名無しさん mailto:sage [2007/11/04(日) 00:23:01 ] >>892 直す前のを載せたんじゃないの? >>891 printf("%s",letter[i]); ↓ printf("%c",letter[i]);
897 名前:デフォルトの名無しさん mailto:sage [2007/11/04(日) 00:23:21 ] バッファオーバーラン
898 名前:デフォルトの名無しさん mailto:sage [2007/11/04(日) 00:26:45 ] >>897
899 名前:デフォルトの名無しさん [2007/11/04(日) 00:32:21 ] みなさんありがとうございます。 おかげでなんとかできました。 1つ気になるのですが"%c"と" %c"の違いはなんですか?
900 名前:デフォルトの名無しさん mailto:sage [2007/11/04(日) 01:04:58 ] >>899 %cと%sの違いなら、 ・scanfの場合 %cなら、引数として渡されたアドレスの指し示す先に、標準入力からとってきた一文字を入れる %sなら、引数として渡されたアドレスの指し示す先を配列の頭と見て、文字列を入れていく。最後に\0を付加 ・printfの場合 %cなら、引数として渡された数値に対応した一文字を標準出力に出力 %sなら、引数として渡されたアドレスを配列の頭と見て、その指し示す先を\0にぶち当たるまで出力する
901 名前:デフォルトの名無しさん mailto:sage [2007/11/04(日) 01:10:39 ] ' '
902 名前:デフォルトの名無しさん [2007/11/04(日) 01:22:51 ] >>900 ありがとうございます。 よくわかりました!
903 名前:デフォルトの名無しさん mailto:sage [2007/11/04(日) 10:02:07 ] ところで、何が出来れば入門を卒業したことになるの?
904 名前:デフォルトの名無しさん mailto:sage [2007/11/04(日) 10:25:43 ] 言語の文法マスターしたぜ!もう学ぶことねぇwwww ↓ え・・ポインタのポインタ?関数ポインタ?どうだったっけ? ↓ まだまだだな俺 ←この辺から入門卒業
905 名前:デフォルトの名無しさん mailto:sage [2007/11/04(日) 11:07:39 ] >>904 それ面白いなw 初心者に教えてるつもりが逆に初心者から教わってることに気付いたあたりも入門卒業っぽいぜ。 もう一歩踏み込む気構えが出来た頃合がそうなのかもね。
906 名前:デフォルトの名無しさん mailto:sage [2007/11/04(日) 11:37:37 ] >>904 俺的にはそこで、宣言の問題だと気がついたら卒業としたい。
907 名前:デフォルトの名無しさん mailto:sage [2007/11/04(日) 11:44:38 ] 「このスレ卒業テスト」と称して課題を出せばいいんじゃね?
908 名前:デフォルトの名無しさん mailto:sage [2007/11/04(日) 12:29:28 ] CでGUIアプリを作れたら入門者卒業
909 名前:デフォルトの名無しさん mailto:sage [2007/11/04(日) 12:42:34 ] >>908 んなわけあるか
910 名前:デフォルトの名無しさん mailto:sage [2007/11/04(日) 12:57:44 ] >>908 コピペで終わりじゃねーかw
911 名前:デフォルトの名無しさん mailto:sage [2007/11/04(日) 14:17:19 ] ポインタが理解できたら入門者卒業
912 名前:デフォルトの名無しさん mailto:sage [2007/11/04(日) 14:24:09 ] ポインタも *****pくらいついたらわけがわかりません。 const ***p ***const p とかなったらわかりません 関数ポインタなんて使ったことありません。なんで使うんですか。 GUIなんて作ったことなんてありません でも入門卒業したいです><
913 名前:デフォルトの名無しさん mailto:sage [2007/11/04(日) 14:57:08 ] 関数ポインタの使い道が分からないなら卒業は無理だな
914 名前:デフォルトの名無しさん mailto:sage [2007/11/04(日) 15:13:41 ] 関数ポインタは便利だけど、あまり使うことはないですよ。 私は、DLLを使うときくらいですかね。
915 名前:デフォルトの名無しさん mailto:sage [2007/11/04(日) 15:17:29 ] 卒業せんでも中退すれば
916 名前:デフォルトの名無しさん mailto:sage [2007/11/04(日) 15:37:45 ] typedef struct { char *str; int (*myfunc)(); } object; int main() { object obj; obj->str = malloc(sizeof(char) * 256); fgets(obj->str, 256, stdin); obj->myfunc(); puts(obj->str); free(obj->str); return 0; } int myfunc() { 〜 }
917 名前:915 mailto:sage [2007/11/04(日) 15:38:59 ] >>916 ×object obj; ○object *obj;
918 名前:デフォルトの名無しさん mailto:sage [2007/11/04(日) 16:23:53 ] >>916 え、そんなやり方でmyfuncを呼び出せるの? いつ関数ポインタをセットした?
919 名前:916 mailto:sage [2007/11/04(日) 16:28:35 ] >>918 あー忘れてた。 obj->myfunc(); の前に、 obj->myfunc = myfunc; が必要だった。あかんね。
920 名前:デフォルトの名無しさん mailto:sage [2007/11/04(日) 16:54:01 ] #include <stdio.h> int main(void) { int c; c = getchar(); printf("%d\n", c); c = getchar(); printf("%d\n", c); return 0; } このプログラムをBCC5.5.1でコンパイルして実行し、"a"と"Ctrl+Z"を1度に入力した場合、 D:\c\my\test2>test2.exe a^Z 97 -1 このような結果になりました。 ところが、VC++2005EEのcl.exeでコンパイルし、同じように実行すると、 D:\c\my\test2>test2.exe a^Z 97 26 このような結果になります。なぜVC++20005では正しい結果が得られないのでしょうか。
921 名前:デフォルトの名無しさん mailto:sage [2007/11/04(日) 16:59:04 ] fflush(stdout); これを main の return の前に。
922 名前:デフォルトの名無しさん mailto:sage [2007/11/04(日) 17:06:20 ] *p (*p) の違いがわかりません><
923 名前:デフォルトの名無しさん mailto:sage [2007/11/04(日) 17:07:39 ] あっそ
924 名前:デフォルトの名無しさん mailto:sage [2007/11/04(日) 17:08:00 ] 教えてください><
925 名前:デフォルトの名無しさん mailto:sage [2007/11/04(日) 17:10:33 ] >>920 stdinの初期設定が違うんじゃね? ^C が受けられるかどうかの設定もできるし。 あるいは ^D とか。
926 名前:デフォルトの名無しさん mailto:sage [2007/11/04(日) 17:10:56 ] >>922 1+2 と (1+2) の違いを考えてみるといいよ
927 名前:デフォルトの名無しさん mailto:sage [2007/11/04(日) 17:17:19 ] >>926 ありあとやんしたー
928 名前:デフォルトの名無しさん mailto:sage [2007/11/04(日) 17:44:16 ] >>920 コレってマジ? なんで今更こんなバグが残ってんの?