過去スレってなんか意味あるのか。
なんだ初心者か。
ほとんどdat落ちしてるし前スレのみでいいんじゃね? ●もちなんかレアだろうし
●なくても見れるよ
それ以前に、読むやついるのかって疑問も。
読むことは無くても検索する事ならあるかもしれない
たかだか2レス程度の過去スレリンクにけちつけるヤツってなんなの?
12 :
デフォルトの名無しさん :2008/02/19(火) 11:02:18
そういう人に限って過去スレよめっていうんじゃない?
C:\Program Files\Microsoft Visual Studio 8\VC\C> test24.c #include<stdio.h> #include"myfunc.h" { ...... } myfunc.c myfunc.h 環境 VC++ 2005 express edition コマンドプロントでのリンクの方法おすえて。
cl で拡張子まで指定すりゃリンクまでやってくれるよ。
まあLINKでもいいけど。 オプションはGUIのほうでプロパティのリンカのコマンドラインみればわかるべ。 まああれ全部指定する必要も無いかもだが。
16 :
13 :2008/02/19(火) 17:19:51
cl teste.c myfunc.c でけますた ありがとう あいしてる・
>>12 反論できなくなると人格攻撃はじめるクセってみっともないから、直す努力したほうがいいよ。
まあ、そういう根性が染みついちゃってて、一生ゲスのまま終わっちゃうんだろうけどね。
>>17 わざわざ同じレベルまで降りてやることもあるまいに。
19 :
デフォルトの名無しさん :2008/02/20(水) 02:03:36
20 :
デフォルトの名無しさん :2008/02/20(水) 02:50:57
>>11 >たかだか2レス程度の過去スレリンクにけちつけるヤツってなんなの?
?例えば、ですが… 2ch-browserの購入installを試みては…
r
21 :
デフォルトの名無しさん :2008/02/20(水) 05:31:03
ポインタへの代入についての質問です。 const char**型の変数にchar **型の変数を代入するのは、 修飾型へのポインタに非修飾型へのポインタを代入することになるので してはいけない(コンパイラが警告を出す)と本に出ていたので、 #include<stdio.h> int foo(const char **p){ printf("ok\n"); return 0; } int main(int argc,char **argv){ foo(argv); return 0; } 上記のようにコーディングしてコンパイルしてみたのですが、 警告の類はでません(argcとpが参照されていないという 警告と標準ライブラリ関数のプロトタイプ宣言に関する 警告は出ます)。コンパイラはvisual studio2005に付属 しているもので/Wallオプションを付けてます。 なぜ警告がでないのでしょうか?
22 :
デフォルトの名無しさん :2008/02/20(水) 08:32:15
>>21 国語の勉強してから、もう一度その本を読め。
>>21 > const char**型の変数にchar **型の変数を代入するのは、
その代入をしていないから
>const char**型の変数にchar **型の変数を代入するのは、 >修飾型へのポインタに非修飾型へのポインタを代入することになるので >してはいけない(コンパイラが警告を出す)と本に出ていたので、 いいえ、そんな大嘘ありえません。
>>25 質問の大元では関数の引数として const 修飾を使っている
const char ** に char ** を代入することは、 「修飾型へのポインタヘのポインタ」に「非修飾型へのポインタへのポインタ」を代入することだから、 >21にあるような「修飾型へのポインタ」に「非修飾型へのポインタ」を代入することとはならないな。
ぶっちゃけ動くならコードなんかどうでもいいですよね?
メンテナンスを考えなくていいならな
偶然動いてるのときちんと動いてるのと区別がちゃんとつくんならな。
こういうのは自分だけで使うのか、他人に提供するのかでもかわってくるしな。
>>26 x がグローバル変数なら似た事ができる。
33 :
21 :2008/02/20(水) 22:26:14
>>24 >>27 そうですね、
「修飾型へのポインタヘのポインタ」に「非修飾型へのポインタへのポインタ」を代入することでした。
>>25 確かににgccでコンパイルしてみたら警告がでました。
リンク先、参考になりました。ありがとうございます。
>>26 関数に引数を渡すのは、仮引数への代入として扱われるらしいので代入と書きました。わかりにくくて
すいません。
>>29 >>30 とりあえず、きちんとわかるまではエラーが出るような書き方は避けるようにしときます。
関数に引数を渡すのは、仮引数への代入ではなく初期化。
35 :
21 :2008/02/20(水) 22:28:36
36 :
21 :2008/02/20(水) 22:29:26
あ、そうですね。 代入だと、constつけたらできないですね。
37 :
デフォルトの名無しさん :2008/02/21(木) 00:43:17
static関数はそのファイルでしか有効じゃないんですよね。 じゃあ、そのファイルでしか使用しない関数はstaticにしておけば、 関数名の衝突の心配が無くていいかと思うんです。 でも、そうしたらほとんどの関数がstaticになってなんか格好悪いんですけど。 そういうものですか?
staticの何が格好悪いんだ
>>38 いや、なんとなくです。
サンプルソースとか見ても、普通はそんなにstaticがついていない気がするし。
普通そんなに関数名衝突しないだろ
サンプルは適当に作ってるから書いてない事もある。 真面目に書く場合は公開しない関数には static を付けるのが普通。
static付けたプロトタイプ宣言を書いといて、 定義は付けずに書けばどう?
43 :
デフォルトの名無しさん :2008/02/21(木) 02:12:09
これに於いて "スタック領域 戻り番地3 変数 戻り番地2 戻り番地1 " 戻り番地とは、どういう意味なんでしょうか?
retで戻る場所
関数から帰ってきて再開する場所 void g() {...} void f(){ g() ; r1: g() ; r2: } 上のgの中を実行中は "スタック領域 r1 下のgの中を実行中は "スタック領域 r2 f内の中を実行中はスタック領域=空
46 :
43 :2008/02/21(木) 02:16:50
47 :
43 :2008/02/21(木) 02:19:26
>>45 詳しく、ありがとうございます
ですが、どうしてこれが”戻る”っているのでしょうか?
if(argc > 1) とは、argcが1より大きければ〜でしょうかね
>>47 関数gにいってr1またはr2に戻ってくるから
>>48 そのとおりだ、見ての通りだ
引数一個の時は、実行ファイル名と引数合わせて二個、argc==2だから注意しろ
52 :
43 :2008/02/21(木) 02:33:49
>>49 ですが、これだと戻り番地が複数ありますよね???
"スタック領域
戻り番地3
変数
戻り番地2
戻り番地1
"
>>52 あなたが手を出すには、まだ早すぎるのかも知れません
どんなに説明していても、読まないみたいだし
>>52 i()
{
今ここを実行中、ここが終わったら"戻り番地3"へ
}
h()
{
i();
戻り番地3:
}
g()
{
変数宣言 変数 ;
h();
戻り番地2:
}
f()
{
g();
戻り番地1:
}
>>52 つまらないアドバイス
プログラムに関数がなく、gotoだけで何とかしたいと思ったらどうする?
実際CPUによってはマシン語にgotoしかないケースもある、その代り今、実行している位置を変数に記録できるとする。
戻り番地はある種の変数だ。goto label のとび先 label を格納することができる。
これで関数同様の処理の流れを作ってみよ
一日ゆっくり頭を悩ませるがよい
56 :
43 :2008/02/21(木) 03:58:14
>>53 確かに、まだレベルが達していませんでした。
>>54-
>>55 何とか何となくですが、理解できました。
gotoと参考書に載ってませんので、レベルを上げてから
深く考えてみます
ありがとうございました。。。
57 :
デフォルトの名無しさん :2008/02/21(木) 05:16:32
UNIXはCで作られているのでしょうか?
>>39 どのサンプルを見ているのか判らないけど、
汎用的なライブラリーとかソースみると間違いなく
ファイル内で完結する関数、変数にはstaticついてるよ
というかついてないと怖いと思う
59 :
37 :2008/02/21(木) 09:56:06
>>58 なるほど。
そういうものってことですね。
ありがとうございました。
整数型の変数に最大値以上の数を入れようとした時、影響があるのはその変数だけでしょうか? 例えばunsigned intの最大値で111...111となってる所に1を足したら000...000となってしまうみたいですが、 この時となりのメモリーに1が繰り上がってしまうってことはあるんでしょうか?
配列使って試してみたら?
>>60 大丈夫、当該メンバ以外は影響受けません。
>>61-62 ありがとうございます。
なるほど、配列だと隣のメモリにおかれるから確認に使えるんですね。
自分でも試して見ます。
>>63 実践コードでは、良い悪いは抜きにして、それを前提にしたコードがかなりあるので確り覚えておくが吉。
二の補数でググッておけ
65 :
ててて :2008/02/21(木) 18:24:29
memcmpについて質問です char *han1; char *han2; char temp1[81]; char temp2[81]; han1 = fgets(temp1,81,Fp1); han2 = fgets(temp2,81,Fp2); となっていた場合に文字数81は memcmp(han1,han2,81)と書いていいんでしょうか? 最後の文字のNULLを飛ばして80 memcmp(han1,han2,80)とどっちなのか悩んでいます 指摘お願いします
むしろstrncmp
67 :
ててて :2008/02/21(木) 19:24:24
strncmpをmemcmpに変えてっていう問題なんです すみません
試せば?
まぁ、80でいいけど81だろうな。
実は80も81も不正解、な気がする。
71 :
ててて :2008/02/21(木) 19:50:46
ええ!? ちなみに試せる環境がありません
そりゃぁ、strcmp()じゃない時点で不正解だ。
73 :
ててて :2008/02/21(木) 20:09:26
ううむ まあとりあえず81って書いておきますw 情報ありがとうございましたw
入力行が80文字未満だとtemp1 temp2にゴミが残るからねえ。
75 :
ててて :2008/02/21(木) 20:18:34
とは思うんですが入力のほうは指定ないので少なく書いても幅が広がってしまうだけのようなきもするんですよね
>>75 memcmp(han1,han2,strlen(han1))
77 :
デフォルトの名無しさん :2008/02/21(木) 22:33:13
#include <stdio.h> int main(void) { char str[80]; int i, spaces; char *p; printf("文字列を入力してください: "); gets(str); spaces = 0; p = str; while(*p){ if(*p==' ') spaces++; p++; /* このポインタのインクリメントは"*p++;"としても プログラムは正しく動作します。なぜですか?*/ } printf("スペースの数: %d", spaces); return 0; } すいません。教えてください。
* よりも ++ の方が演算の優先順位が上だから。 *p++ってのは*(p++)と等しい。
79 :
77 :2008/02/21(木) 22:40:33
>>78 すばやい回答、ありがとうございました。m(_ _)m
80 :
ててて :2008/02/21(木) 22:41:18
>>76 なんという
そうかーなるほど・・・
うう、ひらめきって大事ですね
char temp1[81] = {'\0'};
>>81 temp1[81] == "abcde\0\0";
temp2[81] == "abcde\0f";
このとき文字列としては
途中で送信してもうた...
>>82 のとき文字列としては等価と判定せねばなるまい
memcmp(han1,han2,strlen(han1))の場合 han1が多い時とhan2が多いときで誤差でない?
85 :
76 :2008/02/21(木) 23:44:50
>>80 訂正
memcmp(han1,han2,strlen(han1)+1)
86 :
84 :2008/02/22(金) 00:27:26
han1が10文字 han2が20文字 han1が20文字 han2が10文字 の時にmemcmpだとゴミが入ってしまって無理じゃないかね?ってことね
違いを検出するだけでいいなら、memcmp()でも問題ないね。
88 :
ててて :2008/02/22(金) 09:57:29
han1 = fgets(temp1,81,Fp1); han2 = fgets(temp2,81,Fp2); と、なっているところでテキストファイル同士比べる時に、 han1 = [aaaaaaaaaa] han2 = [aaaaaaaa] などなっていても実際80文字分(1行分?)までの区切りなので初期化する必要ってありますか? 一応比較して結果が0なら比較内容同じ、-1か1なら違うとでるようにするだけなのでfgetの文字数と同じなら大丈夫な気がするような・・・
短いほうが\0で終わってるわけだから そこまでが同じならば短いほうが小さい、という結果になる なのでどっちの長さを指定してもいいが、\0まで含めることが必要。 \0を超えての比較は意味が無いので、バッファのサイズで比較するのは間違い。
90 :
ててて :2008/02/22(金) 10:52:10
なるほど〜 それじゃあ、そろそろ答え81って書いて提出します みなさんのおかげでいろいろわかりました どうもありがとうございました
>>90 han1[]="abcd\0e";
han2[]="abcd\0f";
92 :
ててて :2008/02/22(金) 12:21:24
>>91 の場の場合もあるにはありますよね
そこら辺の指定はまったくないんですよね
問題文
以下のプログラムは起動時に指定された2つのテキストファイルを比較し、
違う行があればその行番号を表示するプログラムです。
空白部分を埋めて、プログラムを完成させなさい。
という文章で自分で strcmp のバージョンは穴埋めはできたと思います
問題2
問題1のプログラムにおいてstrcmpを使用して読み込んだ2つのレコードが同じかどうか判断しています
これをmemcmpを利用したロジックに作り直しなさい
それで比較する部分のstrcmpをmemcmpに変えて書いたんですが読み込みするテキストファイルの指定は全くありません
それで文字列分指定すればいいかなーと思っていたんですが・・・
>>90 のようにそこまで深く考えたほうがいいのでしょうか?
意地悪問題すぎる
だから単に片方のをstrlen()+1すればいい strlenも使用不可なのかな?でも自作するくらいならmemcmpも使わんしなw
94 :
ててて :2008/02/22(金) 13:40:00
>>93 strlenは使えます
と言うか勘違いしてましたw
それで当たってますね
han1 = aaa\0
han2 = aaab\0
memcmp = (han1,han2,strlen(han+1))
だと返す変数0になりません?
と勘違い
文字数で違うなら\0の部分で0以外返しますし
文字が違うならやっぱり0以外返しますね
答えにそうかいて出します
ちゃんと理解して解決しました
本当にありがとうございます
大きい二次元配列の初期化ってどうやればいいんですか? char buf2[20][20];char buf[256]; double dat[10000]; とかだったら。
>>95 ループで各要素に初期値を代入する。
2次元配列の場合は2重ループで初期値を代入する。
char buf[256];が文字列だったら、strcpy(buf, "");
その前に、本当に初期化する必要があるかどうかチェックしてね。 無駄に初期化する人が多いから。
初期化することって規約があることもあるんだぜ・・・。
初期化する必要ない場合ってどういう場合? LINUXでいいデバッガない?
初期化する必要ない場合は初期化する必要ない場合
102 :
96 :2008/02/23(土) 02:26:53
>>98 ヌル文字での初期化の場合ね。
buf[0] = '\0'
でもいいんだが、好みの問題。
double data[10000]={0}だと初期化できてないみたいなエラーでるけどこれは 範囲あるの?
>>102 最適化すればオーバーヘッドなくなるのかな?
まぁもともと無視できるほどの差だろうけど
>>103 規格では全て 0 で初期化されるはずだが。
警告出すコンパイラならあるけど。
ただ、コンパイラが糞だと知らん。
セミコロンがないとかじゃないよな
107 :
デフォルトの名無しさん :2008/02/23(土) 03:15:36
108 :
デフォルトの名無しさん :2008/02/23(土) 03:19:31
コボラーさんがC言語覚えるのは結構大変?
文字列の長さも確認せずに strcpy はやばいだろ。
大変? とか気にしてる時点で脈は無いわ。
>>107 argcはコマンド引数の数+1。
コマンド行がhogeのときargcは1。
コマンド行がhoge arg1のときargcは2。
だからif(argc > 1)とはコマンド引数がひとつ以上あるということ。
112 :
デフォルトの名無しさん :2008/02/23(土) 04:27:04
113 :
デフォルトの名無しさん :2008/02/23(土) 04:28:35
>>111 >>だからif(argc > 1)とはコマンド引数がひとつ以上あるということ。
ないときは、あるんですかね?
ないときはないよ。そんときは、argcが1になる。
>だからif(argc > 1)とはコマンド引数がひとつ以上あるということ。 いや,2つ以上だろ.もしくは1つよりも多く.
argc==2なら引数は1だろ。
117 :
デフォルトの名無しさん :2008/02/23(土) 05:09:25
? ↓-此れは?
006: int main(int argc,char *argv[]
?
>>113 ああああああぁぁあぁ… 永遠に繋げていく事か"!
?
if( argc > 1, argv > 1, argc > 1) = argc[1]
?
118 :
デフォルトの名無しさん :2008/02/23(土) 06:45:19
頭が混乱してきた…整理ついたら、出直してきます ありがとうございました
コマンドラインとmain()の引き数の違いが理解できていない馬鹿がいる。 一般的に、コマンドプロンプトで command arg1 arg2 arg3 と入力すると、 command が実行されてそのmain()にはargv[0] = "command", argv[1] = "arg1", argv[2] = "arg2", argv[3] = "arg3", argc = 4 と言う形で渡される。
#define FREE(p) do{ free(p); (p) = NULL;}while(0) というのを本で見たのですが、このdo-whileにはどういう意味があるんでしょうか? 一回だけで抜けるループ、というのは分かるのですが、単にカッコでくくるだけではいけないのでしょうか?
>>120 if (・・・)
FREE(・・・);
else
・・・
みたいな書き方に対応。
if (〜) FREE(p); else 〜 のように使う場合、単なる { } だと if (〜) { 〜 }; となって、ここで if 文が終わってしまい、elseを続けられない。do-whileを使えば大丈夫。
あー、なるほど。 #define FREE(p) { free(p); (p) = NULL;} だと、セミコロン無しの FREE(p) だけで文が完結してしまうんですね。 そこにセミコロン追加した FREE(p); だと意味合いが変わってしまう、 かといって if(...)FREE(p)else... なんてセミコロンを省略すると書き方が統一できずバグの温床になる、と。 どうもありがとうございました。
それは(free(p),(p)=NULL)じゃだめなんでしょうか?
別にだめなことはない
変数が定義できるというメリットもある
(free(p), (p) = NULL) だと、この式が余計な値を持ってしまうから ((void)(free(p), (p) = NULL)) の方が望ましい。
そもそも #define FREE(p) do{ free(p); (p) = NULL;}while(0) ↑これ自体がだめなコードだと思う。
なんで?
>>129 free()したあとに、無条件でクリアするってのが?
まあ、あんまりいい手筋じゃないね。
そのまま関数終わるときなら NULL クリア要らないってことか? それならそのまま free 使えばいいじゃん。
マクロじゃなくて関数でラップしたらだめなの?
freeしたポインタ=もう使わないんだからわざわざ無駄なことして容量増やさなくてもいいじゃん
>>134 その時は free 使えばいいじゃん。
実際にはまた使うことだってあるだろ。
そういう時には FREE が役に立つ。
マタ使うってのは変数を使いまわすってだけで中身は別物入れるんじゃん。
NULL 入れないと解放されてる状態かどうか判定できないだろ。
>>136 dangling pointerでググれ。
関数でラップするとポインタのポインタを渡さないといけないから面倒だな。
scanf()のマニュアルを読んでいて、型修飾子に'['が有ることを初 めて知りました。といっても説明文の意味が全く分からない。どう やら、↓のように使うと、改行がヌル文字に変わるのでちょっと便 利かな、と思わなくもないのですが、これだ!という使い道は有り ますか? =========== sscanf("abc\ndef\n", "%[^\n] %[^\n]", str1, str2); printf("%s\n", str1); printf("%s\n", str2); ===========
142 :
141 :2008/02/23(土) 19:28:24
型修飾子ではなく変換指定子でした。
>>142 fgets()の代わりに改行まで全て読んだり(或いは無視したり)、
数字と特定のアルファベットだけの文字列を抽出したり、
色々使い途はある。
scanf("%*[^\n]%*c"); 入力バッファをクリア
wikipediaでも、scanf()でエラー時に改行まで読み飛ばして入力バッファクリアってサンプルコードが載ってるけど、 読み込みは行単位でないのに、エラー時のクリアを行単位でやるってのはどうかなって気がする。
インタラクティブな入力なら、改行が伴うからいいんじゃね?
結構大きいプログラムつくるようになったのだけど バグの見つけ方がわかりません。 どうすればいいですか? デバッガとかを使うべきなのでしょうか?
バグが見つからないならデバッガ使っても意味無いような
扱う数値が多すぎで バグなのか計算がおかしいのかわからないんだよなー。
計算がおかしいのはバグだろ
>>147 バグのない期待通りの動作がどうあるべきかはもちろん解ってるな?
どの変数がいつどういう値であるべきか(あってほしいか)、
自分で組んでるんだから当然知ってるはず
あちこちにprintfを入れて色んな変数の値を表示させてみて、
それが期待通りの値を示してるかを確認するのが基本
バグがあるってことは、どこかで期待と異なる値が現れるはず
どこで食い違ってるのかを詳細に追っていけば、だいたい問題の箇所に辿り着く
デバッガはそういった作業を補助するツール
問題の箇所がある程度わかってるなら、そこで実行を止めて変数の値を調べたり
1行ずつ実行して変数の値の変化を調べたり、そういうもの
てすとどりぶん汁!
printfとかはやってます。 数値処理だからオーバーフローかなあとはおもってるけど どこかはわからない。
>>147 初心者ならば机上デバッグ。
プログラムを紙にプリントアウトして、なぜそういう結果になるかをトレースする。
つまり、自分が作ったプログラムの動きを把握できるようにすること。
デバッガーは補助のためのツールとして考えること。
調べるしかないだろ
>>153 どこかわからないってことはないだろう
・最初から間違った値を表示するか、
・途中まで合ってて途中から間違った値を表示するか、
・最後まで正しい値を表示するか、
このどれかしかないんだから
最初から間違ってるなら最初が原因
途中まで合ってて途中から間違ってたら、そこが原因
最後まで正しいってことは結果も正しい=バグはないってことだ
論理的にかいてるのはいいけど 途中経過があっているかどうかがわかるレベルの プログラムなら悩んでないって
わかるレベルまで崩すのがデバッグだ ガンガレ
>>157 大きいプログラムって何行くらいのプログラム?100行?500行?1000行以上?
関数の数は?
プログラムをかいて徹底的に直してくれるような 教室ないのかな? みなさんはどのように進歩していきました?
>>160 人が直してくれたら、自分は進歩しないだろう
自分で直すんだよ、徹底的に
>>160 10行くらいの小さなプログラムからラジコン、バイクまでがんばって修理してきました
今では1万行あってもそこそここなせます
Ne_12275.tar.gz にうpしてみました passはworkです プログラムの説明はそのディレクトリのgaiyou.txtにかいています。 専門的なのでちょっとわかりにくいかと思いますが。
>>154 机上デバッグって。
デバッガでステップ実行するほうがいいよ。
結果がわからないのに、それがバグだとわかるのか? 正しい結果を出してるかもしれないだろう?
>>163 Ne_12775.gzだよな?
書き込みすら見直せないようだとバグの原因追求は難しいぞ
12775でした すいません。
ていうかスレチじゃね? 入門をはるかに通り越してる
唐突にうpしても誰もデバッグはしてくれないと思うぞ それだけだとかわいそうなんで一応アドバイスをしておくと 「あっているとおもう」こういう状態でデバッグするとはまる。 まずあっているとおもう場所を「確実にあっている」と確信できるまで調べるのがいいぞ
char **foo = (char **)MALLOC(sizeof(char*) * 3); みたいにした後、 foo から 3 を引っ張り出すにはどうすれば出来ますでしょうか?
無理 別の変数に3を覚えておくしかない
正規分布の関数のところまでは 入力平均分散重きがいっていて確認はできたけど 正規分布の計算したあとからわからないんだよね。。。
178 :
163 :2008/02/24(日) 02:01:16
171 175です
>>163 仕様がわからないので、だれも答えられないと思う。
各計算プログラムのポイントとなるところで、入力データと計算結果のデータを
ファイルに書き込む
↓
ファイルに書き込んだデータを検証する
この方法がよい思う。
180 :
179 :2008/02/24(日) 02:18:46
たとえば、こんな感じのデータをfprintfでファイルに出力する。 FUNCTION: hoge1 INPUT=XXX.XX.XXX.XXX <-hoge1関数の入力データ OUTPUT=XXX <-hoge2関数の出力データ FUNCTION: hoge2 INPUT=XXX.XX.XXX.XXX OUTPUT=XXX
181 :
179 :2008/02/24(日) 02:27:20
トレース用のfprintfのコードは以下のようにしておく #ifdef TRACE_MODE fprintf(・・・・ #endif コンパイル時に-D TRACE_MODEをつければ、fprintfによるデータ出力が行われ、 -D TRACE_MODEをつけなけれデータ出力はされない。 こうすればコメントアウトをする手間が省ける。 当然だが、fprintfは追加モードで書きこむこと。
>>181 このほうが楽じゃね?
#ifdef TRACE_MODE
#define trace_printf fprintf
#else
#define trace_printf
#endif
>>139 こんなの既に定型句だから可読性なんて損ねないよ。
C++ や C99 ならインライン関数があるからいいけど、
C89 だとこの程度の処理だと
パフォーマンスも考えてマクロを選択するのは普通。
>>183 組込みの人か?
それなら分かるけど、PC上のソフトで関数コールのオーバーヘッドが気になるほどの
パフォーマンス求められるってどんな分野のソフト?
関数でもマクロでも、どっちでも普通じゃねぇ?
そもそも FREE の場合は C にテンプレートがない以上 汎用的な関数の実装は無理だろ。 void ** は厳密に規格に照らし合わせれば違法らしいし。
>>184 15年前はそんなこと言ってられなかっただろ。
関数にするとこうなるのか? こんなことやってられないだろ。 void safe_free(void **p) { free(*p); *p = NULL; } /* p は int * で宣言されているとする */ void *vp = p; safe_free(&vp) p = (int*)vp;
188 :
139 :2008/02/24(日) 14:14:52
>>183 >>184 おれは組込み屋だが、パフォーマンス求めるなら素直に
free(p);
p = NULL;
と書けばいい。
神学論争になるから深入りしないけど、
三段マクロで地獄を見たので、マクロの使用は最小限にとどめるべきだと思う。
189 :
139 :2008/02/24(日) 14:17:37
>>187 ↓これでいいと思う。
void* safe_free(void *p) {
free(p);
return NULL;
}
/* p は int * で宣言されているとする */
p = safe_free(p)
あまりいいコードとは思えないけど。
そもそもポインタをクリアしても、safeにはならんだろ。
freeしてないのに再利用ってのをふせぐためにやってるんじゃないのか?
p がfree()されてないのに、また p = malloc(・・・); と、新しいメモリを確保してしまうことがあるから、 if (p) free(p); p = malloc(・・・); とチェックを入れてからmalloc()するってこと?
if(p) でメモリが確保されているかどうかチェックできるし、 malloc の前にとりあえず free 書いとけばメモリリークは起こらないようになるね。
ASSERT( p == NULL ); p = malloc(・・・); こういうのはたまに書くけど、mallocの前にfreeしたことはないなぁ
ポインタにnullを入れて、ポインタが使われているかどうかのフラグに使うってのは、 ロジック上そうすることがあるっていうのは分かるけど、つねにnullクリアして、常に nullチェック入れるってのは、バグ隠しになる可能性が大。
再利用する可能性のあるポインタはfreeした直後にNULLを入れておく。 これでいいじゃん。何を悩むことがあるのか。
分割コンパイルをするときに 1つの関数を1つのファイルとしてコンパイルしたいんですけど 短い関数も1つのファイルにすべきなのですか? 結構関数おおいのですが
>1つの関数を1つのファイルとしてコンパイルしたいんですけど したいんなら、すべきだろう
なんで1つの関数を1つのファイルとしてコンパイルするのかが分からない。 static 関数とか使わないのか? 1つの static 関数を複数の関数から呼ぶとなると どうしても複数の関数を1つのファイルに置かざるをえないはずだが。
extern
>>196 わざわざマクロとか関数を作ってるのは、無条件に全部クリアってつもりなんでしょ。
>>192 >>193 メモリリークは起こらないかもしれないが、別のわかりにくいバグが出やしないか。
そのポインタはもう使われてない、ということは保証されないわけだし。
そういう意味ではポインタを使いまわすのは良くない。
スタックがどうしようもなく少ない場合は使いまわしたくなるかもしれないが、
そもそもそんな環境でmallocが使えるとは思えんし。
そもそもmallocでスタックオーバーフローを出したことがない。
ローカル変数を想定してそういう事言ってるのかもしれんが、 構造体メンバだとよくあることだぜ。
なんかうまく言えないが、204が何かを勘違いしてる気がしてしょうがない。
mallocでオーバーするのはヒープだろうな。
C言語を勉強しようと思うのですが はじめたばかりでもわかるC言語のサイトってないですか?
209 :
sage :2008/02/24(日) 18:34:19
fseek関数について質問なんですが、第2引数のoffsetの書き方が 10 10L sizeoff(int)*10 などさまざまな書き方があるのですが、どう違うのでしょうか?
>>209 前2者は同じ。最後のそれは、int10個分という意味なので実際は20とか40になる。
ちなみに、ansi89以前のプロトタイプ宣言をしない場合には10ではなくて10Lと(longであることを明示的に)書く必要があった。
211 :
209 :2008/02/24(日) 19:09:31
>210 ありがとうございます。 10や10Lの型は何になるんでしょうか? 又、 typedef struct product{ char ○○; int △△; float ××; }product; のような構造体でランダムアクセスを行った場合、fseek関数のoffsetは sizeoff(product) という書き方でいいんでしょうか?
sizeof、だ。 typoじゃなかったのか・・・
10 : int 10L : long
214 :
209 :2008/02/24(日) 19:15:37
あと、 typedef struct product{ char ○○; int △△; float ××; }product; のような構造体で特定のメンバにランダムアクセスを行うには、fseek関数のoffsetは sizeoff(product.○○) という書き方でいいんでしょうか?
215 :
209 :2008/02/24(日) 19:18:45
typo : タイプミス
×sizeoff ○sizeof
218 :
209 :2008/02/24(日) 19:24:29
220 :
209 :2008/02/24(日) 19:57:59
>>219 ありがとうございます。
sizeofを使って、特定のメンバにアクセスすることはできませんか?
又、この構造体が複数あった場合、その中の一つの構造体の特定のメンバに
sizeofを使ってアクセスすることはできますか?
>>220 offsetof を使うと言ってるんだから素直に offsetof 使え。
パディングがあると sizeof は破綻する。
222 :
209 :2008/02/24(日) 20:17:12
>>221 わかりました、そうします。
パディングというのはよくわからないのですが、構造体メンバの位置を調節
するため、sizeofでは正確に求められないということですか?
よかったら詳しく教えてください。
なんでも構造体のメンバのアドレスを先頭から4バイト刻みでアクセスできるように隙間に詰め物することらしいよ
>>222 >223でほぼ正しいが、4バイト刻みとは限らないので要注意。
構造体で直接読み書きとか、お作法的にはよくないよ。
構造体配列を使って四則演算を行うソースを作っています。 無限ループ内でiをインクリメントさせたいのですが、このソースでは1+1=とやっても1のままで結果が上手く出てきません。 無限ループ内でのインクリメントの仕方を教えて下さい。 int kind= /*数値…1、演算子…2、イコール…3に分類して、構造体配列に設定をするkindの宣言*/ double value= /*数値のみが格納されるvalueの宣言*/ char operand= /*演算子のみが格納されるoperandの宣言*/ double calculate(struct keisan *kei) { int i=1; while(1) { if(kei[i].kind==3) { break; } if((kei[i].kind==2) && (kei[i].operand=='*')) { kei[i-1].value = kakeru(kei[i-1].value,kei[i+1].value); } if((kei[i].kind==2) && (kei[i].operand=='/')) { kei[i-1].value = waru(kei[i-1].value,kei[i+1].value); break; } i++; } この後に足し算引き算を上のように無限ループで行う。
>>226 ちゃんとiはインクリメントされると思うけどねぇ。
尤も、掛け算ではブレークしないのに割り算ではブレークするとか、変なところは色々あるけど。
>>225 パディングをファイルに書き込んでる場合、
1メンバのデータサイズだけ読み出したら
ファイルポインタの位置がパディングの前で止まってる可能性があるな。
パディングを0にすることが許されない状況なら、
構造体を一括して読み書きするか、
常にメンバごとに読み書きしてパディングを書き込まないようにするか、どっちかだな。
229 :
226 :2008/02/24(日) 21:53:38
>>227 ちなみに足し算引き算のループはこれなんですが…
while(1)
{
if(kei[i].kind==3)
{
break;
}
if((kei[i].kind==2) && (kei[i].operand=='+'))
{
kei[i-1].value = tasu(kei[i-1].value,kei[i+1].value);
}
if((kei[i].kind==2) && (kei[i].operand=='-'))
{
kei[i-1].value = hiku(kei[i-1].value,kei[i+1].value);
break;
}
i++;
}
処理の手順は、
イコールかどうか(イコールならブレーク)→演算子かつ*かどうか(*なら掛け算、違うならスルー)
→演算子かつ/(/なら割り算)
となっているので、割り算でブレークという所がおかしいのでしょうか…
kind は列挙体使うべきだな。 value と operand は共用体を使うのが常套手段か。 (kei[i].kind==2) && が並んでるのも気になる。 先に if(kei[i].kind==2) 書いてその中で演算子をチェックしようぜ。 まあそれはいいとして、 結果は i + 1 の方に入れないとダメなんじゃないのかな。 雰囲気的に。
231 :
226 :2008/02/24(日) 22:07:24
>>230 計算結果はi-1番目に入れろという指示が出ているんです…
それと、恥ずかしながら列挙体や共用体というのは使った事がありません。
コンパイルの結果はこんな感じです。
1/2=
[1][1.000000][]
[2][0.000000][/]
[1][2.000000][]
[3][0.000000][]
『2.000000』
答えは0.000000です
(無限ループの後にprintf("『%f』\n",kei[i-1].value);
return kei[0].value;
}を入れていて、メイン関数にkei[0].valueを返し、答えを表示しています。)
素朴な疑問だが、1/2=ではなく2/1=だとどうなる?
233 :
226 :2008/02/24(日) 22:45:51
>>232 1/2=
[1][2.000000][]
[2][0.000000][/]
[1][1.000000][]
[3][0.000000][]
『1.000000』
答えは0.000000です
と出ます…
234 :
209 :2008/02/24(日) 23:29:59
>>223 掛け算を試しても0になるようなら、ソース丸ごとどこかにアップロードして味噌。
236 :
226 :2008/02/25(月) 13:00:22
すみません!解決しました… 戻り値を返してなかったりで駄目だったみたいです。 皆さん有難うございました。
237 :
海苔 :2008/02/27(水) 00:12:03
お初です。 少々お聞きしたいのですが、MSYSをインストールする際に、 heap領域が足りないというメッセージがでます。 heap領域を拡張するにはどうすればよいのでしょうか?
メモリと OS を述べよ
239 :
プログラムを作ってみた。 :2008/02/27(水) 01:20:24
#include <stdio.h> void main(void) { int a,b; char c; printf("Hello,World!\n"); printf("数字を入力して下さい。\n"); scanf("%d",&a); printf("ループ回数を入力して下さい。\n"); scanf("%d",&b); while(a<b) { a++; printf("aの値は%d\n",a); } printf("ループ終了\n"); つづく
240 :
プログラムを作ってみた。 :2008/02/27(水) 01:21:36
前からの続き printf("くじを引きますか?(Y/N)\n"); scanf("%c",&c); if(c=Y) { printf("ガラガラガラ・・\n"); if(a<10) { printf("当たり"); } else{ printf("はずれ"); } if(c=N) { printf("プログラムを終了します\n"); } else{ printf("入力エラー\n"); } } }
241 :
プログラムを作ってみた。 :2008/02/27(水) 01:23:25
エラー cmd.exe /C LCC.EXE roop.c *** コンパイル開始 *** roop.c 22: 'Y' undefined roop.c 31: illegal character roop.c 31: illegal character roop.c 32: 'N' undefined roop.c 33: illegal character *** コンパイル終了 *** なぜYとNが認識されないのか・・?わからない
242 :
プログラムを作ってみた。 :2008/02/27(水) 01:24:08
使用機種はwindowsXP。 コンパイラはLSI試食版を使用。
>>241 「認識されない」ではなくundefined=未定義
if(c == 'Y')
>>241 if(c=Y)
・文字だから、シングルクォーテーションでくくらないとだめ。
・条件式が代入になっている。
教科書があるならもう一度読み直せ。
LSI試食版なんか使うな。
16bit時代の遺産だろ?あれ 未だに使う人がいるのか…
入門書に載ってた文字列からハッシュを取得するサンプルを打ち込んだら ハッシュ(int)がオーバーフローしやがった思い出 さすが16bit
249 :
デフォルトの名無しさん :2008/02/28(木) 11:39:24
マイコンでSW2を押すごとに、1、2、3、・・・・とつづくCのプログラム教えて
>マイコンでSW2を押すごとに、1、2、3、・・・・とつづくCのプログラム教えて 突っ込みどころが多過ぎて話にならん。 あんたは初対面の相手にいきなりそんな質問するのか?
251 :
デフォルトの名無しさん :2008/02/28(木) 12:15:42
2ちゃんで初対面とかw
>>251 えーと、喩話というものを御存知ないのですか?
「あんたは…質問するのか? まさかそんな馬鹿なことはしないだろ?
だったら2chであろうとももう少しましな質問の仕方をしたらどうだ?」
と、ここまで書かないと理解できませんか?
すみません、質問させてください rand()関数だけで 1, 2, 4, 8, 16 ... のように 自分で決めた値だけで乱数を生成するようにできるんでしょうか? それとも上のようにしたい場合は 取り合えず一度値を生成してからswitch()するのが普通なんでしょうか?
1<<(rand()%16); とか。 規則性のある数列ならrand()%整数で必要な個数の整数値を出して、 一般項の形に計算してしまえばいい。
普通はテーブル使うんじゃね? よっぽど数が少くて、計算でも置換できないならswitchでもいいけど。
int a[10] = {2,5,10,21,33,45,100,1001,2222,3232}; a[rand()%10]; とかね。
数が少なくてもテーブルのがわかりやすいと思う
なるほどー、テーブルが分かりやすいかな 規則性計算も勉強になりました レスくれたみなさんありがとうございました
キーボードから正の数値を入力させたいときに、 int a; char buf[32]; do{ fgets(buf,32,stdin); a=atoi(buf); }while(a<=0); とやって、文字列や負の数が入力されたらループする! 正の数が入力されたらループを抜ける!すげー!カッコイイ! というのを見たんですけど、 0や負の数も含めて入力させたいときにはどうしたらいいんでしょう。 ループの中身ってfgetsで文字列入れてしまってもa=0になりますよね?
>>260 ・strtol(buf, & endp, 0)で得られた、変換終了点にある文字がナル文字でなければ変換失敗。
・sscanf(buf, "%d", & a)の戻り値が1でなければ変換失敗。
>・sscanf(buf, "%d", & a)の戻り値が1でなければ変換失敗。 但し、入力が100giga の様な場合は変換に成功してgiga は単純に捨てられることに注意。
#include <stdio.h> #include <stdlib.h> int main(void) { int a; char buf[32]; char *end; do{ fgets(buf, 32, stdin); a = strtol(buf, &end, 0); }while(*end != '\n'); printf("正常終了 a=%d",a); return 0; } こんな感じでできました、ありがとうございました。 変換終了点がヌル文字でなければ〜とありましたが、 fgetsで読み込んだので改行文字との比較でいいんですよね?
あーそうか、改行文字を取り除いてないからその通りだね。
C言語でグラフを出力するプログラムって作れますか?
普通のジグザグ波です フーリエで求めたジグザグ波をグラフにしたいんです。
>>268 X Y
を, ひたすら書いたファイル("fft.dat"でもなんでもいい)に吐き出せ!!!
そのあとで
sprintf(buff, "system %s", "fft.dat");
って, やるんだ!!!
やります!!!
orz > sprintf(buff, "system %s", "fft.dat"); × "system ... 〇 "gnuplot ...
今さっきturboをインストールしたばかりの初心者です。 手元の入門書にしたがってコンパイル・実行したのですが、メッセージペイン上に表示させられません(ごたぶんにもれずHello Worldのプログラムです 表示させるための設定を教えてください
>>272 メッセージペインってなに?
どういう環境で動かそうとしているの?
message pane ---プログラムをコンパイルしたときに発生したerror,warningを表示する画面でプログラムを を実行したメッセージも表示する画面 らしい(手元の本はc++builderXで説明してるけど俺のはturboだから、ちょっと違うみたい)
getch()をreturnの前に置けばよかったみたいです 自己解決したので忘れてください
すんません Cってなんですか? ゲーム開発する事?
プログラミングをするにあたっての使用する言語。 ホームページを作るにはHTML言語ってのが必要。 そういうこと
C言語に慣れるためにいろいろなプログラムを入力してみているんですが、 分からないことがあったので質問させていただきます。 #define N 5 #define start 1 int main(void){ int i, k; float rate[N][l], max = 0.0; for( i=0; i<N; i++ ){ printf("%d番目のデータ >> ", start+i); scanf("%f", &rate[i] ); if( rate[i] > max ){ max = rate[i]; k = start + i; } } printf("最高値は%d年の%.0fパーセントです\n",k, max*100 ); return 0; } とあるサイトの参考プログラムです。 これは、小数点で確率を入力し、最高値を求めるというものですが、 これを改変して、最小値を求めるプログラムにするにはどうすればいいのでしょうか?
>>279 そもそもそのプログラムだと、maxの初期値である0.0未満の値のみを入力すると
最大値が0.0になってしまうから正しく動作しているとはいえない。
だから例えば
if( rate[i] > max ){
のところを
if( rate[i] > max || i == 0 ){
のようにするべき。そしてその場合はmaxを初期化する必要はない。
同様に最小値を求めたい場合は…どうすればいいかわかるよね?
>>280 上手く動作しました!
なるほど、maxを初期化しなくても良くなる方法があったのですね。とてもためになりました
ありがとうございました
確率なんだから-は考えてないだけじゃね? if(rate[i] > max || i==0) は無駄な判定回数増えるし。
283 :
デフォルトの名無しさん :2008/02/29(金) 09:15:27
/* 待っちに待った、4年にいっち度のっ、日っが来っましたよっ と */ int is_leap_year(int y) { int rc = 0; if (y % 4 == 0 && y % 100 != 0 || y % 400 == 0) { rc = 1; } return rc; }
多重ループから完全に抜け出す場合にはgoto文使うのはアリですか? それともフラグを立てての制御のほうがいいんでしょうか?
状況による
俺は自分しか読まないなら可読性重視
>>285 >>286 返答ありがとうです。
この場合にはgoto文もやむなしという解釈でいいんですね。
これからは状況によって使い分けてみます。
ありがとうございました。
>>287 多重ループから抜け出したらそこは関数の外だったって言う状況なら、迷わずreturnだけどねぇ。
すみません、くだらない質問なのですが while(fgets(buffer, sizeof(buffer), fp) != NULL){ p = strtok(buffer, ","); while(p != NULL){ int num = atoi(p); printf("%d ",num); p = strtok(NULL, ","); } printf("\b\n"); } CSVを読み込むのに、このような処理を行う、とあったのですが いまいちstrtokがわかりません bufferに1行読み込んで、それをカンマ区切りで分割するのであれば strtokが1個でいいのではないかと考えてしまいます どのような流れで動いているのかいまいちイメージしにくくて わかりやすく説明していただけませんか
>>289 敢えて呼び出しを一回しか書かないとしたら、
whileの判定部内でstrtok()を呼ぶことになって収まりが悪い。
しかも、初回だけbufferを渡さないといけないから尚更ややこしくなる。
>>290 たとえば 12,34,56,78,
という列があったときに
1回目のpにはナニが入ってくるのか
2回目のwhileはpに1列入ってくるとイメージできるのですが
その中でのstrtokの1番目がNULLなのがわからずで
結局ナニをやってるのかわからないのです
>>291 2回目以降のstrtok()の呼び出しでは、第1引き数をNULLにすることで
前回の呼び出し時の「続き」の処理を行なうことを要求している。
つまり、1回目のstrtok()は'2'の後の','を'\0'に換えて'1'へのポインタを返す。
2回目の(ループ内の最初の)strtok()は'4'の後の','を'\0\に換えて'3'へのポインタを返す。
以降順次、'7'へのポインタを返した次の呼び出しで、NULLを返すことで文字列を使い切ったことを伝えている。
まあできればstrtok使わないで自力でやったほうがいいと思うが。 strtokの動作を知っておくのはあっといたほうがいいが
>>291 これを試してみ
#include <stdio.h>
#include <string.h>
int main()
{
char buffer[] = "foo,bar,hoge";
printf("%s\n", strtok(buffer, ","));
printf("%s\n", strtok(NULL, ","));
printf("%s\n", strtok(NULL, ","));
printf("%s\n", strtok(NULL, ","));
}
まぁ、どの道strtok()は仕事では使い物にならないケースが多いけどね。 # strtok()でできることは大抵sscanf()で%[]や%nを駆使すればできてしまう。
初心者なのですが質問です getch()のカーソル点滅が邪魔なんですが、これを消す(隠す)ことは可能ですか?
>>292-296 ありがとうございます。
もう少し落ち着いて読んでみます。
>>296 今までfscanfで分割して読み込みをよくやっていたので
はじめはsscanfやfscanfでやろうとしていたのですが
読み込むデータが
x,y,z,
x y z
x,y,z,a,
x y z a b
のようにカンマ区切りやスペース、3〜5の不定であるので
strtokを使うことになりました。
まだ学生なのですが、仕事で使えないと聞いて少し悲しくなりました
>>284 読みやすさを考えて選べばいいと思う。
俺は、breakやgotoはループ内には1個までと決めてる。それ以上はフラグを併用するかな。
>>298 char * tmpStr = "12,34,56,78,";
char buf[10];
sscanf(tmpStr, "%[^,]", tmp);
を試して見給え。
とてつもなくアバウトな質問で申し訳ないんですが、 みなさんはソースを読むとき、どういう順番で目をつけて読んでますか? 私は今までFortranで書かれた一つのコードしかないプログラムしか 読んだことが無かったのですが、今、Cの複数のソースコードで構成された プログラムを読む羽目になってます。Fortranのときは、call文を検索して 流れをざっと把握出来たんですが、Cは読みづらくて仕方ありません。 (ちなみにフローチャートとかはありません…) 読み方のコツのようなものがあれば教えていただけませんか?
>>302 てきとーに思いついたのをいくつか
・ヘッダファイルを見て構造体や関数の一覧を眺める
・main関数を探してそこから順に辿っていく
・doxygenなどを使って見やすくする
初心者です 教養程度の数学の実験ができるようになるまでにどのくらいの時間が掛かると思いますか?
算数で6年数学で10年プログラミングで1年 計17年くらい
>>302 誰もgetoptなど頭から挙動全部を読み取れなんて言ってないんだったら、
そのプログラムの中核をなす部分の検討をつけて、そこはじっくり読む事に専念する。
他の雑多処理関数などは後回し。 そんな事しないと何日も日が暮れる。
あと、なるべく存在する変数などは極力頭に入れて理解しておくと流れが良くなる。
分かりにくい表現は、自分で書き直したり、コメントを入れるといいかも。
>>305 小学校からかよw
10年というと、大学までか
>>301 んじゃ、更にこれを。
char * tmpStr = "12,34,56,78,";
char buf[10];
int read;
sscanf(tmpStr, "%[^,]%n", tmp, & read);
309 :
デフォルトの名無しさん :2008/03/01(土) 01:18:26
外部ファイルの内容を終端から逆順で別ファイルにコピーする簡単なプログラムですが スマートなプログラムが作れません。 教えていただけませんか?? 今のソースは↓↓ fp_src = fopen(argv[1], "r"); fp_src = fopen(argv[2], "w"); fseek (fp_src, -2L, SEEK_END); while (ftell(fp_src) != 0) { ←条件にEOFを使うのはNG c = fgetc(fp_src); fputc(c, fp_desc); fseek (fp_src, -2L, SEEK_CUR); } c = fgetc(fp_src); fputc(c, fp_desc); }
310 :
デフォルトの名無しさん :2008/03/01(土) 01:21:13
↑上の者ですが間違いだらけでした訂正します。 fp_src = fopen(argv[1], "r"); fp_dest = fopen(argv[2], "w"); fseek (fp_src, -2L, SEEK_END); while (ftell(fp_src) != 0) { ←条件にEOFを使うのはNG c = fgetc(fp_src); fputc(c, fp_dest); fseek (fp_src, -2L, SEEK_CUR); } c = fgetc(fp_src); fputc(c, fp_dest); }
うしろから1kBとかまとめて読んで、 前後を入れ替えてから書き出していけばいいんじゃねえの。 そのやり方はあまりにも時間掛かるぞ。
>>309 ファイルが巨大でないなら、
メモリ確保して全部読み出して、メモリ上でひっくり返すのが楽チンだと思う。
313 :
デフォルトの名無しさん :2008/03/01(土) 02:03:28
>>311 312
それが出来れば簡単なんですが
fseek fputc fgetc 関数を使えという課題なんですよ・・・
じゃあ、それでいいんじゃね。 変な条件つけられたら、変なコードしかかけないのは当然だ。
Cの入門書やってるのですが サンプルを打ち込むのは意味があるのでしょうか? 説明を読んで理解して章の最後の問題をやるだけでプログラミング上達するのでしょうか?(基本情報を取れるレベルという意味で 何回かやったんですがいつも途中の難しくなる所で(ポインタ、ファイル操作 挫折してしまいます。どうすればいいでしょうか?
>315 小学校の国語でもまずは文字の書き取りからだろ?作文はその後だ。 プログラミングが上達うんぬんは作文できるようになってからであってそれ以前の段階。
getch以外でキーボードの方向キー入力を認識する方法はありますか?
318 :
317 :2008/03/01(土) 13:00:15
すみません、質問を変えます getch以外に処理を中断させる方法はありますか?
>>315 サンプルを見てただ打ち込むのはタイピングなので、プログラミング能力は上達しない。サンプルの意味を考えたり、サンプルを少し変えて、動きの変化を見るようになれば、プログラミングの上達につながるかもしれない。
挫折する場合は、その手前の基礎知識が不足しているか、その入門書が基礎の説明を端折っているかだ。
TRUE, true, FALSE, falseなどを使いたいのですが、定義されていないとエラーになりました。 これらは自分でdefineするものなのでしょうか?
enum bool {false, true}
「真の場合0以外を返す」という関数が多いですが、それで100%正しい判断ができますか?
はい。
ありがとうございました。
>>323 その戻り値はenum boolとは違うものなので、enum boolと比較してはいけない。
Cはtrueとかfalseとか定義しないで、生の数字を使った方がいいよ。
あら・・・ if(modotiri != 0) こんな感じで真と判断するのが良いということですか?
if(modortiri) まあ意味的には同じだ。
皆さんありがとうございました。
まぁ、普通はstdbool.hをインクルードしてfalse, trueを使うのだが、 trueと比較するのはナンセンスだ。
そんなC99のヘッダ持ち出されても
C言語スレなのに仲間外れなC99涙目
334 :
317 :2008/03/01(土) 19:37:09
>>319 ごめんなさい、中断ではなく一時停止でした
「↓」を表示後、キー入力があるまで処理を一時停止させ、
キー入力があればそれに対応した動きをさせたいのですが・・
値が不定( -1000〜0 かもしれないし 0〜1000 -1000〜1000 かもしれない) のデータから max と min を出そうというとき データを一時的にtempに入れて評価しようと思っているのですが tempとmax minを比較するときに max/minをどのように初期化したらいいのかわかりません。 たとえば0で初期化したとき、データが -1000〜-10 の値だった場合、maxが初期化した0になってしまい、データとの整合性が おかしくなってしまいます。 このような場合どうしたらよいのでしょうか
tempと比較する前に一旦値を全部しらべる
>>337 ・一番目のデータで初期化し、2番目のデータ以降を比較する。
・値域を越える、意味のある最大(最小)値で初期化する。
>338はありえないな。
レスありがとうございます >・一番目のデータで初期化し、2番目のデータ以降を比較する。 これはflgなどを設定してやるのですよね。 どうもフラグの扱いが下手で前に失敗して敬遠していました。 >・値域を越える、意味のある最大(最小)値で初期化する。 maxを-9999 minを9999で初期化するようなことですよね。 何がブチこめられるか検討がつかない場合、ちょっと怖くて…
>>342 ・フラグは、いりません、垂れ流しプログラムで、おk
・データーの、型の、最大値、最小値で、初期化すれば、おk
>>342 // 前者の例
int getMaxValue(int * array, unsigned dataLen)
{ // dataLen が0のときには何らかの対策が必要
int maxValue = array[0];
for (unsigned ic = 1; ic < dataLen; ++ic) {
if (maxValue < array[ic]) maxValue = array[ic];
}
return maxValue;
}
// 後者の例
int getMinValue(int * array, unsigned dataLen)
{
int minValue = INT_MAX;
for (unsigned ic = 0; ic < dataLen; ++ic) {
if (minValue < array[ic]) minValue = array[ic];
}
return minValue;
}
>>343 すみません…頭が悪くていまいち理解ができなくて。
型の最大値・最小値というのはどういうことなのでしょうか
ちゃんと書いてなかったのですが、データは
while(fscanf(fp,"%f\n",&temp) !=EOF){
…
}
という感じで読み込んでいます
>>344 更新する前に書き込んでしまいました、すみません。
ちゃんと読んで理解して試してみます
>>343 データ(data)はコンピュータ(computer)などの例と違い、
最後は延ばさないのが一般的です。
・延ばさないのが一般的
データ(data)
・延ばすのが一般的
キー(key)、カー(car)
・どちらも使われる
コンピュータ(コンピューター)(computer)
>>344 >if (minValue < array[ic]) minValue = array[ic];
処理がgetMaxValue()と同じになってるw > だな。
>>345 例えばunsigned charなら最大を0、最小を255で初期化するってこと。
>>345 fscanf(fp,"%f\n",&temp) !=EOF
これはいけない。
fscanf(fp,"%f\n",&temp) ==1
としよう。
>>347 老婆心、ありがとうございます、そういう、理由だったんですか
IMEが「データ」「ー」としてしか、受け付けて、くれず、意味が、わかりません、でした
読点多すぎw
>>347 一般的かどうかで言えばそうだね。
技術用語としては、基本的に
・ 3文字以下の単語は末尾の長音記号は省略しない
・ 3文字以上の単語は末尾の長音記号は省略する
で、一部慣用的な例外があるって感じ。
ミスった。 × 3文字以上 ○ 4文字以上
スレ違いだが論拠になるのはこの辺だな。
JISZ8301:2005 規格票の様式及び作成方法(より適当に抜粋)
附属書G(規定) 文章の書き方,用字,用語,記述符号及び数字
G6.2 外来語の表記
c) 長音符号は,通常,次によって用いる。
2) 規格の用語及び学術用語にない用語の語尾につける長音符号は,表 G3 による。
表 G.3―外来語の表記に語尾の長音符号を省く場合の原則
a) その言葉が 3 音以上の場合には,語尾に長音符号を付けない。
b) その言葉が 2 音以下の場合には,語尾に長音符号を付ける。
c) 複合の語は,それぞれの成分語について,上記 a) 又は b) を適用する。
d) 上記 a)〜c) による場合で,長音符号を書き表す音,はねる音,及びつまる音は,それぞれ 1 音と認め,拗音は 1 音と認めない。
ttp://www.jisc.go.jp/app/pager?id=23428
数値処理で注意すべきところはなんですか?
数値を対数で計算するときに注意するところは?
底を、まちがえない
使えるライブラリーを探す
ライブラリーってどうやってつかうの? 行列計算のライブラリーとかはとってこないといけないらしいが
どう使うってヘッダーとして入れればいいだろ
微妙に意味不明
具体的には?
>>361 そのライブラリの配布物かサイトのどこかに使い方の説明書きが付いてると思うが
ライブラリってライブラリ関数のこといってるの? だとしたら #include <string.h>とか #include <stdio.h>とかやってると思うけど、 そのヘッダーファイルを自分の使いたいライブラリに書き換えて使えばいいんじゃ?
おまえら大抵の標準外のライブラリはリンクが必要な事を教えてやれよ
>>361 普通は、
1.ヘッダーファイルとオブジェクトライブラリとマニュアルを入手する。
2.使用するライブラリ関数を呼んでいるソースファイルで、必要なヘッダーファイルをインクルードする。
3.コンパイル時にオブジェクトライブラリを指定する。
>>367 標準のライブラリもリンクは必要ですが。
カーニハンさんの本を買った、それ見ながら なにか作りたいけど、どうせ作るなら日常で多少の役に立つものを作りたい。 しかしそれが思いつかない。 なんかヒント下せぇ。
金の管理
嫁の管理
管理する嫁が無い ありがとうございました また困ったら質問させていただきまふ
自分でUNIXの基本的なコマンドつくってみるとか catとか
>>370 単純な話、パソコン使ってて不便だなと思った時に
それを解決するプログラムを作ればいい。
マルチですみません main()ってどれが正しいのですか? 実効環境によってちがうのですか? この手のドキュメントは何になるでしょうか? void main(void); int main(void); int main(int argc, char *argv[]); int main(int argc, char **argv);
下3つは全ての環境で常に正しい。 下2つは文法的に同等。 一番上は環境依存。 最も確実なドキュメントは規格。 JIS X3010 を嫁。
>>375 おれはその本と Unix のソースコードで C を覚えたが...
>>378 適切な回答ありがとう
>>379 おれはポインタ本に頼ってしまった…隠してあるけど
GNUのソース見るとすごいなと思う
現在でもUinixのソースコードを見るのが一般的なのでしょうか?
そもそも一般的だった時代があるのか?
>>381 一般的だった時代があるかどうかはともかく、
ごちゃごちゃしたコードもあるので、勉強にはあまり勧めない。
>>374-376 おお、さらにレスが
ありがとうございます
いつかはソース眺めてフムフム、と言ってみたい
ソーっスね〜
>>381 以前、catコマンドだとかlsコマンドのソースコードを見たことがあったけど
えらい汚いコードだった。
初期のUnixのコードはいろいろな開発者が手を加えているので
統一性が取れていなくて見苦しい。
ちゃんとした製品として作られたものでオープンソースのものがあるから
それをダウンロードして見るのもいい。
素数を求めるC言語プログラミングを教えてください 条件が有りまして for文のネストもしくはwhile文のネストを使ってなおかつgoto文を使って下さい よろしくお願いします。
gotoを使ってくださいって、やな課題だな
void use_goto() { goto hoge; hoge: return; } これかましてたらいいんでね
よし、俺に任せろ。 #include <stdio.h> int main() { while (1) while (1) goto next; next: puts("2"); return 0; }
これで問題なかろ? #include<stdio.h> #define NUM_MAX 100 int main(void){ int i, j; for(i=2;i<=NUM_MAX;i++){ for(j=2;i/j>=j;j++){ if(i%j==0) goto as_break; } as_break: if(i/j<j) printf(" %d", i); } return 0; }
gotoである意味なくね? breakでいいじゃん。
396 :
デフォルトの名無しさん :2008/03/03(月) 23:08:10
>>395 いや、命題がgoto使えってことだから
単純にbreakを置き換えるんじゃなくて、gotoを使う意味があるようなのにしたらってことじゃね?
質問者は既に移動したんだからスレ違い自粛しる。
goto使うんなら for(i=2;i<=NUM_MAX;i++){ for(j=2;i/j>=j;j++){ if(i%j==0) goto as_break; } printf(" %d", i); as_break: } だな。
ファイルの行数を 一度読み込みをしないで調べる方法ありますか 9 0 78 7 みたいなのを 今まで一度最後まで読み込んで、行カウントして その分の配列を確保して、先頭から読み直してたのですが 1億行とかになると時間が掛かりすぎて。
>>399 そうするならラベルの名前は変えたほうがいい
>>401 いい加減にしなさい。
>>400 動的確保すればいいんじゃない?
要は、1万行分確保しておいて、溢れるようなら更に1万ってな調子で。
C++ならvectorで簡単にできるけど、Cならrealloc()使ってちと面倒だけど。
gotoは絶対禁止って頭から覚えこまされるヤツがおおいせいで、まともな使い方できないのが多いね。
禁止じゃなくても、あんまり使う機会無いからな
Cはラベル付きbreakとか例外とか使えないからgotoの価値があるけど、 それ以外になんか有効な使い方ってある?
うちの会社だといちおうコーディング規則で使うなとなっていまふ goto あんまり便利な用途も思いつかない(エラーで飛ぶぐらい?)
407 :
デフォルトの名無しさん :2008/03/04(火) 19:17:46
質問です。 定数の配列って出来ますか? #define HOGE {123,456,789} こういうのがしたいんですが、 constでグローバル変数にするしかないですか?
>>407 それをどう使うつもりなのか知らんが、グローバル変数では困るわけは?
409 :
デフォルトの名無しさん :2008/03/04(火) 19:25:28
>>408 constで困りませんが、
他に方法があるのかな?と思い質問しました。
>>409 C99に対応したコンパイラなら
(int[]){123, 456, 789}
こんな書き方ができるらしい
定数でいいならenumという手もある。そうでないならconstだな。
413 :
デフォルトの名無しさん :2008/03/04(火) 23:11:42
すいません。教えてください。℃素人です。 "return"と"exit"ってどのような違いがあるのでしょうか?
return は値を返す exitはその場で終了
勉強を進めていけば分かるよ 説明しても今は理解出来ないと思う
ごめんもうちょっと詳しく書くわ。 勉強最中に 関数 ってのを習うと思うんだけど、今は int main( void ) ってのでしょ? これはメインとなるプログラム本体だと思ってOK。 そして 1つのプログラム だと思ってもOK。 でも通常プログラムってのは、色々なプログラムを集合させて1つのプログラムにするんだ。 何気なく使ってる printf もプログラム。 printfは、文字を渡すと文字を表示させるっていうプログラムだけど、 たとえば数字を二つ渡すと 計算をしてくれるってプログラムがあって、それを main のなかで使いたいとすると、 二つの数字の結果がほしいわけでしょ?その結果を返すために return なんちゃら ってのが必要なのです。
417 :
413 :2008/03/04(火) 23:18:50
>>414 さん
レスありがとうございます。
"return"はmain関数に値を返すのは
わかっているのですが、例えば"exit(1)"と
いった場合の"1"という値は何処へ行くのですか?
度々ですみません。
プログラムの呼び出し元。
>>417 どこって、exit関数内に行くんですよ。
exitの引数で指定した値はOSに返る
>>420 プログラムの呼び出し元は OS だけとは限らんぜ。
main関数内でのreturnとexitってことでしょ? それならreturn 1もexit(1)も同じ
横レスでスマソ。 main関数内で終了させる場合はreturn 0;。 main関数以外の関数で終了させる場合はexit(1);。 ちなみにmain関数内でexit(1);で終了させることも可。 こういう解釈でいいのかい?
>>416 滅茶苦茶だな。
>>417 main()関数は一般的にOSからの入り口と出口になる。
入り口は当然関数の先頭であり、出口はreturn。
この出口に直行するショートカットがexit()になる。
これは、main()からに限らず他の関数からいきなり
OSへの出口に直行するためにも使えると言うわけ。
まぁ、何かと不都合が生じる原因にもなるから
「対処不能な障害による」緊急脱出でもなければexit()はお勧めしない。
>>423 そういうこと。
425 :
413 :2008/03/04(火) 23:27:05
みなさん、ありがとうございます。
>>422 さん
なるほど、同じなのですね。理解できました。
ありがとうございます。
すげー18分しかかかってねえ!不思議!
EXIT_SUCCESSかEXIT_FAILURE使った方がいいけど
>>421 OSが介在しない特殊な環境を除けば、コマンドライン以外の例えば
何がしかのアプリから直接起動しているように見えても実はOSを経由している。
だから、一般的にはOSとのI/Fと考えて問題はないと思うが。
>>423 呼び出し元へ返す値は一般的には
0 正常終了
0以外 異常終了
だよ
(もちろん正常終了しても意図して 0 以外を返す場合もあるよ)
>>416 は滅茶苦茶なの?間違ってはいないと思うんだが・・・まだまだ俺が未熟なせいか?
内部的には大体こんな感じになってる。 これは概念的な物で、実際にはもうちょっと複雑だろうけど。 void __startup() { // これが C で作られたプログラムの全体 int status; __initialize(); // main より前に行う必要のある初期化 status = main(); // main を呼ぶ(場合によってはコマンドライン引数を渡す) exit(status); // main の戻り値を使って exit を呼んで、プログラムを終了する } void exit(int status) { __atexit(); // atexit で登録した後処理を行う __finalize(); // 後始末を行う(ファイルのフラッシュとか) __quit(status); // プログラムの呼び出し元に値を返してプログラムを終了する } まあ、必ずしもプログラムの呼び出し元に値を返さないといけないわけじゃないだろうけど、 プログラムの呼び出し元に終了状態を示すのに「使う事ができる」と規定されてたと思う。
>>429 ということは、
main関数以外の関数で終了させる場合、
正常終了ならexit(0);
異常終了ならexit(1);
ということなんですね。
>>432 ちがう。異常終了は非0
-1かもしれないし100かもしれない
呼び出し元に返される値は必ずしも exit の引数(main の戻り値)と同じとは限らない。
ただ、とにかく exit の引数(main の戻り値)が 0 の時は
呼び出し元に正常終了を表す値が返り、
1 の時は呼び出し元に異常終了を表す値が返る。
>>433 0, 1 以外の値の場合にどうなるかは環境依存。
>>432 異常終了は非0か。
ある意味こういうところがCの難しいところな気がしてきた。
0返そうが非0返そうが何か起こるわけじゃないから気にしなくて良いよ
そんなんにこだわってるから難しいんじゃないの?
>>427 でいいじゃない
>>432 Yes.
ただ、できるだけ main に戻った方が個人的にはいいと思う。
途中で行った処理に色んな後始末が必要な場合もあるだろうから、
main にまで戻る間にその後始末を行うと良い。
できるだけグローバル変数を使わないプログラムの場合、
後始末を全部 atexit に任せるのは結構辛いものがあると思うしね。
>>435 異常終了は 1 。
規格ではそれ以外で異常終了になる事を保証してはいない。
使っている処理系で保証していれば話は別だが。
規格ではEXIT_SUCCESSは0だと定められている。(EXIT_FAILUREは忘れた) よってmain関数はとりあえずreturn 0;で問題ない。別にEXIT_SUCCESSでも一向に構わない。
ちなみに、main()から-1を返したりexit()に-1を渡す例をしばしば見かけるが、 大抵のOSでは負値を受け取るようにはできていないので要注意。 255と解釈されるかもしれないし、65535と解釈されるかもしれないし、 巡り巡って-1と解釈されるかもしれないわけだ。
441 :
デフォルトの名無しさん :2008/03/04(火) 23:48:01
関数に引数でポインタを渡して関数内で引数のアドレスを変更しても 呼び出し側の引数のポインタのアドレスが変更されないのはなぜでしょうか? void foo(char *c) { c++; return; } void main() { char c[256]; char *p = c; foo(p); }
>>441 関数にポインタのポインタを渡して、そのポイント先を変更するようにすればOK。
例えば gcc 4.0.1 / Mac 10.4.11 で実行してみると、 呼び出し元には exit の引数(main の戻り値)を 256 で割った余りが返る。 昔 Turbo C++ / MS-DOS でチェックしたときも同じだった気がする。 こういう環境だと、非 0 だろうが、256 の倍数を返せば正常終了になる。 どんな環境でも異常終了を示すことが保証されているのは 1 だけ。 0, 1 以外を返した時にどうなるかその環境のドキュメントを読むべし。
>>441 仮引数はすべてコピーでしかない
コピーをいくら弄ろうとオリジナルに影響は無い
>>441 引数で渡した値を変更しても、呼び出し元には反映されない。
ポインタが指してる先なら変更できる。
ポインタを変更したいならポインタのポインタで渡す。
>>441 変数だろうとポインタだろうと渡された値は関数内でコピーされたローカル変数。
それ自体を変化させても呼び出し元の値が影響を受けることはない。
呼び出し元の値を変えたければ「変えたい値のポインタ」を渡して、
関数内で「そのポインタが指し示す変数」をいじる必要がある。
だからポインタの値を関数内でいじりたければ「ポインタのポインタ」を渡さないといけない。
>>441 関数に引数で変数を渡して関数内で引数の値を変更しても
呼び出し側の引数の変数の値が変更されないのと同じ理屈。
void foo(int i)
{
i++;
}
int x = 5;
foo(x);
そのために、変数へのポインタを使う。
void foo(int *i)
{
(*i)++;
}
int x = 5;
foo(x);
ここではint型だったが、ほかの型でも同じこと。例えば、char *型でも。
void foo(char **c)
{
(*c)++;
}
int main()
{
char c[256];
char *p = c;
foo(&p);
return 0;
}
448 :
441 :2008/03/04(火) 23:53:56
>>442 ,444,445,446
ありがとうございます。
>>441 当時中学生だった俺は当日に買いに走った
運良く数冊残っていてそれを持ってレジに行ったんだ
レジのおばちゃんが俺をみてこう言ったんだ
「あんた未成年でしょ。未成年には売らないよ。」
その日は諦めて次の日に遠出して他の本屋に行ったんだが全て売り切れだった
あの日ほど絶望感を感じたときはない
441 大人気だなw
>>441 の人気に嫉妬wこの手の質問はFAQだからなぁ
goto goto goto goto goto goto goto goto ゴートゥーだけで組んだらどうなるかな
goto が嫌いになる
すばらしい回答だな
goho とか混じっていても気がつかない
#define g int #define o main #define to () { #define go return #define tog 0; #define oto } g o to go tog oto
なんというすばらしいmain関数
gohome yankee;
#include <stdio.h> #include <malloc.h> main(togo,toog) int togo; char *toog[]; {char *ogto, tgoo[80];FILE *ogot; int oogt=0, ootg, otog=79, ottg=1;if ( togo== ottg) goto gogo; goto goog; ggot: if ( fgets( tgoo, otog, ogot)) goto gtgo; goto gott; gtot: exit(); ogtg: ++oogt; goto ogoo; togg: if ( ootg > 0) goto oggt; goto ggot; ogog: if ( !ogot) goto gogo; goto ggto; gtto: printf( "%d goto \'s\n", oogt); goto gtot; oggt: if ( !memcmp( ogto, "goto", 4)) goto otgg; goto gooo; gogo: exit( ottg); tggo: ootg= strlen(tgoo); goto tgog; oogo: --ootg; goto togg; gooo: ++ogto; goto oogo; gott: fclose( ogot); goto gtto; otgg: ogto= ogto +3; goto ogtg; tgog: ootg-=4;goto togg; gtgo: ogto= tgoo; goto tggo; ogoo: ootg-=3;goto gooo; goog: ogot= fopen( toog[ ottg], "r"); goto ogog; ggto: ogto= tgoo; goto ggot;}
なんか記号使わないperlとかいう奴思い出した
462 :
デフォルトの名無しさん :2008/03/05(水) 01:18:03
K&Rの演習解答本「Cプログラミング言語アンサー・ブック」を読んでいて、 わからないところがありました。 演習7−4のアンサーで、scanf関数に実引数を渡さないケースがあったのです が、この場合、具体的には何が行われるのでしょうか。 %で始まる変換仕様でない部分なので、読み飛ばされるような気がするのですが……。 よろしくお願いします。
なぜその部分のソースを晒さない。
ファイルのサイズにはEOFは含まれるものなのでしょうか?
なにー、そうなんですか。 でもファイルの一部なんですよね? EOFのコードが埋め込まれていて、それがファイルの一部なのに入らないんですか。 EOFのコードって処理系によっても違うんではないでしたっけ? テキストファイルの後ろに必ずあるものでもないって聞いたことあったから 含まれてるものだと思った。 ところでlsとかで表示されるファイルのサイズっていつ調べるんだろうね。
>>468 ファイルによってデータの終わりをサイズ情報によって管理するものと、終端のしるしである
EOFによって管理するものがある。
前者が一般的で後者はまれ。
昔の磁気テープはEOFを書き込んでいたと記憶する。
> ところでlsとかで表示されるファイルのサイズっていつ調べるんだろうね。
ディレクトリーファイルを読み込んだとき。
>>468 ファイルシステムとOS依存だが、埋め込まれているなら含まれる。
今時のOSとファイルシステムなら、特に埋め込まれないから含まれない。
また、ファイルサイズはファイルシステムが管理しているので、書いたときの
サイズが保持されているだけ。
つーか、鼬害だがね。
その昔CP/Mというのがあってな…
^Z
sscanfで何かしらのデータを読み込んだ時、文字列から何バイト読み込みに使ったか 知る術はありますか? int i; sscanf("100,100","%d",&i); ここから読み込んだ文字は"100"の3バイトだから、何とかして3を取得したい。
int main(void){ . . . return 0; } のreturn 0; の意味がいまいち分かりません。これは0じゃなきゃ駄目なんでしょうか? 1とか2とかだとどうなんですか?
この値はプログラムの呼び出し元(OSとか)に送られる数字で、 一般に0は正常終了、1は異常終了。 何らかのエラーで終了する時にはreturn 1;と書いたりする。
477 :
475 :2008/03/05(水) 13:55:50
>>474 すいません、もう少しヒントいただけますか?
scanf()の書式の説明に書いてあるだろう。 その場で実際にいろいろ試してみないと今後苦労するぞ。
>>479 とおもったら・・・
すいません。すぐに出てきたんでやりました。
482 :
302 :2008/03/06(木) 00:41:02
>>303 >>306 遅くなりましたがありがとうございます。
doxygenというのは知らなかったので参考にします。
483 :
462 :2008/03/06(木) 01:10:43
>>463 どうもすみません。初心者なので、どうお伝えすればよいのかよくわからなかったのです。
ソースが結構長く、どう抜粋すればよいのかもわからないため、言葉で説明したいと思います。
scanfは、「int scanf(char *format, ...)」のように引数を取りますが、
このうち可変引数リスト「...」がない状態で使用していたソースを見つけました。「scanf(format);」のような形になっているのです。
こうした場合、どういう挙動を取るのでしょうか?
ソースはscanfが可変引数をどのように処理するかを示すための関数で、次のように宣言されるものです。
int minscanf(char *fmt, ...)
関数では、まず、fmtを読み取り、%とそれに続くアルファベット1文字まで、charの配列localfmtに代入します。
次に、%に続くアルファベット1文字でswitch文を分岐させ、アルファベットが対応する変換仕様の文字が表す型で、可変引数リストの引数を読み込み、scanf関数に引き渡します。
例えば、アルファベットが「d」や「i」なら、次のようになります。
scanf(localfmt, ival);
ivalはint型のポインタです。
問題は、アルファベットが変換仕様の文字に対応していなかった場合です。
その場合は、switch文のdefaultとして、次のように処理されます。
scanf(localfmt);
このscanfの呼び出しに、可変引数部分がないため、挙動が予測できないのです。
もし、お分かりの方がいらっしゃいましたら、ご教示いただけますよう、何卒、お願い申し上げます。
484 :
デフォルトの名無しさん :2008/03/06(木) 02:35:40
第1引数の文字列を大文字にして第2引数にコピーする関数をつくったのですが うまく動きません 何故か文字列によっては正しくコピーされます どなたか原因をご教授ください #include <stdio.h> #include <ctype.h> void string_up(char *source, char *result); int main(void) { char *str; string_up("lsdk",str); printf("%s",str); return 1; } void string_up(char *source, char *result) { while(*source) *result++ = toupper(*source++); *result = '\0'; }
>>484 結果を入れるべきstrに、結果が入るアドレス設定されていないから。
char配列なりmallocで動的になり結果が入るだけのメモリを準備して、
それをstrに設定してやる。
486 :
デフォルトの名無しさん :2008/03/06(木) 02:57:17
>>485 なるほど!
分かりました
ありがとうございました
>>484 strは宣言されただけで初期化されていないのでstring_upで大文字化した文字が代入される場所は不定になる
何が起きても不思議ではない状態になっている
string_up("lsdk",str);を呼び出すのならstrはchar *str;でなくchar str[5];とかで場所を確保しておかないといけない
つまり元の文字列と同じかそれ以上のサイズのメモリー領域を確保する
488 :
デフォルトの名無しさん :2008/03/06(木) 03:21:22
質問です 引数で渡した文字列の中から一部分を抜き出し、 そのアドレスを返す以下の様な関数を作ろうとしているのですが、 constでない変数をconstをつけて返すのは許されるのでしょうか? 駄目な場合戻り値で返すアドレスの中を書き換えられたく無い場合はどうすれば良いのでしょうか const char* funcA( const char* input_data) { static char data_area[32]; memset( data_area, 0x00, sizeof(data_area) ); strncpy( data_area, input_data+15, 30); data_area[31] = '\0'; return (const char*)data_area; }
>>483 minscanfで処理できる変換指定ではないが、scanfで処理可能な変換指定をlocalfmtが含むときは、
変換指定の数が後続のポインタ引数の数より多いのでscanfの動作結果は未定義になる。
localfmtに変換指定が含まれない場合は、入力がlocalfmtの各文字に一致していなければならない。
>>488 許される。
しかも、constが追加される方向の型変換は、キャストを書かなくても行える。
プログラム始めたばかりなのですが if(a==0) if(b==0) と if(a==0) else if(b==0) の違いってあるんでしょうか?
どう違うんでしょうか?
else の意味はわかってるのか?
elseの意味は大体なら。 if(a==0) printf("%d", a); else printf("not a \n"); のような使い方は出来ると。 if if if が並んだものと if else if else if となったとき、何が違うのか混乱してしまって
if(a==0) else if(b==0) は、 if(a==0) if((a!=0) && (b ==0))
ということは if(a==0) if(b==0)のbで行われるのは a!=0でもa==0のときでも行われる、ということでおkですか?
おk if(a==0) // この時点で前のifに関する処理は全て終わって以降の処理とは無関係になってる if(b==0)
ありがとうございます 納得できました!
500 :
mahhi :2008/03/06(木) 22:25:40
はじめまして。 少々お聞きしたい事があるのですが、Cの環境構成の事で質問が あります。 現在、CDTでGDB Debuggerを使用してデバッグを行っているのですが、 Socket関数を使う際に、 kernel32!IsBadWritePtr(); という表示がでて、デバッガが飛んでしまいます。 言語とは少し話がそれてしまうかもしれませんが、 何かアドバイスがあればどうかお願いいたします。
Eclipseは使ったことないなあ
502 :
488 :2008/03/06(木) 23:08:05
>>490 ありがとうございます。
Cのconst修飾子に関する資料が中々見つからなかったので助かりました。
まだはじめたばかりだで計算のプログラム書ける程度の雑魚だけどおもすれぇ 次はifを使うらしい、楽しくなってきた!
504 :
デフォルトの名無しさん :2008/03/06(木) 23:34:27
今日はじめたばかりの素人です。 本を買ってほんのとおりに進めたのですが、コマンドプロンプトでコンバイルするときに、 一番最初のプログラム #include <stdio.h> main() { printf("Hello World\n"); } がインクルードファイルstdio.hをオープンできないとエラーがでました。 何処にミスがあったのでしょうか?・・・ 多分しょうもない事なのでしょうが、三時間考えてます・・・誰かお助けを・・・
コンパイルね。 コンパイラのアドレスとかきちんと設定した? インクルードするためのファイルきちんとある?
506 :
462 :2008/03/06(木) 23:42:43
>>489 どうもありがとうございました。
厚く御礼を申し上げます。
Cプリプロセッサで条件コンパイルする場合 1. #if defined(評価式) 2. #if 評価式 のどちらでもかけてしまいますが正しい使い分けはあるのでしょうか? ご存知の方ご教授願います
#if defined(〜) はマクロが定義されているかいないかを判定する #if 〜 は値が0か0以外かを判定する
#ifdefの話かと思ったら違うのか
#if defined と #ifdef は同じかと
511 :
デフォルトの名無しさん :2008/03/07(金) 00:35:17
>>505 ありがとうございます!!
かさねてすみませんがコンパイラのアドレスと言うのは、システム変数の編集とかってやつですか?
その辺は設定しました。
インクルードするためのファイルってのはさっぱり分からないので多分ない気がします。
どうすれば良いのでしょうか?・・・
>>510 一緒じゃないぞ。defined(〜)なら他の式と組み合わせられる
単体で使うことが多いからifdefの方が便利だけど
513 :
507 :2008/03/07(金) 01:04:51
皆様素早いレスありがとうございます。 大変参考になりました。
コマンドプロンプトを立ち上げると C:\Documents and Settings\<ユーザネーム> > と出るのですが、このパスを変更するにはどうしたらいいですか?
コマンドプロンプトへのショートカットのプロパティ
>>514 スレ違い。
>>515 私は寧ろ、cdコマンドさえ知らないのかと思ったのだが、その可能性もあったね。
517 :
デフォルトの名無しさん :2008/03/07(金) 02:22:13
初心者です if〜elseとif〜else〜ifの違いはなんですか?
>>518 バカじゃないのに、コマンドプロンプトの質問がスレ違いかどうかも判らなかったの?
それとも、スレ違いと承知の上で質問した阿呆?
if () {} else if () {} else {} のelse if か?
enumの意味は大体分かるのですが、何のためにあるのかがいまいち分かりません。 どういう時にenumを使えば便利なのでしょうか?
#define SUNDAY 0 #define MONDAY 1 #define TUESDAY 2 ・・・ という時に enum dayofweek_t { SUNDAY, MONDAY, TUESDAY, ..... }; と書けば短くて便利
enum {baka, aho, manuke}; switch (getchar() - '0') { case baka: break; case aho: break; case manuke: break; default: break; }
525 :
TKN :2008/03/07(金) 16:03:45
SCC1010 "認識できない識別子 %n0 が発見されました" そういうエラーを出るプログラムを教えていただけませんか。
527 :
522 :2008/03/07(金) 16:42:41
>>523 #define… が省略できるだけということですか?
>>527 void func(enum dayofweek_t);
のように関数プロトタイプを書けば、1とか2といった無意味なint値ではなく
SUNDAY, MONDAY, .... のいずれかを渡すべきであることが明確になる
529 :
522 :2008/03/07(金) 16:54:33
>>528 わかりました!ありがとうございました。
getchar()関数を用いてswitch文を実行したいのですが、まるで反応なしです、switch文。 文法上に誤りがあるのでしょうか? while(1){ c = getchar(); if( c == EOF ){ break; } printf("文字\n"); switch(c){ case 'A': case 'a': printf("文字\n"); break; case 'Z': case 'z': printf("文字\n"); break; case 'X': case 'x': printf("文字\n"); break; default: printf("-------------------\n"); break; } if( mhp == 0 ){ printf("文字\n"); }
531 :
530 :2008/03/07(金) 19:35:45
↑ ”}”追加です。
まるで反応無しの意味がわかりません。
533 :
530 :2008/03/07(金) 20:02:52
ごめんなさい。 入力待ちの状態になるのですが、エンターを押すと一番目のprintfの文字が実行されて(エンターを押す限り)、 switch文の処理にいきません。
534 :
530 :2008/03/07(金) 20:10:15
ただzを押すと、switch文の処理に移行するのですが、 ============ 文字@ Zの、文字B 文字@ ============ ↑が永遠に繰り返されます。
535 :
530 :2008/03/07(金) 20:11:39
#include <stdio.h> int main(){ int i; printf("文字\n"); printf("文字\n"); scanf("%d" , &i); if( i == 1 ){ printf("文字\n");
536 :
530 :2008/03/07(金) 20:12:25
int hp,atk,mhp,c; hp = 10; atk = 1; mhp = 20; while(1){ c = getchar(); if( c == EOF ){ break; } printf("文字@\n");
537 :
530 :2008/03/07(金) 20:13:26
switch(c){ case 'A': case 'a': printf("文字A" , atk); mhp -= atk; break; case 'Z': case 'z': printf("文字B\n"); break; case 'X': case 'x': printf("文字C\n"); break; default: printf("-------------------\n"); break; } if( mhp == 0 ){ printf("文字D\n"); } } }else { printf("文字E\n"); } return 0; }
>>527 途中に値を追加したい場合、
#define だと番号ふり直す必要があるけど、
enum だと勝手に番号ふってくれるので便利。
小心者です ネット上にあるファイル(index.htmみたいな)を ローカルに保存するプログラムを教えて頂けないでしょうか
>>539 ・ソケットを作成する
・サーバに接続する
・HTTPリクエストを送信する
・HTTPレスポンスを受信する
・データを受信する
・ローカルに保存する
・終了
>>539 勉強用にCで書きたいとかなら、ソケットやらプロトコルやら勉強して
>>540 みたいに書かなくちゃならないけど、
そうでないなら、スクリプト系の言語を勧める。
C#やらJavaとかでも一発だけど。
#define SIZE 1024 のかわりに enum { SIZE = 1024 }; とタグなしで書いているのを読みましたが、何かメリット/デメリットはあるのでしょうか?
名前空間の汚染の度合いが抑えられる
デバッグ時にシンボルが埋め込まれる
#ifdef で定義チェックできない
今独習Cをやってるんですけど解答に // ファイル2をファイル1にコピー while (!feof(f2)) { ch = fgetc(f2); if (!feof(f2)) fputc(ch, f1); } と言うコードが含まれているのですが、なぜfeofが2回必要なのでしょうか? while文の条件がf2がファイルの終わりではない と言う条件なのになぜ、while文のなかでもう一度feofが必要なのでしょうか? それとfgetcは、(ファイルから1文字読み込みその際、ファイル位置指示子を進めます。) と説明に書いてあるんですが ch = fgetc(f2); のところで、f2がファイルの終わりなったらf1に書き込まれないのでは?
feof()なんて使ってるコード初めて見た
feof()が妥当かどうかはこの際置いておくとして、 fgetc()してみないとfeof()かどうかは判らないのでfgetc()した後にもチェックは必要。 但し、普通はfgetc()の戻り値を使って判定するからわざわざfeof()を呼ぶようなコードを書く香具師は少ない。 そもそもそのサンプルの目的だけなら、これで事が足りる。 int ch; // 前提として敢えて明記 while ((ch = fgetc(f2)) != EOF) fputc(ch, f1);
550 :
547 :2008/03/08(土) 13:05:36
>>549 答えてくださりありがどうございます。
>fgetc()してみないとfeof()かどうかは判らないので
もしf2のファイル位置指示子が、最後の1文字を指していて
ch = fgetc(f2);でファイル位置指示子を進めたら、次のif()はfeof()が
ファイルの終わりになるので、if()文は、実行されない、と思っていたのですが
実行されているようなので、なぜ実行されるのでしょうか?
だからぁ、feof()はファイルを調べることをしないで直前に行なった (この場合はfgetc()の)結果を参照するだけなんだってばさ。 だから、余程の神経症で「fgetc()の結果を使ってEOFを判断するのは間違っている。 本来の意味的にfeof()を使うのが正しい」なんて思い込みのある人以外は使わないんだって。
552 :
547 :2008/03/08(土) 13:47:45
>>551 ありがとうございます。
>feof()はファイルを調べることをしないで直前に行なった
>この場合はfgetc()の)結果を参照するだけなんだってばさ。
これで理解できました。
>>551 バイナリや非ASCIIテキストなどを扱わなければEOFでの判断でもいいけれど、
汎用性を考えればfeof()を使うべきでしょ。
>>553 EOFは、何か負の値とされている。
一方、fgetcはEOFでなかったときに返す値は、
0から255 (正確にはUCHAR_MAX)。
だからバイナリファイルでも何でもEOF判定で絶対に問題ない。
そのためにfgetcはint型を返すのだから。
何でchar型じゃなくてint型なんだろうと思ってたらそういう事だったのね
独習Cの俺評価が急落した。読んだこと無いけど・・・
そうか、feof()を使ううちの新人は独習Cで独習してたのか……
manですらtest for end of file とか書いてるんだし独習Cが悪いわけじゃないよ多分 ANSI Cが時代遅れのロートル言語って事なんだよ
fgetc()はエラーでもファイル終わりでもEOFを返すけど、feof()は本当に終わりの時しか真を返さないから、 それだけでループの終了判定をしてると、エラーのときに無限ループになる。
CUI=コンソールアプリケーション。 GUI=Windowsアプリケーション。 なんですか?
いいえ。
記号が「=」→「∈」なら、「はい。」ともいえなくもない。
563 :
560 :2008/03/09(日) 03:36:53
CUIでWindows.hをインクルードした場合、それはwindowsアプリではないんですか。 もうよくわかんね('д`)
GUI=グラフィックユーザーインターフェース CUI=キャラクターユーザーインターフェース 名前のまんまだ。 アプリ云々は二の次の話
565 :
560 :2008/03/09(日) 03:45:32
ありがとうございます。 助かりましたm(_ _)m
>>563 CUIのウィンドウズアプリケーションだって存在しうる。
ウィンドウズでしか動作しないCUIアプリケーションがそういう存在。
567 :
デフォルトの名無しさん :2008/03/09(日) 11:55:18
int max_of(const int vc[]) { ................. } const修飾子って配列の中身をいじくる動作がないときでも付けたほうがいいんですか???
568 :
デフォルトの名無しさん :2008/03/09(日) 11:56:32
>>567 追加なんですが
constをつけたらコンパイラから警告がでるんですが
gccです
constは「この関数内で値をいじらない」という意味でつける、紳士協定のようなもの。 実際にはいじれる。 モジュールを作る人=設計者 モジュールを使う人=プログラマ と考えると分かる。 以下エスパー ... discards qualifiers from pointer target type const付きの引数をほかのconstなしの引数を持つ関数に渡した場合出る。 void func2( int *a ) { return; } void func( const int *a ) { func2( a ); return; }
571 :
通りすがりのホゲホゲEX :2008/03/09(日) 16:47:30
すみません、質問させてください char *p="abあかさcたな";と宣言したポインタpを使って pが今指している1文字がワイド文字かそうでないかを判定し 最後の文字まで同様に判定したいのですがこういうのはできるんでしょうか?
573 :
572 :2008/03/09(日) 18:11:12
質問した後に解決できました、ごめんなさい
574 :
デフォルトの名無しさん :2008/03/09(日) 20:18:25
>>570 それってCだと警告ですむんだっけ?
エラーかと思ってた。
すみません。 VC++2008を使用しているのですが、コンソールAPIを記述し実行するにはどうしたら良いでしょうか?
>>575 コンソール系のAPIってAllocConsole()とかあのあたりの?
使ったことないけど、ほかのAPIが使える状態なら、コンソール系のAPIも普通に使えそうだけど。
578 :
デフォルトの名無しさん :2008/03/09(日) 22:32:51
初心者な質問ですみません。 ヘッダを作成する際に、変数ではなく、関数を呼び出しする時にexternをつける理由を教えてください。 extern AtoI()などです。 変数の時につける理由はわかるんですが、関数につける理由がいまいちわかりません…。
変数と同じ理由だよ 「どこかにある(定義されている)関数を使いますよ」 という宣言
ちなみに関数はdefaultでexternなので付ける必要はない
>>579 ありがとうございます。やっと謎が解けました。
数学の知識はどの程度必要なんでしょうか? (C言語プログラミング)
繰り上がりのある足し算くらいは出来たほうがいい。
>>582 分数の、加減乗除、約分、方程式の、移項、多角形の、内角の、和、九九、あげたら、きりが、ありません
何がやりたいかによるとしか
上がっているほとんどが算数である事実。
>>582 「日本語を学ぶのに、漢字の知識は度の程度必要か」以上に意味がない質問になっている。
Cで数学の諸問題を解くならば高等数学の知識が必要になるが、
事務処理的なプログラムを作るだけなら算数程度の知識で充分。
まぁ、必要なら都度学べばいいしね。
588 :
582 :2008/03/10(月) 15:35:55
ありがとうございます。 必要に応じて勉強します。 すみません。
MS-DOS上で Lattice C ver 3.2を使いプログラミングしたいのですが分からない事があります。 .cのファイルをコンパイルし .objのファイルを作る所まではできました。 次に、リンカを使い実行ファイルを作る所なのですが、リンカをどう使っていいのか分かりません。 よろしくお願いします。
link -? で出ないか? 普通は環境変数ちゃんとしてたら、objファイル名並べるだけでいけそうだが。
>>590 でないんです><
objファイル名書いただけでは、実行ファイルは作成されますが、実行してもエラーになります。
それはプログラムがバグっているか、環境が合っていないかじゃないのか?
何かライブラリが必要なのかな?
とりあえず Hello プログラムが動けばプログラムの問題。 あるいは、その程度では顕在化しないようなバグがコンパイラかリンカに存在するか・・・だな。
英小文字をgetsで標準入力より配列テーブルへ入力する。 入力されたデータの個数と共に配列の先頭アドレスを関数英大文字変換に渡す 英大文字に変換されたデータをprintfで標準出力に出力する。 ただし、入力するデータの戸数は最大10個までとする。 入力の時の表示はstr=とする 出力の時の表示はSTR=XXX......Xとする これどう書けばいいのでしょうか?参考書を読んでも全然わからないです
>>595 宿題は宿題スレへ。
そうでないなら真面目に勉強しましょう。
597 :
デフォルトの名無しさん :2008/03/11(火) 09:11:07
>>597 どう見ても、入門向けの質問ではないしlibxml2とやらの仕様に関わる問題なので
xml関連のスレへどうぞ。
つーか、単にそのライブラリが所謂%エスケープ文字列に対応してないんでないの?
ブラウザみたいになんでもありなものと較べちゃかわいそうだよ。
599 :
598 :2008/03/11(火) 10:04:24
質問させてください ある関数の引数としてprintf()と同じ書式指定付き文字列と複数の変数を取って その関数内部のprintf()に引数をそのまま渡してprintf()と同じ出力にしたいのですが こういう場合の引数の指定法やprintf()への渡し方はどうすればいいのでしょうか?
>>599 やる羽目になった張本人に聞けばいいんじゃないの?
少なくとも、>598を読んで対処方法が何も思いつかないなら聞くだけ無駄かと。
動的確保をやらないでファイルが以下のような感じであって。 例えば2次元配列なら x y 1 2 3 4 5 6 を num[x][y]として確保するにはどうすればいいでしょうか。 プログラムの関係で、動的配列は使えなくて 一度読み込みを行うと時間が掛かってしまいます。 x yはファイルによって様々です。
>>604 の場合ですが
上の3行の場合だと
num[6][7]が領域として必要となります。
num[2][3]のようにファイルに書かれていない領域は0で初期化して
メモリ上に存在するということで。
>>604 「動的確保しないで、動的に確保するにはどうしたらいいですか」と聞かれても困ります。
>プログラムの関係で、動的配列は使えなくて どんな関係だ?授業上の制限とかか?
vectorで確保していたのですが num[2][3]のような空の値をちゃんと空としてくれなかったので 使う関数の関係で空のところを指定しないと破綻してしまうのです これまでは ファイル一時読み込み 値の最大値分を確保 ファイルポインタを先頭へ 確保した領域に順次代入 という手順を踏んでいたのですが これだと行数が莫大になったときに、読み込みだけで時間がひどく掛かってしまい。
>>608 どうしたって2スキャン掛かるものは掛かるからねぇ。
処で、「空」と言うのはどういう状態を指しているの?
そのnumとやらの宣言がどうなっているのか知りたいのだが。
# つーか、>606-607は無視かYO!
2スキャンを、スキャンしないようにするのはキツイですか。 2スキャンであれば簡単なので問題ないのですが…… すんません、無視したわけではないのですが。 授業とは違います。 空の状態は0初期化がベストですが、intのゴミが入っていても構いません numはint型で、ファイルの値に準じて幅が変わる配列です。 現状はvector(int)のような一次元配列で確保していってます。
vector<vector<int>>でいいんじゃね? 読み取ってsize調べて小さければreserveして・・・ 二次元になっててややこしいけどできなくはないよ。
× vector<vector<int>> ○ vector<vector<int> > なんだが、次期規格では >> が許容されて、 さらに gcc がこの前 >> に対応したみたいだな。
一次元でもアクセスするときはnum[][]で大丈夫だと思っていたのですが if( (int)num.size() < temp[0] + temp[1]*maxValue[0]){ num.resize( temp[0] + temp[1]*maxValue[0]); num[ temp[0] + temp[1]*maxValue[0] -1 ] = POINT; } else num[ temp[0] + temp[1]*maxValue[0] - 1 ] = POINT; 値を入れる個所はこのようになっています。POINTはとりあえず値が入っている状態です。 temp[0] temp[1] に読み込んだ値が入っていて numは二次元配列を一次元配列として扱ってアクセスするようにしています。 これだと0のときにエラーが出たり、よくわからないところでvectorが値を確保しなかったり 関数に送ると望まない結果がでてしまっています。
すみません、1行目は何か変なこと書いてました。
temp[0] + temp[1]*maxValue[0] ばっかで目が痛い。 一時変数にでもいれとこうぜ。
xの最大値が決まらない内にvectorにアクセスしたいなら、 offset = (x + y) * (x + y + 1) / 2 + yでアクセスすればOK。 つーか、vectorのreserveにもこのoffsetが使える。
ちょっと待て、ここはCスレじゃないのか?w
たしかにw
>>608 でいきなりvectorが出てきてからおかしくなったなw
>>616 その使い方だとどうなるか教えていただけませんか?
offsetを使ったソースを描いたことが無くて
>>617 確かにそのとおりでした。ほんとすみません
>>619 そもそもこちらの解釈があっているか判らんので確認。
--
ファイルにはxとyが各行に記録されていて、(0, 0) から(xMax, yMax)までを収容できる配列が欲しい。
Cでは可変長の多次元配列を扱えないから、
・一次元配列の、ポインタ配列(vector<vector<int> >に相当)
・仮想的に一次元の配列(vecotr<int>に相当)
のどちらかで扱うことになる。
前者は、順次必要なだけ確保することはそれほど難しくないし、アクセスは容易。
但し、長さの異なる配列へのポインタ配列と言う構造から長さの等しい配列へのポインタ配列への変換コストが掛かる。
# でないと、ファイル内に書かれていない座標に相当する空間が得られない恐れが出てくる。
これを避けるには、事前にxMaxが確定している必要がある。
後者は、xMaxが確定していれば確保することは容易だが、アクセスにはオフセット計算が必要。
勿論、ファイルを全部読むことなしにxMaxを確定することはできない。
--
ここで、xMax, yMaxを確定するには一旦ファイルを全部読むことになるから避けたいと言う要求が発生。
どうすればいいか、と言うのが問題。
先程の方針では、どちらも都合がよくない。そこで、xMax, yMaxに拠らないアクセス方法と確保手段があればいい。
その為には、後者のオフセット計算においてxMaxに依存しない形でオフセットを計算できればいいということになる。
上記のオフセット計算は、次のように番号を振ることに相当する。
y座標↓x座標→0 1 2 3 4
0 0 1 2 3 4
1 5 6 7 8 9
2 10 11 12 13 14
3 15 16 17 18 19
4 20 21 22 23 24
これを次のように振ることにすればいい。
……
おっと、余白がないので詳細は割愛。
三角行列はサイズによらないインデクシングが行える。 行列全体を上三角行列と下三角行列の2つに分けて扱えば 行列全体もサイズによらないインデクシングが行える。 これを使えば1パスで読み込めるし、 インデクシングもそれほど大変じゃなく行えるよ。
例えば下三角行列で考えるとする。 んで、こういう風にインデクシングする。 * 0 1 2 3 : j 0 0 1 1 2 2 3 4 5 3 6 7 8 9 i この時、インデックスは i と j から次のようにして求められる。 (インデックス) = i * (i + 1) / 2 + j j が 0 の時、そのインデックスはその上にある要素の数に等しい。 これは高校で習う簡単な和の公式(Σのやつ)で i (i + 1) / 2 と求まる。 あとはそれに j を足すだけ。
さて、>620の続き。 xMaxに依存しない番号の振り方はこう。 y座標↓x座標→ 0 . 1 . 2 . 3 . 4 0 . 0 . 1 . 3 . 6 10 1 . 2 . 4 . 7 11 16 2 . 5 . 8 12 17 23 3 . 9 13 18 24 31 4 14 19 25 32 40 この方式だと、番号即ちオフセットの計算式は先程書いたように(x + y) * (x + y + 1) + yになる。 これならば、各行を読み込んでxとyが確定した時点でそのときのxMax, yMaxと比較、 更新する必要があれば更新してメモリを再確保すればいい。 つまり、どの行を読み込んだ時点でもそのときの(0, 0)-(xMax, yMax)の空間は確保されていると言うこと。 # 勿論、xMax * yMax程度の無駄な空間が発生することにも要注意。
>>623 インデックスの振り方が違う。
それだと 15, 20〜22, 26〜30 とかのインデックスが宙に浮く。
>>621-622 だとそういう宙に浮くインデックスが発生しない。
具体的にコードを書くとこんな感じ。 #define SIZE 100 static int num1[SIZE * (SIZE + 1) / 2]; static int num2[SIZE * (SIZE - 1) / 2]; int get_value(size_t x, size_t y) { assert(x < SIZE && y < SIZE); if(x >= y) { return num1[x * (x + 1) / 2 + y]; } else { return num2[y * (y - 1) / 2 + x]; } } void set_value(size_t x, size_t y, int value) { assert(x < SIZE && y < SIZE); if(x >= y) { num1[x * (x + 1) / 2 + y] = value; } else { num2[y * (y - 1) / 2 + x] = value; } }
実装はこっちのが見通しいいかね。 アドレス欲しい事もあるだろうし。 int* get_address(size_t x, size_t y) { assert(x < SIZE && y < SIZE); if(x >= y) { return &num1[x * (x + 1) / 2 + y]; } else { return &num2[y * (y - 1) / 2 + x]; } } int get_value(size_t x, size_t y) { return *get_address(x, y); } void set_value(size_t x, size_t y, int value) { *get_address(x, y) = value; } /* 速度が気になる人用 */ /* C++ ならインライン関数でいいと思うが。 */ #define GET_VALUE(x, y) (*get_adderess((x), (y))) #define SET_VALUE(x, y, value) (*get_adderess((x), (y)) = (value))
そこでC99ですよ
動的に確保しないとなると、 スタックサイズをよほど大きくするのでなければ、 巨大配列は静的変数にしなくてはいけないだろうな。
set_value の戻り値の型が void だから SET_VALUE も void にした方がいいし、 GET_VALUE の値も右辺値にした方がいいな。 #define GET_VALUE(x, y) ((int)(*get_adderess((x), (y)))) #define SET_VALUE(x, y, value) ((void)(*get_adderess((x), (y)) = (value)))
void main(void) { JIKAN a, b, c; printf("時1?"); scanf("%d", &a.ji); printf("分1?"); scanf("%d", &a.fun); printf("秒1?"); scanf("%d", &a.byo); printf("\n"); printf("時2?"); scanf("%d", &b.ji); printf("分2?"); scanf("%d", &b.fun); printf("秒2?"); scanf("%d", &b.byo); c = t_add(a,b); printf("%d時%d分%d秒 + ", a.ji, a.fun,a.byo); printf("%d時%d分%d秒 = ", b.ji, b.fun,b.byo); *2 「計算結果の表示の仕方」 } JIKAN t_add(JIKAN x, JIKAN y) { JIKAN a; a.byo = x.byo + y.byo; *3 「時、分、秒の加算処理の仕方」 *4 「計算結果の返し方」 } のプログラム構成の時、*1〜4のところに何と打てばいいかを教えてもらえませんか?
アクションゲームみたいなものをつくってみたいのですが、今までCでは計算系のこと しかしてないので、絵の描き方・動かし方などどこから手をつけていいのか分かりません。 自分で描いたものを画面上で動かすには具体的にどうすればいいのでしょうか?
>>632 具体的には、環境に依存するAPIを使ったり使わなかったり。
WindowsならWin32 APIとか、UNIXならXlibやSDLとか。
634 :
デフォルトの名無しさん :2008/03/12(水) 14:31:44
現在main側で CreateFile GetFileSize calloc(ファイル読み込み用バッファ) ReadFile という処理を行っているのですが この処理を自作関数にして main側から自作関数内のバッファにアクセスしたいのですが どうすればできますか?
>>634 自作関数からバッファへのポインタを返す
main:
char* buffer = myfunc();
...
free(buffer); /*不要になったら消す */
myfunc():
...
char* buffer = calloc(...)
...
return buffer
636 :
デフォルトの名無しさん :2008/03/12(水) 15:29:03
637 :
デフォルトの名無しさん :2008/03/12(水) 15:30:11
>>632 単にゲーム作りたいだけならD言語とかでやってみたら?
バイナリ吐けるし、GCあるし、言語機能とか段違い。ついでに文法もCに似てる。
638 :
デフォルトの名無しさん :2008/03/12(水) 15:33:35
char * buffer = calloc(...)
>>637 いくら似ているとは言え、別の言語なんだから、
ライブラリのこととD言語のことを同時に学ぶことになり、
大変だと思うんだけど。
まあ、DはCの標準ライブラリ全部つかえるけどな
641 :
デフォルトの名無しさん :2008/03/12(水) 16:50:22
>>639 そりゃまあそうだけどゲーム作るんならDでやっておいた方が後々楽だろうと思ってな
Cだとプログラムでかくなればなるほどしんどくなるだろ
無難にC++でいいよ。 最新バージョンのDMDでコンパイル通るまともなライブラリがない。
Visual C++ 2005を使っていて気づいたんですが *str="aiueo"; と str[]="aiueo"; では、 str[]のほうは文字列をいじれるのに対して、 *strだと文字列いじれないんですね。 以前はいじれた気がしたんですが・・・。
環境によってはいじれることもあるけど、危険なのでいじらない方がいい。
ということはVC++2005では*strで文字列扱うのはもう推奨していないというかダメということですね?
デバッグのときに混合表示で見てみるとわかる
連投すみません。 C/C++ではそういう操作が出来るのがいいところだったのに ガチガチに縛られ始めてなんか悲しい。
全然ダメじゃないんだが、 >*str="aiueo"; >と >str[]="aiueo"; の違いはちゃんと理解してるか? 前者はメモリ上のどこかに"aiueo"という文字列を置いて、strにそのポインタを代入する。 後者は"aiueo"で初期化された配列を確保する。
>>643 *str="aiueo";
"aiueo"という文字列定数へのポインタがstrに入っている。
"aiueo"という文字列定数がどこに置かれるかはコンパイラ次第
コード領域で書き込み不可のところにあるかもしれないし、組み込みだとROMかもしれない
str[]="aiueo";
strという配列をスタック(staticならスタック以外のデータ領域)に作製し、"aiueo"という要素で初期化。
スタックまたはデータ領域なので書き換え可能。
>>648 >>649 *str="aiueo";とstr[]="aiueo";の違いは分かっているつもりなのですが、
以前は出来たものが出来なくなって不便を感じたんです。
でも安全面のことを考えたら使えないほうがよさそうなので
これからはstr[]="aiueo";を使っていこうと思います。
ありがとうございました。
以前は出来たってなんだよ。 出来ないことを無理やりやって偶然うまく動いてただけだろ。
>*str="aiueo";とstr[]="aiueo";の違いは分かっているつもりなのですが、 分かってるつもりで分かってない。 >以前は出来たものが出来なくなって不便を感じたんです。 分かってたらこの台詞はでてこない。 ポインタと配列は初心者のうちはどうしても混同する。 恥ずかしいことじゃないからもう一度入門書読んでおいで。
>>650 常にstr[]を使う必要はないんだぞ。文字列を書き換えたいときだけ
str[]にすればいい。
10年以上Cを書いてるけど、配列を文字列定数で初期化する機会はほとん
どなかった。
C言語なつかしす
>>650 わかっているなら文字列「定数」を書き換えようと思わないはずだ。
>>647 規格としてはC89のときから駄目になっている。
あと、これには/GFオプション(同一文字列を1つにまとめる)のような
最適化が可能という利点もある。
>>630 JIKAN t_add(JIKAN x, JIKAN y)
{
JIKAN a;
//*3 「時、分、秒の加算処理の仕方」
a.byo = x.byo + y.byo;
a.fun = x.fun + y.fun;
a.ji = x.ji + y.ji;
a.fun += a.byo / 60;
a.byo %= 60;
a.ji += a.fun / 60;
a.fun %= 60;
a.ji %= 24;
//*4 「計算結果の返し方」a.byo = x.byo + y.byo;
return a;
}
// *2 「計算結果の表示の仕方」
printf("%d時%d分%d秒\n", c.ji, c.fun, c.byo);
659 :
デフォルトの名無しさん :2008/03/12(水) 23:27:25
すんまそん・・・下の図形ってコマンドプロンプトでどうやって表示させるんでしょうか・・・? for文を使って書く問題で、入力した数字で深さを決定するんですが・・・ 入力:4 出力: * * * * * ******* 今は入力4なので、縦の長さが*4つ分になってます。マジでわからん・・俺はアホでした・・・ 底の*は入力数をnとすると、2n-1になるから一番最後に表示すればいいかなと思ったんですが・・ここまでで思考停止してます・・・
660 :
デフォルトの名無しさん :2008/03/12(水) 23:28:23
>>659 Cじゃなくて算数の質問ならスレ違いですよw
おもいっきりズレてますすんません・・・ちゃんと表示されない・・・ * * * * * ******* こうかな・・・?
すげー下らん質問ですが、 定期的に呼び出されるタイマー関数内で計算中の変数を保管しておいて、ゲームループで再び呼び出されたとき、 その続きから開始したいです。どうすればできますか? お願いします。
>>662 グローバル変数とかstaticにするとか。
>>661 空白を入れたいなら で入力したほうが
662ですが、ありがとうございます。
>>665 こんな機能が・・・どうもです
*
* *
* *
********
668 :
667 :2008/03/13(木) 00:19:36
>>667 高さが4のとき、最下段は8個なのか?
面倒だから7個だと仮定して。
・最下行
*が7個
・その上の行
空白1個、*1個、空白3個、*1個
・その上の行
空白2個*1個空白1個
・最上行
空白3個、*1個
最上行をm=0として、以下順にインクリメントして最下行をm=n-1とする。
・m=0のとき、空白(n-1)個、*1個
・m>0且つm<n-1のとき、空白(n-m-1)個、*1個、空白2m-1個、*1個
・m=n-1のとき、*(2n-1)個
要は、こうなる。
for (int m = 0; m < n; ++m) {
for (int i = 0; i < n - m - 1; ++i) putchar(' ');
if (m == 0) {
putchar('*');
} else if (m < n - 1) {
putchar('*');
for (int i = 0; i < 2 * m - 1; ++i) putchar(' ');
putchar('*');
} else {
for (int i = 0; i < 2 * n - 1; ++i) putchar('*');
}
putchar('\n');
}
かなり汚いけど・・・ int size = 7;// 自分で入力。 for ( int i = 0; i < size - 1; i++ ) { for ( int j = 0; j < size - i - 1; j++ ) printf( " " ); printf( "*" ); for ( int j = 0; j < i* 2 - 1; j++ ) printf( " " ); if ( i > 0 ) printf( "*" );// 1行目は*1個なので出力させないためのif printf( "\n" ); } // 最後の行 for ( int i = 0; i < size * 2 - 1; i++ ) printf( "*" );
シンプルに行こう。 -- // 変数名などは>669に準じた。 for (int m = 0; m < n - 1; ++m) { printf("%*c", n - m, '*'); if (m > 0) { printf("%*c", 2 * m, '*'); } putchar('\n'); } for (int i = 0; i < 2 * n - 1; ++i) putchar('*');
現在やさしいCのP263でファイルの分割をやっているのですが #include <stdio.h> #include "myfunc.h" int main(void) { int num1, num2, ans; printf("1番目の整数を入力してください。\n"); scanf("%d", &num1); printf("2番目の整数を入力してください。\n"); scanf("%d", &num2); ans = max(num1, num2); printf("最大値は%dです。\n", ans); return 0; } を実行してもインクルードファイルmyfunc.hをオープンできないとエラーがでます。 以下myfunc.hファイルの内容 /* max関数の宣言 */ int max(int x, int y); 関数を定義したmyfunc.cファイルもあるのですがエラーいまいちよくわからず まずオープンできないというエラーを解決したいのですが なにがおかしいのでしょうか? コンパイラはBorland C++ Compiler と CPadを使っています。
ヘッダーに関数の中身も書けばいいよ
>>671 printfとか長く使ってないとそういう仕様をド忘れしちゃうんだよね・・・
%の数と引数の数が合わない時点で?が出てしまったorz
>>672 パス関係の問題だと思う。
なんで一つのループに最初と最後も入れたがるのかね。
>>673 まだよくわからないのですが
この後にその関数を定義したファイルのオブジェクトファイルと
上のmain関数が含まれているファイルのオブジェクトファイルをリンクして
1つのプログラムにするらしいので・・・
>>674 パス関係とはつまりどういうことなのでしょうか
677 :
667 :2008/03/13(木) 01:25:32
すげええええええええええええええ なるほど!!!みなさんマジでありがとうございました!! アホには思いもつきませんでした・・・・さっき自分でやってたら、変数がいっぱいになってわけわかんなくなりました(((´・Д・))) 内側の空白がn-m-1コとか、式がぜんぜん思いつきませんです・・・。やっぱセンスですか。。。
678 :
672 :2008/03/13(木) 01:26:35
すいません、自己解決しました。 ファイル名だと思っていた.hというのが拡張子だったことに気づきました・・・ ヘッダファイル==.hのファイルということですね まぬけな落ちですいません。 こたえてくれた方ありがとうございました
>>678 includeするファイルは別に.hに限らない。.tbl/.data/.txtなんでもかまわない。
バイナリは無理な気がするがテキストならまず問題ない。
単純にincludeはその位置にファイルを展開する(コピペしたのと同じ)と思っていい。
規格まで確認したわけじゃないし、.h以外のincludeを認めないコンパイラもあるとは思う。
680 :
672 :2008/03/13(木) 01:47:23
>>679 なるほど、自分は.h.cとかいうマヌケなことをしてました。
2つのオブジェクトファイルをリンクするので詰まってしまいました。
Borlandとかでぐぐってるけどイマイチわからない
素直に本のとうりにVC++2005しとくべきだったか\(^o^)/
main.c と 〜.h を同じフォルダに置いてincludeするだけでできるとおもうが
683 :
672 :2008/03/13(木) 02:11:49
>>681 目を通したことならあります、ありがとうございます。
>>682 mainのファイルの#includeにヘッダファイルの他に
関数を定義したファイルの.cを追加したらできました。
なんとなくわかってきた・・・かも
アホな質問ばっかですいません、ありがとうございました。
>>677 いや、申し訳ないがセンスの問題じゃない。
センスがなくても>669の前半のように実際に調べてそれに当て嵌めるだけ。
ちなみに、n-m-1は左側の空白の個数だ。
これも、最上段(m=0)のときにn-1必要であることが判れば難しくないだろう。
尤も、>677で間違えるようなそういうミスを排除する注意力をセンスと言うかは別の問題だが。
685 :
667 :2008/03/13(木) 03:09:27
グホッ間違ってました・・・すみまそん これから頑張ります。今日は寝ないです
>>677 思いつくんじゃない、計算するんだ。
100円と200円の商品買って税込みいくらになるか、って聞かれたら思いつきじゃなく計算するだろ?
char a[]="(2+3)*3"; aの文字列を自動計算させてint型にしたいのですが、 どういう関数を使えばできますか?
自分でそういうことする関数を作れ。
一文字づつ解析するしかないんじゃね?
回答ありがとうございます 作る方向でやってみます
int calcString(const char * str) { char buf[strlen(str) + 25]; sprintf(buf, "awk 'BEGIN{print %s;}'", str); FILE * fp = popen(buf, "r"); fgets(buf, sizeof(buf), fp); fclose(fp); return atoi(buf); }
693 :
デフォルトの名無しさん :2008/03/13(木) 18:39:17
//アルキメデスの円周近似 #include<stdio.h> #include<math.h> int main(void) { int i; long double a[100],b[100]; a[0]=4.0*sqrt(3.0); b[0]=6.0; for(i=0;i<99;i++) { a[i+1]=2*a[i]*b[i]/(a[i]+b[i]); b[i+1]=sqrt(b[i]*a[i+1]); printf("6X2^%d角形を用いた近似値:%Lf~%Lf\n", i,b[i+1]/2,a[i+1]/2); } return 0; } 桁数が足りなくなるのですがどう修正すればいいですか?
%.20fとかにする。とはいっても結局すこし進めば結果は同じだけど 俺の環境じゃ「6X2^24角形を用いた近似値」あたり以降は同じ結果になった。
C言語ならって一年くらいになるものです 少し大きめのプログラムを作っていて、いくつか線形リストを作ることになったのですが 構造体ごとに線形リストの関数を作るのはどうも綺麗じゃないので 線形リストを作る関数一つで各構造体の線形リストを作成したいと思っているのですが そういったことは可能なのでしょうか?
void*を使って、ユーザ側で適当にキャストさせるとか、 マクロでジェネリックプログラミングするとか。
要素はvoid*にして、リストを管理する関数を共通にする。 リストの要素に関する関数を外出しにする。 (生成、廃棄、参照など)
>>694 Windows/VC++だとlong doubleとdoubleの精度は同じ
15,6桁が上限
それ以上を望むならdoubleを使わないで、自前で整数の配列を用意して
それで計算する。
ちょっと面倒。
700 :
デフォルトの名無しさん :2008/03/14(金) 03:18:11
>>696 C言語だとそれぞれの構造体ごとに関数作るしかないね
C++なら話は別
>>700 いや、
>>697 さんのいう「void *」でおk
struct list {
struct list *next;
void* data; <-ここにぶら下げる
};
>>694 これでn=30まで出るが。
--
int main()
{
const long double eps = 3e-19;
long double p = 2 * sqrtl(3);
long double q = 3;
for (int n = 1; p - q > eps; ++n) {
printf("n = %2d: %22.20Lf, %22.20Lf, %22.20Lf\n", n, p, q, (p + q) / 2);
long double r = 1 / p + 1 / q;
p = 2 / r;
q = sqrtl(p * q);
}
printf("%.20Lf\n", p);
return 0;
}
--
sqrtl()のない環境なら、sqrt()の結果を初期値にニュートン法でsqrtl()を実装すればいい。
要は、long doubleで計算するなら平方根も同じ精度が必要と言うことと、
n=100まで求めたいのならそれなりの他倍長演算を実装する必要があるということ。
>>701 可変長構造体でもいいかな。
二重にメモリ確保しなくていいし。
>>704 それだと汎用的に作れない。
用途が特定だったらいいけど。
>>701 のやり方が一般的だと思う。
また質問しにきました・・・・
http://www.u-gakugei.ac.jp/~miyadera/LECTURE/ElecBook2/ptech06.htm ここの4−11で、
/* 34 */ for (i = 0; i < n; i = i + 1)
/* 35 */ {
/* 36 */ k = i;
/* 37 */ for (j = i+1; j < n; j = j + 1)
/* 38 */ if(s[j] < s[k])
/* 39 */ k = j;
/* 40 */ dummy = s[i];
/* 41 */ s[i] = s[k];
/* 42 */ s[k] = dummy;
/* 43 */ }
ってあるんですが、理解できないです・・・
@まずi=0番目のときに、そこの配列に格納された値とj=i+1からj++としていって、そのj番目の配列で最小値を見つけたら入れ替えると思うんですが、
if(s[j] < s[k])←ここで判断してるんでしょうか?これは最小値ではなく、大小しかわからないと思うのです(おいらが間違ってるんでしょうけど・・・)
Ak=i として、さらに k=jとしてますが、このくだりがまったく理解でしましぇん・・・
このkは何の役割なんでしょうか?kを消して、iとjに書き換えて実行したら変な結果になるんで、これもおいらが間違ってるんでしょうけど・・
/* 38 */ if(s[j] < s[i])
/* 40 */ dummy = s[i];
/* 41 */ s[i] = s[j];
/* 42 */ s[j] = dummy;
/* 43 */ }
詰まってます・・・どなたか教えてクダシャイ・・・・
変数名が最悪だなw
/* 37 */ for (j = i+1; j < n; j = j + 1) /* 38 */ if(s[j] < s[k]) /* 39 */ k = j; これでforループワンセット。 {}でくくれば分かりやすいのに、不親切なコードだね。 for (j = i+1; j < n; j = j + 1) { if(s[j] < s[k]) { k = j; } } つまりこういうこと。 jをi+1からn-1まで動かして、s[k]より小さいのが見つかったらそれを新たなs[k]にする。 ループを抜けたときはs[i+1]からs[n-1]の中で最小のものがs[k]になってる。
kっていうのはiからn-1までの中で最も小さい数が入ってる番目。 まず仮にi番目を最小と仮定する。 k=i 次に一つずつ大きさを比較して、より小さいものがあればkにその番目を入れる。 for(j=i+1; j<n; j++) if(s[j]<s[k]) k = j; n-1まで比べ終わったら、i番目と最小の位置を入れ替える。 dummy = s[i]; s[i] = s[k]; s[k] = dummy; これを繰り返すことで配列が小さい順に並ぶ。
読みやすさよりサイズ優先の人ってたまにいるよね
ぬおおおおおおおおおお!!!なるほど!!!理解できました!! みなさんどうもです!!!
712 :
サッカー :2008/03/14(金) 16:29:40
助けてください。 c言語の文字列ソートで char * month[]={"january" ,"february", "march","april","may","june","july"} をアルファベット順に大文字に変えてソートするやり方 がわかりません。教えてください。今日までなので時間がありません。 お願いします。
宿題は宿題スレへ
714 :
サッカー :2008/03/14(金) 16:44:09
教えてください。 本当にわからない。 お願いします。
716 :
◆nUWYoBn0RQ :2008/03/14(金) 16:53:02
今日はじめてやったから・・・。 ありがとうございます。
今日はじめてでトリップ付けてるってどういうことだよw
718 :
サッカー :2008/03/14(金) 17:42:21
トリップって#のこと? 宿題スレに書いてあったから付けてみた〜。 あと宿題スレ返事来ないよ どーしよー。
719 :
696 :2008/03/14(金) 19:45:16
皆さんどうもありがとう、まだ少し理解してない部分もありますが参考書片手にがんばってみます。 ありがとうございましたorz
>>702 >n=100まで求めたいのならそれなりの他倍長演算を実装する必要があるということ。
今はスキル不足で無理なのでいつかリトライしてみます
>>720 速度を求めないならニュートン法とかFFTとか使わない単純な多倍長演算でも可能
最近のPCなら1000桁くらいならあっというま。
作りもしないで言うだけなら簡単だよな。 平方根関数をニュートン法使わないで実装する方が面倒だっての。
すごく初心者な質問なんですけど たとえば5秒間何もしないで待つと「a」、その間に何かキーを押すと「b」を出力するのってどうやるんでしょうか?
724 :
デフォルトの名無しさん :2008/03/16(日) 08:12:24
>>723 環境依存の方法に頼るしかないんじゃないかな。
たとえばUNIXならselectやpollを使う。
>>723 環境による。
非同期型のイベント駆動型のプログラムにするか、ループでキー入力を監視する同期型のにするかでも違う。
ループでキー入力を監視する方式でkbhit関数が使える環境ならばこんな感じ。
time_t start_time, current_time;
int anykey_pressed = 0;
time(&start_time);
current_time = start_time;
while (difftime(current_time, start_time) < 5) {
if (kbhit()) {
getch();
anykey_pressed = 1;
break;
}
time(¤t_time);
} }
printf("%s\n", anykey_pressed? "b": "a");
727 :
デフォルトの名無しさん :2008/03/16(日) 15:05:17
Cのソースが10個 → 1つのDLL にするにはどうしたらいいのですか?バッチファイル使うので すか? makefileですか? WDKをつかって buildでしょうか? お願いします。DLLが作れません。
catでくっつけてコンパイルする
まずコンパイラのマニュアルを読みましょう
aを底とするxの対数を求めたいんですが、log()とlog10()しか見つかりませんでした。 aを自由に決めれる関数はないのでしょうか? もしくは、log()やlog10()をつかって簡単にだせるんでしょうか? 教えてください。
自作すればおk
対数の底の変換公式は高校数学必修ではなかったのか…
737 :
デフォルトの名無しさん :2008/03/16(日) 15:39:22
そういやそんな公式あったな 普段 底はEだからあまりつかわないけど
738 :
デフォルトの名無しさん :2008/03/16(日) 16:32:33
スクリーンセーバーを自作してみたいのですが、 その手助けになりそうなWebサイトとかないでしょうか?
スクリーンセイバー C言語 でぐぐっとけ
740 :
デフォルトの名無しさん :2008/03/16(日) 17:26:25
*so = calloc(ry while((*so++ = *ptr++) != '?'); printf("%s",so) 動的に確保した領域に文字をコピーしたいのですが、 どうしたらできますか?
最初の3行は何だ?
calloc()の略してる部分が分からないってことかね。
743 :
デフォルトの名無しさん :2008/03/16(日) 17:57:47
whileのところでコピー出来なくて、 原因がわかりません。
わからないなら略さないで晒せよ
>>743 '?' のところは、文字化けじゃなくて、ソースのまんまなの?
746 :
デフォルトの名無しさん :2008/03/16(日) 18:31:18
まんまです。
'?' は'\0'だね。 strdup() (もしくは _strdup())を使えば、一発で処理できるよ。
ん?文字列中の?までを確保した領域にコピるんじゃないの?
cgi のパスを保存したいのかな?
それならそれでsoの最後に\0を追加する必要があるんでない?
const char* get_hoge(const char* str) { const char* end_str; size_t len; char* res; end_str = strchr(str, '?'); if (end_str == NULL) { return NULL; } len = end_str - str; res = (char*)malloc(sizeof (char) * (len + 1)); if (res == NULL) { return NULL; } memcpy(res, str, len); res[len] = '\0'; return res; }
>>750 calloc()つかってるのは、それ省くためなんじゃないの?
>>740 ? 以降の長さを無視してよいならこれでもおk
so=strdup(ptr);
p=strchr(so, '?');
if(p!=NULL) *p='\0';
ptr が書き換え可能な領域に存在するなら 一旦 '?' を '\0' に書き換えてから strdup して 後で元に戻すという手もあるが あまりオススメしない。
標準入力からオーバーフローを起こす危険性無しに文字列を 読み取る方法を考えているのですが、 for(i = 0; i <= sizeof(str)-2; i++){ cc = getchar(); if(cc == '\n'){ str[i] = '\0'; break; }else{ str[i] = (char)cc; }} if(i == sizeof(str)-1){ str[i] = '\0'; } ↑と fgets(str, sizeof(str), stdin); p = strchr(str, '\n'); if(p == NULL){ str[sizeof(str)-1] = '\0'; }else if{ *p = '\0'; } ↑では、どちらの方が実行速度が速くなるのでしょうか?
速度は実測が基本。でも下が速くなりそうだな・・・
>>755 下のは、 p == NULL のときは、'\0'を入れる処理はいらないんじゃね?
>>755 コンパイラが最適化を掛けるから、結局は実測しないとわからない。
環境によって違うこともあるだろう。
この場合は下が速そうな気がするけど。
759 :
755 :2008/03/16(日) 23:35:47
回答ありがとうございます。
みなさんがおっしゃってくれたように実測してみることにします。
>>757 そうでした。ありがとうございます。
入力された文字列をMallocで確保した部分にコピーしたいと思っていますがうまく出来ません。 どうしたらいいでのでしょうか? char line[100],*linep,*word; int x; linep=line; gets(line); while (*linep != '\0'){ x=x+1; linep=linep+1; }; printf("%d",x); linep=line; word=(char *)malloc(x+2); do{ *word = *linep; word=word+1; linep=linep+1; }while(*linep != '\0'); printf("%s",word); 最初はlineのサイズをSizeofで取って、mallocで空間を作ってstrcpyでコピーしていましたが、 それだと配列の最大サイズを使ってしまうので、なんとかして入力された文字列ちょうどのサイズで 入力内容を受け取りたいです。どうかご教授願います。
>>760 x初期化してないってことは・・ないよねぇ・・やっぱ
>>760 あ、すいません。書いてませんでしたが初期化はしてあります。
>>760 printfで使う時のwordって
末尾指してないか?
gets(line); x=strlen(line); word=(char*)malloc(x+1); strcpy(word,line); みたいな流れじゃないの?
>>763 仰るとおり、末尾を指してました・・・
通りでprintfで(null)って表示されるわけだ・・・
>>764 お書きいただいた方法でやってみたら、アッサリ出来ちゃいました
お二方ともありがとうございました!
766 :
デフォルトの名無しさん :2008/03/17(月) 05:36:57
C言語ソフトのインストールについての質問いいですか? ただいま、無料のC言語のダウンロードに挑戦中なのですが、コマンドプロンプトの起動はどうしたらよろしいでしょうか? cygwinをインストール中です。 C言語の開発の勉強をしようと思ってるのですがまだ入り口にも入れず。 現在状況 1.C言語って何ぞや? 2.初心者用の本数冊購入。 3.C言語開発にインストールしなければいけないソフトがあると判明。 4.インターネットよりcygwinをダウンロード 5. システムの環境変数を変更。 6.ウィンドウズパスの設定。 7.動作確認。コマンドプロンプトの起動←???の状態 あと、そのソフトがCドライブに入っているかどうかも心配。
>>766 スタートメニューにcygwinのアイコンできてない?それをクリックしろ
768 :
766 :2008/03/17(月) 05:47:11
できていません。 ちなみに、使用環境は、ウィンドウズXPです。
>>768 スタートメニューのアクセサリにあるかと
770 :
766 :2008/03/17(月) 06:06:13
766 ありましたありがとうございます。 すいません、続いてですが、参考書にCドライブのしたにcprogというフォルダを作成しそこを今回のプログラムを割く整数rのに使うこととします。 Cドライブのすぐ下にcprogというフォルダを作成してください。 とでたのですがどうすればよろしいでしょうか? 右クリックで新規作成のフォルダを作ろうと試みたのですが表示できませんでした。
>>770 まず、この板で聞くのではなくwindowsの使い方そのものを勉強しろ
プログラミングの勉強は3年先だ
>>765 というか誰か gets を使ってることに突っ込もうぜ!
板違いだったらスマソ C C# C++ この3つの中で一番良い言語はどれ?
774 :
デフォルトの名無しさん :2008/03/17(月) 09:30:28
C
>>773 鼬害ではないが、スレ違い。この板のスレ一覧をよく見たまえ。
777 :
デフォルトの名無しさん :2008/03/17(月) 11:58:16
できました。 あともう少しで開発できると思うんですけどまだ分からないとこがあります。 現在状況 1.C言語って何ぞや? 2.初心者用の本数冊購入。 3.C言語開発にインストールしなければいけないソフトがあると判明。 4.インターネットよりcygwinをダウンロード 5. システムの環境変数を変更。 6.ウィンドウズパスの設定。 7.動作確認。コマンドプロンプトの起動←???の状態 解決 ありがとうございます。 8.C:¥ドライブにフォルダを作成する。意味が分からなかったんですけどC:の中にフォルダを作るということだったみたいです。 9.ソースファイルの作成。 10.メモ帳出現。 11.gccのコマンド入力中。←??? 入力が正しいのか分かりませんが、出た文字がno input files です。 フォルダできてないのかな? C:直下にcppogのフォルダを作るというのをC:をクリック後新規で作りました。 でも一応フォルダの中にコマンドプロで出現したメモ帳はあるみたいです。 追伸ここで聞くことでなければどこで聞くべきか教えてください。 一応C言語をはじめるということでこの初心者の掲示板で聞いています。
778 :
デフォルトの名無しさん :2008/03/17(月) 12:01:27
追記 参考書では、exeの実行ファイルができているとなっているのですが、私のは、.c のままです、
>>777 カレントディレクトリがあってるかな?
コマンドプロンプトでlsって入力して実行して作ったテキストがあるかどうか教えてくれ
780 :
777 :2008/03/17(月) 12:19:05
質問事項 C言語を始めるためにウィンドウズに開発言語用ソフトのインストールの方法。 ソフト名 cygwin 作業状況 4.インターネットよりcygwinをダウンロード 5. システムの環境変数を変更。 6.ウィンドウズパスの設定。 7.動作確認。コマンドプロンプトの起動←???の状態 解決 ありがとうございます。 8.C:¥ドライブにフォルダを作成する。意味が分からなかったんですけどC:の中にフォルダを作るということだったみたいです。 9.ソースファイルの作成。 10.メモ帳出現。 コマンドカレントでの入力 c: cd \cprog notepad p01-04-1.c ←メモ帳出現 dir ←ソースファイル.c確認参考書ではここまで一緒。 gcc-ansi-pedanic p01-04-1.c -o p01-01-1 入力後のメッセージgcc-ansi-pedanicは、内部コマンド、または外部コマンド、 操作可能なプログラム又バッチファイルとして認識されていません。 というメッセージです。 やり直して再度打ち込んだ後こなりました。 もしかして、最初のダウンロードからして失敗?
>>780 gcc p01-04-1.c
とだけ打って
a.exe
ができればおk
>>780 which gccと入力して実行した場合の結果はどうですか?
gcc -o p01-04-1.c p01-04-1
じゃないか?
783 :
780 :2008/03/17(月) 12:27:06
>>781 usr/lib/gcc/1686-pc-cygin/3.4.4./../../../と続きました。
>>782 /usrbic/gcc
です。
>>783 gccは、エラーがなければだんまりなので、何か出たらそれはエラーだ
エラーメッセージは自分で打ったり略したりせずなるべくコピペしる (あまり多い場合は最初の数行くらい)
コマンドプロンプトを右クリックするとメニューが出るから範囲指定を選んで、左ボタンでびろーっと範囲を選択して、Enterキーを押す
で、ここに貼り付け
785 :
783 :2008/03/17(月) 12:46:09
貼り付けるのはエラーメッセージだけでいいですか? 全部貼り付けて何か問題ないですか? ネットにどこまで公開しても大丈夫か分かりません。 一応シリアル等分からない範囲で貼り付けます。 シリアルのみ削除しました。 Microsoft Windows XP [Version 5.1.2600] (C) Copyright 1985-2001 Microsoft Corp. C:\Documents and Settings\NEC-PCuser>c: C:\Documents and Settings\NEC-PCuser>cd \cprog C:\cprog>notepad p01-04-1.c C:\cprog>dir ドライブ C のボリューム ラベルは Windows XP です ボリューム シリアル番号は です C:\cprog のディレクトリ 2008/03/17 12:16 <DIR> . 2008/03/17 12:16 <DIR> .. 2008/03/17 12:16 0 p01-04-1.c 1 個のファイル 0 バイト 2 個のディレクトリ 2,310,393,856 バイトの空き領域
>gcc-ansi-pedanic あなたには空白が足らないわ。
787 :
783 :2008/03/17(月) 12:48:14
続き C:\cprog>which gcc /usr/bin/gcc C:\cprog>dir ドライブ C のボリューム ラベルは Windows XP です ボリューム シリアル番号は です C:\cprog のディレクトリ 2008/03/17 12:23 <DIR> . 2008/03/17 12:23 <DIR> .. 2008/03/17 12:16 0 p01-04-1.c 1 個のファイル 0 バイト 2 個のディレクトリ 2,309,021,696 バイトの空き領域 C:\cprog>gcc p01-04-1.c /usr/lib/gcc/i686-pc-cygwin/3.4.4/../../../libcygwin.a(libcmain.o):(.text+0xab) undefined reference to `_WinMain@16' collect2: ld returned 1 exit status C:\cprog>gcc-ansi-pedanic p01-04-1.c -o p01-01-1 'gcc-ansi-pedanic' は、内部コマンドまたは外部コマンド、 操作可能なプログラムまたはバッチ ファイルとして認識されていません。
788 :
783 :2008/03/17(月) 12:54:36
Microsoft Windows XP [Version 5.1.2600] (C) Copyright 1985-2001 Microsoft Corp. C:\Documents and Settings\NEC-PCuser>c: C:\Documents and Settings\NEC-PCuser>cd \cprog C:\cprog>notepad p01-04-1.c C:\cprog>gcc -ansi -pedanic p01-04-1.c -o p01-01-1 gcc: unrecognized option `-pedanic' /usr/lib/gcc/i686-pc-cygwin/3.4.4/../../../libcygwin.a(libcmain.o):(.text+0xab): undefined reference to `_WinMain@16' collect2: ld returned 1 exit status C:\cprog>
で、なんでcygwinの使い方も判らない香具師のスレ違いの質問に付き合っているんだ?
>>787 俺は cygwin じゃなくて mingw を使ってるんだが
wmain を使うと同じようなエラーが出る(まだ解決していない)
d:/usr/mingw/bin/../lib/gcc/mingw32/3.4.2/../../../libmingw32.a(main.o)(.text+0x
104): In function `main':
d:/src/mingw/build/runtime/../../runtime/main.c:73: undefined reference to `WinM
ain@16'
collect2: ld returned 1 exit status
** error 1 ** deleting a.exe
とりあえず wmain または _tmain を main にしてみてはどうだろう
791 :
783 :2008/03/17(月) 12:58:58
dir抜けてますけど788の入力で行き詰っています。
入門編てのはC言語に関してであって、 cygwinやコンパイラの使い方のわからん奴のスレじゃないぞ
>>787 >2008/03/17 12:16 0 p01-04-1.c
>1 個のファイル 0 バイト
0バイト?
書いたプログラムの中身は?
cygwinやコンパイラどころかメモ帳の使い方も分かってない板違いじゃないか なんで熱心に付き合ってるんだ?
保存してないというオチか…
よくあることだったのに、気づかなかったな
>>791 type p01-04-1.c
C言語を習得するために Visual Studio Professional Edition 買ったんですが最初は何をすればいいんでしょうか?
わかりやすそうな本を買うもしくは借りる。
>>796 ExpressEditionがあることを知り、無駄な買い物をした事に気付いて臍を噛む。
よくわからないままC++/CLIで.NETアプリを作ってしまってスレに再び質問に来る
800 :
デフォルトの名無しさん :2008/03/17(月) 17:10:39
800
801 :
デフォルトの名無しさん :2008/03/17(月) 20:07:01
変数の型を調べる関数ってないですか?
標準には無い
803 :
801 :2008/03/17(月) 20:25:14
ありがとうございます 他の方法考えてみます
用途による。 宣言に使うとかならtypeof(非標準) 同型か比べるとかならtypeid(標準)
806 :
デフォルトの名無しさん :2008/03/17(月) 21:50:24
Hello World!のC言語プログラムあってます? #include<stdio.h> main() { printf("hello\nword!\n"); }
>>806 合ってるかどうかは実行してみれば分かる
>>806 スペルミスがあるのとその main 関数の型は推奨できない
>>806 hello word! のプログラムとしてなら、及第点です。
それはさておき、こう書きましょう。
--
#include <stdio.h>
int main()
{
printf("Hello world!\n");
return 0;
}
>>808 K&Rもプログラミング言語C++も、Hello worldのmain()はその書き方。
>>811 「それ、どうでもいいっていうか、むしろいらんツッコミだね」って意味。
戻り値の型省略すると警告するコンパイラもあるから 省略しない方が鬱陶しくなくていい。
C99だとエラーになった気がするし、 うっかりC++としてコンパイルすると絶対にエラーだし、 俺もあったほうがいいと思っている。
逆だろ
逆?
K&Rにしたがっておけば間違いないよ。
>>817 10年前ならね。しかし、最早その台詞は旧仮名遣いに固執するかの如く無意味だ。
乱数の初期化にはどういう役割があるのですか?
自分の思ったとおりの乱数を発生させたり、 自分の思ったとおりの乱数を発生させないようにしたりする役割がある。 いつも同じ値で初期化すれば、 (randの実装が同じなら)その後のrandが返す値はいつも同じ経過を辿る。 同じ結果を再現させることが可能になる。 time(0)の値を使うなどして、いつも異なる値で初期化すれば、 その後のrandの経過は毎回異なるものになる。 同じ経過ではランダムっぽくなくてつまんないときに役に立つ。
821 :
デフォルトの名無しさん :2008/03/17(月) 23:56:45
>>819 発生させる乱数を初期化値によって変える。
初期化を明示的に行わなかった場合、 毎回同じ値で初期化される。 そうなると毎回同じ乱数列しか出てこない。 それが嫌な時に初期化を行う。
823 :
819 :2008/03/18(火) 00:07:11
ありがとうございました。よく分かりました。
824 :
806 :2008/03/18(火) 00:14:59
C:\cprog のディレクトリ 2008/03/18 00:10 <DIR> . 2008/03/18 00:10 <DIR> .. 2008/03/18 00:10 12,941 p01-01-1.exe 2008/03/17 21:59 63 p01-04-1.c 2008/03/17 22:22 8,873 p01-04-1.exe 3 個のファイル 21,877 バイト 2 個のディレクトリ 2,216,493,056 バイトの空き領域 C:\cprog>p01-04-1 hello word! コマンドプロントでこう表示されたんですけどこれでOKですか?
825 :
デフォルトの名無しさん :2008/03/18(火) 00:40:43
wordでええのやったら。
OKかどうかは他人が判断できることじゃないだろう・・・
827 :
デフォルトの名無しさん :2008/03/18(火) 05:35:11
符号なし掛け算のプログラムをしているのですが unsigned int x,y; unsigned long long z; z = x * y; で2^32-1までの値同士の計算が2^64-1まで扱えるはずの zに正確に収まるのを期待したのですが。 たとえばx=28938y=2930866のときz=3209021684というように 違う値が返ってきます。どうしてでしょうか?
828 :
デフォルトの名無しさん :2008/03/18(火) 05:38:53
出力は printf("x=%u y=%u z=%llu"x,y,z); としています。
829 :
デフォルトの名無しさん :2008/03/18(火) 06:31:45
C言語(C++も可)で、ファイルをソートする方法はありますか? メモリに載せてからソートするしかないですか? たとえばサイズが1Gだとメモリを節約したい所です
求めているのは外部ソートなんだろうけど、 そーゆーのはDBに放り込んで知らんぷりするのが正しい気もする
>>827 unsigned int * unsigned int -> unsigned int
つまりすでにunsigned intで表現できる範囲を超えて
オーバーフローした値をunsigned long longに代入しても
時すでに遅しということ。期待通りの動作を得たいのなら
z = (unsigned long long)x * y;
とする。
そのように突っ込まずに、そぉ〜っとしておいてやることさ、ふっ。
初心者にオススメの参考書ってありますか?
836 :
デフォルトの名無しさん :2008/03/18(火) 09:18:44
839 :
デフォルトの名無しさん :2008/03/18(火) 10:17:58
>>829 です
ソートは改行区切りの文字列をソートしたいです
vector<string>に読み込んでsortという手はファイルが大きいと難しいです
>>839 multiset といいたいが C言語だから文字列の先頭アドレスの配列を qsort
841 :
デフォルトの名無しさん :2008/03/18(火) 10:27:12
1ギガとか5ギガとか巨大ファイルでメモリは200mしか無い場合はどうすればいいですか? あと別質問ですが、DOS時代に作成されたソートのEXEとASMファイルをみつけました。 ASMはどのようにコンパイルできますか?
ASMはコンパイルするもんじゃないよ
843 :
デフォルトの名無しさん :2008/03/18(火) 10:33:07
844 :
デフォルトの名無しさん :2008/03/18(火) 10:36:41
出来たら、一度に巨大ファイルをソートしてくれるライブラリがあったら良いのですが・・ありませんか? あと、C、C++ → ASM → EXE と変換されるはずですよね? だからASMのコンパイラも内蔵されていますよね? visual studioだとなんという名前ですか? intel やBCCも教えてください
845 :
デフォルトの名無しさん :2008/03/18(火) 10:41:58
マージソートのコツ教えてください。 データ数Nだとすると、各小分割は√Nにしたら速いですか? 半分くらいが良いですか? マージの手数を増やすか、各ソートの行程を増やすかですが
846 :
デフォルトの名無しさん :2008/03/18(火) 11:03:42
自己解決しました ml.exeでした
移動平均をCで書いたんだけどあってる? static char digitalNum = 16; /* 移動平均回数 */ static unsigned long digitalBuf[16]; /* 移動平均用のバッファ */ long digitalFilter(unsigned long ad) { int i; static char ct = 0; static unsigned long tmp; tmp = 0; digitalBuf[ct++] = ad; if(ct >= digitalNum){ ct = 0; } for(i = 0; i < digitalNum; i++){ tmp += digitalBuf[i] / digitalNum; } return tmp; }
>>847 合ってる
一要素に対しての移動平均しか求められないくてよければこれでもおk
#define BUFSIZE 16
long simple_moving_average(long value)
{
static long buf[BUFSIZE], sum;
static int bufindex;
sum-=buf[bufindex];
sum+=(buf[bufindex]=value);
bufindex=(bufindex+1)%BUFSIZE;
return sum/BUFSIZE;
}
下記のような構造体を作って関数に構造体のアドレスを渡してやるほうが後々楽かも
struct hoge
{
long *buf;
int bufsize, bufindex;
long sum;
};
>>835 >>836 の言っていた 高橋麻奈の「やさしいC」をやり終えたら
アラン・R. フューアー (著)の「Cパズルブック」をやってみてください
20年くらい前に出版された方でも、最近出版された方でもいいんで・・・・・
メイクできないんですがこれはどこがおかしいでしょうか? #include <stdio.h> int main(void){ int a = 5; if(a<10){ printf("under"); } }
>>850 ソースコードが無い
コンパイラがない
path の設定をしていない
make がない
makefile がない
makefile の書式が間違っている
makefile 内のファイル名が間違っている
unicode で保存した
その他
>>850 >メイクできない
これ以上無いほど詳しく
853 :
デフォルトの名無しさん :2008/03/18(火) 22:19:31
勉強の前に、プログラミングを学ぶ上での姿勢を教えていただけますか?
855 :
デフォルトの名無しさん :2008/03/18(火) 22:21:05
猫背がいけなかったんですね
>>847 16個の合計がunsigned longの最大値を超えないなら、
割り算は合計を出してから最後に1回だけ行うべき。
処理速度と計算誤差の両面で損してるぞ。
>>851-852 ごめんなさい最初から書き直したら出来ました
何が問題だったかはわかりません
ありがとうございました
>>847 ・移動平均回数は未だいいとして、なんでバッファまで公開しているの?
・移動平均回数をcharに制限する理由は? 只の整数定数ならint(或いはunsigned int)にするべき。
・adはunsigned longなのに戻り値はlongなのは何故?
・既出だけど、割り算は最後に行なうべき。
・tmpを静的にする理由は? 特に理由がないなら静的にしない方がいい。
>>858 >>・既出だけど、割り算は最後に行なうべき。
これはオーバーフローがありえるのでこうしてます。
そのほかはまったくご指摘のとおりです。
860 :
デフォルトの名無しさん :2008/03/19(水) 12:42:44
double で足して最後に割る
グローバル変数で質問です グローバル変数は初期化をしないと0で初期化される この0って言うのは int i; char str1; char str2[10][10]; int *p; って言うグローバル変数を宣言した場合 i = 0; str1 = '\0'; str2 = 全部 '\0'; p = NULL; で初期化されるって言うことですか? それともintとかdoubleなどの数値を扱う型しか0で初期化されない?
>>861 >で初期化されるって言うことですか?
そーです
863 :
861 :2008/03/19(水) 14:56:34
>>862 ありがとうございます
スッキリしました
p = NULL; ってところは意外に重要で、 ヌルポインタのビット表現が 0 じゃない状況でも ちゃんと p はヌルポインタで初期化される。 浮動小数点数の 0 についても同様。 特殊な環境か状況じゃないとまず関係ない話かもしれないけどね。
int *p = 0; 全然問題無い。 まぁ言いたいことはそう話じゃないのは分かってるケド。
>>859 unsigned long longを使ってもdoubleを使ってでもまとめて割った方がいい。
極端な話、adが15ばかり16回連続して来たら15になるべき戻り値が0になってしまう。
>>864 int *p = 0;
と書けば、コンパイラは賢いから
「ヌルポインタのビット表現が 0 じゃない状況でもちゃんと p はヌルポインタで初期化される。」
C++ では私はよくみかけるのですが。
>>867 それで正しい
コンパイラが賢いというか、規定でもそうなってる
>>867 >>864 は、グローバル変数が0クリアされるってのが、ポインタの場合はどうなるかって説明だろ。
質問者はその違いをちゃんと理解してて
>>861-863 のやり取りですべてが終わってるように見えるんだけど。
つまり理解してない人が勝手に盛り上がってると。
質問です。 あるプログラムのヘッダーファイルを読んでいるのですが初めて見る書式なので、 その書式がどういう意味なのか理解できず、苦しんでいます。 ググってもそれらしいものが出てこなかったのでご教授頂ければ幸いです。 --- sample.h --- struct smaple { char hoge; int fuga; void *what; } #define sample_call(var1,var2,var3) \ struct sample sample1 = { \ var1, \ var2, \ (var3) \ } \ このようなマクロと構造体があったとして var3を()で括るとどのように扱われるのでしょうか。 よろしくお願いいたします。
この場合特に影響は無いと思うけど、 マクロの引数は基本的には とりあえず括弧で囲んでおいた方がいいとは思う。
874 :
872 :2008/03/20(木) 12:37:09
>>873 ありがとうございます。
影響がある場合もあるということですね。
ありがとうございました。
質問です。列挙定数を使用して文字に色をつけたいのです printf("\033[0m\033[01;31mHellow\033[0m\n"); これでHellowが赤くなる、という手本があったので仮に組んでみました。 #include <stdio.h> int main(void) { printf("\033[0m\033[01;31mHellow\033[0m\n"); return(0); } これをgcc cygdriverでコンパイルしたところ、 ●[0m●[01;31mHellow●[0m ●=エンターキーのような記号 と表示され、実際に色はつきませんでした。 ググってもみましたが、解説が見当たらなかったので書き込みました。 正しい記述を教えてください。
877 :
875 :2008/03/20(木) 14:55:45
>>876 ありがとうございます。
補足ですが
cygでコンパイルをし、Hellowの色を変更できるようにせよ、とのことでした。
ですからcygのコンパイル画面だったら色が変わるはず・・・なんです。
conio.hは?
875のエスケープシーケンスはDOS由来のもので、 Win32のコンソールアプリケーションの場合、 9xのDOS窓なら(Cygwinでも)使えるが、NTでは使えない。
880 :
875 :2008/03/20(木) 15:09:39
>>878 ありがとうございます。
これは、<stdio.h>を<conio.h>にしろ、ということでしょうか?
一応今試してみましたが、結果は変わりませんでしたorz
>>880 違うぞ、conio.hでぐぐってこい。色変えたりできる。環境依存だけど。
telnetサーバたてて、teratermとかputtyとかでXPに 入る手はあるけど。cmd.exeが超絶使いにくい。 poderosaには、cygwinコンソールを開くオプションが あったはずだから使ってみるのも手
本題とは全然関係ないけどHellowってHelloじゃないのか。
ハローw
885 :
デフォルトの名無しさん :2008/03/20(木) 18:12:29
ループ処理を、かなり長い時間(数十秒とか)待たせてから行いたいんですけど なんかいい関数ないですか? usleepで引数に10000000を与えるくらいしかないですか?
sleepを複数回呼び出せばいいんじゃまいか?
usleepでは困るという理由を挙げてくれないと代替案も出せない
>>887 いや、大きい数字を使うのが何となく気持ち悪いんで
もっと適した関数が用意されてたりするのかなぁと思いまして
>>886 sleep自身をループさせる、と?
というか数十秒ならsleep使えばいいんじゃナインか?
つか、環境依存だろ。
>>888 sleepの引数の単位はmsか?なら秒のラッパー関数でも作れば?
void mySleep( int second ) {
for( int i = 0; i < second; i++ ) {
sleep( 1000 );
}
}
>>889 んぁあっ
usleepしか知らなかったっ sleepだと1秒単位なのか
ありがとうございます
ついでに本命のほうを聞きたいのですが、
基本的には無限ループさせておいて、
任意のタイミングのキーボード入力でループを抜けさせるって出来ますか?
無限ループってなにか計算をさせるってことか? スレッド使えば?
環境によってはできる。 標準Cだけではできない。
スレッド……? ちょっと調べてみましたが難しそうだ…… ありがとうございました
ミリ秒単位はSleep()のほう、と言ってみるテスト。
891にだまされるとこだった。
900 :
デフォルトの名無しさん :2008/03/20(木) 20:14:24
C勉強中の僕に教えてください キャストを勉強しているのですが、パーセントを求めるプログラムを作ってます。 DWORD Ad、DWORD Size、double parcent です。 parcent = (double)((Ad / Size)*100); これだとAd、Sizeがどんな値だろうと、parcent に0.0しか表示されません。 この問題を解決するにはどうすればいいでしょうか? ご教示お願いします
それだとまず (Ad / Size)*100 がDWORD型で計算されて、最後にdouble型にキャストされる。 Ad / Size は端数切捨てで0だろうから、結果は0.0。 parcent = ((double)Ad / Size)*100); これでおk。
percent = (double)Ad / Size * 100; とか percent = Ad * 100.0 / Size; とか色々。 Ad / Size が整数同士の割り算になってるのがいけない。
>>901-902 素早いお返事ありがとうございます。
括弧をつける位置で結果が大きく変わるんですね。。
動作まで詳しく教えてくださり、本当にありがとうございました。勉強になりました。
×parcent ○percent
>>904 おっと・・ご指摘ありがとうございます
これは恥ずかしいです。直しておきます。^^;
906 :
デフォルトの名無しさん :2008/03/21(金) 22:27:37
構造体で使う ->と.の違いはなんですか?
>>906 struct table1 {
int a;
int b;
};
struct table1 *pl
strucy table1 tab
/* tabのaを参照する */
tab.a;
/* p1にtabのアドレスを代入して、tabのaを参照する */
p1 = &tab;
tab->a;
908 :
907 :2008/03/21(金) 22:34:44
まちがえた! struct table1 { int a; int b; }; struct table1 *p; struct table1 tab; /* tabのaを参照する */ tab.a; /* pにtabのアドレスを代入して、tabのaを参照する */ p = &tab; p->a;
A->B = (*A).B
struct ABCD { int def; } struct ABCD abc; struct ABCD* p_abc = &abc; abc.def と p_abc->def と (*p_abc).defは同じ
なんか入門書でも買った方がはやくね?
912 :
デフォルトの名無しさん :2008/03/21(金) 23:05:10
なるほど、ありがとうございます。 続けて質問したいのですが、 struct mem{ char data[64]; } dataの中に"abcdef"という文字列を入れる場合 .か->、どちらを使ったほうがいいですか?
同じって上でいってるじゃん・・・ struct mem foo; struct mem * bar = foo; strcpy( foo.data, "abcdef" ); strcpy( bar->data, "abcdef" );
>>912 説明がまったくわからなかっということですかw
915 :
デフォルトの名無しさん :2008/03/21(金) 23:12:30
for文を使って一文字ずつ追加していく場合です。
そのものずばりのソースが書き込まれるまで頑張るつもりなんじゃね? だれか書いてあげてよ。
だからどっちでもいいと何度いったら・・・ struct mem foo; struct mem * bar = foo; const char hoge[] = "abcdef"; int i; for( i = 0; i < strlen( hoge ); i++ ) { foo.data[ i ] = hoge[ i ]; //上と同じ、同じって言ってるんだから同じ! // bar->data[ i ] = hoge[ i ]; } // ケツに\0ちゃんと入れるように
919 :
デフォルトの名無しさん :2008/03/21(金) 23:33:55
代入の際、->と. どちらの方が見やすいですか?
www
bar->data[i] と (*bar).data[i] 、どっちが見やすいか、という質問か せっかくだから俺は右を選ぶぜ!
俺も右の方が見やすいとおもうから->のことは忘れた方がいいよ
->なんて使わなくてもいいよ!
キャストと見間違えそうだなw
五重ポインタから参照するとき、 (****pp)->data[i] と (*****pp).data[i] では後者がわかりやすいよな!
(*****ppppp).data[i]だろ
928 :
デフォルトの名無しさん :2008/03/22(土) 00:26:24
これコンパイルすると終了しちゃうのはなぜでしょうか? #include <stdio.h> int main(void) { int pr, sum; sum = pr = 0 ; printf("買いたい商品の値段を入力してきださい\n"); scanf_s("%d",pr); while ( pr != 0) sum = sum + pr ; printf("小計;",sum); printf("税込み:%d", (int)(1.05*sum)); printf("次の商品の値段を入力してください\n"); scanf_s("%d", pr); return 0; }
>>928 while ( pr != 0)
sum = sum + pr ;
×scanf_s("%d",pr); ○scanf_s("%d", &pr);
931 :
930 :2008/03/22(土) 00:38:09
ごめん・・
printf("買いたい商品の値段を入力してきださい\n"); printf("小計;",sum);
どうせなら配列の参照も a[i]→*(a+i)変換を…
wikiからコピってきた再帰なんですが int fact(int n) { if (n==0) return 1; /* 脱出条件。0!は1である */ else return fact(n-1)*n; /* n!は(n-1)!にnを乗じたもの。再帰呼び出し */ } elseのとき、なんで return fact(--n)*n; じゃダメなの?
fact(--n)*(n+1)ならいけそうな気がするけどどういう順序で計算するのかわかんね
>>934 その記法は未定義動作だからやっちゃだめなの
>>934 定義されていないからかな
a=3;
printf("%d %d\n", --a, a);
未定義!
そもそもnの値を変更することに意味ないだろ
ちょっと気になっただけなんだけど、 >fact(--n)*n >printf("%d %d\n", --a, a); 不定じゃないっけ? なんで未定義なのか教えて貰えると助かる。 未定義なら俺の理解が間違えてるので。
>>941 規格で決まってないから未定義、それ以外に理由は無い
決まって無いから動作は不定
不定という言葉が悪かったかな。 941で書いた式は未規定だと思うんだけどどう?
副作用の完了前に参照することが未定義じゃなかったか?
あー、なるほど。 追って調べてみたらその通りだった。 ありがとう。
947 :
デフォルトの名無しさん :2008/03/22(土) 13:44:43
func(long *l){ *l = 10; } short s; func((long *)&s); エンディアン等の環境によらず、Cの規格でsは10になることは保証されますか? 最適化は行われない前提で。 よろしくお願いします。
>947 なるわけがないというか、C の規格では未定義動作で何が起こっても OK。つまりやっちゃいけないコードだ。 が、仮に short と long が反対だったとして、その結果が変わってしまうことがエンディアンの違いってやつなのだが。
short*からlong*へのキャストは定義されていないからUB
950 :
947 :2008/03/22(土) 14:14:21
すみません。間違いです。 longとshort逆でした。 この場合、リトルエンディアンな環境だと10になることが保証されている、 でよろしいでしょうか?
>>950 メモリアドレスのアライメントの関係で、環境によってはアクセス違反が発生する。
よって規格の保証はないな。
> 最適化は行われない前提で。
そもそもこう書いているのは、実装依存上等ってことだろw
952 :
950 :2008/03/22(土) 14:33:59
あー、longとshortが逆ってことは、アライメントの件はクリアか。 前半は無視してね。 あとは、longの上位ワードも初期化してやればいけそうだが、規格上はどうだろ?
>>952 Cの規格では、あるポインタを他のポインタ型にキャストした場合の動作は定義されていない。
long*は汎用ポインタにしかキャストできない。
mallocを否定するとは。とか言ってみる。
汎用ポインタは除いてね。
別ポインタへのキャストは未定義じゃなくて処理系定義なんじゃないの?
#include<stdio.h> int main(void) { int a=5; printf("%d\n",-a); return 0; } で-5が出力されるわけですがprintf("%d\n",-a);のaの前の-はaに-1をかけてるってことでいいんですよね?
「a の符号を反転した値を取得する」 ということしか言っていない。 それを実際にかけ算で行っているか別の方法で行っているかは環境次第。
Intel 系なら NEG って命令があってそれで符号反転できる。
>>954 いや、定義されてるだろ。
オブジェクト型のポインタから他のオブジェクト型へのポインタへのキャストは出来る。
ただし正しく境界調整されていない場合の動作は未定義。
963 :
デフォルトの名無しさん :2008/03/22(土) 22:32:58
#include <stdio.h> #include <stdlib.h> int main(void) { FILE *fp1, *fp2; double d; int i; if((fp1 = fopen("values", "wb"))==NULL) { printf("ファイルを開くことができません\n"); exit(1); } if((fp2 = fopen("count", "wb"))==NULL) { printf("ファイルを開くことができません\n"); exit(1); } d = 1.0; for(i=0; d!=0.0 && i<32766; i++) { printf("数字を入力してください(終了するには0を入力してください): "); scanf("%lf", &d); fwrite(&d, sizeof d, 1, fp1); } fwrite(&i, sizeof i, 1, fp2); fclose(fp1); fclose(fp2); return 0; } 数字を入力するたびにファイルに書き込むプログラムを作成ということなんですが、何故上書きされないのでしょうか?。入力した数字すべてがファイルに書き込まれる仕組みがわかりません。
質問の意味が分からない
fwrite()はそういう仕様です。
ファイルポインタでググれ。
967 :
デフォルトの名無しさん :2008/03/22(土) 22:47:19
>>964 初めに1.0と入力したとして次に2.0と入力したら前の1.0の値の上から書き込まないということなんでしょうか?。
質問の意味がわからなかったらすいません。
どう書いたらいいのだろう…。
>>967 ファイルポインタは書き込みをした分だけ自動的に先に進む
同じ場所に書き込みをするにはファイルポインタを移動する
ex.
fseek(fp, -4L, SEEK_CUR);
970 :
デフォルトの名無しさん :2008/03/22(土) 22:52:13
>>965 ありがとうございます。
fwrite()を理解できて無いようです。
>>963 ポインタ難しい><。ポインタが理解できて無いようです。
>>967 fseek()で、ファイルポインタを先頭にもどす。
ファイルポインタとポインタは別物だぞ。
973 :
デフォルトの名無しさん :2008/03/22(土) 23:00:16
たくさんの回答ありがとうございます。
>>968 更新モード知らないかもです。
>>969 そうなんですか。ファイルポインタを理解しないといけないみたいですね。
>>971 fseek()なんてあるんですか〜。
>>972 違うのですか〜。勉強になります
975 :
デフォルトの名無しさん :2008/03/22(土) 23:41:58
一つ質問させてください 多次元配列についてなんですが 要素ごとに違う数の要素を持たせることって可能ですか? たとえば、 A[0]には A[0][0], A[0][1] があって A[1]には A[1][0], A[1][1], A[1][2] があるみたいなです 分かりにくくてスマソ
色々方法はあると思うが、動的に確保するのが一番分かりやすい実装法。 もちろん、1つの配列をそういう区間に切り分けて扱うこともできるけどね。
978 :
デフォルトの名無しさん :
2008/03/22(土) 23:49:00