1 :
ぬるぽ > v(^o^i)d :
03/08/25 11:52
2 :
デフォルトの名無しさん :03/08/25 11:54
∧_ 人 (;´Д(__) ( つ (__) ) 「( ・∀・) おじさん今日は5回もウンコしたんだよ |/~~~~~~ヽ
4 :
デフォルトの名無しさん :03/08/25 11:55
5 :
デフォルトの名無しさん :03/08/25 11:56
6 :
デフォルトの名無しさん :03/08/25 11:57
>>1 乙。それと、
( ・∀・) | | ガッ
と ) | |
Y /ノ 人
/ ) < >__Λ∩
_/し' //. V`Д´)/ ←
>>1 (_フ彡 /
今回のコミケと同じ番号に到達。
ども、前スレの927でつ。 また質問なんですが、マクロ展開される文字列にプリプロセッサ命令は 入れられないのでしょうか? たとえば #define def(name,age) #define name age みたいな。 あと、 #define FIRST Tanaka #define LAST(name) FIRSTNAME##name で LAST(Taro) を TanakaTaro にするようなことはできないのでしょうか? # 厨な質問ばかりスミマセン
>マクロ展開される文字列にプリプロセッサ命令は入れられないのでしょうか? 基本的にできない。 C99 なら #pragma については _Pragma 演算子で何とかなるけど。 >LAST(Taro) を TanakaTaro にするようなことはできないのでしょうか? 間を挟めばいい。 #define FIRST Tanaka #define LAST(name) LAST1_(FIRST, name) #define LAST1_(first, name) LAST2_(first, name) #define LAST2_(first, name) first##name LAST(Taro) → LAST1_(FIRST, Taro) → LAST2_(FIRST, Taro) → LAST2_(Tanaka, Taro) → TanakaTaro
>>12 > 基本的にできない。
そうですか...別の方法を考える事にします。
> 間を挟めばいい。
おぉ! なんていうか、アクロバティックですね。
C言語は奥が深い...
ありがとうございました。
奥が深いっちゅーかマクロが糞なだけ。
組み込み系のPGは他のPGよりレベル高いってホント?
スレ違いだぉ
一番レベル高いのはゲームPGに決まっとろうが
ということにしたいのですね。
19 :
デフォルトの名無しさん :03/08/26 05:43
void FloodFill ( int x, int y, int fill, int old, int* w, int* h, int* cnv ) { if (old == fill) return; if ((x < 0) || (x >= *w)) return; if ((y < 0) || (y >= *h)) return; if (cnv[ PIXEL(x, y, *w) ] == old) { cnv[ PIXEL(x, y, *w) ] = fill; FloodFill(x+1, y, fill, old, w, h, cnv); FloodFill(x, y+1, fill, old, w, h, cnv); FloodFill(x-1, y, fill, old, w, h, cnv); FloodFill(x, y-1, fill, old, w, h, cnv); } } これがスタックオーバフローになってしまいます。スタック領域は1000000くらい 割り当ててるんですが、10000回くらい呼ばれるとだめみたいです。 w2kのVC7です。どうすればオーバーフローさせずに済みますか?
22 :
デフォルトの名無しさん :03/08/26 07:05
>>19 いくらなんでも、一ピクセル単位で塗りつぶしというのはあんまりな気がする。
でも、昔のパソコン雑誌だとペイントアルゴリズムは毎年どこかに載っていたけど、
今はもう見かけないなぁ・・・
>>19 今すぐ上手い方法を思い出すことはできないけど、せめて、「どちら側から
塗りつぶしに着たか」だけでも、引数に持たせておいたほうがいいんじゃないかな。
この関数だと、呼ばれるたびに自分の位置の上下左右を呼びに行くけど、呼び出し元
は既に塗りつぶされているんだから、呼び返す必要はない。
今の状況だと、同じ座標の点を何度も何度も見に行くことになって、実際に塗りつぶす
画素数よりずっと多い回数の再帰呼び出しが発生していると思う。
>>19 それだと一つの再帰の枝が延々と触手を伸ばしてしまう。ような気がする
google("スキャンラインシードフィルアルゴリズム");
26 :
デフォルトの名無しさん :03/08/26 12:10
qsortって関数でソートしたいんですが、引数の関数ポインタっていう のがよくわからないんですけど、どうすれば使い方えますか?
日本語も分かってない。
29 :
デフォルトの名無しさん :03/08/26 14:03
irc.2.10.3+jp6をRedhat9+gccでmakeしたんですが、 clsend.o(.text+0x16b): In function `send_queued': ../common/send.c:352: `sys_errlist' is deprecated; use `strerror' or `strerror_r' instead とでます。 FreeBSDやTurboLinuxでは正常だったんですが、なにがいけないんでしょうか? このエラーの前に、 ../ircd/s_bsd.c: In function `read_message': ../ircd/s_bsd.c:2032: `POLLWRNORM' undeclared (first use in this function) ../ircd/s_bsd.c:2032: (Each undeclared identifier is reported only once ../ircd/s_bsd.c:2032: for each function it appears in.) make: *** [s_bsd.o] Error 1 とでたので、 ../common/os.hに # define POLLWRNORM 0x0100 を追加しますた。 わかる方おながいします。
旦那の出張中に渡すバイブみたいなもんだ=関数ポインタ
つい二週間前から独学でC言語を勉強してるのですが、大文字、小文字に関わらず入力された 文字を小文字に変換して表示するにはどうしたらいいのでしょうか?
32 :
デフォルトの名無しさん :03/08/26 15:20
考えな。
sobokunagimon gcc入ってなかったらどうやってmakeすんでつかぁ?
gccがなければccを使えばいい
>>35 cc入ってなかったらどうやってmakeすんでつかぁ?
>>36 ccのソースを手作業でどうつるんでつかぁ?
おながいしますおしえてくだしゃい
ccがなければCCを使えばいい
ありがとうございます。 結構簡単だったのでかなりショック受けました。
42 :
デフォルトの名無しさん :03/08/26 15:32
for( ; ; ) for( ; ; ) if(1) break; breakのところは、これだと最初のforしかぬけてくんないですが 全部抜けるって事できないんですか?
>>42 for(;;)for(;;)if(1)goto HOGE;
HOGE:
>>38 まず、ズボンとパンツを足首辺りまで降ろして、ティムティムの先っぽをやさしく
撫でてみる。それでティムティムが大きくなったら異常はない。ズボンとパンツを
元に戻してmakeに取り掛かれ。おっと、くれぐれも手の匂いを確認するなよ。
> (^^) スレ違い、開発環境のスレへ逝くか ビルの屋上から一歩踏み出せ
>>44 ティムティムがない場合はどうすればいいんつかぁ?
>>41 makeすればプログラムができるでつよぉ
>>46 ティムティムをクリクリに読み替えるだけでいい。
センセーワカッタァ〜 make ティムティム make クリクリ これだぁこれで動くんだぁ
>>48 うん、そうだよ。さて、今日はこれまで。さぁさぁ帰った帰った。
50 :
デフォルトの名無しさん :03/08/26 15:51
51 :
デフォルトの名無しさん :03/08/26 19:50
配列 a[100] に1から100までの数字をランダムに、 且つ、重なりなく入れる方法を教えて下さい。 以下のように、乱数を生成して、それが重なっていないかどうか 確認する方法では、非常に時間がかかって効率的でないです。 もし効率的な方法があれば教えて下さい。 flag=1; for(i=0;i<100;i++) { while(flag) { r=int(rand()/RAND_MAX*100.0); flag=0; for(j=0;j<i;j++) { if(r==a[j]) { flag=1; } } } a[i]=r; }
100個から1つ選び、残りの99個から1つ選び、残りの98個から(以下略
>>51 一部C++の文法を使っている。
g++でコンパイルして動かしたら、配列aには全部0が入った。
for(i=0; i<100; i++) a[i] = i+1; for(i=0; i<100; i++) swap(&a[i], &a[int(rand()/RAND_MAX*100.0)]); /* swap()は、よしなに。*/
55 :
デフォルトの名無しさん :03/08/26 22:27
rand()/RAND_MAX*100.0 は rand() が RAND_MAX 以外のときは 0 な気が...。 (int)(rand()/(RAND_MAX+1.0)*100) か rand()*100/(RAND_MAX+1) かじゃなきゃ。 後者は RAND_MAX*100 がオーバーフローしないことが条件になるけど。
>>54 ,56
まず整数で rand() / RAND_MAX を実行してから、ほとんどいつでも
ゼロですね。
割り算より掛け算のほうが一般に高速ですが、この程度のプログラムなら、
素朴に rand() % 100 のほうがいいかも。
>>58 実は、出来すぎた話なんですが、私も、昨晩、まさに rand()/RAND_MAX と
書いてしまって、30分くらいバグに悩むはめになっていたんです。
何度も同じミスをやっているような気がする。
% 範囲 を使う方法 利点: RAND_MAX * 範囲 がオーバーフローする状況でも(一応)そのまま使える。 欠点: rand がボロい(シフトしてない)と、周期が著しく減る。 0 〜 RAND_MAX % 範囲 という偏った範囲の値の出現確率が、それ以外よりも微妙に大きくなる。 * 範囲 / (RAND_MAX + 1) を使う方法 利点: 上記の欠点にあるような出現確率のばらつきの偏りがない。 rand がボロくても、周期が著しく減ることはない。 欠点: RAND_MAX の値が大きいとオーバーフローを起こす危険性があるため、 一般にはそれを回避するため大きな範囲の型にキャストして使う必要がある。 計算量が微妙に多い。 うっかり RAND_MAX で割ると、rand が RAND_MAX の時のみ範囲を超えた値が出るというバグになる (このせいと思われるバグはたまに見かける)。
うっかり先に割ってしまうと常に 0 になるというバグで悩むことになる、を追加した方が良さげ?
>>60 仰るとおり、
たとえば、乱数発生器が混合合同法を使っている場合(たいていそうだと思う)、
剰余を求めるために割る数が2のべき乗だと、周期は、その「割る数」そのものに
なりますね。
2のべき乗でなくても、公約数しだいではかなり短くなります。一般的な傾向として、
乱数発生器の上位ビットに比べて下位ビットのほうは周期が短い場合が多いので、
下位ビットだけを取り出すと言うのは、ホントウは、あんまりよくないです。素数で
割った余りの場合は別ですが。
43億超の数値ってdouble使うのは解りましたが、プリント命令すると 変になります。どうやるのか教えて下さい。 #incude <stdio.h> main { doube dbl = 10000000000; printf("dbl=%lf\n",dbl); }
>>64 main → int main(void)
%lf → %f
で、最後に return 0;
小数点以下を表示したくなければ %.0f 。
確かに double だと43億超の値を扱えるけど、
15〜16桁くらいの精度しかないから注意。
long long
>65 レスサンクスです。 main → int main(void) って内部的な動きは何が違うのですか。 %fはfloat型ではないのですか?ちなみに%fでも変な数字が表示されました。 あと、returnはなぜ必要なのですか?
僕は島で唯一のC使いになります!(^^;
そうか
>>67 >main → int main(void) って内部的な動きは何が違うのですか。
main だけじゃそもそもコンパイル通らんだろ?
>%f は float 型ではないのですか? ちなみに %f でも変な数字が表示されました。
scanf だと float は %f で double は %lf だけど、
printf だと float 渡そうとしても double に変換されちゃうから
どちらを渡そうが %f を使うことになっている。
>あと、returnはなぜ必要なのですか?
戻り値の型が int だから。
沖縄・・・もう飽きたー グアム・・・なにもないじゃん! ハワイ・・・高いしー そ ん な 今 、 小 笠 原 が 熱 い !
>>70 度々レスサンクスです。 明日、学校でためしにやってみます。 もしかしたらまた明日聞いちゃうかも(^^; >71は私ではありません。変なのが一人混じってますね(w
>>71 個人的に非常にタイムリーなレスだ。熱いという根拠を小一時間聞かせて欲しい所だが。。。
なぜって、、、夏だからだろ。
75 :
デフォルトの名無しさん :03/08/27 12:46
あぐぇ
すみません 初歩的なことなんですが。。 double → int への型変換を行なう際には ライブラリって必要なんでしょうか? void main(void) { double d = 1.5; int i = 0; i = (int)d; } これだけのプログラムなんですが,DOS から cl を叩くと /out:b.exe b.obj b.obj : error LNK2019: 未解決の外部シンボル __ftol2 が関数 _main で参照されまし た。 b.exe : fatal error LNK1120: 外部参照 1 が未解決です。 上記のようにリンクエラーになってしまいます。 書籍やサイトを見る限りではライブラリが必要とかは 何も書かれていなかったもので。。どなたか教えていただけますか? 環境は WinXP Home edition Visual C++ 6.0 です。
環境依存の質問は該当スレへ。
そういや昔はコプロがかなり高価なオプションだったからな なつかしい
>>76 もしかしてコマンドラインからCL叩いてるのか?
81 :
デフォルトの名無しさん :03/08/27 22:03
教えてください。 1行入力の関数を使って、スペースまたはコロンで区切った数字を入力し、 それぞれの数字をint型の配列に入れるよい方法はあるでしょうか? たとえばこんな感じです。 2 8 37 ↓ a[0]=2,a[1]=8,a[2]=37 1行入力の場合、char型の配列を使うので 別に用意したint型の配列に1文字ずつ入れなおし、 数字が連続している場合はつなげて、a[ ]に入れていく方法を考えましたが・・・ もっといい方法があるでしょうか?
scanf("%d,%d,%d",&a[0],&a[1],&a[2]); scanf(",%d",&a[3]); scanf(",%d",&a[4]); if(scanf(",%d",&a[5]) != 1) goto hell;
hell: while(1)malloc(1);
strtokを使う処理を関数化しろよ、必ず 少なくともscanfよりマシな関数にできるよな?
86 :
デフォルトの名無しさん :03/08/27 22:59
質問させて頂きます。 現在ローカルWebサーバでCGIの実験を行っているのですが CでコンパイルしたEXEファイルをCGIとして動かす場合、 クライアントから送られてきたFormデータを受け取るには 1.どのような手法をとらなければならないのでしょうか? 2.その場合、どういうコードを書かなければならないのでしょうか? どなたか教えて下さい
板違い、か?
少なくともスレ違い。
GETなら環境変数から取得、
POSTなら環境変数からデータサイズを取得し標準入力から読む。
その後、名前と値に分割しURLデコード。
WebProg
http://pc2.2ch.net/php/
>>81 fgets()してからsscanf()。
strtok()を持ち出すような問題じゃない。
行末コードの始末が思いの他面倒な罠。<fscanf()
>>82 >>83 どうもです。
数字の数は任意なので、これは使えないと思います。
せっかく教えてくださったのにすみません。
>>84 >>85 C始めて一ヶ月ですが、strtok関数は使ったことないです。
存在も知りませんでした。
後で試してみます。
>>89 >>90 >>91 >>92 皆さん、ありがとうございます。
初心者なので関数の違いがまだよく分かりません。
勉強してみます。
ども、
>>11 でつ。
またマクロまわりの質問なのですが、
マクロ関数の引数を可変個にする事はできないのでしょうか?
#define hoge(arg1, arg2) printf(arg1, arg2) で
hoge("a=%d b=%d", a, b); と呼び出したとき、arg2に「a,b」と入れられるように。
あ、「入れられるように」っていうのは「入れられるようにできないでしょうか?」なので。 ちと誤解を招く書き方でつな。
>>94 無理。
#define hoge(arg1, arg2) printf(arg1, arg2)
hoge("a=%d b=%d", (a, b));
というトリックはあるけどな。
C99なら
#define hoge(arg1, ...) printf(arg, __VA_ARGS__)
とすればいい
>>96 >>97 あ、C99って仕様の名前だったんですね。てっきりコンパイラの名前かと...
>>98 調べたつもりでしたがまだまだ調べた事になってなかったようですね...
ディスプレイに穴が開くまで読ませていただきます。
ありがとうございました。
101 :
デフォルトの名無しさん :03/08/28 16:22
C言語のプログラム中のコメントは 日本語で書くべきですか、それとも英語で書くべきですか?
102 :
デフォルトの名無しさん :03/08/28 16:23
>>97 それじゃ
printf("a=%d b=%d", (a, b));
と展開されるから使えん。
105 :
デフォルトの名無しさん :03/08/28 16:27
>>101 eigojanakute ro-majide kakunoga saikyo
>>101 英語しか使えないエディタ/コンパイラを使う予定が無く、
日本人だけが読む予定なら、日本語で良い。
char *ipbuf に dns1.hoge.com [192.168.1.1] という文字列が入ってるんですが、これを *dns = dns1.hoge.com *ip = 192.168.1.1 というふうに分けたいんですが、どうすればいいでしょうか?
110 :
デフォルトの名無しさん :03/08/28 16:44
for(i=0;i<13;i++) { dns[i]=ipbuf[i]; } for(i=15;i<26;i++) { ip[i]=ipbuf[i]; } これでダメならもっと情報を出せ。
>>108 適当でいいんなら " []" をデリミタにして strtok 。
>>112 while文で一文字ずつ調べてたルーチンがおかげさまでたった2行で済みました。
ありがとうございます
ip = strtok(ipbuf," ]");
dns = strtok(ipbuf,"[]");
普通こうする。 const char* sep = " []"; dns = strtok(ipbuf, sep); ip = strtok(NULL, sep);
sprintf(ipbuf, "%s%[0-9.]", dns, ip);
machigaeta. sprintf(ipbuf, "%s[%[0-9.]", dns, ip); datta.
trf.v6.sfc.wide.ad.jp [3ffe:501:100c:5310:2a0:24ff:fe48]
>>108 です。
>>111-116 さんどうもです。
114さんの方法でばっちり動きました。
これで、あやしげなwu-ftpdが完成しそうです(^^;;
いまファイル操作のソフト作ってます、 そこで今やりたいのは指定したフォルダのファイルを全て列挙する事です コマンドのDIRとかじゃなくて関数でやりたいのです。 そんな関数だれかご存じないですか?
>>119 > GUIなどの標準Cではできない事の質問は使用している開発環境のスレへGo! (←ここ注目)
標準Cではできないのでしょうか・・・? いったいどこまでが標準なんでしょうか?
ディレクトリ操作は標準 C ではできん。
123 :
デフォルトの名無しさん :03/08/28 21:32
すいません、分からないことがあります。 char型の値をPackedDecimalに圧縮して格納する方法がわかりません。 たとえばHEXで FF 12 となってるcharの2バイトを 1 2 と1バイトのところにいれるにはどうすればいいのででょう?? どなたかお願いします。
>>123 分けりゃいいだけだろ。
あと、unsigned char にしとけ。
>>124 あ、そうですね。unsigned char にします。ありがとうございます。
分けりゃいい、の意味はさっぱりわかりませんが・・・(涙)。
charの2バイトをそれぞれ分ければいいんだろ? 自分で言ってることの意味もわからない? 1バイトのデータを16進二桁で表したいというなら話は別だが。
>>124 アンタ凄いね。
漏れは、
>>123 が何を言ってるか理解出来ないよ。
>1バイトのところ
って何処の1バイトなんだろ?
とりあえず123は"HEX"が何の略なのか調べてみると良いと思う
0xFF(ごみデータ?) 0x12 を 0x01, 0x02 にするってことじゃなくって?
それはpackedではない
もしかして、0xF1 0xF2 となってるのを 0x12 にするのか?
パックトデシマル知らないのか? 0xFF 0x12 を 0x31 0x32 (ASCII) または 0xF1 0xF2 (EBCDIC)にするんだろ。 で、 0xFD 0x12 なら 0x2d 0x31 0x32 になる。
ぜんぜん違った。 鬱だしのう。
134 :
デフォルトの名無しさん :03/08/29 00:19
質問なんですが #include<stdio.h> main() { float a[2][2]={0,0,0,0}; float *b; b=a; } これをコンパイルしようすると、 型が違うということで弾かれます。 a[4]として一次元の配列だと問題ないのですが これは一体なぜなんでしょう? またどうすれば2次元の配列でポインタのやりとりができるでしょうか?
float (*b)[2] = a;
Cには 多次元の配列というものは無いのよ。 そいうふうに記述できるだけ。
>>136 >Cには 多次元の配列というものは無いのよ。
あるって。
あるからこそ問題になるんだろ。
あるのは配列の配列 初心者はポインタの配列を似たような物と勘違いすることもある
136,138,139におかしなことをいっている奴がいるな。 >When several "array of" specifications are adjacent, >a multidimensional array is declared.
141 :
デフォルトの名無しさん :03/08/29 01:00
float a[2][2]={ { 0.0 , 0.0 } , { 0.0 , 0.0 } } ; でどう?だめ?
142 :
デフォルトの名無しさん :03/08/29 01:03
はっはっは。 まったく変なことをかいてしまった。 まじでしのう…
143 :
デフォルトの名無しさん :03/08/29 01:04
多次元配列か… int array[2][2]= { {0,0}, {0,0} }; *( *( array + 0 ) ) = 1; *( *( array + 0 ) + 1 ) = 2; *( *( array + 1 ) ) = 3; *( *( array + 1 ) + 1 ) = 4; 今時は配列の添字を使わないと、ポインタの配列を扱えないのか ポインタが分っていれば多次元配列は存在しないって言葉の意味も分るだろうに…
>>140 配列の配列をCでは多次元配列とよぶ
(そういう風に言語仕様書に書いてあるんだからしかたがない)
それに対しADAやC♯では配列の配列と多次元配列は別物である。
実用上ははっきりいってどっちでも大差ない。
>>145 >When several "array of" specifications are adjacent,
>a multidimensional array is declared.
「多次元配列は存在しない」とうるさい人は どんなのが多次元配列だと思ってるんだろうね。 メモリ自体が多次元インデックスでアクセスできないと、とか?
「多次元配列は存在しない」わけじゃないよね。 配列が(Pascal、Java、Fortranなど他の言語と違って) 一人前のオブジェクトじゃないだけだ。配列型変数だけは 値渡しも代入もできない。配列を使った式は、すべてポインタを 使ったアクセス法の略記とみなされてしまう。
>一人前のオブジェクトじゃないだけだ。 >配列を使った式は、すべてポインタを >使ったアクセス法の略記とみなされてしまう。 データ型と演算子(アクセス方法)を混同している。
int a[2][4]; int *b[2]; の時、a や b はどのポインタ型の変数に代入でき、 a + 1 や b + 1 の + 1 がアドレスをどれだけ進めるかをちゃんと分かっていれば、 a が多次元配列だという表現が別に変じゃないことが分かるだろうに。
152 :
デフォルトの名無しさん :03/08/29 16:41
>データ型と演算子(アクセス方法)を混同している
別にしてないと思うが…
というか、Cの配列はそもそも(他の言語と違って)
単なるアクセス方法の略記法にすぎないんだが。
>>151 にもそれが良く現れている。
ポインタじゃない「配列オブジェクト」を
表す式を挙げてみろよ。
>>152 配列型(の要素)はポインタ経由でしかアクセスできないが
p++などを行うにはポイント先は配列型(の要素)で
なければならない。
>配列はそもそも単なるアクセス方法の略記法
つまりこれがまさにデータ型と演算子の混同
アクセスには配列演算子[]を使いこれはもちろん
(対象が配列であっても)ポインタの演算だが
これによりアクセスしている先が配列型(の要素)に他ならない
(ただし添え字が0のみの時は配列でない事もある)
>(そういう風に言語仕様書に書いてあるんだからしかたがない)
>>151 で、
a + 1 は sizeof (int) * 4 だけ進んで、
b + 1 は sizeof (int*) だけ進む。
この違いがどれだけ大きなものか分かってないと
(多次元配列を使うのは)難しい。
この「4」という数字がどこから出てきたかを
よく考えることが大切だな。
てか、アセンブリ言語に毒されていない奴なら 「〜だけ進む」とか言われなくても分かる訳だが。
>>134 typedef float F[2][2];
int main()
{
float a[2][2]={1,2,3,4};
F *b;
b = &a;
printf("%f %f\n", (*b)[1][0], (*b)[1][1]);
>154 えーと、 要素数が4つのint型の配列が2つあって、 a++とした場合、次の配列へ移動することになるからかな? 後者はポインタの配列だから、 b++とすると... 違いがよくわからないや(泣
158 :
デフォルトの名無しさん :03/08/29 21:02
#include <stdio.h> int main(void) { char c; while( (c=getchar())!=EOF ) putchar(c); return 0; } とありますが、これは getchar();がよばれたとき、Dosで入力待ち状態になり、エンターキー(\0なのかな?) が押されるまでの文字を順次実行していく。と言った解釈でいいのですか? abcdefg と入力した場合、まずaをgetchar()で変数Cに入れ、その後putchar()で出力 んで次のループでbを取り、putで出力。でEOFにたどり着くとでる。 間違ってますかな?
>>158 下三行はあっている。putがputcharのことならば。
>>157 a と b は配列名だから + 1 はできても ++ はできないじょ
>>156 そんなくだらんことにtypedef使うこと自体そもそも話にならんが
どうせ使うならこうだ
typedef float F[2][2];
int main(void) /* 戻り型に固執しながら引数間違ってちゃ世話ねえな */
{
F a;
F *b;
b = &a;
printf("%f %f\n", (*b)[1][0], (*b)[1][1]);
もしくは、
typedef float G[2];
int main(void)
{
G a[2];
G *b;
b = &a[0];
printf("%f %f\n", b[1][0], (*(b + 1))[1]);
無知を庇うことより型の同一性に関心持ちな
>>148 多次元配列というからには
各々の添え字や次元がそれぞれ等価で
同じに扱えないとちょっと不自然に感じる。
例えばCで
int array[10][10]:っていう2次元配列?があったとして
array[5]で1行?単位の1次元配列は簡単に抜き出せるのに
列を抜き出すのはメンドクサイ、というようなこと。
殆ど気分の問題だけどね。
>>148 漏れもその「うるさい人」の1人だが
int wara(int, int);
のようなものを多次元配列に見立てて使うことならあるな
int sine[Y][X];
もそういうカテゴリーになら入れてもいい
164 :
デフォルトの名無しさん :03/08/30 00:27
age
int (*array)[10] = (int(*)[10])&array[0][5]; for(i = 0; i < 10; i++) printf("%d\n", array[i][0]); とかなら出来はするけどにぁ。
俺も「うるさい人」のひとりだけど、俺の場合 「多次元配列は無いんだよ、基本的に。」 って言ったほうがなんとなくカコイイからだな。
167 :
ANSI-C学習中 :03/08/30 01:48
以下のソースように、関数の引数に関数原型と異なるシグネチャをもつ関数(へのポインタ)を渡した場合、 コンパイラによって動作が異なるのですが、なぜでしょうか? VC++(cl):ワーニング mingw32-gcc.exe:ワーニング Borland C++ 5.5.1:コンパイルエラー #include <stdio.h> typedef struct{ char c; int l; }Data; void test(int i,char s); void f(int j,void t(int i,Data s)); int main(void){ int i=10; f(i,test); return 0; } void test(int i,char s){ printf("test invoked ,i=%d,s.c=%c\n",i,s); } void f(int j,void t(int i,Data s)){ Data s_={'A',10}; printf("f invoked \n"); t(j,s_); }
168 :
ANSI-C学習中 :03/08/30 01:49
上のつづき fの2つ目の引数はtest(int i,Data s)なのだから、test(int i,char s)を指定した場合は 当然コンパイルエラーになると考えていたのですが。 ANSI-C規格では、たとえ関数原型を宣言していても、その関数の引数に関数へのポインタを指定する場合、 その引数となった関数のシグネチャが関数原型と異なるときの動作は未規定なのでしょうか? できればANSI-C規格の、どこにこの事ついて記述されているか教えてください。 わかりにくい説明ですみませんが、よろしくお願いします。
void (*t)(...) じゃないのか?
170 :
ANSI-C学習中 :03/08/30 02:28
あれ、そうですね・・・。。直しました。 でも結果はおなじですね・・・。 関数宣言で a(void (*test)(int,Data));と a(void test(int,Data)); は、結局同じ意味になるんでしたっけ? 修正後: #include <stdio.h> typedef struct{ char c; int l; }Data; void test(int i,char s); void f(int j,void (*t)(int i,Data s)); int main(void){ int i=10; f(i,test); return 0; } void test(int i,char s){ printf("test invoked ,i=%d,s.c=%c\n",i,s); } void f(int j,void (*t)(int i,Data s)){ Data s_={'A',10}; printf("f invoked \n"); t(j,s_); }
ん?みんなsageてるのか。sageます
ちなみに、 mingw32-gccのコンパイルメッセージは以下です testFunction.c: In function `main': testFunction.c:13: warning: passing arg 2 of `f' from incompatible pointer type 連続かきこすみません。
>>153 >アクセスには配列演算子[]を使いこれはもちろん
>(対象が配列であっても)ポインタの演算だが
>これによりアクセスしている先が配列型(の要素)に他ならない
おいおい。いつのまにか「配列型」を「配列型の要素」に
すりかえようとしてやがる。
しかし結局、Cの「配列」ってのは(他の言語と違って)
ポインタ演算になる構文糖にしかすぎないってことを
認めちまったな。
Cの「配列」ってのは、単にポインタの加減算の単位を計算してくれるだけ。
JavaやPascalみたいに1個のまとまった「配列オブジェクト」は存在しない。
他の言語みたいに「配列添え字範囲チェック」が
(コンパイラのオプションとしてさえも)存在しない理由は、
単なる効率上の理由じゃなく、Cのセマンティクスがそれを許さないからだ。
添え字チェックすると、C的に「正しい」プログラムも動かなくなる。
あ、ちなみに俺は「Cに多次元配列が存在しない」とは思っていない。 そう言っているやつらは、たぶんJavaとごっちゃにしてるんだろ。 「多次元配列ではなく『配列の配列』だ」というなら、他の言語も同じ。 例えばPascalで var a: array [0..m-1, 0..n-1] of integer; という宣言は、 var a: array [0..m-1] of array [0..n-1] of integer; と同じだ。
>>174 ほかの言語なんてどうでもいいだろう?
Cの話をしているんだ。
>>175 「Cに多次元配列が存在しない」かどうかの話をするなら、
C言語に留まらない「多次元配列一般」の話をせざるを得ないが。
「配列オブジェクト」も同じ。
>>176 うるせえ。Cしか知らないから話についてけねーんだよ!
そもそものぉ〜、 初めての高級言語であるFORTRAN、そして実務において世界を席巻したCOBOLではのぉ〜、 多次元配列ちゅうもんはのぉ〜、(ry
本当はみんな、Cに多次元配列が「ある」とするか「無い」とするか なんてどうだっていいんだよ。 初心者にまずは hoge[2][3] みたいなのを見せておいて、少ししてから 「多次元配列というものは無いんだよ」という謎かけをして、配列とポインタに ついてじっくり考えてもらう。これが目的。 つまりな、優しさなんだよ。先人の。
配列とポインタはまったくの別物。 2次元配列や3次元配列は多次元配列ですよ? それにな、ANSI規格で定められてるんだから従えっつーの。 どうせどんな言語も結局はマシン語にならないと実行されないんだからよ。 きにすんな。 多次元配列ないって言ってる奴らは、Javaはポインタを扱えませんっての無視して 無理やりCみたいな表現してむかつくこと極まりない。オブジェクト指向解れよ。と お前ら、なんのためにたくさんの言語があると思いますか?
そんなことより配列へのポインタの使いどころを教えてくれよ
>>173 まだデータ型と演算子の混同してるぞ
>「配列」ってのは(他の言語と違って)
>ポインタ演算になる構文糖にしかすぎない
>配列オブジェクト」は存在しない
>多次元配列ではなく『配列の配列』
脳内妄想を並べる前に規格書を精読しろ
> 2次元配列や3次元配列は多次元配列ですよ? なにを当たり前のことを・・・
185 :
デフォルトの名無しさん :03/08/30 10:22
配列なんて所詮は一定量のメモリの個数を表しているにすぎない。 二次元配列であろうが構造体の配列であろうが。
配列の半分は優しさでできています。
四次元以上は異次元配列
三角形や四角形は多角形ですよ?
> 三角形や四角形は多角形ですよ? なにを当たり前のことを・・・
二角形は?
191 :
デフォルトの名無しさん :03/08/30 13:48
char str[][4]={{"abc"}};
>>191 int i = {0};
が通る(VC7)から、中括弧を一個余分につけてもいいんでない?
char str[] = "abc"; はポインタの代入 char str[] = {"abc"}; は初期化 char str[] = {'a','b','c'};と同じ VC使ってるなら char abc[] = "abc"; char str[4] = abc; ってやってみるとコンパイラのエラーが意味を教えてくれるよ。 *コンパイルエラーでる
>>194 うそをつくな。
char str[] = "abc";
は
char str[] = { 'a', 'b', 'c', '\0' };
の略記。
そりゃ、
char str[4] = abc;
はエラーがでるだろう。 abc が未定義だからな。
>そりゃ、 >char str[4] = abc; >はエラーがでるだろう。 abc が未定義だからな。 間違えた、未定義じゃなくて、「配列をポインタ変数じゃ初期化できない」だ。
>>195 char str[] = "abc""def""ghi";
だと
char str[] = {{'a','b','c','\0'},{'d','e','f','\0'},{'g','h','i','\0'}};
の略記になるのですか?
略記じゃないと思うけど?
許されてる初期化方法の一つでしょ。
i++;
は
i = i + 1;
の略記になるのですか?
198 :
デフォルトの名無しさん :03/08/30 16:25
char str[] = "abc""def""ghi";はchar str[] ={'a',...'i','\0'};だと思う。 隣接する文字列リテラルは連結されるから。俺は構文糖という呼び方が好き。
>>197 > i++; は i = i + 1; の略記になるのですか?
はい。
1を足したり引いたりするためにi=i+1と記述するのが面倒なので、省略した記法が作られました。
>>199 おれには、はいと答えきる勇気がないよ
最適化に期待すれば、はいかもしれんが
++i;はi=i+1;の略記になるのですか?
少なくとも、 >記述するのが面倒なので これは真っ白な嘘。 初期の最適化をしないコンパイラで、足し算ではなくインクリメントニモニックを使うためのヒントにした。
ネタならもう少し面白いことを書いて欲しいな。
>197
JIS X3010-1993(ISO/IEC9899: 1990)
6.5.7 初期化
(略)
文字型の配列は、単純文字列リテラルで初期化してもよい。それは波括弧で囲んでもよい。
文字列リテラルの連続する文字(空きがある場合又は配列の大きさを指定しない場合、
終端ナル文字も含めて。)がその配列の要素を初期化する。
http://www.jisc.go.jp/app/pager?id=12090
>>200 勇気っていうか、「はい」と答えたら間違いだもんな。
(続き) 例7. 宣言 char s[] = "abc", t[3] = "abc" は、要素を文字列リテラルで初期化された"単なる"char型の配列オブジェクトsおよびtを 定義する。この宣言は char s[] = { 'a', 'b', 'c', '\0' }, t[] = { 'a', 'b', 'c' }; と同一となる。
++iはi=i+1と同じ。i++は別物
208 :
デフォルトの名無しさん :03/08/30 21:53
enumの値って違うenumでも重複が許されないんですか? enum sex {MAN, WOMAN, UNKNOWN}; enum status {POSITIVE, NEGATIVE, UNKNOWN}; とかするとコンパイルエラーになるんですが...
こんなの作るとエラーになります. /* enum_test.c */ #include <stdio.h> #include <math.h> #include <unistd.h> #include <stdlib.h> enum sex {MAN, WOMAN, UNKNOWN}; enum status {POSITIVE, NEGATIVE, UNKNOWN}; /*--- Main function ---*/ int main(void){ enum sex dareka; enum status jyotai; printf("Virus status questionnaire.\n"); printf("Input your sex. (0: man, 1: woman, 2: unknown)\n"); scanf("%d", &dareka); printf("Input your HIV status (0: positive, 1: negative, 2: unknown)\n"); scanf("%d", &jyotai); return(0); }
enum sex {MAN, WOMAN, ANDROGYNOUS}; enum status {POSITIVE, NEGATIVE, UNKNOWN}; とすると通ります.gcc-3.2 これがCの仕様だとすると自分が今リンクしてる全てのコードについて (他人が定義したかも知れない)全てのenum型変数の値の名前空間 で重複が許されず、非常に不便だと思うんですが.
211 :
デフォルトの名無しさん :03/08/30 22:02
「猫でもわかるプログラミング」
ttp://www.kumei.ne.jp/c_lang/intro/no_26.htm というホームページの第26章のプログラムが
うまく動かないんですが…
------以下ソース------
#include <stdio.h>
#include <conio.h>
#include <time.h>
int main()
{
time_t present_tm;
struct tm *my_time;
char *now_time;
while(!kbhit()) {
time(&present_tm);
my_time = localtime(&present_tm);
now_time = asctime(my_time);
printf("\x1b[4;1H");
printf("now_time=%s\n", now_time);
}
return 0;
}
実行すると、カーソル位置の移動がされずに時刻が表示されてしまいます。
>>211 最近のWindowsについてるDOS窓はエスケープ・シーケンスを無視する
エスケープシーケンスがうまく機能していないように感じるんですが… 初心者なもんで、すいません。 ちなみに、VC++.NET Academic でビルドしました。 OSはXP(SP1)です。
あ、やっぱりそうなんですか!! じゃあ、同じことを実現するには、どうしたらいいんでしょうか?
216 :
デフォルトの名無しさん :03/08/30 22:13
216 そうですか! わかりました。 とりあえず、自分の環境にバグがあるわけではないようなので安心しました。 どうもありがとうございました。
218 :
デフォルトの名無しさん :03/08/30 22:39
exec系関数というのを詳しく教えてください。 いくつか種類があるのは分かったんですが、どういう違いがあって どう使うのか分かりません。
219 :
デフォルトの名無しさん :03/08/30 22:40
>>219 すいませんでした。そちらで聞いてみます。
>>210 int s;
s = MAN;
s = POSITIVE;
というように書ける。で、
s = UNKNOWN;
と書いたときにsexのUNKNOWNなのか、statusのUNKNOWNなのか
区別がつかない。コンパイラはどちらが正しいのか知らないので
エラーとしている。
ファイルスコープという名前空間があるので、
ファイルが別だと重複しない。逆に他のファイルでも使いたい場合は
ヘッダファイルで記述して、#includeで取り込む。
>>183 たしかに規格にarray objectという言葉は出てくるがね。
配列がセマンティックには一人前の(first classの)オブジェクト
でない事は明らかだろう。
>>149 参照。
223 :
デフォルトの名無しさん :03/08/31 00:23
typedef int BOOL; #define FALSE 0 #define TRUE 1 void funcxxx(BOOL xxx) { } void funcyyy(void) { int a, b : : funcxxx(a == b); } 上で funcxxx(a == b); の引数の書き方は悪い書き方なのでしょうか? すなわち、以下のように書くべきなのでしょうか? 自分は、上の書き方はCらしい良い書き方と思うのですが。 void funcyyy(void) { int a, b : : if (a == b) funcxxx(TRUE); else funcxxx(FALSE) }
論理値が引数ってのが元凶とおもう。
>>223 なぜ悪い書き方と思ったのだ?
すくなくとも下の、無駄がある書き方のほうがアホっぽい。
227 :
208〜210 :03/08/31 00:49
>>221 簡潔にして明解、それでいて十分なレスありがと!
確かに
enum hoge {YES, NO, UNKNOWN, NOT_ANSWERED_YET};
enum foo {MAN, WOMAN, NEWHALF, ANDROGYNOUS, UNKNOWN};
みたいな時にもこれを許してしまうと駄目だわ.
UNKNOWNが2か4か決められなくなってしまう.
>>170 >void test(int i,char s);
void test(int i,Data s);
>void test(int i,char s){
>printf("test invoked ,i=%d,s.c=%c\n",i,s);
void test(int i,Data s){
printf("test invoked ,i=%d,s.c=%c\n",i,s.c);
デバッグは自分でやろうね。
>>228 すみません。やはり説明がわかりにくかったようです。
void test(int i,char s); は、わざとこのように書いています。
お聞きしたいのは、
関数原型が
void f(int j,void t(int i,Data s));
のような関数に対して、
その関数の2つ目の引数に
void test(int i,char s)へのポインタを渡してコンパイルした場合、
なぜコンパイルエラーにならないのか?ということです。
コンパイル時、
mingw32-gccには-ansiオプションをつけてます。
>>229 同じ意味
6.5.7.3.8
>A declaration of a parameter as "function returning type"
>shall be adjusted to "pointer to function returning type", as in 6.3.2.1.
回答ありがとうございます。 では、 void f(int j,void (*t)(int i,Data s)); の2つ目の引数に 関数void test(int i,char s)へのポインタを渡してコンパイルした場合、 ”Data s”と”char s”とが異なるのだから、コンパイルエラーになると思うのです。 コンパイルエラーとならないのはなぜでしょうか?
232 :
デフォルトの名無しさん :03/08/31 01:53
Windows2000のコマンドプロンプトで旧来のDOS窓のように 文字色を変えたりしたい(テキストタイプのゲームを作ってみようと思って)のですが、 エスケープシーケンスも使えず、どうすればいいか悩んでます。 方法をご存知の方、どうか教えてください。 なお、VC++6.0でコンパイルしますが、ソースはできるだけANSI Cに近い形にしようと思ってます。
>>231 手持ちのBorland C(BC++5.6.4)ではエラーになった
>パラメータ 't' は void (*)(int,Data) 型として定義され
>ているので void (*)(int,signed char) は渡せない(関数 main )
>>233 Borland C++ではコンパイルエラーになるのですが、
mingw32-gccではワーニングとなり
実行ファイルが生成されました。
testFunction.c: In function `main':
testFunction.c:13: warning: passing arg 2 of `f' from incompatible pointer type
VC++もワーニングがでるだけです。
どっちも-ansiオプションつけたり、ワーニングレベル上げたりしてるのですが。
ANSI-C規格としては、どうなってるんでしょう?
コンパイラのエラーや警告メッセージの出し方までANSIで規定してないと思うんだが?
>>235 どうもANSI-Cではその変換が自動的に行われてできるようだね。
もちろんもとの型と違う型でポインタを利用した場合には未定義になるけど
>>234 、
>>237 有難う御座います。
教えていただいた方法やサイトで
なんとか解決できそうです。
240 :
デフォルトの名無しさん :03/08/31 11:18
質問です。任意の数Nを与えて、それについてコラッツ算法 Nが偶数ならば、N=N/2 Nが奇数ならば N=N*3+1 を繰り返し、N=1になるまで繰り返すというプログラムを組みました。 簡単なプログラムなのですが、反例を探すためのプログラムなので 一応、1にならない場合(なるだろうと予想されている問題です)の事 も考えようと思っています。 そこで、もし反例だとしたら、Nが同じ数を2回以上とったら反例という 事なので、通過する数Nをすべて配列に代入して、毎回すべてをNと照合 して反例ではないかと確かめるというぐらいしか思いつきません。 しかし、小さな数でならいいのですが、2^10000とかの数になると、配列 の要素数も馬鹿になりませんし、なにより、プログラムが遅くなってしまい ます。何か良いアイデアないでしょうか?
>>240 霰算問題か。最初から答えを得るようなプログラムを作らないで、
絞り込むようなプログラムを作ってはどうか。
例えばNに対してf(N)回計算しても1にならないならリストに載せる
といった方法で。リストに載った数はあとでゆっくり調べればいい。
どうでもいいが2^10000なら10000回連続で2で割られて1になって終わりだぞ。
242 :
デフォルトの名無しさん :03/08/31 13:22
>>241 本当は2^10000-1でメルセンヌ数に対してのコラッツ算反例探し!!
をやりたいと思っているんです。
Nという数に対してN回計算しても1にならない場合ですか、通常ではそういう数はあるん
でしょうかね?反例じゃない場合でも?(スレ違いっぽいですね)
243 :
デフォルトの名無しさん :03/08/31 13:24
質問です。すでに書き込まれているバイナリのファイルの先頭Xバイトだけ 書き換えたいときに、追加書き込みモードで先頭だけ書き換えるというのは できるのでしょうか?初心者質問ですがよろしくおねがいします。
244 :
デフォルトの名無しさん :03/08/31 13:27
>>243 やってみればわかるのに。
書き換えるならr+(読み込み書き込みモード)で。
「追加書き込み」なんだからできないだろ。
ファイルを切り詰めない読み書きモードと言うべきか。
>>243 追加書き込みモードだとfseekしても、書き込む時には
ファイル終端にされてしまう。"r+"でオープンしる。
249 :
デフォルトの名無しさん :03/08/31 13:40
みなさんサンキューです。
250 :
デフォルトの名無しさん :03/08/31 13:43
追加質問です。r+でオープンした時の開始自は終端からじゃないです よね。つまり、fseekで終端に持ってかないとだめですよね?
無論。
言うまでもなく。
初歩的な質問ですが、 for(a=0;a<3;a++) for(b=0;b<3;b++) printf("%d",c[a][b]); で 1 2 3 4 5 6 7 8 9 を表示した後 scanfで入力した数字と一致した場合のみ 1 2 3 4 5 *6 7 8 9 というようにするにはどうしたらよいのでしょうか?
>>242 N回ならある。例えば7
7,22,11,34,17,52,26,13,40,20,10,5,16,8,4,2,1
いずれにしてもCというより数学の問題だと思うが。
255 :
デフォルトの名無しさん :03/08/31 14:03
>>254 なるほど、7以上でも結構あるんでしょうかね?
256 :
デフォルトの名無しさん :03/08/31 14:04
フリーのC言語の静的解析ツールってありますか?
何かスレ違いの香りがしてきたので数学板に逝ってきます。では
>>240 リンクリスト使った疎な配列に格納すればいいよ
よく考えたらだめだった。 発散していったら確かめようがないんだな。
263 :
デフォルトの名無しさん :03/08/31 17:02
C言語とアセンブルはセットと考えた方がいいですか?
>>253 一度表示した文字の脇に別の字を出したいということ?
そうならスレ違い。
>>263 質問の意図がわからないのだが、C言語はアセンブリ言語ではないし、
Cコンパイラはアセンブラではない。
>>253 一度表示した「6」を消して、「*6」と書き直すということなら、
画面表示を制御する話になるなぁ。
「エスケープシーケンス」という言葉を検索してみるといいかも。
ただし、文字を表示する端末によって対応している規格は違うことが
あるよ。端末によっては、文字の色なんかも変えることができる場合もある。
267 :
デフォルトの名無しさん :03/08/31 18:12
行末の判定ってどうやってます? 1 1 2 3 2 のようなデータファイルから1列目の数字と2列目の数字を別々の 配列に格納する場合なのですが。
268 :
デフォルトの名無しさん :03/08/31 18:15
>>267 > 行末の判定ってどうやってます?
'\n'かどうか。
行末かどうかでなくスペースで区切ればいいんじゃないのか
270 :
デフォルトの名無しさん :03/08/31 18:17
?
行末の判定なんて、聞かなきゃいけないほど難しいものなのか?
273 :
デフォルトの名無しさん :03/08/31 18:22
>>267 ・fgets()で読み込み、終端が'\n'かどうか
・fgetc()で読み込み、'\n'かどうか
・fread()で読み込み、'\n'が含まれるかどうか
>>261 リンクリスト使った疎な配列とは?
>>260 発散しない場合でも(ループになる場合でも)、ずーっと計算した結果
今までに計算した値に戻ったとします。そこで、最小値の先の値(大きいと
か小さいとかではなく、その最小値によって導かれた値)に戻った場合、
最小値がループに含まれず判定する事はできません。生意気な事言って
すいません。
質問です。 コンパイルしようとしたら以下のエラーが出ました。 >Error: 外部シンボル '_main'が未解決 (C:\BORLAND\BCC55\LIB\C0X32.OBJ が参照) これは一体何が原因と思われますか?
WinMainを定義してんだろ
278 :
デフォルトの名無しさん :03/08/31 20:17
>>276 コンパイルのオプションに-tW(だったっけ?)を付ける
280 :
デフォルトの名無しさん :03/08/31 21:01
>>279 おまえ、ム板よりマ板で聞いたほうがいい
reallocを一つの変数に対して2回行ったら書き込み違反になるケースって ありますか?
283 :
デフォルトの名無しさん :03/08/31 22:23
>>282 きちんとreallocの戻り値を受けている?
reallocの第一引数に渡したものと戻り値が同じになるとは限らないんだけど。
>>283 回答ありがとうございます。
最初のreallocの時に対象となる変数に++をしてずらしてます。
これが間違っていると思います。
理解できてない項目(間違って理解している項目)は
reallocして拡張した変数へは++をすれば参照できると思っている。
だと思います。正しく2つ以上reallocした構造体を参照できる正しい
方法はどのようにすれば良いでしょうか?
>>284 最初のreallocの戻り値を、二回目のreallocの引数に渡してその戻り値を使う。
286 :
デフォルトの名無しさん :03/08/31 22:41
>>284 ん?もしかしてポインタをインクリメントしている?
そんなことしたらfreeやreallocができなくなっちゃうよ(予め待避しておいたら話は別)。
とにかくfreeやreallocにはalloc系関数が返したもの以外は与えてはいけない。
++ するという発想はどこから産まれるのだ?
>>287 検索サイトでreallocで引っかかったサイトを参考にしました。
>>286 reallocの対象となる変数(アドレス)は退避しておいて、
2つ目に拡張した変数へアクセスするにはどうすれば
良いでしょうか?
>>288 ポインタ演算とメモリの確保を理解出来てないんだろ?
そんな事を検証や調べもせず載せるサイトは無いと思うが。
>>290 なんだか、何もわかってない予感。
オマエがreallocを使うのは10年早いよ、マジで。
質問でつ 初心者なんでつが、 現在の日付を"20030831"のような形で取得するには一体どうしたらいいでしょうか 時間関係は初めてなんで誰か教えて下さい
294 :
デフォルトの名無しさん :03/08/31 22:54
>>293 timeとlocaltimeとstrftimeでできないかな。
>>290 reallocは再確保してるんだよ?
二回拡張したら、退避も何も最初のアドレスは無効。
もしもstrftimeでうまくゆかないようならsprintfで。
298 :
デフォルトの名無しさん :03/08/31 22:57
機械系人間なのですが、いろいろな経緯からC言語に携わる機会があり 自分でプログラムを組んでみたいと思うようになりました。 自分の趣味の範囲で独学するにはまず何から始めたらいいのでしょうか?
>>294 助言ありがdございます
ちょっとそれらについて調べて見ますね
300 :
デフォルトの名無しさん :03/08/31 22:58
>>297 戻り値が指している。
唯一再確保に失敗してNULLが返った場合のみ、以前のアドレスが有効。
>>300 そういう事なんですね。
そもそも構造体をreallocで2つ確保してそれぞれにアクセスするという
事は可能なんでしょうか?
なんで「構造体の確保」に realloc を使うんだ? malloc でいいだろ。
>>298 Cの入門書を1冊買う。
ネットだけでも必要な情報は得られるが、手元に1冊あって、いつでも読めるといい。
まあ、その最初の1冊を間違えると痛い目にあうかもしれんが・・・。
>>301 もう一度、はっきり言う。
オマエのプログラムにreallocは必要ない。断言しよう。
やりたいことを晒せ!
>>302 最初にmallocで一つ確保して状況に応じて数を増やしたいのです。
JavaでいうHashMapみたいな機能をイメージしています。
>>301 reallocはイメージとしては配列の大きさを変えるもの(a[10]→a[20]のように)なんだけど、その辺は分かっている?
>>realloc 埒があかないな int *pData; int DataSize; DataSize = 10; pData = malloc( sizeof( int ) * DataSize ); DataSize += 20; pData = realloc( pData, DataSize ); if ( !pData ) //この時はpDataは以前のまま else //新しいアドレス DataSize += 30; pData = realloc( pData, DataSize ); if ( !pData ) //この時はpDataは以前のまま else //新しいアドレス これでreallocを理解出来た?
>>306 それは理解できています。それを構造体に応用できないかと
思っていたのですが用途としては間違っていたようですね。
>>307 はい 理解できました^^;
ありがとうございます。
>>307 実際はいきなりpDataで受けるのはまずいけど、こういう場合はきちんと書くと大事な部分がわかりにくくなるね。
realloc( pData, DataSize ); ↓ realloc( pData, sizeof( int ) * DataSize ); Missですた
>>307 > pData = realloc( pData, DataSize );
>
> if ( !pData ) //この時はpDataは以前のまま
pData は NULL だろ。
>>308 全然理解してないよ。
型を構造体にすれば良いだけジャン。
>>313 型に構造体を指定しているのですが
”ここは2番目の構造体”
”ここは最初の構造体”
と指定して値を抽出する書き方が分からないのです。
すいません。原因は理解できたので思考錯誤します。
回答ありがとうございました。
>>315 struct KOZOTAI *pKOZOTAI;
/* mallocとかいろいろやる */
pKOZOTAI[0]; /* 最初 */
pKOZOTAI[1]; /* 二番目 */
>>315 それとも自己参照型の構造体の方が良いかもしれません。
>>316 *と[](配列)との関係がはっきり理解できました。
ありがとうございます。
>>315 相変わらずトンチンカンなこと言ってるな。
mallocしてる部分を書いてみなよ。
>>318 確かに++でも以下のようにできるけど、このままじゃfreeできないとか面倒なことになる。
struct KOZOTAI *pKOZOTAI;
/* mallocとかいろいろやる */
*pKOZOTAI; /* 最初 */
pKOZOTAI++;
*pKOZOTAI; /* 二番目 */
>>315 やっぱりポインタ演算でのメモリアクセスを理解してないだけなんだ。
最初のSIZEを取っておいて、次に再確保したSIZEとの差が
再確保した領域のデータが無い部分の先頭だろ。
思考錯誤じゃなくてさ、メモリの動的確保とポインタでのメモリアクセスを
理解するのが先じゃないのかな。
>>319 すいません。今使っているのはcallocです。
構造体の中に入り込んでいるので部分的に即表示できる部分です。
= (struct map *) calloc( 1, sizeof(struct map));
>>320 ですね、このパターンではまってました。
>>315 >思考錯誤します
確かに。思いっきり錯誤してるよな。
>>303 まあ、その最初の1冊を間違えると痛い目にあうかもしれんが・・・。
ということですが具体的にどういうことでしょうか?
また最初は他人のプログラムを理解し自分なりにアレンジしたり
プログラムの概念的なことを理解するようにしたらいいのでしょうか?
なんかこの板荒れてる
327 :
デフォルトの名無しさん :03/09/01 13:22
Cのファイル入出力で扱えるファイルってどんな種類があるの?
>>279 Win32アプリケーションなら動くかも。
>>327 どんなファイルでも。結局は文字で書かれているから。
でも、読み込み専用とかはダメとかいろいろ制限がありそう。
>>328 通常、リードオープンなら読み込み専用ファイルを扱える。
330 :
デフォルトの名無しさん :03/09/01 22:18
あの超超初心者的質問ですいませんがウインドウズXPホームエディションの コマンドプロンプトでC言語プログラミング組むことできるのでしょうか? また超初心者お勧めのコンパイラーも教えていただけると幸いです よろしくおねがいしますm(__)m
>>330 まず日本語覚えた方が良いぞ。
マジで。
>>330 Windows Updateから.NET Frameworkというのをインストールすると
Cコンパイラも使えるようになる。それが一番楽。
LSI C-86とかβクターで探してみ!
334 :
デフォルトの名無しさん :03/09/01 22:22
335 :
デフォルトの名無しさん :03/09/01 22:22
336 :
デフォルトの名無しさん :03/09/01 22:27
>>331 すいませんどう表現してよいかわからないほど超素人なものでm(__)m
>>332 ありがとうございますm(__)m
>>333 ありがとうございますm(__)m
>>レスしてくれたみなさま
もう一度林春比古さんの本読んで出直してきますm(__)m
337 :
デフォルトの名無しさん :03/09/01 22:28
はるピコかぁ・・・
>>336 「超素人」とは、中級者あるいは上級者などの玄人のことをいう。
>>339 へぇへぇへぇ(68へぇ)
素人を超えているってことか。
引数としてテキストファイルを渡すとhtmlに変換するプログラムを作ってます。 <html>〜<body>などが書かれたheader.txtを読み込んで 書き込みモードで開いたファイルの先頭にそれらを書き込みます 次いで引数で渡されたhoge.txtを1行ずつ読み出し、 <p></p>で囲んで戦術の書き込み先のファイルに書き込んでいきます コンパイルは通って、コマンドプロンプトから txt2html hoge.txt などと打ち込んで実行するとうまく変換してくれるのですが、 実行ファイル(txt2html.exe)に変換したいファイルをドラッグ&ドロップして 実行すると、header.txtを読み込んでくれません header.txtを読み込むところは head = fopen("header.txt", "r"); if(head == NULL) { fprintf(stderr, "header.txtがありません\n"); fprintf(stderr, "Enterを押せば終了します\n"); getchar(); exit(-1); } こんな感じです。原因を教えてもらえないでしょうか?
>>341 ネタ?
一応釣られておく。
ドラッグ&ドロップはOSの機能。
それをアプリケーションが利用するためには、
そのOSに特化したなんらかのコードが必要。
拠って、スレ違い。
>>341 細かいことだが、exit()に-1を渡すのはやめておいた方がいい。 環境依存だが、-1を渡すメリットがまったくないか、デメリットがあるので。
>>342 すみません。ネタじゃないです。headerをファイルから読み込まず、
直接fprintfで書いた場合はドラッグ&ドロップで大丈夫だったものですから
いけると思ってました。
>>343 修正しておきます。exit(1)で大丈夫でしょうか
>>344 カレントディレクトリを取得してから読み込ませる、と言うことでしょうか?
ちょっと考えてみます
スレ違いすいませんでした。
とまれ、答えてくださった方々はどうもありがとう。
多分argv
>>343 >環境依存だが、-1を渡すメリットがまったくないか、
ここはいいが
>デメリットがあるので。
あんたも人のこと言えねえな
質問いいですか? 先に出たreallocなんですけど、 main() { char*p_data; int size = 10; p_data = (char *)malloc( sizeof(char) * size ); strcpy( p_data, "hogehoge" ); printf( "文字列%s, アドレス%p\n", p_data, p_data ); size = 20; p_data = (char *)realloc( p_data, sizeof(char) * size ); printf( "文字列%s, アドレス%p\n", p_data, p_data ); free( p_data ); } のプログラムで実行結果が 文字列hogehoge, アドレス10DE 文字列hogehoge, アドレス10EC になったので、ポインタの指すアドレスが 変わったのはわかったんですけど、 この場合、freeされるのはアドレス10ECの部分ですよね。 でも10DEの部分はどうなるのでしょうか?
>>350 reallocさんが上手い事やっといてくれるから心配するな。
>351,352 ありがとうございます。 よくわかりました。
10進数字を BCD化するソースコードを教えてください
>>354 (n に「10進数字」が入っている場合)
n - '0'
>>355 そうか そうでした
どうもありがとう
気付きませんでした
さらに質問いいですか? 350のプログラムをちょっと書き換えて main() { char*p_data; int size = 10; p_data = (char *)malloc( sizeof(char) * size ); p_data = "hogehoge"; printf( "文字列%s, アドレス%p\n", p_data, p_data ); size = 20; p_data = (char *)realloc( p_data, sizeof(char) * size ); printf( "文字列%s, アドレス%p\n", p_data, p_data ); free( p_data ); } とすると、reallocではNULLを返したのですが、これは、 mallocにより、p_dataは動的領域を指す 次の行でp_dataはhogehogeを指す hogehogeは文字列リテラルなので、静的領域に入っているから、 p_dataは静的領域を指す その後、reallocをしたが、p_dataは静的領域を指しているので、 メモリの再確保ができず、NULLを返した であってますか?
>>357 reallocはp_dataが静的領域を指しているか、動的領域を指しているか
区別せずに処理するかもしれない。実装次第じゃないかと。
んあ? 引数にとるのはヒープじゃないのか
だからある処理系ではそれをチェックしてエラーを返すかも知れないが、 別の処理系では気にせず処理してヒープか静的領域かをどっかをぶっ壊すかも知れんってこったろが。
C++のソースをCにするようなのを探します。 Cfrontなる物が、それっぽいとわかったんですが 現行Cfront (C++ 3.0.3)を購入して使えば実現できるんですかね? または他の方法があれば教えてください。
362 :
デフォルトの名無しさん :03/09/02 16:52
363 :
デフォルトの名無しさん :03/09/02 19:49
単純な配列のクイックソートはアルゴリズムの本に載っていたのですが、 連結リストのソートについてヒントを教えて下さい。
364 :
デフォルトの名無しさん :03/09/02 20:05
>>363 一度配列にコピーしてソートしてからリストを再構築する。
再構築しないでソート済みの配列を元にリストの要素を書き換えた方が効率がいいか。
>>363 リストの先頭を取り出し、リストをそれより小さいもの、大きいものの
2つのリストに分ける。
2つのリストに対してクイックソートをする。
最後に先頭と2つのソートされたリストを連結する。
阿呆らしい質問と思うのですがお願いします。 unsigned char* buf=malloc(256); として確保したbufに buf[0]=0xFFとして価を代入しようとすると落ちるんですが、 正しく代入するにはどうすればよいでしょうか。
すいません。やっぱ勘違いですた。
>>361 【現行】cfrontなるものを漏れは知らんが
よければ教えてくれんか?
templateやRTTIをどう訳しているのか非常に興味深い
371 :
デフォルトの名無しさん :03/09/03 00:12
K&R(p245 A7.1 ポインタの生成)の 「式あるいは部分式の型が、ある型 T について、“Tの配列” であれば、その式の値は配列の中の最初のオブジェクトへの ポインタであり、式の型は“Tへのポインタ”に変更される。」 というのがよく分かりません。 配列名が配列の最初の要素のポインタであるというのは知ってるのですが、 式あるいは部分式の型ってなんですかね? あと、&演算子,++,--,sizeofの被演算数と、代入演算子,.演算子の左被演算数なら この変換が行われないってありますが、.演算子の左被演算数の場合に変換されない例が思い浮かびません。
372 :
デフォルトの名無しさん :03/09/03 00:22
> 式あるいは部分式の型ってなんですかね? int *p,a[10]; p=a; /* こういうことじゃないの? */
373 :
デフォルトの名無しさん :03/09/03 00:25
> .演算子の左被演算数の場合に変換されない例が思い浮かびません。 変換できないってことだろ。 配列名.memberはやったことないけどエラーになるんじゃないかな。
374 :
デフォルトの名無しさん :03/09/03 00:33
>配列名.member ポインターに変換できたとして、 ポインター.member でエラーが出ない時ってあります? 他の演算子の例だと、ポインターに変換できたとしたら、 エラー出ない演算ばかり(&, sizeof, ++, --, 代入演算子)だと思うのですが。
375 :
デフォルトの名無しさん :03/09/03 00:38
>>374 ない。
別にこれはエラーになるがこれはならないと言っているわけじゃないでしょ。
int a[20]; として
&aはaをポインタに変換しないのでint **ではなくint (*)[20]を返す
a++,a--はaをポインタに変換しないのでエラーになる。
sizeof aはaをポインタに変換しないのでint *の大きさではなく配列の大きさを返す。
あとはわかるよね?
そういうことを言っているんでしょ。
要はポインタに変換しない例を全てあげただけってこと。
377 :
デフォルトの名無しさん :03/09/03 00:48
>375 はい、それはわかるんです。 なぜ、ありえないことをK&Rはわざわざ書いたのかがわからなかったんです。 じゃないと、「ポインターに変更したら.演算子も使えるようになるんだけど、 配列名に関しては.演算子のときはポインターに変更されないんだよ〜」って 読みとってしまうと思うんですが。 >376 やっぱ、そうですか。 でも、全部書くのは冗長だと思うんですが。。。
378 :
デフォルトの名無しさん :03/09/03 00:52
>>377 冗長・・・か。確かに言われてみればそうかもな。規格書じゃないんだしな。
379 :
デフォルトの名無しさん :03/09/03 00:52
>>372 p=a; /* こういうことじゃないの? */
どういうことですか?ちょっとわかりませんです。
式、部分式の意味が分かってないのかなぁ
380 :
デフォルトの名無しさん :03/09/03 00:54
>>379 p=a; ←式 配列aをポインタに変換してpに代入する式。
9; ←これも式
全部挙げないとUSはうるさいのじゃよ。 タコのしでかしたことがわしのせいにされちまうんだ。
382 :
デフォルトの名無しさん :03/09/03 01:23
式あるいは部分式の型って書くんじゃなくて、 “識別子”の型って書いてくれればわかるのになぁ。 配列名に“式”って言葉を使うなんて、意味が広すぎだよ。 間違ってはないけどさ。
p=a ← 式 p=a; ← 文
>>369 移動しといた。俺もよ〜わからんから買ってみてマニュアルでも
見てみます。
templateやRTTI<使用しないでくださいだったりしてΣ(゚Д゚;
array[0]=1; array[1]=2; ... array[10000]=10001; ってやると for(i=0;i<10000;i++){ array[i]=i+10000; } よりも実行速度は速くなりますか?
array[10000]=10001; <誤 array[9999]=10000;<正
>>385 さあね。どうコンパイルするかによるでしょ。
ループアンローリングも程々にしないと、 コードがキャッシュから溢れて遅くなる気がする。
>387-388 どもです。程々にってことすね。
390 :
デフォルトの名無しさん :03/09/03 18:37
2つの構造体 typedef struct Hoge { char a; struct Hoge *p; } Hoge; typedef struct Piyo { char a; struct Piyo *p; } Piyo; があったとき、 void foo( void *f ) { printf( "%s", f->a ); } とか、 void *bar( void *b ) { return( b->p ); } みたいなことは可能ですか?
391 :
デフォルトの名無しさん :03/09/03 18:38
Hoge hoge; Piyo piyo; foo( &hoge ); bar( &piyo ) 忘れた。
392 :
デフォルトの名無しさん :03/09/03 18:39
>>390 やってみればわかると思うけど。
とりあえずそれは不可能。void *はそのままでは間接参照できないから。
ありがとうございます。 コンパイルエラーなのは分かっていたのですが、 なんか、うまい方法があるのかなと思ったので。
>>393 何がやりたいんだ?
それがわからなきゃ、うまい方法も何もあったもんじゃない。
ちと問題発生... どうも今作っているプログラムは malloc() のところで落ちているようなのですが、 こういうことってあるのでしょうか? もちろん、戻り値がNULLでぬるぽ発生してるってことはありません。 ちゃんと確認はしています。
>>395 おまえの能力が問題。プログラミングやめろ。
397 :
デフォルトの名無しさん :03/09/03 19:32
>>396 むしろお前がこの板くるな。
……「むしろお前がこの板くるな。」も余計か。
>>395 とりあえず、落ちてる所の周辺だけでもあげてくれ。
議論さえできない。
>>398 では以下に。そんなに参考にならないと思いますが...
ObjList *list;
printf("Before\n");
list = malloc(sizeof(ObjList));
printf("After\n");
とすると、出力は
Before
だけになります。
処理系はBCC、OSはWin2k。
これ以外の場所でもかなり使っているのですが、どうも落ちるのはここだけのようです。
2台のPCでプログラムを実行(ビルドではない)して、どちらでも結果は同じでした。
あ、「かなり使っている」のは malloc() です。念のため。
401 :
デフォルトの名無しさん :03/09/03 20:10
>>399 それとは関係ないところが原因で落ちていると思う。
mallocで確保したものを使っているところを中心に注意深く見直してみたら?
デバッガないの?<bcc
「使っているところ」と言っても、実際、この問題のコードを含む関数の中身を 上にageたものだけにしてリビルドしてもやはり出力は "Before" だけなのです。 しかも他のところではちゃんと使えている...こんな事は起きうるのでしょうか? もう処理系変えるしか道がないように見えて欝ダ...
とりあえず、今いえるのは... ObjList *list; printf("Before\n"); // list = malloc(sizeof(ObjList)); printf("After\n"); で、Afterが表示されるのを確認することと、 >これ以外の場所でもかなり使っているのですが で、(メモリリークとかも含めて)ヒープ領域全部使っちまう可能が考えられるが...
405 :
デフォルトの名無しさん :03/09/03 20:16
>>403 きちんと使えているように見えることがあるのが面倒なところ。
>>402 TurboDebuggerがありますが、malloc() のところで「エラーが出た」みたいなこと言って
終了するだけで、さっぱり参考にならんわけです。
本当は間違いがあるのに、一見問題なさそうに動くこともあるってこと。
>>404 表示されています。まぁそのあとの処理で落ちますが。
可能性として、malloc() で落ちる原因はどんなものがありますか?
大量にメモリを確保しすぎても落ちないと思うんだけど... ただ、BCCのデバッガーがエラーを出してるならば、その周辺に問題があるはず。
できることといったら関数の位置変更ぐらいでしょうか。 では今日はもう切るので。サヨウナラ
ヒープの管理ブロックを壊してる そこに到達する直前のfree/reallocを調べる
もちろん、mallocした領域をオーバーフローしてないかも調べる
void foo( char c, void *f ) { Hoge *h; Piyo *p; if( c == 'h' ) { h = ( Hoge *)f; ... } else if( c == 'p' ) { p = ( Piyo *)f; ... } }
>408 ありそうな原因。 1) mallocした領域を越えて書き込んでいる。 2) freeした後にも mallocした領域に書き込んでいる。 3) mallocしていない領域をfreeした。 いずれにせよ、原因は落ちたところにはない。 それ以外の、まったく無関係に見えるところにある。
( ^▽^)<本気で好きだっていったじゃん!
つまり、malloc()に至る前にヒープが破壊されていて、 それと気づかずにそのmalloc()で踏んづけるってことかな?
毒を食ってから下痢をするまでにはタイムラグがあるのだ。
中カッコを付け忘れると、ずっと後ろのほうでエラーになることがあるようなものか。
こんばんは。 今日は例のmalloc()のところをいじってもしょうがないという事で関係ないところを いじっていたのですが、どういうわけかそれで直ってしまいました... malloc()とは関係ない処理だったんですけどねぇ... まったく、C言語は神秘的です。まぁともかく解決したのでよかったのですが。 アリガトウゴザイマシタ
後で別のところをいじったら症状が再発する予感。
>まったく、C言語は神秘的です。 s/神秘的/わからない/ うだうだした屁理屈を取り去った裸の機械なのによ、 機械も女もムいてもわかんなきゃお前には早すぎんだよ。
C言語を機会に喩えるとはまた奇怪な
奇怪な魔人語
高等機械語
426 :
デフォルトの名無しさん :03/09/05 00:32
下でこそこそやってんじゃねーよ! age!
427 :
デフォルトの名無しさん :03/09/05 01:03
>>420 プログラムは、プログラマが書いたとおりに動くのであって、
プログラマが望んだとおりには動かない。
428 :
デフォルトの名無しさん :03/09/05 01:05
>>420 直した部分が、ヒープをぶっ壊していたわけだ。
で、なぜ治ったかが分からないということは、いつでも再発する可能性が
あるし、そもそも、治っているかどうかさえアヤシイ。
>>420 むしろバグが表面化してた分
前のほうが幸せだったのかも
430 :
デフォルトの名無しさん :03/09/05 14:22
ageruyo
431 :
デフォルトの名無しさん :03/09/05 17:24
mallocした構造体の配列の開放に失敗しているようなのですが。。。
Program received signal SIGSEGV, Segmentation fault.
0x40082c1b in free () from /lib/libc.so.6
構造体10個分をmallocし、Segmentation fault がおこる直前の行でgdbで
p *array@10
しても異常はないように見えます。
どのような原因が考えられるでしょうか?
>>395 さんのように全く別の箇所に問題があるのでしょうか?
>>431 あてずっぽうなんですが、
配列の中味ではなくて、ポインタそのものの値は大丈夫ですか?
猫でもわかるプログラミング(
ttp://www.kumei.ne.jp/c_lang/index.html )
のC言語編第57章のプログラムがエラーになるのですが、どうすればよいのでしょうか?
-------エラーメッセージ----------
'WinMain' : 関数はオーバーロードできません。
--------以下ソース---------------
#include <windows.h>
int WINAPI WinMain( HANDLE hInstance ,
HANDLE hPrevInstance , LPSTR lpCmdLine , int nCmdShow )
{
MessageBox(NULL,
(LPCSTR)"メッセージ・ボックスのテストです。",
(LPCSTR)"猫でもわかるプログラミング",
MB_OK);
return 0;
}
---------------------------------
436 :
デフォルトの名無しさん :03/09/05 23:57
以下のように、構造体を関数(func)に引数として渡して、その関数の中でその構造体をさらに関数(func2)に渡します。 ところが関数 func2 の中で参照しようとすると Bus error になってしまいます。どこか間違っていますでしょうか? 構造体を孫関数に渡すにはどのようにしたら良いのでしょうか?よろしくお願いします。 /* ここから */ struct test { double a[100]; }; int main() { int i; struct test temp; for(i=0;i<100;i++) { temp.a[i]=i; } func(temp); return; } func(struct test *temp) { func2(temp); return; } func2(struct test *temp) { printf("temp->a[50]= %e\n", temp->a[50]); return; }
このコードにコンパイラは警告を出さないのか?
438 :
デフォルトの名無しさん :03/09/06 00:01
入力して、それが条件にあっていなかったら入力し直し、 というのを作りたいのですが、そういうときもgotoを使うのはよくないのでしょうか。 もしgotoがだめならdo whileとcontinueを代用するべきなのですか? //gotoを使う again: printf("1-3までを入力\n"); scanf("%d",&a); if(a<1||a>3){ printf("やり直し\n"); goto again; } //do whileを使う do{ printf("1-3までを入力\n"); scanf("%d",&a); if(a<1||a>3){ printf("やり直し\n"); continue; } }while(0); また、プログラムが終わる直前にもう一度実行するかをたずねて、 もう一度なら最初に戻るようにするときはgotoかdo whileどちらがいいですか。
>>437 うちではでまくったなー。(w
まず関数のプロトタイプ宣言はされてないし、
戻り値の型はないし、
値をポインタに変換しようとしてるし、
mainは戻り値を返さないし。
釣り?
>>438 gotoは使っちゃダメという宗教的教えがあります。(w
>>438 入力が2回出てくるから気持ち悪いけど、私は、こういう書き方をする。
2回目のメッセージの文章を、1回目とは違うもっと注意を促すものにできるし。
printf("1-3までを入力\n");
scanf("%d",&a);
while (a<1||a>3){
printf("だから、1-3までだってば!\n");
scanf("%d",&a);
}
gotoを一生使わないというのは誤りですが、
とりあえず初心者のうちはgotoを封印すべきです。
>>438 のケースでは、gotoは使うべきではありませんね。
whileとbreakを使えばスマートに組めると思いますよ。
むしろ入力を促す無限ループを作り、 条件に適合したときだけループから脱出するようにすればどうか? 無限ループ{ 入力 入力が指定された条件なら脱出 }
>>439 すみません。釣りではなくてまじめだったのですが -Wall を付けたら
warning がたくさん出ました。もう少し考えて、
以下のようにしてうまく行きました。修行が足りなかったみたいです。
#include<stdio.h>
struct test {
double a[100];
};
void func(struct test );
void func2(struct test );
int main() {
int i;
struct test temp;
for(i=0;i<100;i++) {
temp.a[i]=i;
}
func(temp);
return 0;
}
void func(struct test temp) {
func2(temp);
}
void func2(struct test temp) {
printf("temp->a[50]= %e\n", temp.a[50]);
}
444の名前の437は、436の間違いでした。
俺は結構goto使う派だが、438のようなケースは使わない。 入力を別関数にして普通にwhileで回す。 まあ、入力部が短くて手を抜くときは whileの条件式にカンマ演算子を使って判定しちゃうことも。
>>440-443 ありがとうございました。やはりgotoはまだ使わない方がいいですか。
それとプログラムを実行させてもう一度処理させるか入力するときもgotoを使わず
do{
/* 文 */
printf("もう一度? 1:はい 0:いいえ\n");
scanf("%d",&a);
}while(a);
でいいのですか。
>>436 アドレス演算子ってしっている?
func(&temp);
449 :
ビル・ジョブス :03/09/06 00:44
gotoは使っちゃダメという宗教的教えはC言語にはありません。(w 但し、gotoは適材適所で使用しましょう。"1関数に1つ"とかです。 その"1関数"も50ラインを超えてはいけません。 1関数50ライン以上になったら私がコンパイルエラーにします。 くれぐれもお馬鹿だと思われないようにソースコードはエレガントに 記述してください。
450 :
デフォルトの名無しさん :03/09/06 00:45
setjmp&longjmpは御法度ですか?
451 :
デフォルトの名無しさん :03/09/06 01:03
関数ポインタどうしビットANDしてはいけましぇん
>>447 繰り返しの実現にgoto文は不要です。
再処理時に行う処理がなければdo〜while文でよいです。
再処理時に行う処理があれば無限ループ+break文にしてください。
繰り返さないループ+continue文よりは
無限ループ+break文の方が読みやすいです。
while(1){
while(1){
printf("1-3までを入力\n");
scanf("%d",&a);
if (1<=a&&a<=3)
break;
printf("やり直し\n"); /* 再入力要求 */
}
/* 文 */
printf("もう一度? 1:はい 0:いいえ\n");
scanf("%d",&a);
if (a==0)
break;
printf("もう一度処理を行います\n"); /* 再処理時に表示 */
}
多段ループを抜けるのに使ってもいいと思う。 下向き限定。 retuenは一個にしろとか結構うっとうしい。 goto禁止ならtry exceptionも禁止なのか?
try exceptionって何?
goto使ってもいいしループの途中でreturnしても構わんが 要は ・でかい関数を書くな ・見通しの悪い引数を書くな ジーオーティーオーという字面からスタートするのは非科学的。 方法論の前に目的と評価基準を明確化しる。 当たり前のplan-do-seeを真面目に繰り返した結果として 30年前のダイクストラ先生と同じ解に収束するかどうかは やってみてのお楽しみだ。
458 :
デフォルトの名無しさん :03/09/07 15:30
今日C言語を始めてみたのですが、分からない点がありました。 それは、日本語で表示させようとすると、文字化けするのですが、 どのようにすれば文字化けしないのでしょうか? 教えてください。
>>458 どうやって表示させたかとか具体的に示したほうがレスが付きやすいと思うぞ
460 :
デフォルトの名無しさん :03/09/07 15:39
sizeofについて教えて欲しいのですが、 sizeofの使い所と何故使うのかを教えて頂けないでしょうか?
461 :
デフォルトの名無しさん :03/09/07 15:47
構造体をいれるための領域をmallocで確保するときとか?
#!/usr/local/bin/perl print "Content-type: text/html\n\n"; print << "-----END-----"; あいだに普通のHTMLを入れました その中に、日本語を入れました -----END----- 上のような感じです
>462 このスレのタイトルを100回読め "C言語なら俺様に聞け! Part 64"
>>460 仕様変更に強くなったりソースコードの移植性が高くなったりする(かも)。
例えば、
FOO_T *hoge;
hoge= malloc(100*sizeof(*hoge));
としとけば、hogeの型を変えても他のコードの修正をしなくて済む。
あと、こんなのとか。(ちょっとANSI規格外の事を仮定してるけど。)
union {
int i;
char s[sizeof int];
} cnv;
cnv.i= 12345;
fwrite(cnv.s, 1, sizeof cnv.s, fp);
C言語って関数型言語ですよね。
466 :
デフォルトの名無しさん :03/09/07 16:27
467 :
デフォルトの名無しさん :03/09/07 16:28
int i=12345; fwrite(&i,sizeof(int),1,fp);でいいと思うけど。
あ、変数定義か(鬱
void hoge(double *a); int main() { double a[1200]; double b[1200][1200]; hoge(a); return 0; } void hoge(double *a) { return; } このプログラムを実行するとsegmentation faultになるのですが、どうしてで すか? gcc hoge.c -o hoge ./hoge segmentation fault
471 :
デフォルトの名無しさん :03/09/07 16:38
たぶんスタックに変数とりすぎ
473 :
デフォルトの名無しさん :03/09/07 16:39
>>470 多分スタックオーバーフロウ。
double bの前にstaticつけてもそうなる?
>>472-473 速いレスありがとうございます。
staticをつけたらsegmentation faultにならなくなりました。
>>475 やっぱり。
でもstaticつけることは解決策じゃないので勘違いしないでね。
b の大きさが sizeof(double) * 259368 までなら segmentation fault にならなかった
それはよかったですね。
481 :
デフォルトの名無しさん :03/09/07 20:19
putcharとかfputcとかのライブラリ関数は、文字の引数はデータ型がcharではなくてint なので、呼び出し元でchar型の変数を実引数として渡すには、(int)でキャストすべきですか。
482 :
デフォルトの名無しさん :03/09/07 20:40
Windowsのコンソールプログラムで、 カレントフォルダ以下のフォルダの中の特定の文字列を含む ファイル名を列挙したいのですが、どうしたらよいでしょうか。 _popenで dir 検索文字列 /s を実行すると一応それらしきものは出てくるのですが、 これだとそこからさらにその文字列をパースしなければ ならないですよね。 もっといい方法がないか教えてください。
>>481 必要なし。 implicit promotion が行われる。
Win32APIのFindFirstFile、FindNextFile使えよ、、まあスレ違いだけど。 dir /b /s という手もあるか。
そうなのか、数学関数のdoubleの引数にintを渡すと結果がおかしくなるそうだが、 intにcharを渡すのはいいのか。
>485 でまかせだ。 どこで聞いた? $ cat a.c #include <stdio.h> #include <math.h> int main() { printf("%f\n", sqrt(2)); } $ cc a.c -lm $ ./a.out 1.414214
>486 オーム社の「C言語によるプログラミング」の基礎編か応用編のどっちかに書いてあった。 ところで他の本でどこかに、C++では自動的に型変換するようなことは書いてあった。
それは、「プロトタイプ宣言が無かった場合」の話ではないのか?
悪いが、やっぱり俺が間違ってたかも知れん。 どこかに書いてあったような気がして、今該当する箇所を捜してたが、基礎編(第2版) の127ページには、「たとえばtをint型の変数とすると、sin(t)と記載された場合には、 sin( (double)t )と解釈されます。したがって、sin(1)と記述しても、sin(1.0)と解釈さ れます。」て書いてあった。 でも何かそのようなことを書いてあったところがあったよな気がするし、またあとで捜し て見つかったら、それをここに書いて、はっきりさせとくわ。
492 :
デフォルトの名無しさん :03/09/07 22:15
>>485-491 暗黙の型変換(キャスト)って知ってる?
プロトタイプ宣言で
double sin(double);
と宣言されていて、
sin(1)とコーディングするとsin((double)1)となります。
>492 implicit promotion
>>493 > implicit promotion
符号付き整数→符号無し整数→よりサイズの大きい整数→浮動小数点数→よりサイズの大きい浮動小数点数
の方向にしかキャストしないからpromotionという表現は適当かもしれない
495 :
デフォルトの名無しさん :03/09/07 22:57
7個の値をランダムで求めたいのですがどうすれば いいのでしょうか?
496 :
デフォルトの名無しさん :03/09/07 22:59
>>495 srandで初期化してrandで得る。
>>495 > 7個の値をランダムで求めたいのですがどうすれば
> いいのでしょうか?
7個の値をもっと具体的に
>>492 確かに基礎編(第2版)の181ページ
第5章 関数
5.2 関数宣言と引数
5.2.2 引数の個数と型の一致
の項にはそう書かれてる。
勉強したつもりで、まだまだ分かってないことが多いようなので、俺には復習が必要なのがわかった。
499 :
デフォルトの名無しさん :03/09/07 23:34
C言語で書かれたソースの綺麗な掲示板ってありますか? お勧めのものを紹介してください。 よろしくお願いします。
500 :
デフォルトの名無しさん :03/09/07 23:39
500 > v(^o^i)d
>>491 第1版は、1991年だから、もしかして当時の本だとプロトタイプ宣言なしの場合の
記述があったのかもよ。
503 :
デフォルトの名無しさん :03/09/08 22:48
素朴な質問で申し訳ないのですが、 calloc() の二つのパラメータの与え方って、メモリのアライメントなどの影響を 受けるのでしょうか? 例えば、 calloc(1, N) と、calloc(N, 1) とでは、 確保されるメモリの容量が違ったり、ゼロで初期化する範囲が違ったり するのでしょうか? てっきり、単純に、(1番目のパラメータ×2番目のパラメータ)のメモリが確保 されて、その中がゼロで埋められるのかなと思ったのですが、どうも違うような 感じもします。コアを吐いたりするわけではないのですが、ゼロで初期化されて いることをあてにして、確保したメモリを作業領域として使おうとしたりすると、 ゼロでない場所があるみたいなんですが・・・
>>503 その処理系で最も厳しい境界を守ったアドレスがシーザー
つーと、ページ境界とかセグメント境界かよって
突っ込みたくなるがシラネーヨ
void *calloc(size_t nmemb, size_t size) { void *p; p=malloc(nmemb*size); if(!p) return NULL; return memset(p,0,nmemb*size); }
配列型に別名を付けたいんですが、できますか? こんな風に書いたんですがVC++6.0ではエラーを吐きました。 typedef (short [16]) block;
>>506 他の順番も試してみよう。
普段、配列を使うときに、
short[16] block;
なんて書かないでしょう?
>>506 誰かが言っていた。typedefは変数定義の頭にtypedefをつけたものだと。
すなわちその場合はtypedef short block[16];だ。
>>507-508 ありがとうございます。その通りでした。
そして新たな疑問が…
block* p_block;
p_block[0] += 1;
などとすると2行目のでエラーが出るのですが、これは何故でしょうか?
ここではshort型配列のインデックス0番を使いたいと思ってます。
(*p_block)[0]++;
いや、メモリ確保しろよ。 p_blockはどこを指しているのか。
>>509 単なるshort16個分の配列を作りたいならblock p_block;だろ。
>>510 この方法でうまく行きました。多謝。
>>511 悪例でした。スミマセン。
ところで、typedef short block[16]; と struct block { short value[16] }; は
等価じゃないですよね?
structにするとこれを引数とする関数を void func1(block* p_block) と
void func2 (short* p_array) の2通り作る必要があるので
何とか共通化したいのですが…。
func2 ((short*) p_block); と func2 (p_block->p_array); が等価だから
func2 のみ作ればいいのではないかと考えたのですが、
どうしても block* を引数に取る func1 のみの記述で済ませたいのです。
void func1(block* p_block)は void func1(short** p_block)だろ。 void func2 (short* p_array)とどうやって共通化するんだ。
“どうしても”ならキャストで済ませろ。 C++でオーバーロードしない事には無理だろ。
void func(void* pblock) 型の保証は渡す人の責任で。
>>514 そこで使ってるblockはstructで宣言した方なので
共通化できるっぽいです。
というか、void func1(struct block*) と書くべきでした。
>>515 やはりそうですか…。
>>514 block *p_blockはshort (*p_block)[16]だろ。
ありゃ、なんか混乱してきた。 構造体の頭にshortの配列がきてれば、 ポインタを強引にキャストすれば逝けるのか。
データファイルを読み込む方法について教えて下さい。 /* -- data.txt ------------- */ density 1.4E2 presure 3.4E-2 energy 7.2E0 current 4.3E3 /* end of data.txt ------------*/ 上記のようにテキストで書かれたデータをC言語のプログラムから 読み込んで、数字の部分だけ double の変数に読み込みたいと思います。 どのように書けば良いでしょうか?
>>521 fopenでオープン
fgetcで一文字ずつ読みながらisdigitで判断
>>521 ああdoubleか。
その数字ってのは行の初めに出てくるのか?
それと一行にいくつその数字列が出てくるかきまっていないの?
>>523 , 524
数字列の数はあらかじめ決まっています。
上記の場合にように、4つだと思って下さい。
テキスト中にその数字が何か分かるように書いておきたいので、
文字列 (空白) 倍精度の数字
のようにしたいと思っています。もしくは、
文字列
倍精度の数字
でもいいです。お願いします。
>>525 そのフォーマット(文字列には空白を含まないと仮定)なら
double d;
FILE *fp;
(中略)
fscanf(fp,"%*s %lf",&d);
もしくは一行読んでsscanf(buf,"%*s %lf",&d); これでいけると思う。
>>513 オレには二つに分ける必要性が感じられないが?
とりあえず、データ構造とアルゴリズムについて勉強した方がよさそうなヨカーン!
>>504 ,505
コメントありがとうございます。calloc()はちゃんと全部クリアいるのですね。
(境界にあわせて整列していて、パディングのところは放置・・・ なんて思った
のですが、そんなことはないと。)
と、いうことで、「じゃあオレが別のところでヘマをしているに違いない」と
自分の書いたプログラムを見直していて、見つけました。
ある自作の関数の中で、ひとつ、初期化を忘れたまま使っている変数があり、
これをちゃんと修正したら、calloc(1,N)でもcalloc(N,1)でも、正しく動くように
なりました。
どうやら少し前に別の関数で呼び出していたcalloc()の第2パラメータと、
この初期化を忘れていた変数が、スタック上の同じアドレスに配置されていた
ようです。このため見かけ上、calloc() のパラメータに依存して挙動が変わって
いるように見えていただけ、という、単なる自分のミスでした・・・
どうもすみません。
>>528 >パディングのところは放置
むしろ余計面倒だと…
>>529 はい、私も、自分で思いついておきながら、「いや、わざわざ断続的に初期化する
ほうが面倒だし、そんな馬鹿なことやっているわけないじゃん」と、いう気は
していたのですが、昨日は、どうしても自分のミスが見つからなくて、思わず、
ライブラリ関数に言いがかりをつけてしまったと・・・ ああ、情けない。
普通sizeofで得られるサイズにはパディングまで入ってる。
532 :
デフォルトの名無しさん :03/09/10 19:04
知り合いから、円周率を使うときは #define PI 3.141592654 とするよりも、 # define PI 4e0*atan(1e0) とした方が良いと聞きました。 理由はその知り合いも知らなかったのですが、 なぜ後者の方が良いか、もしご存じでしたら教えてください。
>532 doubleの有効精度は約15桁だ(64bitの場合)。 M_PI があるなら、それを使えば?
お願いします。 要素が3つある整数型の配列 A[3] をプログラムの中で初期化( {3,5,7} )し、その配列と文字列 "TEST" を、ダイナミックアロケーションによって確保されたメモリへ格納する。何かキーを押されたら、プログラムを終了する。
宿題は自分でやれやクソガキ
荒らしはてめえだカス!
ここにも負け犬のウンコの食物繊維が。
まあまあ、落ち着いて問題に答えてください。提出日迫ってるんです。
ポインタ、構造体、ファイル操作以外で 特に念入りに勉強しといたほうがいい分野(というかなんというか)ってありますか?
>>540 インデントがないし書式に統一性がないしキモイ
545 :
デフォルトの名無しさん :03/09/10 20:59
>>540 そんな簡単な分けない!
もっとソースが長いし、アルゴリズムも迷路とか画像処理とか回帰処理の多重化とか使ってくる。
選択はJavaが簡単みたいだけどその年によって難易度が違うらしいので注意。
二種の時と違って基本情報は選択以外が難しくなってきた。
今年の春の第一問目がアセンブラの16bitアドレス計算だった。
三問目が飛行機の貨物の日程とか情報処理と関係ないのが出てきたし。
そんなわけで、落っこちましたよ。今度こそリベンジだ。。。
出会い系サイトの書き込みの「リンカ」と言う名前を見て、オブジェクトファイルを結合するリンカを思い出したオレは逝ってよしでしか?
出会い系サイトなど見たことがない
実は、以前C++を勉強しようとして完全に挫折 した者です。 つい最近、C言語の勉強をしようと思いつきました。 そのためCygwinを導入しました。現在Cygwinを 使ってCの解説書を見ながらプログラムを組んでい ます。 けれど、実際に使ってみて無理かもと悩んでいます。 基本的にプログラムを学ぶ際は、C言語とC++の 二つがありますが、どちらの方がより学びやすい (初心者にとって)と感じますか?
Cじゃない
やっぱ楽じゃないか・・これは楽なのチョイスしたわけだ。 いつか受けようと思っているが、、先になりそうだ。 多重構造の再帰とか、アルゴリズムヘとか、ベンキョしまつ。 ところでここの住人さん、ハノイの塔って知ってますヵ? なんとか式を使うらしいのですが、自分にはサッパリサッパリでした、 これってやっぱ基礎ですか・・? アルゴリズムの問題なので、違いスマソ。
ドルアーガの搭なら知っています
ものみの塔なら知ってます。
だれかGCCスレの勤労少年を誰かひきとってやれ
息をひきとりました
>>553 最初に、GCC固有の問題なのか、もしくはコンパイラ依存の問題か、
それともCの一般的な問題かを切り分けなきゃいけないんだけど、
たまたまGCCを使っているというだけで、GCCのスレに書いちゃうんだよなぁ
>>555 そういう切り分けはここでよいのですか?
切り分けができない奴を初心者と呼びます。 Cの初心者スレが良いと思うがまぁGCC擦れよりはここのほうがいいだろうな。
>>549 ありがとうございます。。
もうしばらく続けて勉強してみます。
>>532 # define PI 4e0*atan(1e0)
こんなことしちゃいけない。
せめて、
# define PI (4e0*atan(1e0))
と書いてくれ。
尤も、>533の言うようにM_PIを使う方がいいし、
上記マクロは毎回計算するコストも考えないといけない。
>>550 「なんとか式」ってなんだ?
ハノイの塔なら少なくとも3種類の解法があるぞ。
ハノイの塔は再帰を使わずに手続き的に処理するアルゴリズムが美しい。
「三角形の塗りつぶし」というのは C言語の範疇ですか、それともC++とかVCとかの範囲ですか?
>>561 計算幾何学という意味であれば、Cどころか、特定のコンピューター言語の範疇
でさえないような気もする
看板に描かれた三角形ならば美術の範疇
変数に格納されている2バイト文字を16進数のデータとして扱うにはどうしたらいいでしょう。
>>565 意味不明だな。
16進数のデータとして扱えよ、としか言いようがないぞ。
2バイトのchar配列をshortにしたいんだろうな。
char *str; で
*(short *)str だ。
ただし環境依存だ。たとえばWindowsなら大丈夫。
>>565 いまいち、質問の趣旨がわからないけど、
16進数4桁の文字列に変換したいという意味?
だったら、sprintf を使うとか。
URLエンコードをしたいと予想。
570 :
デフォルトの名無しさん :03/09/12 00:00
保守
関数ポインタint(*)(int)を取る関数の引数に isdigit標準ライブラリ関数を渡したら, コンパイル時に「警告 (旧式機能)」とか出て 「仮引数にextern "C" int(*)(int)が渡されています」と出るのですが, 原因を教えてもらえないでしょうか?
573 :
デフォルトの名無しさん :03/09/12 00:26
>>573 マクロと同じ名前の関数も用意されていることになっている。
int f = isdigit(c); /* マクロの呼び出し */
int g = (isdigit)(c); /* 関数の呼び出し */
int foo(int (*)(int));
foo(isdigit); /* 関数ポインタ */
>>572 Cだとは思います.
処理系はSUNWSproのCCです.
576 :
デフォルトの名無しさん :03/09/12 00:30
>>574 そうなのか。
マクロと決まっているわけじゃないからそうすべきなのは当然か。
cc は Cコンパイラで CC は C++コンパイラなんだが。
g++ならそんな警告は出ないね。
580 :
デフォルトの名無しさん :03/09/12 15:32
俺を一流のプログラマにしてくださいッ まず、習得する技術の順番を教えてくださいッ
まずBasic
続いてPascal
さらにコボル
一応、winsdk?っていうか、win32apiはヘルプ見れば分かるんだが 次は何をすればいいのか分からない
win32api の丸暗記
そしてまたBasic
ヽ( `Д´)ノウワァァァァン
そこでアセンブラ
>>559 タブン漸化式って書いてあったような・・・読みからがわからん。
そんであの、ハノイの塔を解く再帰を使ったプログラムをだれか自分に伝授してくださぃ!
再帰を使えるよう・・・。!
宿題は自分でやれ。
宿題じゃないです。好奇心です。がんばります。
指定した二つのフォルダを比較して同じファイルが合った場合、そのファイルの容量を比べて、 小さいファイルを大きいファイルで上書きするプログラムを書きたいと思っています。 今、javaとCを勉強中(まだ初歩の初歩)なのですがどっちでもできるんですかね?
>>592 大多数の環境において、どっちでも書ける。
しかし、Javaなら規格内で完結して書けるだろうけど、
C言語の場合は 特にディレクトリ内のファイル一覧取得
のあたりは環境依存の関数を使用する必要があるので
規格(ANSI-C)内の関数だけでは書けない。
>>593 ありがとうございもつ。
java先行で勉強していきます!
>>594 しかしその仕様でいいの?
日付の新しいほうを残すんじゃない?
>>595 いや、これでいいんですよ。
あまり他人には必要とされないプログラムかもだけど。
でもひょっとしたら、特定のディレクトリならbatファイルでできちゃう?
>>596 batだとわからないけど、シェルスクリプトなら容易にできそう。
>>589 作ってみました。動作確認済みです。
#include <stdio.h>
#include <stdlib.h>
void hanoi(int n, char *from, char *to, char *other);
int main(int argc, char *argv[])
{
if(argc != 5){
printf("3枚重ねをAからBへ移動したいなら hanoi 3 A B C\n");
return 1;
}
hanoi(atoi(argv[1]), argv[2], argv[3], argv[4]);
return 0;
}
void hanoi(int n, char *from, char *to, char *other)
{
if(n <= 1){
printf("1枚目を%sから%sへ\n", from, to);
}else{
hanoi(n-1, from, other, to);
printf("%d枚目を%sから%sへ\n", n, from, to);
hanoi(n-1, other, to, from);
}
}
599 :
デフォルトの名無しさん :03/09/13 12:45
JAVAなんてあと5年以内に完全に死滅するので勉強は止めておくべきでしょう。
根拠は?
602 :
デフォルトの名無しさん :03/09/13 21:05
ほしゅ
603 :
デフォルトの名無しさん :03/09/13 21:38
捕手 今日は古田捕手がよくやってくれた!
ハノイのコードなんてネット上にくさるほどあるぞ。 いろんなパターンがあって、hanoi関数の引数の数が違うのもあったりするから いろいろみてみるといいよ。
>>601 俺、JAVAやってないし。ただ根拠を聞きたかっただけ。
606 :
デフォルトの名無しさん :03/09/14 18:00
C言語のエスケープシーケンスを使ったプログラムを Windows98のMS-DOSプロンプトだと動くのですが、 Windows2000のコマンドプロンプトではうまく動きません。 これってどうゆうことでしょうか?
607 :
デフォルトの名無しさん :03/09/14 18:01
>606 あなたが「C言語のエスケープシーケンス」と思っているものが、 実は「C言語のエスケープシーケンス」ではないから。
>>606 FAQだ。ANSI.SYSをCONFIG.NTに追加すれ。
いまどき16bitコンパイラですか(w
>>606 Win32 Console APIを使え。
>>607 はアナルキッツキツの阿呆なので
気にしないでがんばれ。
いや、ユルユルでも困ると思うのだが。
>>608 1) C言語の(エスケープシーケンスを使ったプログラム)を
2) (C言語のエスケープシーケンス)を使ったプログラムを
気にするな。まあ「いまどきMSDOSでCとはメデテーな」スレを作ってもいいかもしれないな。
つーか「いまどきCとはメデテーな」スレだな。 あ、それはC死滅スレか。
だれか、ConsoleAPIを使ったansiprintfでも実装しないかな、、
>>616 なんでprintf()なんだ? センスないなぁ。
cursesライブラリ互換でいいじゃないか。
>617 cygwinつかっとけよ
>>616 CONIN$ と freopen でぐぐれ
ぐぐってみたが、ANSIエスケープシーケンスと関係なさそうだったが。
621 :
デフォルトの名無しさん :03/09/16 13:50
typedef struct { int suuji; } kozo, * LPkozo; #define NUM 10 main() { kozo aaa[NUM]; : : mod(&aaa, NUM); : : } void mod(LPkozo aaa, int num) { int i; for (i = 0; i < num; i++) aaa[i].suuji += 10; } 例えば上記のような、配列形式の構造体を変更する関数mod()を 作りたいのですが、このままではC4047のワーニングが出てしまいます。 ワーニングの回避方法、もしくは根本的に作り方が誤っている のであればご指摘下さい。
622 :
デフォルトの名無しさん :03/09/16 13:59
>621 mod(aaa, NUM);
>>622 ありがとうございました。解決しました。
良く考えたら、文字列操作する時、
// aには"abc"が入ってる。宣言はchar a[10];
strcpy(str, a);
ってしますもんね。
バカでした。
あほでした。
逝ってきます。
624 :
デフォルトの名無しさん :03/09/16 15:00
質問です。 while(fgets(s, 62, fin) !=NULL ) で得た文字列の1文字目から24文字目を抜いた文字列を 得たい(25文字目から61文字目までを使いたい)のですが、 どういう方法がありますですか?
追加です。 質問の意味は、上の方式で得た文字列のうち、25文字目から61文字目だけの 文字列を作りたい、ということです。 for(i=24; i<=62; i++) s[i-24] = s[i] ; としても、うまく行かないのです。よろしくお願いします。
>625 memmove(s, s + 24, 61 - 24); s[61-24] = '\0';
>625 つうか、 s + 24 をそのまま使うとか、別の配列にコピーするのが普通じゃないか? char * p = s + 24; または char t[38]; strcpy(t, s + 24);
628 :
デフォルトの名無しさん :03/09/16 16:52
>626 ご指摘の方法にしましたが、うまく行きません。 1行目はうまく行きますが、2行目に48文字目〜61文字目の列が 出来てしまいます。 while(fgets(s, 62, fin) !=NULL ){ memmove(s, s + 24, 61 - 24); s[61-24] = '\0'; printf("%s\n",t); } >627 別の配列にコピーもしましたが、うまく行きません。 以下のようにしましたが、同じ列が2度書き込まれます。 while(fgets(s, 62, fin) !=NULL ){ strcpy(t, s + 24); printf("%s\n",t); } ちなみに読み込むファイルの構造は以下のようになっています。 (はじめの2行だけ貼り付けてみます。) PETREL PET NDB -63.467222 -56.200833330.00N ISLA REY JORGE IRJ NDB -62.199444 -58.961389360.00N このうち、1行目ですと"PET NDB -63.467222 -56.200833330.00N"、 2行目だと"IRJ NDB -62.199444 -58.961389360.00N"、という形の 文字列を得たいのです。
sでもtでも、printfしたあとで、0フィルしてみたら?
>>628 62を63(=61文字+\n+\0)に
>>630 なるほど。その方法で成功しました。
ありがとうございます。
先ほどは、丁寧にお教えくださりありがとうございました。 先ほどと同じデータに関する質問なのですが、 PETREL PET NDB -63.467222 -56.200833330.00N ISLA REY JORGE IRJ NDB -62.199444 -58.961389360.00N 以下のようなデータが並んでいるファイルのそれぞれの列から name(24文字)、id(5文字)、facility(4文字)、latitude(10文字)、latitude(11文字)、freq(6文字)、type(1文字) を得る場合には、どのようにしたら良いでしょうか。fscanfは文字列の間に空白文字があると 使えないので、"ISLA REY JORGE"のような文字があるため使えません。
>>632 latitude(10文字), longitude(10文字)の間違いだろ。
#include <stdio.h>
int main()
{
FILE *fp;
char name[25], id[6], facility[5];
char latitude[11], longitude[12], freq[7], type[2];
fp = fopen("a.dat", "r");
while (fscanf(fp, "%24[^\n]%5s%4s%10s%10s%6s%1s\n",
name, id, facility, latitude, longitude, freq, type) == 7) {
printf("name=%s, id=%s, facility=%s, latitude=%s, longitude=%s, freq=%s, type=%s\n",
name, id, facility, latitude, longitude, freq, type);
}
fclose(fp);
}
latitude, longitude, freqをdoubleに、typeをcharにしたバージョン。 #include <stdio.h> int main() { FILE *fp; char name[25], id[6], facility[5]; double latitude, longitude, freq; char type; fp = fopen("a.dat", "r"); while (fscanf(fp,"%24[^\n]%5s%4s%10lf%10lf%6lf%c\n", name, id, facility, &latitude, &longitude, &freq, &type) == 7) { printf("name=%s, id=%s, facility=%s, latitude=%f, longitude=%f, freq=%f type=%c\n", name, id, facility, latitude, longitude, freq, type); } fclose(fp); }
>633 本当にありがとうございます。勉強になります。 > latitude(10文字), longitude(10文字)の間違いだろ。 latitude(10文字)、longitude(11文字)の間違いでした。失礼しました。 > while (fscanf(fp, "%24[^\n]%5s%4s%10s%10s%6s%1s\n", > name, id, facility, latitude, longitude, freq, type) == 7) もしよろしければ、最後に愚問2つにお答えください。 [^\n] を使用すると、fscanfでも空白文字を含めて読み取ってくれるのですか? ==7 ここは != EOF としないのは、特に意味は無いのですか?
636 :
デフォルトの名無しさん :03/09/16 19:41
C99についての質問です。 C99でtgmathを使う場合、sinなどがマクロになりますが、 getc()のように、引数が複数回評価される可能性を考慮 しなければならないのでしょうか?それとも、sizeof のような引数を評価しない演算子だけで実装されている ことが保証されているのでしょうか?
>>635 マニュアルくらい読めよ。
・scanf()系には、%sのほかに%[...]の指定ができる。これは、文字セットの指定ができるので空白も読み込める。
・scanf()系の戻り値は変換に成功した個数。これをチェックしないと安全に使えない。
639 :
デフォルトの名無しさん :03/09/17 01:41
>>638 すいません。手元においてある入門書には出ていなかったもので。
入門書の次なる本でも買ってきて調べます。どうもありがとうございました。
>>639 >
>PETREL PET NDB -63.467222 -56.200833330.00N
>ISLA REY JORGE IRJ NDB -62.199444 -58.961389360.00N
>
>以下のようなデータが並んでいるファイルのそれぞれの列から
>
>name(24文字)、id(5文字)、facility(4文字)、latitude(10文字)、latitude(11文字)、freq(6文字)、type(1文字)
「以下の」は「以上の」のタイポだとして、これは「name(24文字)、…」っていうフォーマットじゃないような気がする。
正確なフォーマットはどんなのなの?
推測するに
name: 最長24文字の空白を含む文字列
id: 最長5文字の空白を含まない文字列
facility: 最長4文字の空白を含まない文字列
latitude: 小数点以下6桁固定の数値
latitude: 小数点以下6桁固定の数値
longitude: 小数点以下6桁固定の数値
freq: 小数点以下2桁固定の数値
type: 一文字の文字列
−ただしlongitude, freq, type の間以外はそれぞれ空白で区切られる。
って感じ?
641 :
デフォルトの名無しさん :03/09/17 09:40
>>640 > 「以下の」は「以上の」のタイポだとして、これは「name(24文字)、…」っていうフォーマットじゃないような気がする。
そうですね。書き方が不正確だったと思います。失礼しました。
> 推測するに(以下略)
その通りです。ただ、
> −ただしlongitude, freq, type の間以外はそれぞれ空白で区切られる。
それぞれの間は空白で区切られているわけではありません。
それぞれの文字数がマキシマムの場合は、空白は無くなります。
例として、以下のものを挙げておきます。
CAPITAN FUENTES MARTINEZCFM NDB -53.246667 -70.352222340.00N
INVERCARGILL NV VORD-46.411561 168.317608116.80H
兎にも角にも、目指すプログラムを作成できました。
ありがとうございます。
文字列からユニークなハッシュ値(64bit)の作り方を教えてください。
>>642 2の64乗個分のハッシュテーブルを持つ気ですか?
>>643 ハッシュテーブルで使うのではなく
各種インスタンスの識別用につかいまっす。
あ、それで テーブル参照用の要素値でつかうんではないので マイナス値でもありありんす。
>>642 ラビンカープ法とかで文字列のハッシュ使うから参考にしる
>>646 すみません、書き方が紛らわしかったですね。
最終的には文字列からユニークな数値にしたかったと言う事です。
>>647 おお〜、どうもです。
ありがd
>>648 ラビンカープ法ではあまりヒットしなかったな
長さ n の文字列 string = (c1, c2, c3, ..., cn) を数値と見なして,
string = c1 * d^(n-1) + c2 * d^(n-2) + ... + c(n-1) * d + cn
のように表す.d は char なら 256 だろう.
で, string mod q の値をハッシュとする.
q は大きめの素数がいい.ただし,計算途中でオーバーフローしない程度の.
実際にサイズ q のテーブルを必要とするわけではないので,大きめでいい.
mod q の計算は和や積の計算の途中におこなってもいいので,
string の計算過程でこまめに行うといいだろう.
string の計算はこんな感じ 例えば,string = (c1, c2, c3, c4) だったら, string = ( ( c1 * d + c2 ) * d + c3 ) * d + c4 * d はシフト演算でできる. で,mod q を演算途中で毎回やればいいから, string mod q = ( ( ( c1 * d + c2 ) mod q * d + c3 ) mod q * d + c4 ) mod q みたいな感じになる で,64ビットのハッシュが欲しいなら,string の計算過程で 64 + log d ビットの計算領域が必要. (char 型なら log d = 8 なので,72ビット) このときは q は64ビットで. 56ビットのハッシュが欲しいなら,計算領域は64ビットで,q は56ビット.
全くの独学で構造体がうまくできません。 これでいいでしょうか? #include <stdio.h> struct book{ char dai[10]; char sha[10]; int ne; } int main() { struct book Hon[4]{ {"Cbook","ank",1800}, {"Lamn","Bump",3000}, {"Power","match",1500}, {"notice","road",800} } int i; for (i=0;i=<4;i++) printf("%cの出版社は %c\n値段: \\%d\n",Hon_dai[i],Hon_sha[i],Hon_ne[i]); return 0; }
>>651 %cは文字出力で文字列の出力は%sを使用します。
メンバー指定はピリオドを使用します。
printf("%sの出版社は %s\n値段: \\%d\n",Hon.dai[i],Hon.sha[i],Hon.ne[i]);
文字列を書き換えるつもりがなければ配列よりポインタの方が
不必要にサイズが大きくならなくて良いです。
struct book{
char *dai;
char *sha;
int ne;
}
>>652 配列添字の位置も変でした。
printf("%sの出版社は %s\n値段: \\%d\n",Hon[i].dai,Hon[i].sha,Hon[i].ne);
>>652 ,652
すみません、ありがとうございます。
できました。
自分の意図したとおりに動いてくれると嬉しいですね。
なかなか動いてくれませんけど。
>654 ほんとにできたのか?
ごめんなさい。もう動くと思って書き込んだんですが、mainの宣言が多すぎるとか言われちゃいました。 エラー E2176 jisaku.c 9: 宣言に型が多すぎる エラー E2141 jisaku.c 11: 宣言の構文エラー(関数 main ) エラー E2451 jisaku.c 18: 未定義のシンボル i(関数 main ) エラー E2188 jisaku.c 18: 式の構文エラー(関数 main ) エラー E2379 jisaku.c 18: ステートメントにセミコロン(;)がない(関数 main ) エラー E2110 jisaku.c 21: 互換でない型変換(関数 main ) *** 6 errors in Compile *** です。難しいよぅ
できました。 自分の意図したとおりに動いてくれると嬉しいですね。
ありがとうございます。本当にできました。途中俺じゃない書き込みもあったけどなんとかなりました。 if文の書き方も違いましたね。もっと精進してきます。 #include <stdio.h> struct book{ char *dai; char *sha; int ne; }; int main() { int i; struct book Hon[] = { {"Cbook","ank",1800}, {"Lamn","Bump",3000}, {"Power","match",1500}, {"notice","road",800} }; for(i=0;i<4;i++) printf("%sの出版社は %s\n値段: \\%d\n",Hon[i].dai,Hon[i].sha,Hon[i].ne); return 0; }
if文じゃなくて for文でした。すみません。
>>659 >if文の書き方も違いましたね。
どこに「if」文があるのか?と(ry
>>649-650 なるほど。
とりあえずラフで組んでみました。
u_long GetHash(char *str, int d, int q)
{
int n = strlen(str);
u_long val = 0;
for(int i=0 ; i<n ; i++)
{
val = (val * d + str[i]) % q;
}
return val;
}
こんな感じでしょうか。
d, qなどは定数で良いんでしょうが
とりあえず使いながらやってみる事にします。
ご教授ありがとうございました。
※遅レス申し訳ないっす
C言語で文字列を解析する関数を作りたいんですけど、 char同士の代入のあたりでコアダンプしてしまいます。 どうすればいいか教えていただけませんか? $ cat whyerror.c #include <stdio.h> #include <stdlib.h> int test(char ** string_ptr, char * string) { int len = 0; *string_ptr = (char *)malloc(sizeof(char)); while (*string) { printf("%d: %c\n", ++len, *string++); *string_ptr = (char *)realloc(*string_ptr, sizeof(char) * (len + 1)); **string_ptr++ = *string; /* ??? */ } **string_ptr = '\0'; return 0; } int main(void) { char * string; char * result; string = "this is test!"; test(&result, string); printf("result: %s\n", result); return 0; } $ gcc whyerror.c -Wall; ./a.exe 1: t 2: h Segmentation fault (core dumped)
最初間違って「C++相談室 part23」のほうに書き込んでしまいました。
http://pc2.2ch.net/test/read.cgi/tech/1062690663/269-274 以下、自レスより引用。
> /* ??? */ の一行が間違っていそうな気が
> するんですが、何がどう間違っているかが分からないんです。
> ポインタの扱い方を勘違いしているのかな?
> charにcharってそのまま代入してもいいんですよね?
で、274さんから
> ちなみになんで落ちるかっつーとreallocの第一引数がmalloc/reallocで確保された
> メモリ領域を指していないから。原因はstring_ptr++;
というレスを頂いたのでstring_ptr++しないように
*string_ptr[len-1] = *string;
としてみました。でもやっぱり同じです。
こんな漏れはPerlでも触ってたほうがいいでしょうか。。。
>>663 > **string_ptr++ = *string; /* ??? */
string が sizeof(char**) 分 ++ されているな
* と ++ の優先順位の問題
>>664 > *string_ptr[len-1] = *string;
これも (*string_ptr)[len-1] としないと駄目
ただ,何でこんな変なことやってるの?
char *test(char * string) {
int len = 0;
char *string_ptr;
string_ptr = (char *)malloc(strlen(string)+1);
while (*string) {
printf("%d: %c\n", ++len, *string++);
}
return string_ptr;
}
じゃ駄目なの?
>>665 誤: string が sizeof(char**) 分 ++ されているな
正: string_ptr が sizeof(char**) 分 ++ されているな
あと、ソースじゃ malloc や realloc の戻り値をチェックしてないけれど
ちゃんとチェックするようにな
char *test(char * string) {
int len = 0;
char *string_ptr;
string_ptr = (char *)malloc(strlen(string)+1);
if (string_ptr == NULL) return NULL;
while (*string) {
printf("%d: %c\n", ++len, *string++);
}
return string_ptr;
}
あと,sizeof(char) は言語仕様で 1 と決まってるからあまり意味がないよ
うあ、ソースが大変なことに… みんなどうやってインデントしているの?
何度もゴメン、不慣れで… char *test(char * string) { int len = 0; char *string_ptr; string_ptr = (char *)malloc(strlen(string)+1); if (string_ptr == NULL) return NULL; strcpy(string_ptr, string); /* ← 抜けてた */ while (*string) { printf("%d: %c\n", ++len, *string++); } return string_ptr; }
>>663 プログラム中に ** なんてのが出てくるとろくなことがないので、
一時変数を導入して、プログラムをわかりやすくする。
*string_ptr = (char*)malloc(長さ);
*string_ptr = (char*)realloc(長さ);
なんてするかわりに
char* p;
p = (char*)malloc(長さ);
p = (char*)realloc(p, 長さ);
として p を使っておいて、
呼び出し側に帰る直前に渡されたポインタの先にpを書き込む。
*string_ptr = p;
return 戻り値;
こんなふうにすると見通しがよくなる。
p を戻り値にできるんなら、そのほうが良い。
670 :
デフォルトの名無しさん :03/09/18 20:54
よくわからんが、
>>663 さんのやってることを極力変えないで文法が
正しくなるように、昨日K&R本を読み終えたばかりの僕ちゃんが直しました。
#include <stdio.h>
#include <stdlib.h>
int test(char **string_ptr, char * string) {
int len = 0;
char *p;
*string_ptr = (char *)malloc(sizeof(char));
p = *string_ptr;
while (*string) {
printf("%d: %c\n", ++len, *string);
*string_ptr = (char *)realloc(*string_ptr, sizeof(char)*(len + 1));
*p++ = *string++; /* ??? */
}
*p = '\0';
return len;
}
int main(void) {
char *string = "this is test!";
char **result;
test(result, string);
printf("result: %s\n", *result);
return 0;
}
>>665-670 懇切丁寧にありがとうございます!
>> **string_ptr++ = *string; /* ??? */
> string が sizeof(char**) 分 ++ されているな
> * と ++ の優先順位の問題
後学までに、これをそのまま使うとしたら、どこかに
カッコを付ければ動くようになるんでしょうか。
*(*string_ptr++)とか試してみましたが、うまくいきませんでした。
> ただ,何でこんな変なことやってるの?
今回のソースは簡略化しています。
もともと文字列を解析したくて関数を作っていました。
で、関数自体の返り値は何通りかの結果コードを
返すのに使いたいな、と思ったわけです。
ただ、変なソースなんだろうとは思います。
いままでRuby/Perl/Shellばかりで、
C言語の経験は全くありません。
ポインタ・メモリ周りは何冊も本を読んで
分かったようで全然分かっていません。。
これからもう少し実験してみます。
ありがとうございました。
>>671 > *(*string_ptr++)とか試してみましたが、うまくいきませんでした。
*(*string_ptr)++ですかね
char **string_ptr; と宣言したなら
string_ptr は char ** 型(これに++するとsizeof(char *)分進む)
*string_ptr は char * 型(これに++すると文字の位置が1つ進む)
**string_ptr は char 型(これに++すると文字のASCIIコードが1つ増える)
になります
* は ++ より優先順位が低いので(演算子の結合の強さの問題であって,演算の順序ではない)
*(*string_ptr++) では,やはり *( *(string_ptr++) ) となってしまいます
でもやはり
>>669-670 さんのやり方が一番だと思います
で,私にも後学のために2chでのインデントの方法を教えてもらえますか?
お前ら知ってたか?staticってのは、はじめ(start)からあるからstaticっていうんだぜ。rをつけると語呂が悪くなるから省略したんだと。
>>670 > char **result;
> test(result, string);
> printf("result: %s\n", *result);
これだと
*string_ptr = (char *)malloc(sizeof(char));
のところでSegmentation faultになりました。
char *result;
test(&result, string);
printf("result: %s\n", result);
にすると動きました。
なんでかよく分かっていないんですが、ご報告まで。
>>672 > 2chでのインデントの方法
で半角スペースほどの空白が空きます。
if (a > b) { c = a; } if (a > b) { c = a; }
>>674 >>674 さんが正しい
main()の中で char **result; してtest()に値渡ししても,
実際に char * の領域が確保されているわけではないから
test()の中で*string_ptrで参照しようとしている所でアクセス違反になる
>>669 ≠
>>670 だったんですかね?
>>669 で言ってることは正しいが,
>>670 の実装は不味すぎ
> で半角スペースほどの空白が空きます。
thx
実際に で半角スペースが空いてしまったわけだが…
どれどれ <pre>は使えるのかな。 <pre> main(){ printf("hello\n"); } </pre>
>>673 脳内辞典ですか?
まぁ、仮に語源がそうだったとしても、プログラムとは関係ないわな。
たびたびすみません。 やっぱりまだ変です。 $ gcc whyshort.c -Wall -ggdb; ./a.exe 1: t (1) 2: h (2) 3: i (3) 4: s (4) 5: (5) 6: i (6) 7: s (7) 8: (8) 9: t (9) 10: e (10) 11: s (11) 12: t (11) 13: ! (11) result: this is tes こんな具合で、最後の2文字がコピーされません。 ソースは次のとおりです:
$ cat whyshort.c #include <stdio.h> #include <stdlib.h> #include <string.h> int parse_num_list(char **string_ptr, char * string) { int len = 0; char *p; *string_ptr = (char *)malloc(sizeof(char)); p = *string_ptr; while (*string) { printf("%d: %c ", ++len, *string); *string_ptr = (char *)realloc(*string_ptr, sizeof(char)*(len + 1)); *p++ = *string++; printf("(%i)\n", strlen(*string_ptr)); } *p = '\0'; return len; } int main(void) { char *string = "this is test!"; char *result; parse_num_list(&result, string); printf("result: %s\n", result); return 0; }
>>680 トップページをヤフーからinfoseekに換えることを勧める。
辞書が揃ってるから。
質問なのですが、 関数の手前に!を付けるのって if (!strcmp(array1.array2)) ↑みたいな感じの これってその関数の戻り値の真偽を逆にするって事で良いんですか?
>>684 Yes
strcmp を「文字列が異なっていれば真」を返す関数と捉えていれば
!strcmp は「文字列が一致すれば」と自然に理解できる
実際,戻り値が正か負かなんて気にすることも少ないしね
0か非0か,と認識しておいた方がいいと思う
qsort をつかったことがないらしい。
mergesortなら使ったことがあるらしい。
>>685 ありがとうございます。
入門書読みながらがんばってたのですが、どうもそういった細かい部分が
知っていて当たり前の知識とでも言うかのように割愛されているのです…
ですが、おかげで謎が解けました。
>>686 お前は文字列の「順序関係」と「等価性」のどちらを判定することが多いのか,と
>>681-682 自己レスです。
printf("(len:%i, s-ptr:%p, p-ptr:%p)\n", strlen(*string_ptr), *string_ptr, p);
としてポインタのアドレスを調べてみたら
$ gcc whyshort.c -Wall -ggdb; ./a.exe
1: t (len:1, s-ptr:0xa040408, p-ptr:0xa040409)
2: h (len:2, s-ptr:0xa040408, p-ptr:0xa04040a)
3: i (len:3, s-ptr:0xa040408, p-ptr:0xa04040b)
4: s (len:4, s-ptr:0xa040408, p-ptr:0xa04040c)
5: (len:5, s-ptr:0xa040408, p-ptr:0xa04040d)
6: i (len:6, s-ptr:0xa040408, p-ptr:0xa04040e)
7: s (len:7, s-ptr:0xa040408, p-ptr:0xa04040f)
8: (len:8, s-ptr:0xa040408, p-ptr:0xa040410)
9: t (len:9, s-ptr:0xa040408, p-ptr:0xa040411)
10: e (len:10, s-ptr:0xa040408, p-ptr:0xa040412)
11: s (len:11, s-ptr:0xa040408, p-ptr:0xa040413)
12: t (len:11, s-ptr:0xa040820, p-ptr:0xa040414)
13: ! (len:11, s-ptr:0xa040820, p-ptr:0xa040415)
result: this is tes
となりました。どうやら途中から*string_ptrとpとで
参照しているアドレス領域が食い違ってしまったようです。
もう一度やり直します。。。
>>690 最後まで p を使って string_ptr に反映するのは return 前にすればいい
int parse_num_list(char **string_ptr, char * string) { int len = 0; char *p; p = (char *)malloc(1); while (*string) { p = (char *)realloc(p, len + 1); p[len++] = *string++; } p[len] = '\0'; *string_ptr = p; return len; }
>>682 メモリの動的確保は予想以上に重いし神経使うので
できるだけ1度にやってしまった方がいいと思う
realloc で再確保してるのは何か意味があるの?
>>692 p = (char *)realloc(p, len+2);
じゃない?
>>669 さんのレスをもう一度読みながら
試行錯誤したらできましたー!
>>669 さん≠
>>670 さんだったみたいですね。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int parse_num_list(char **string_ptr, char * string) {
int len = 0;
char *p;
p = (char *)malloc(sizeof(char));
for (len = 1; *string; ++len, *string++) {
printf("%d: %c ", len, *string);
p = (char *)realloc(p, sizeof(char)*(len+1));
p[len-1] = *string;
p[len] = '\0';
printf("(len:%i, ptr1:%p)\n", strlen(p), p);
}
*string_ptr = p;
return len;
}
int main(void) {
char *string = "this is test!";
char *result;
parse_num_list(&result, string);
printf("result: %s\n", result);
return 0;
}
>>692 ありがとうございます!
すっかり勘違いしていました。
>>693 もともと文字列を解析して必要な部分だけを
*string_ptrに格納して返すという関数を
作りたかったので、長さは最初は分からないんです。
まあ最初からある程度大きめにしておいてもいいとは思います。
これでようやく解析ルーチンに移れます。
>>694 おっしゃるとおりです。
++lenを後ろに移動したときに、バグを入れちゃいました。
解析内容によってはもっといい解決策が存在するに10000ペリカ。
>>695 sizeof(char) が 1 になるのは言語仕様で決まってるよ
あと,malloc と realloc の失敗処理は入れた方がいいね
特に realloc の方
みんな言ってるように、1文字ごとにrealloc()するのは良くない。 realloc()は想像以上に重い処理だし、小刻みにrealloc()すると ヒープの断片化も起きやすくなる。 必要な長さをあらかじめ計算して1回のmalloc()ですませるほうが良い。
>>699 そうかも。。。最初のプログラムなので練習もかねて
自分なりに考えて作ってみてから、
あらためて批評を請いたいなぁと思っています。
その節はよろしくお願いします。
>>700 そうですね。
>>666 でも指摘されていましたが、
読み流していました。ちゃんとやろうと思います。
>>702 多分 realloc を繰り返すより
string を2回走査する方が速い
ポインタへのポインタ **string_ptr を使う意図がわからんのだが 呼び出し側でわざわざ引数に & つけるならcharへのポインタでもよさげ
アセンブラ知っててポインタがわからない? どういうしと。
抽象化されるとアウト
漏れも**は多次元配列渡すときに使うもんだとおもってた
構造体についての質問です。 まず、他の関数からの引数のInputで整数nが入力されます。 このときchar a, char b, char c のセットをnの回数分だけ 用意したいのですが、以下のような構造体を定義して 使用すればよいのでしょうか? typedef struct _structA{ intn;/* structBの出現回数 */ structB*pStructB; }structA; typedef struct _structB{ chara[5]; charb[10]; charc[20]; }structB; 識者の皆様、ご指導よろしくお願いします。
713 :
デフォルトの名無しさん :03/09/19 01:00
>>712 なんだかよくわからないけど、structB*pStructB;はポインタにする必要があるの?
アセンブリをアセンブルするアセンブラ。覚えとけ。
というか、全てstructAのメンバーにしてもよさそうな・・・
>>712 それでOK。
関係ないが、struct _structB のようにアンダスコアをつける必要はない。
typedef struct structA { ........... } structA;
として何の問題もない。
>>716 つーかstructのあとのstructAはいらん。自己参照型のポインタをもつなら必要だけど。
>>712 若干の修正が必要かもしれんが、ええんでないの。
何に使うかわからんが、とりあえず 作るとすればこんなかんじかな・・・ structA* CreateFunc(int n) { structA *datA = (structA *)malloc(sizeof(structA)); datA->n = n; datA->pStructB = (structB *)malloc(sizeof(structB) * n); return datA; }
ああそうか。structBの配列を動的に作成してそれへのポインタをいれるつもりなのか。 ならそれでOKだな。
いや、OKじゃない。型structBの定義はstructAの定義よりも上に書かないとエラーになる。 structB *pStructB; ←ここで
まぁどうでもいいことだが、 structB とかは境界を意識して 改良するも良。
>>722 前方参照って知ってる?
//取り合えず型がある事をコンパイラが分るように
typedef struct structB;
typedef struct _structA{
intn;/* structBの出現回数 */
structB*pStructB;
}structA;
typedef struct _structB{
chara[5];
charb[10];
charc[20];
}structB;
>>713 712は構造体を提示しているだけでコードを提示している訳じゃないでしょ?
>型structBの定義はstructAの定義よりも上に書かないとエラーになる。
この頭悪い表現を突っ込まれてるるんでしょ?
構造体の定義をAとB逆にしろって意味に取れる。
>>726 「型」structBの定義と書いているんだが・・・
わざわざ
>>724 のように書いているとはとてもじゃないけど思えない。
↓ならまだ考えられるけど
typedef struct _suructB struct B;
typedef struct{
・・・
}structA;
struct _structB{
・・・
};
typedef struct _suructB struct B;はtypedef struct _suructB structB;の間違い
typedef float[4] RGBA; RGBA image[100]; という型の配列を16バイトのアライメント境界上に 置くためにはどのような構文を書けばいいのでしょうか? Cというよりコンパイラの実装の問題なんでしょうか? 使用してるのはVC++7.0です。
730 :
デフォルトの名無しさん :03/09/19 09:09
Win32 をサポートするプロセッサにおけるアライメントは適切に処理されます。 データ型 アライメント char バイト境界に配置 short (16 ビット) 偶数バイト境界に配置 int および long (32 ビット) 32 ビット境界に配置 float 32 ビット境界に配置 double 64 ビット境界に配置 構造体 いずれかのメンバの最大のアライメント要件に合わせる 共用体 最初のメンバのアライメント要件に合わせる なんで 16バイトアライメントにするには pragma使ってやるしかないかも。
>>729 new や mallocは確か16バイト単位だったような記憶もある。試してみたら?
>>729 > Cというよりコンパイラの実装の問題なんでしょうか?
その通り。
image[100] のあとにアライメントオプションとか表記すればいけなかったけ?
floatになってるのはSSEか何か使うってこと?
ありがとーございます。それから
typedef float RGBA[4];
こうでした。間違えましたすいません。mallocは16バイト境界には
置いてくれないみたいです。アライメントのオプションとか探したんですが
あまりピンと来るのが見つけられなかったので、多めにmallocで確保して
#define ALIGNE16BYTE(address) ( (void *)( (unsigned long)(address) + 16 - ((unsigned long)(address))%16 ) )
こんなマクロ関数でちょこっとずらして使うことにしました。
>>736 そうです。そっちの方でもわからん事が出てきてるんですが
それはこのスレの趣旨ではないので・・・
もまえら、ヘッダファイルの #include <admmsg> って何ですか? ちょっと調べてみたが分からんので解説できる人おながいします
.hが付いてないからC++じゃないか?
>>737 スマソ、."h"ついとった・・・
ググッて見ても分かんねぇ・・・
_| ̄|○
最近安易に使うやつがいるけど、これムカツクんだよね俺。→_| ̄|○
|_ ○ _| |_| ̄ ○|_| ̄○ |_|__| ̄|○|_| ̄_| ̄|○ ○_| ̄|○ _|_|○○|_| ̄ ○| ̄| |_ | ̄○|_| ̄ ○ ○_| ̄|○○| ̄|_○ _|  ̄|_| ̄|○ ○|_| ̄_| ̄|○○| ̄|_○
_no
743 :
デフォルトの名無しさん :03/09/19 22:05
>>735 アライメント
#pragma pack(1)だったような・・・
昨晩
>>663-704 あたりでお相手いただいた者です。
あのあと、本来欲しかった関数を書いてみました。
http://www.geocities.jp/ohmycode/upload/20030919/numlist.c int parse_num_list(char **string_ptr, char *string, int max_len);
max_len: リストの最大長。0 なら無制限 (= realloc を使う)
/* Example Code */
char string[] = "1-3,30,5-3";
char *result;
if (!parse_num_list(&result, string, 0)) {
while (*result) {
printf("%d ", *result++);
}
}
"1-3,30,5-3"という入力から"1 2 3 30 5 4 3"というリストが得られます。
扱いたい数値はせいぜい0-100程度なので char 配列に格納しています。
素直に int にでもしたほうがいいかも知れませんが。。。
ソースを見て何かお気づきになった点などあればお聞かせ願えますか?
745 :
● ◆65BWNgLL2E :03/09/19 23:24
あと、もっと簡潔に (or わかりやすく) 同じことを実現する方法などあれば知りたいです。
parse_num_list()の第2引数にconst付けた方がよい。 int parse_num_list(char **string_ptr, const char *string, int max_len);
747 :
デフォルトの名無しさん :03/09/19 23:29
cファイルをプラウザで見れるような設定ってIEにありますか? あったら教えてください。
>>746 なるほど、そういう風にすれば安全であるばかりか、
関数を使うときに変えられずに済むことが一目瞭然ですね。
ありがとうございます!
>>744 あー、1-3-5,30,2みたいな文字列を解析するツールなら作ったなぁ。
逆順はなしってのと1-3-5-7みたいな連鎖もできるってのが違うけど。
確かハイフン処理の関数を全体処理の関数から呼ぶ形だった気がする。
複雑さの度合いは似たようなもんかもしれない。
つーか、少なくとも私にはそんなに大きな関数は作れない。
>>745 細かいけど,sizeof(char) はいらないよ
あと,fgetsの引数でsizeof(string)-1の-1はいらない
>>751 昨日から何回も指摘されていたんですが、
まだ慣れていないので何を意図しているのかを
示しておかないと不安でsizeofを残してました。
fgetsは、どっかのサンプルを真似しました。
-1はいらないんですね。。
>>745 reallocの失敗時にメモリリークするがいいのか?
>>752 分からないときは慎重にすべきだが,fgetsはnを与えたらn-1まで読み込むと規定されている.
755 :
デフォルトの名無しさん :03/09/19 23:53
というか、 まず最初に",\n\r"など strtokで抜き取ったあとハイフンチェック とかはどう?
>>753 ほんとだ。。こういう場合はきっと呼び出し側ですぐに
exit(1)するはずなので実用上は問題が起きないのかも
知れませんが、freeしておかないといけないんですね。
>>754 なるほど。一つ学習しました。
>>755 どこかにstrtokは絶対に使うな!とか書いてあったんです。。。
>>745 strtokか何かで , で分けた後,
別の関数で, 30 や 1-3 の処理をした方がいいと思う.
あと,数字の処理も atoi か何かで.
オーバーフローが心配なら,先に atof で変換して INT_MAX と比較すればいい.
シングルスレッドなら問題ないけど。
man strtok に これらの関数は絶対に使用しないこと。 とか書いてあるな. まあ,ちゃんと理解して使え,ということだ.
あった、ここだ。
http://www.linux.or.jp/JM/html/LDP_man-pages/man3/strtok.3.html > char *strtok(char *s, const char *delim);
> char *strtok_r(char *s, const char *delim, char **ptrptr);
>
> これらの関数は絶対に使用しないこと。
> もし使用する場合は、以下のことに注意すること。
> ・これらの関数はその最初の引数を変更する。
> ・これらの関数は const な文字列では使えない。
> ・終端文字はすべて \0 になってしまう。
> ・strtok() 関数はパーズに静的バッファを用いるので、スレッドセーフでない。
> もしこれが問題になる場合は strtok_r() を用いること。
「これらの関数は絶対に使用しないこと」って書いてあったから
怖くて使えませんでした。。strtok_rなら問題ないんですか?
>>762 strtok_r
いや,マルチスレッド対応してるだけで,実体は同じだ.
内部でstatic変数を使用している関数はスレッドセーフではない,ということだ.
getsと違ってきちんと理解していれば使ってもいいと思うけどな。
>>762 strtok は引数に与えた s を破壊してしまうから,
strtok を使う前に別のバッファに文字列をバックアップする必要がある,ということだ.
それを理解しておけばいい.
作業用のローカルバッファに文字列コピーして やれば、ソースを壊さなくてすむ。 マルチスレッドなら・・・しゃあない。
そうですか、別のメモリ領域に文字列をコピーして strtok_rを使えば問題はないわけですね。 それでは明日はstrtokを使ってどのくらい短くなるか やってみたいと思います。
>>744 realloc しなくてもいいように,一度文字列を走査して必要なサイズを確かめるべきだと思う.
realloc は想像以上に重い.最悪,関数全体で使用する時間の80%くらい持っていく.
771 :
デフォルトの名無しさん :03/09/20 00:08
>>769 strtokでいいって・・・どうせシングルスレッドだろ?
それなら標準関数を使った方がよい。
>>762 スレッドセーフなら問題ない
スレッドアンセーフでも、単一のスレッドでのみ動くのであれば問題ないが、
将来にわたってそうであることは保証できないので危険である。
いずれの場合もstrtok()の注意点に十分気を払う必要がある。
しかしstrtok()はかなり便利である。
一般にはスレッドアンセーフな関数は単一スレッドでのみ動くことが担保されていれば
大丈夫だが、OS内でも使われている可能性があり(OSのバグ)、トラブルに巻き込まれることがある。
>>771 一応 strtok_r も POSIX 標準のようだが…
774 :
デフォルトの名無しさん :03/09/20 00:10
>>773 標準関数と言ったらPOSIXじゃなくてCの標準関数のことだろ。
ああちなみにC99はしらん。
>>772 まじ!?
ということはlocaltimeもOSによってはまずいの!?
>>770 第三引数のmax_lenを決め打ちにしてしまえばreallocはしません。
max_lenが0のときだけreallocします。
必要なサイズを確かめていたら2回同じ解析を
しなきゃいけませんよね、、、
あ、
>>703 さんの
> 多分 realloc を繰り返すより
> string を2回走査する方が速い
っていうのはそういう意味だったのか。
>>776 ところで、環境(OSとかコンパイラとか)は?
>>775 それは知らんが、usleep()はやばかった。
>>768 ういうい。
>>769 あとは、他の方々もいってるとおり
ちびちびreallocすると処理重くなるので
大胆にひろげときなさい。
>>777 CYGWIN_NT-5.0 1.3.22(0.78/3/2) 2003-03-18 09:20
gcc (GCC) 3.2 20020927 (prerelease)
です。
>>779 だって、"1-100,1-100,1-100,1-100,1-100"とかやられたら
幾らあっても足りませんよぅ。
>>780 それか。じゃあ多分strtok_rはあるな。
>>782 一応Unix/Linux(GCC)でもWindows(Visual C++)でも
動くようなコードを書きたいんですが、
でもPOSIX標準なら最近のコンパイラは大丈夫ですよね?
>>780 小問題に分割する方法は分かるよな
例えば,四則演算の解析だって
式 ::= 項 + 項
項 ::= 因子 * 因子
因子 ::= 数 | ( 式 )
とか定義して,式を解析するルーチン,項を解析…,とやるよな.
今回も,
リスト ::= 項 { , 項 }
項 :: = 数 | 範囲
範囲 ::= 数 - 数
って小問題に分けられるよな?
んじゃ、 連結リストを使って 初出の数字のみ、連結リストに加えていくってのはどう? 最終的に出来たリストは煮るなり焼くなりと。 realloc頻発よりは早いんでないかな。
>>784 あ、なんかXMLのDTDなんかで似たような概念を
目にしたような気が・・・。
でもどうすればそのルールに基づいて
解析できるのかピンときません。
なにぶん知識がないものですみません。。。
演算の解析なら「はじめてのアルゴリズム入門」にでも
載ってたかな? 明日会社に行って見てみます。
>>786 同じ数値は何回出てきてもいいように、
かつ順番も保持するようにしたいんです。
ふと思ったんですが、毎回1ずつreallocするよりも
n回ごとにnずつreallocしたほうが
ぐんと早くなるかも知れませんね。
最後のほうは多少無駄になるかも知れないけど、キニシナイ。
>>788 いや、そういうことを
>>779 あたりで言ってたんだがw
最後の方の無駄は気にしない
というかそんなもんです。
>>788 reallocにかかる時間に比べたらそんなものなんてことない。
>>788 縮小方向のreallocは普通失敗しないが?
意味が分からなかったな 余分に取った領域は最後に縮小すればいいんでない?
>>787 (拡張)BNF記法というんですよ
「リスト」を解析する関数
「項」を解析する関数
「範囲」を解析する関数
「数」を解析する関数
を作ってそれらが内部から別の関数を呼ぶのですよ
794 :
デフォルトの名無しさん :03/09/20 00:48
出たぁバッカス。
「リスト」を解析する関数は strtok で , 毎に「項」に分割して 「項」を解析する関数を呼ぶ. 「項」を解析する関数は「項」が「範囲」か「数」か区別して 「範囲」を解析する関数と「数」を解析する関数を呼ぶ. 「範囲」を解析する関数は - の前後で「数」に分割して 「数」を解析する関数を呼ぶ. 「数」を解析する関数は atoi などで文字列から数値へ変換する. と,まあこんな感じです. もちろんそれぞれの関数内ではエラー処理(構文エラーなど)が入ります.
>>792 なるほど、そうですね。
>>793 >>796 BNF記法・・・なんだか聞いた覚えがあります。
前に読んだhyuki.comさんの「Java言語で学ぶ
デザインパターン入門」のInterpreterの章に
そんなのが出てました。
なんとなく概念は分かってきたような気がします。
それでは、そろそろおやすみなさい。
今日はありがとうございました。
それにしてもいろいろな本を読んでるね PGの鑑やね
以下は「3の倍数のアドレスに境界調整されたオブジェクトへのポインタを関数に渡す」 ことを意図したプログラムですが、何か問題があるでしょうか? #include <stdio.h> void showValue(long* value); int main(void){ long surplus,*p; unsigned int address; char temp[40]; int alignment=3; /* 3バイトアライメントの場合 */ address=(unsigned int)&temp[0]; surplus=address%16; if(alignment>16) return 1; p=(long*)&temp[16-surplus+alignment];/* 3の倍数のアドレスに境界調整する */ *p=1000000; showValue(p); return 0; } void showValue(long* value){ printf("value addr=%p\n",value); printf("value=%d\n",*value); }
800
>>799 CPUによっては4バイトアライメントにあっていないアドレスに32bitアクセスすると
例外が発生する場合がある。
あくまでもsizeof(long)の幅でアクセスするので、3バイト単位ではアクセスされない。
説明が半端だ。 例外が発生する場合があるのではなくて、CPUによっては必ず例外が発生する。 CPUによっては、2回に分けてアクセスするので例外は発生しないがパフォーマンスが落ちる。
>>802 言いたいことは解るが、ここのスレタイに照らすと801の説明が正しいんでない?
Cの規格上は未定義の動作であって処理系定義ではないのだから。
つーと801も最後の1行はおかしいんだが。
804 :
デフォルトの名無しさん :03/09/20 23:20
const int a ; と int const a ; のどちらが正式な宣言なのでしょうか? const int a ; が一般的に使われているような気がしますが・・・
>>804 const int* a ;
int* const a ;
の場合を考えれば、
const int a ;
だろ。
>>804 どちらも正しい。
そうだね、漏れも前者の書き方するし、よく見るような気がするね。
807 :
デフォルトの名無しさん :03/09/20 23:32
でも後者の方が仕様に忠実ですよね?
>>807 どちらも正しいのに、なぜ後者の方が忠実だと思うの?
>>808 わるいが、805は全く見当違い。
ポインタが絡む場合、*の前にconstが書かれているのか*の後ろかで、何がconstなのかが違う。
const int* a ;
は、aが指す内容がconst、
int* const a ;
は、aがconstだ。
>>809 いま
「エキスパートCプログラミング」
読んでいる最中なのですが、それを読んでいるとそのような気がしたので・・・
>>810 > わるいが、805は全く見当違い。
>>810 が見当違い(w
const int* a ;
int* const a ;
が違うのを踏まえた上で
const int a ;
int const a ;
は同じ意味になるんだけどって話でしょ
>>805 const int*
は
int const *
と同じ。
int* const
とは違う。
宣言についての質問者ですが、みなさんありがとうございました。 なんとなくわかった気がします。
レベル低〜
>>817 別に、お前は来なくていいよ。
ここは質問スレなわけだが。
const int * const * const * const ppp; int const * const * const * const ppp; もまいらどっちが筋通ってると思う?
既に筋が通ってても意味が無いと思う。
>>820 何っ!
健全性定理が破綻しているというのか…
ザコめが...つまらん!
>>823 ゲーーーーーーーーーーーーーーーーーテルか?
すみません、全く初心者で樹木のシミュレーションを始めたいのですが 簡単な分枝をC言語で書いたものって何処かのサイトに ありますでしょうか
樹木のシミュレーション?? 簡単な分枝?? C言語の問題と、特定のアルゴリズムの問題はわけて考えろよ。 おそらくスレ違いだな。 もう少し、具体的なプログラムが組めるようになったら、またここへ来な。 それと、何が初心者なのかな? プログラミングか、Cか、樹木のシミュレーションか。 おそらく、全てなんだろうけどな。
>801,802,803 回答ありがとうございました。 実行させるコンピュータのアライメントを確認してみます。
>826 全くもっておっしゃるとおりです。 その具体的なプログラムを書くためにはどのような勉強をすれば いいのかわからず、やる気だけが先へいってしまい書き込んでしまいました。 なんとか自分で頑張ってみます。
異常終了する可能性がある関数を定義します その関数の正否を戻り値で返すとして どのような戻り値にすればいいと思いますか? 1. 正常終了時:非0, 異常終了時:0 真偽値を返す関数との親和性が高くなります if ( function1() && function2() ) exit(EXIT_SUCCESS); のような使い方ができます 2. 正常終了時:0, 異常終了時:非0 (または負値) 異常終了時に複数のエラーコードを返せます if ( function1() || function2() ) exit(EXIT_FAILURE); のような使い方ができます 適材適所だとは思いますが,こういうときに 1. 2. を使い分ける という指標があれば,混乱が少なくなると思うのです どうかご意見をお聞かせください
>>829 自分でもそれぞれのメリットがわかっているみたいだから、
それ以上のアドバイスは出てこないんじゃなかな。
どうでもいいところで神経質に悩んでるようだと・・・、
重要な問題が見えてこないこともあるから気をつけてね。
あっ、俺だとその場合はね、正常終了は0で異常終了は負だね。
理由は、あとで複数のエラーコードに対応させたくなる場合もあるからかな。
C++だと、例外で対処できるんだけどなぁ。
遅レスとなってしまいますが、 ご回答ありがとうございました。
>>829 自分で答え言ってるから、それ以上言うことがない。
ちなみにプログラムがエラーを返すのは異常終了ではない。
異常終了とは例えば記憶保護例外のようにプログラムの仕様に定義がない現象が
原因で終了することで、仕様に従ってエラーを返す動作は正常終了に分類される。
>>829 もっとトリビアルにしたほうがメンテナンス制は高いので
変なとこで悩むより、初心者が見て判りやすいコードにした方がよい。
あと、統一してればどちらでも良い。
まちまちにすると自分でもわからなくなる。
と思う。
>>833 初心者が理解できる必要があるコードって? サンプルか??
>>829 迷うところですね…
個人的にやってるのは、
・戻り値に含むのが成功か失敗かだけの場合
成功:0 失敗:-1(or それ以下でエラーコード)
例:
if (Initialize()) { /* 失敗〜 */ }
・戻り値になんらかの値を含む場合(特にポインタを戻す場合)
成功:具体的な値 失敗:0
例:
if (fp = CreateFile()) { /* fp使う */ }
else { /* ファイルつくれねー */ }
・関数が何かを判定する場合(Is〜な関数名にする場合)
成功:非0 失敗:0
例:
if (IsEmpty(fp)) { /* どーもfpは空っぽらしい */ }
という具合ですかね?
まあ成功で非0の方に統一した方が混乱がなくていいかもですが…
>>829 が示しているような長所短所をふまえた上でまだ統一とか言ってるのは不毛だね。
837 :
● ◆65BWNgLL2E :03/09/21 12:54
皆さんのアドバイスを参考にしてnumlist.cを作り直してみました。
前よりもかなり長くなってしまいましたが・・・。
http://www.geocities.jp/ohmycode/#20030921 >>793 >>796 さんの言われたように
・「リスト」を解析する関数
・「項」を解析する関数
・「範囲」を解析する関数
・「数」を解析する関数
を作りました。
ついでに、簡易Unit Testを書いてみました。
Rubyのtestunitを思い出しながら自分流に作ってみたんですが、
C言語でUnit Testを実装する標準的な方法ってありますか?
何かお気づきのことがあればご指摘いただければ嬉しいです。
838 :
● ◆65BWNgLL2E :03/09/21 13:01
あと、strtok_r の使い方がよく分かっていません。
こんな感じでいいんでしょうか。
char *strtok_buf = NULL;
char *strtok_ptr = NULL;
char *strtok_ptrptr = NULL;
strtok_buf = (char *)malloc(strlen(string)+1);
if (strtok_buf == NULL) {
return(ERR_ALLOC_FAIL);
}
strcpy(strtok_buf, string);
strtok_ptr = strtok_r(strtok_buf, "-", &strtok_ptrptr);
/* いろいろ処理 */
free(strtok_buf); strtok_buf = NULL;
strtok_ptr を解放しなきゃいけないのは分かるんですが、
strtok_ptrptr は解放しなくてもいいんですか?
free(strtok_ptrptr)するとたまにStackdumpすることが
あったのでしていないんですが。。
そもそも、「関数自身が持つ静的バッファを使う代わりに
ユーザーが確保したバッファの char* ポインタを要求する。
このポインタである ptrptr 引数は、同じ文字列をパーズ
している間は同じ値にしておかなければならない。」と
書いてあるので、自分でmallocしておく必要はないんでしょうか?
NULLでも動いているのでいいのかな、と思ってしていないんですが。
http://www.linux.or.jp/JM/html/LDP_man-pages/man3/strtok.3.html
進めたものはmallocが返したものと異なるんだからfreeに渡しちゃまずいだろ・・・
>>839 ん?ひょっとしてstrtok_ptrptrってのはstrtok_bufの
あるアドレスに対するポインタってことですか?
なんか勘違いしていたような。。。
>>838 あと、
>strtok_ptr を解放しなきゃいけないのは分かるんですが、
は
>strtok_buf を解放しなきゃいけないのは分かるんですが、
の誤りでした。
>>838 strtok_ptrptr っていうよりは strtok_bufptr って呼ぶべきじゃないかなぁ?
strtok_buf の現在位置を持っている変数だから
で,strtok_r 内部でも strtok_ptrptr に対して malloc しているわけではない
(strtok_buf の現在位置を保存しているだけ)
ので,free で解放するのはまずい
>>840 そういうこと。
strtokでは関数内の静的変数に記憶させておくものをstrtok_rでは再入可能にするために呼び出し側に(ポインタを使って)返す。それがstrtok_rの第三引数。
だからそれはbufが指す配列のどこかを指している。
>>842 strtok_buf の現在位置
→
strtok_buf 内での現在位置(次のトークンが strtok_buf 内のどこから始まるかを保存)
>>837 最初 scope って何のことだろなと思っていたら「範囲」のことだったのね
range くらいにしてくれると思っていたのだが
>>846 英語が苦手なもので、英辞郎で「範囲」を調べました。
ambit●area●bound●circle●circuit●compass●confine●coverage
●dimension〔【語法】通例、複数形〕●domain●extend●extent●incidence
●pale●plus or minus●province●purview●radius〔【複】radii〕●range
●range of observations●realm●region〔【略】reg.〕●scope●scouth
●span●spectrum●sphere●terrain●tether
で、なんとなくよさげなものを選んだというわけです。
他の関数名・変数名・コメント等も全部そんな感じです。
>>837 numlist.c 外部で使用しない関数は static にするってのはどうよ?
>>848 そうですね。
本来、外部から呼び出すのは parse_num_list と errmsg_num_list
だけなので、あとは static にしてもいいかと思います。
でも、そうすると関数の単体テストはどうしましょうか。。
C言語での標準的方法って存在しないんでしょうか。
>>849 標準的方法は知らないが…
numlist.c に main 関数を作って #ifdef __NUMLIST_C__ 〜 #endif
とかで囲んでおくというのはどうだろう?
>>837 errmsg_num_listで変換指定子がひとつもないのにsnprintfを使っているのはなぜ?
それと、その関数は文字列リテラルの先頭アドレスを返せばいいと思う。
もしも呼び出し側で書き換えることがあるのなら、呼び出し側が用意したバッファに書き込むようにするのが良いと思う。
char *errmsg_num_list(int errnum) {
static const char *msglist[]={NULL,NULL,"memory allocation failed!",・・・,"invalid character!"};
return (errnum>=ERR_ALLOC_FAIL&&errnum<=ERR_INVALID_CHAR)?msglist[errnum]:NULL;
}
↑errnumが連続していなければswitchで。
>>850 なるほど、PerlやRubyでの
if ($0 eq __FILE__) {
# test code
}
と似たような感じで、単体テストができますね。
今後はその方法を使ってみたいと思います。
>>851 msglist を static にしなければならないのが痛いな…
あと,その例で
(errnum>=ERR_ALLOC_FAIL&&errnum<=ERR_INVALID_CHAR)?
って意味あるの?
>>853 変な値を渡してきた方がわるいとは思うけど、元がNULLを返すようになっているから。
> msglist を static にしなければならないのが痛いな…
なぜ?
別にstaticにする必要はないけど。ただ不変だからstaticをつけた。
>>851 snprintfはstrncpyでもよかったですね。
あと、配列を使うと順番や対応メッセージが間違っていないか
チェックするのが面倒くさそうなので、switchにしていました。
配列を使ったほうがずっとシンプルではありますね。
>>851 > errmsg_num_listで変換指定子がひとつもないのにsnprintfを使っているのはなぜ?
strncpy の '\0' の扱いが微妙だから,というのを推測してみる
strncat 使え,と言われたら終わりだが…
または printf だけ使おう,という姿勢なのかもしれない
フォーマット解析に掛かる時間的空間的資源が…というほどのものでもないしな
> もしも呼び出し側で書き換えることがあるのなら、呼び出し側が用意したバッファに書き込むようにするのが良いと思う。
これは同意
各所で malloc しているとソース追うのが大変
>>854 const 変数は static 付けなくても勝手に static 扱いになるんだっけ?
そうでないと errmsg_num_list 関数抜けた瞬間に msglist の内容が消えるだろ
>>857 おいおい。
autoの場合、msglistというポインタ配列は消えるが、その要素が指していたものは文字列リテラルだから消えないぞ。
staticつけたのはその配列を呼び出しのたびに作るのは無駄だと思ったから。
>>858 > その要素が指していたものは文字列リテラルだから消えないぞ。
そうなん?
>>859 そうなの。で、書き換えようとしてはいけない。
>>858 >その要素が指していたものは文字列リテラルだから消えないぞ。
そうなんですか。
あれ? ということは、
char *errmsg_num_list(int errnum) {
return "error message!";
}
としても平気ということですか?
>>858 =
>>860 > autoの場合
というのが激しく気になったので
auto でない場合を含めて詳しく説明してもらえませんか?
>>863 と聞く前にK&R本をひもといてみると・・・
「auto記憶クラス指定子 ……260」
これかな?
だめです。理解不能です。
>>861 そうそう。もしswitchでやるならそうしよう。
>>862 autoだろうがstaticだろうが文字列そのものは同じところにおかれる。
少なくともプログラムの実行中は常に存在する。
問題はそれを指すポインタの配列がどこにつくられるか。
autoならスタックなどに呼び出しのたびに作られる。抜ければ消える。
staticならプログラムの実行中は常に存在する。
つまり&msglist[4]はstaticならOK(型の不一致は別として)だが、autoならまずい。
>>863 自動変数ってこと。
普通はつけない。関数内ではつけなければautoだから。
>>867 なるほど、「自動変数」=「動的な局所変数」で、
対義語は「静的な局所変数」(static)ですね。
>>856 printf系に統一かなるほど。
俺も文字列の出力は大抵printfだな。統一というかCといえばprintfだから(^_^;)
>>866 > 少なくともプログラムの実行中は常に存在する。
確かに,少なくとも文字列は
テキストセグメント(セグメント云々の話はともかく)には
存在し続けるはずだよなぁ…
でも…なんか納得できないなぁ…
>>872 こんなのがあるんだ。。strerror_rと同じように作ってみようかな。
でも、なんで悪い仕様なんですか?
ところで、manによく「スレッドセーフ」という言葉が出てきます。 (今回のstrerror/strerror_rやstrtok/strtok_rなど。) numlist.cは「スレッドセーフ」になってるでしょうか? 後々どんな状況で使うことになるか分からないので。。。 「スレッドセーフ」でない関数を呼ばないことと、 static変数を使わないことに気を付ければいいだけでしょうか?
>>873 書き換えてはいけないならなぜ静的バッファなんか使うんだよーと。
関数ポインタを使って状態遷移を実現したいのですが 上手い宣言の書き方がわかりません。 typedefを使えば出来るそうなのですが、どのように書けば良いのでしょうか。
>>871 実行時の話をC的にこうかくと納得できるかい?
addr:0x10 {NULL, NULL, 0x100, 0x200}
addr:0x100 "memory allocation failed!"
addr:0x200 "invalid character!"
const char *msglist[4];
memcpy(msglist, 0x10, sizeof(msglist));
staticなら,&msgstrが不変,memcpyの初期化も一度きり。
autoだと,&msgstrが呼び出し毎に変化,
呼び出し毎にmemcpyで0x10から配列の内容がコピーされる。
これらと関係なく,0x100や0x200の文字列はいつでも呼び出しOK。
>>874 2つの文字列を同時にパースしてみそ、strtok使って。
たぶん困ると思うが、それが「スレッドセーフではない」問題の例だ。
>>877 > addr:0x100 "memory allocation failed!"
> addr:0x200 "invalid character!"
これらがロードされたプログラム中(=テキストセグメント)に常に存在することは分かります
が,文字列定数はこのように特別扱いされるものなのでしょうか
まあ,実際に実行してみれば納得するのでしょうが…
>>837 次のように段階的に処理すると簡単になるかも
1.与えたリスト文字列を扱いやすい形式に変換
2.扱いやすい形式から整数配列の必要要素数を取得,整数配列確保.
3.扱いやすい形式から整数配列へ整数の書き出し
ここで,扱いやすい形式というのは,「範囲」構造体の配列(と配列要素数).
"1-3,30,5-3" → { {1,3}, {30,30}, {5,3} }
のように変換してしまえば,整数配列に必要な要素数の計算も簡単,整数の書き出しも簡単.
(30 のような単項は 30-30 のような範囲として扱う)
parse_num_single() は 1 や 3 や 30 のような整数を返すことに専念.
parse_num_section() は {1,3} や {30,30} のような「範囲」を返すことに専念.
parse_num_list() は { {1,3}, {30,30}, {5,3} } のような「範囲」配列を返すことに専念.
整数配列の必要要素数の取得や,整数の書き出しは
「範囲」配列を用いて行う関数を作成する.
typedef struct { int begin; int end; } range_t; /* 範囲型 */ range_t *range_array = malloc( sizeof(range_t) * (strlen(string) / 2 + 1) ); int range_count; errcode = parse_num_list( string, range_array, &range_count); みたいな感じになるかなぁ. range_array は要素数 strlen(string) / 2 + 1 で動的確保すればいいと思う. 最悪でも,string = "1,2,3,4,5" のように,「項」の数は string の長さ / 2 + 1 だから.
>>879 別に文字列に限ったことじゃない。
ポインタと配列は違う。それだけ。
文字列を配列と勘違いしちゃ,駄目♪駄目♪
てっきり,ポインタと配列の複合で混乱してるものと勘違い。
>>882 いや,const int型ローカル変数へのポインタを返しても同様になるんですか?
int *int_ptr(void) { const int i = 3; return &i; } char *str_buf(void) { const char s[] = "abc"; return s; } char *str_ptr(void) { const char *s = "def"; return s; } int main(void) { int *ip; char *sb, *sp; ip = int_ptr(); sb = str_buf(); sp = str_ptr(); /* 関数呼び出しなど,スタックを使った処理 */ printf("*ip = %d, sb = %s, sp = %s", *ip, sb, sp); return 0; }
>>885 それじゃ,char *string="aaaaaa"; は文字列のポインタというべきなのか?
言語のドキュメント書いてないから,用語の扱いが自分でもちと怪しい。
>>883 const修飾子は一切関係ない。
一番の基本はポインタの参照先が static か non-static か。
>const int型ローカル変数
は,non-staticだから,そのポインタをreturnしちゃ駄目。
>>886 配列に初期値与えると,staticな領域から,
自分自身にデータコピーしちゃうんだよぉ。
嘘いってないよ〜。
ポインタなら,staticな領域のアドレス保持するだけ。
>>888 ありがとうございます!
後でじっくり研究してみます。
890 :
デフォルトの名無しさん :03/09/22 00:12
#include <stdio.h> int main(void) { printf("%cは文字です。\n",'A'); printf("%dは整数です。\n",123); printf("%fは少数です。\n",10.5); return 0; } と書いてビルドをしたんですが 「HelloWorld.c error LNK2005: _main は既に HelloWorld.obj で定義されています。」 「HelloWorld.c fatal error LNK1169: 1 つ以上の複数回定義されているシンボルが見つかりました。」 とエラーが起きてしまいます。 どこに間違いがあるのでしょうか?
>>887 >885は、「リテラル文字列は配列だ」だろう。
char *string="aaaaa"はcharへのポインタに静的な配列のアドレスを代入しているだけ。
つまり、stringの指す先がたまたま静的な領域だってだけだね。
char string[]="aaaaa"はcharの配列に静的な配列の中身をコピーしている。
つまり、stringは動的な配列。
sizeof "aaaaa"とsizeof *stringとsizeof string[]をそれぞれ表示してみるといい。
>>890 そのプログラムは間違ってない。(誤字は別としてw)
たぶん、前に作ったHello Worldプログラムが残っててそれも一緒に
リンクしようととしてるんでしょ。
何のツールを使ってるか判らんけど、どこかに「プロジェクトの新規作成」
みたいなのがあると思うから探してみ。
開発ツールの使い方はすれ違いだから、探して判らなかったら当該ツールの
スレで質問してちょ。
>>892 解決しますた!(・∀・)サンクス!!!
>>890 そのソースのファイル名と
プロジェクト内のソースのファイル名を晒せ
新着確認せずにレスしてしまった…
ドンマイ
もうひとつ質問させてください。 #include <stdio.h> int main(void) { printf("10進数の10は%dです。\n", 10); printf("8進数の10は%dです。\n",010); ptintf("16進数の10は%dです\n",0x10); printf("16進数のFは%dです。\n",0xF); return 0; } と書いてビルドすると 「c:\documents and settings\袋井謙一郎\my documents\visual studio projects\vsmacros71\mymacros\helloworld.c\sample\sample1.cpp(7): error C3861: 'ptintf': 識別子は、引数依存の照合を使用しても見つかりません。」 というエラーメッセージが出てきます。 なにが原因なのでしょうか?
なんか887は「スタック領域にないものは配列とは言わない」と読める
袋井謙一郎
名前でちゃった・・・
ptintf → printf
ケコーン
(・∀・)プティントフ!!
907 :
デフォルトの名無しさん :03/09/22 11:27
Cで実行中のプログラムのメモリ使用量を表示するプログラムを作りたいのですがどうすればいいですか? タスクマネージャとかはなしで。
#define STR_1 "あいうえお" #define STR_2 "かきくけこ" というのがあって、 char str[] = STR_1 STR_2; と書くと char str[] = "あいうえお" "かきくけこ"; と展開されてコンパイルが通るんですが、 char str[] = "あいうえおかきくけこ"; というの以外はエラーになると思ってたので 意外なんですが、文法的に正しいんですか?
909 :
デフォルトの名無しさん :03/09/22 12:29
>>908 隣接する文字列定数はひとつに結合される。
>>907 1バイトづつ動的に確保して、確保が失敗したところで何バイト確保できたか調べる。そしてそれを総容量から引けば使用量が出るって寸法よ。
>>911 1バイトづつ確保しても 管理用の領域はそれ以上取られるからそれでは上手くゆかないと思うよ
それ以前に消費メモリーは動的に確保されたものだけじゃないだろ。
907も911も、バカさ加減がそっくりだ。
>>907 #include <sys/sysinfo.h>
int sysinfo(struct sysinfo *info);
…え,Windows?
>>907 Win32APIならこの辺か?
GetProcessMemoryInfo
GlobalMemoryStatus
917 :
デフォルトの名無しさん :03/09/22 13:57
K&Rの演習1-16の題意がよくわらかないんですが、何をしたらいいんでしょうか? 一番長い行を印字するっていう目的は忘れていいんですかね? Revise the main routine of the longest-line program so it will correctly print the length of arbitrary long input lines, and as much as possible of the text.
918 :
初心者です :03/09/22 14:01
2次元配列をポインタで渡せますか? char a[4][4],b[4][4],c[4][4];等、いっぱいあるうちのどれかを渡したいのですが。 受け側では、x[4][4]として参照したいのですが‥。
あ、改定しろって言ってるからプログラムの目的は変わらないのか。 MAXLINEを超える字数があったとしても、 正しい行の長さと、可能な限りのテキストを表示させろってことであってますかね…?
>>918 受け側の関数を、
void test(char x[][4])
と書けばよい。他にも書き方はあるけどね。
921 :
初心者です :03/09/22 14:22
>>920 ありがとうございます
実は受け側が割り込み処理でして、引数として渡せないんです。
何か別法は‥
>>919 それで、あってる。
久しぶりに、K&Rを引っ張り出して読みふけってしまった。
くしゃみが止まらない。
>>921 割込み処理を書く初心者、ってのが想像しにくいんだが・・・
アセンブラのエキスパートでC言語は初心者、ってこと?
char *x[4];
x = a;
924 :
デフォルトの名無しさん :03/09/22 15:45
プログラムを実行してからの実行時間をプログラムに定期的に表示させるには どのようにしたら良いですか? 例えば for ループでひとまわりする毎にその時点での実行時間を 表示させたいのですが。
>>924 プログラムの冒頭で time_begin = time();
実行時間を表示させたいときに time_now = time();
time_now - time_begin
が経過秒
>>923 ありがとうございます。ほこりっぽいんですか
僕のはまだピカピカです。
928 :
デフォルトの名無しさん :03/09/22 16:17
>>929 char *x[4]; /* char * 4個分の配列 */
x = a;
↑配列名に代入しているじゃん。
ごめん char (*x)[4]; だった。 漏れも、K&R勉強し直さないといけないな。 逝ってくる。
おばかな質問なんですが たとえば2次元配列 a[100][100]; とありまして。 main() { char a[100][100]; test( (char **)a ); } a( char **a ) { a[0][0] = '1'; } とか参照と格納方式は誤ってるでしょうか? えらいひとおしえてください
>>932 > test( (char **)a );
> a( char **a ) {
明らかに駄目だろ
>>933 miss
test( char **a) {
a[0][0]='1';
}
の誤り。つまりメインから2次元の呼び方なのれす
すんません
>>934 main() {
char a[100][100];
test( a );
}
test( char a[][100] ) {
a[0][0] = '1';
}
キャストすればいいというものではない
>>935 例では1個だけなんですが、実際は中で文字型とかつかったりしてたので。。。
>>936 どもありがとうございます!
さっそく参考にしてみます。
ありがとうございます
>>937 関数の型を省略するとintを返す関数と見なされる。
>>937 おまえ、すげぇ馬鹿
それならとっくの昔に答えてやったろ。
940 :
デフォルトの名無しさん :03/09/22 17:28
すいません。誰かCで画像のパターン認識をするソース持ってないですか?載せてもらえると有り難いです。
>>940 パターン認識の方法ぐらいかけ
そしたら次はprg中での画像の扱い方について突っ込んでやるから
すいません。 C言語を始めて1ヶ月ぐらいの者です。 学校でですが・・・。 気になったのが、構文で if とか for とか whike は 関数ですか? 上記のやつを使うときは () ← これでくぐりますよね。 だから、関数と思いました。違うんでしょうか?
945 :
初心者です :03/09/22 18:07
>>ALL みなさん、ありがとうございます。試して見ます。
>>944 違う。
whikeは関数かも知れない(w
あっ 間違えてしまいました。 whike じゃなくて while でした。 whike もしこれだと自作の関数になってしまう恐れがありますね。 そうですか。わかりました。
948 :
初心者です :03/09/22 18:31
わっ、出来た!感激です。先輩方、ありがとうです!
>>947 whike = ホワイク
whike = ホワイク
whike = ホワイク whike = ホワイク
whike = ホワイク whike = ホワイク
whike = ホワイク
950 :
デフォルトの名無しさん :03/09/22 20:20
うぃけ
951 :
デフォルトの名無しさん :03/09/22 20:24
スレ立ててこよう
952 :
デフォルトの名無しさん :03/09/22 21:37
#include <stdio.h> void main() { printf("hello"); } というソースで ビルドの時に エラー E2209 a.cpp 1: インクルードファイル 'stdio.h' をオープンできない エラー E2268 a.cpp 4: 未定義の関数 'printf' を呼び出した(関数 main() ) というエラーがでました。なぜでしょうか。また対処法を教えてください
カンでレスすると、stdio.hのあるディレクトリにパスが通ってない 環境書いてみ?
954 :
デフォルトの名無しさん :03/09/22 21:43
どういうことですか?
956 :
デフォルトの名無しさん :03/09/22 21:57
952はソフト開発には向いてないようですね
・・・なんか段々凄いスレになってきましたね・・・
>>952 インクルードパスが通ってないってこと。
コンパイラがstdio.hってファイルを見つけることができなかったってことだよ。
埋め立て
VC++でのremoveとrenameの使い方を教えてください。 何度も試してるんですが出来ません。 文法はサイトなどでしらべてあってるはずです。 なにか使えない理由とかあるんでしょうか?
>>961 どれだけマルチすりゃ気が済むんだ?
吊ってこい
馬鹿はバットファイルでもかいてろよ
964 :
デフォルトの名無しさん :03/09/23 14:39
>>959 では、どうすれば改善されますか?教えてください
>>964 >環境はBorland C++ ver.2.31です。
フリーのコンパイラ?
バッチファイルのことか(w
>>964 コンパイラ導入の過程をもれなくこなしたか確かめろ
968 :
デフォルトの名無しさん :03/09/23 14:53
それがこなしてないかもしれないんです 一度Borlandを消してもう一度DLしてやりたいのですが きちんとインストールできなかったみたいで アンインストールできません。 だからBorlandのファイルをすべて消去しようかとおもうんです。 しかし、ファイルをけしてしまうとwindowsと共有するファイルが あったらOSがこわれますよね だから困ってるんです。(* ̄ロ ̄)
>>968 アンインストールできないなら
上書きでインストールも無理?
970 :
デフォルトの名無しさん :03/09/23 14:57
このBorlandは親戚がメッセで送ってきたんです。 だから不充分な所があるかもしれないので 上書きしてみます。
割れ厨キタ━━━━━(゚∀゚)━━━━━!!!!
前橋は割れ厨
973 :
デフォルトの名無しさん :03/09/23 16:27
いやまて。 BCBはさすがにメッセンジャでは送れんだろ BCCならフリーだったかと。
1000!!!
>(* ̄ロ ̄) 困っているようには見えない例。
スレとあんま関係ないんだけどさ、
昨日吉野屋行ったんですよ、吉野屋。
そしたら、なんか人大杉で書き込めないんです。
>>983 最近の吉野屋では、にちゃんねるに書き込みできるのか。
吉野家が経営不振で松屋になってたんです
吉野屋、メニューが色々選べたらいいのになあ
>>986 いろいろ選べるぞ。
並・大盛り・特盛り・つめ・ひや・なし・だく・だくだく・ねぎだく・・・
ああ、つかれた。もうダメぽ。
一つのスレが終りを告げるとき
1000キター
993
やたな
コーヒー飲っと♪
旦
1000ゲット
C言語なら俺様に聞け!
1001 :
1001 :
Over 1000 Thread このスレッドは1000を超えました。 もう書けないので、新しいスレッドを立ててくださいです。。。