1 :
デフォルトの名無しさん :
2007/01/29(月) 19:03:00
>>1 乙様です。
早速ですが、↓マクロについて教えてもらえますか
#define ROUND_TO_INT(x) ((int) ((x)+(((x)>0)?0.5:-0.5)))
size = ROUND_TO_INT(sqrt(dx*dx + dy*dy));
のような使い方をするようなんですが、さっぱりです。
>>2 それは x が 0 より大きければ 0.5 を足し、0より小さければ 0.5 を引く。
それから int 型にキャストする。
ということだ。
何が起こるかというと、四捨五入。
つまり、 x がたとえば 3.4 だったとすると 0.5 足されて 3.9になる。
それから int 型にキャストするので 3 になる。
3.5 だったら 0.5 足されて 4.0 になってそれから int 型にキャスト
するので 4 になる。
>>3 回答感謝します。
四捨五入でしたか。マクロの見方もわかりました。
ソース上で数値を扱う場合、 プログラムの軸構造を無惨に変更する(?)#defineは使わず、 enumを使うべきだと習いました。 無惨に変更するって、#defineはCソースでよく使われていると 思いますが、問題を抱えているんでしょうか?
#define は危険って言っても、 適正な使い方をする分には問題ないし、 連続定数以外は #define した方がいいと思われ。 連続定数以外に enum 使うのは可読性が悪い気がする。 goto は絶対使っちゃダメ、っていうぐらい極端な思想だと思う。 C++ なら const 定数をその代わりとして使えるから、 #define は使わないんだけどね。
7 :
5 :2007/01/29(月) 21:31:04
>>6 ありがとうございます。
>#define は危険って言っても、
>適正な使い方をする分には問題ないし、
>連続定数以外は #define した方がいいと思われ。
わかりました。
>連続定数以外に enum 使うのは可読性が悪い気がする。
そうですね。
>goto は絶対使っちゃダメ、っていうぐらい極端な思想だと思う。
>
>C++ なら const 定数をその代わりとして使えるから、
>#define は使わないんだけどね。
はい。
C言語でExcelの作成のデータベースファイルを読み込む場合、 ランダムで1行読み込ませるにはどういう方法をとればいいでしょうか またランダムであっても出力する行に偏りを出すことは可能でしょうか
>>8 いったん全データを取り出し、行数を数えてから
ランダムで行を取り出せばいいんじゃね
後半は何言ってるか分からんが、
偏らないランダムなんてランダムじゃないよ
>>9 自分である程度狙った結果を出せるか、という意味です
例えば漢字のみの名前とひらがなのみの名前で構成されたデータベースで
漢字の名前が比較的出力されやすいように・・・といった感じです
>>7 デバッガで追いかけっこをするときはenumを使っていた方が幸せになれるかもしれない。
>>11 最近はマクロもインテリセンス効くけど、それじゃダメ?
ああ、インテリセンスじゃないや。 いや、インテリセンスもだけど、 マウスカーソル置くと数値の出てくるアレ。
14 :
デフォルトの名無しさん :2007/01/30(火) 12:29:34
プログラムの中で配列(要素数が大きい)を定義して、それが例えば200MBの領域だったとしたら、 メモリがそれ以下のPCでそのプログラムを実行することはできないのでしょうか?
>>14 できる
極端にスペック足りないとできない
17 :
14 :2007/01/30(火) 15:06:03
↓の関数の使い方がわかりません。 int addname(Nameval newname) { Nameval *nvp; if (nvtab.nameval == NULL){/* 一番最初 */ nvtab.nameval = (Nameval *)malloc(NVINIT * sizeof(Nameval) ); if (nvtab.nameval == NULL) return -1; nvtab.max = NVINIT; nvtab.nval = 0; }else if ( nvtab.nval >= nvtab.max ) { /* 伸張 */ nvp = (Nameval *)realloc(nvtab.nameval, (NVGROW*nvtab.max) * sizeof(Nameval) ); if( nvp == NULL ) return -1; nvtab.max *= NVGROW; nvtab.nameval = nvp; } nvtab.nameval[nvtab.nval] = newname; return nvtab.nval++; }
構造体は、↓です。 typedef struct Nameval Nameval; struct Nameval { char *name; int value; }; struct NVtab{ int nval;/* 値の現在の個数 */ int max;/* 割り当て済みの値の個数 */ Nameval *nameval;/* 名前-値ペアの配列 */ } nvtab; enum{NVINIT = 1, NVGROW = 2};
20 :
18 :2007/01/30(火) 19:11:18
↓こういう風に使うと、コンパイルは通りますが、 問題が発生したため、○○.exeを終了します、というエラーが出ます。 どこがいけないのでしょうか? よろしくお願いします。 void func_test() { Nameval newarray0 = { "tarou", 0x44 }, newarray1={ "shinzo", 0x88 }; if ( addname( newarray0 ) == -1 ) { return; } if ( addname( newarray1 ) == -1 ) { return; } cout << "\nnvtab.nameval[" << "0" << "].value" << nvtab.nameval[0].value << '\n'; cout << "\nnvtab.nameval[" << "0" << "].value" << nvtab.nameval[1].value << '\n'; } ※ 環境はVS C++ 2005 Expressです。
ここC言語なんだけどなぁ nvtabはどこにあるの?main の中?グローバル? 構造体NVtabのnamevalメンバはいつNULLで初期化?0埋め保障されてたっけ? あと関係ないけど NVINIT を 列挙型で宣言ていうのはどーかと思うけど
>>18 普通に動いた。
実際にエラーの出るソースコードでは、自動変数の寿命のこと考えてる?
>>18 出せる情報は隠すな。
これはエラーが出るコードではないだろ?
24 :
18 :2007/01/30(火) 20:00:59
すみません。説明不足でした。 ファイルをわけています。 //Sort_02_01.c int addname(Nameval newname) { //(18の内容)// } //SortData.h typedef struct Nameval Nameval; struct Nameval { //(19の内容)// }; struct NVtab{ //(19の内容)// } nvtab; enum{NVINIT = 1, NVGROW = 2};
>>18 どこでエラーになったかわからないなら
デバッグ手法を考え直したほうが後々の為
26 :
21 :2007/01/30(火) 20:03:30
>>18-20 >>24 構造体NVtabのnamevalが最初にNULLでない場合不正なアドレスにアクセスする可能性あるのと
nvtabが下の関数から出た後に nvtab.nameval[nvtab.nval].name にアクセスするとダメだね
void func_test()
{
Nameval newarray0 = { "tarou", 0x44 }, newarray1={ "shinzo", 0x88 };
・・・・・・・
}
>>22 さんも言ってるけどnewarray0とnewarray1を
関数 addname のnvtab.nameval[nvtab.nval] = newname でコピーしてるよね
でもnvtab.nameval[nvtab.nval].name は newarray0.name のアドレスをコピーするだけで文字列用のメモリは確保しない
Nameval.name の生きている時間はnewarray0と同じでnewarray0は関数func_testが終了すると消えちゃうから
nvtab.nameval[nvtab.nval].name のポインタも関数func_test以外では有効ではなくなる
関数func_test以外でnvtab.nameval[nvtab.nval].nameにアクセスすると不正処理で落ちるよ
27 :
18 :2007/01/30(火) 20:07:55
//main.cpp
void func_test()
{
//(20の内容)//
}
int main()
{
func_test();
}
>>21 cppですが、C言語の文法しか使っていないので、
ここで質問させてもらいました。
>>18 cout << "\nnvtab.nameval[" << "0" << "].value=" << nvtab.nameval[0].value << '\n';
cout << "\nnvtab.nameval[" << "1" << "].value=" << nvtab.nameval[1].value << '\n';
↓
cout << nvtab.nameval << endl;
//cout << "\nnvtab.nameval[" << "0" << "].value=" << nvtab.nameval[0].value << '\n';
//cout << "\nnvtab.nameval[" << "1" << "].value=" << nvtab.nameval[1].value << '\n';
にして実行してみて。
もし 0x00000000 が出力されたとすれば nvtab の実体が複数あるのが原因
29 :
21 :2007/01/30(火) 20:27:48
>>27 cout ってC++じゃなかったっけ?まぁ細かいことはいいや
そうだね
ヘッダ内で
struct NVtab{ //(19の内容)// } nvtab;
の宣言してるから
各ソース //Sort_02_01.c と //main.cpp の両方に別々の nvtab が存在してることになるね
30 :
18 :2007/01/30(火) 20:35:27
>>28 >もし 0x00000000 が出力されたとすれば nvtab の実体が複数あるのが原因
0x00000000が出力されました。
自分、構造体がよく分かってないようですorz
nvtabは、関数func_test()とaddname()で
(それぞれincludeしているので)
2つ存在してしまっているということですか?
ってことはこの構造体の宣言をglobalですればOKですよね?
struct NVtab{
int nval;/* 値の現在の個数 */
int max;/* 割り当て済みの値の個数 */
Nameval *nameval;/* 名前-値ペアの配列 */
} nvtab;
31 :
21 :2007/01/30(火) 20:37:34
あっ だからなんだ?ってかんじか
>>27 ソースを分けないでひとつのソースファイルにしてコンパイルするか
nvtabの実体はmainソースにおきヘッダでは型宣言のみで extern 宣言するとか
32 :
18 :2007/01/30(火) 20:38:08
みなさん、回答ありがとうございました。 (私自身が、混乱していて申し訳ないです。) これから修正してみようと思います。
33 :
21 :2007/01/30(火) 20:40:30
リロード忘れた
>>30 >>nvtabは、関数func_test()とaddname()で (それぞれincludeしているので) 2つ存在してしまっているということですか?
その通りです
>ってことはこの構造体の宣言をglobalですればOKですよね?
今現在グローバルで宣言してますよ
→
>>31 >>32 またのおこしをお待ちしております
34 :
18 :2007/01/30(火) 21:25:02
できましたぁ。ありがとうございました!
#defineによる定数と列挙型定数の、使い分けの指針みたいなものを教えてください。
36 :
デフォルトの名無しさん :2007/01/30(火) 21:37:04
「バイナリファイルはテキストファイルよりもデータ効率がいい」と習ったんですが、下のコードを実行してできたファイルのサイズを 見てみるとテキスト18バイト、バイナリ20バイトになっています。バイナリのほうが効率がいいなら、サイズは小さくなるのではないでしょうか。なぜサイズにこのような違いがでるのか教えてください。よろしくお願いします。 #include<stdio.h> #include<stdlib.h> int main(void){ FILE *f,*g; char line1[10] ="分からん"; char line2[10] ="助けて"; f = fopen("a.txt","w"); if(f==NULL){ printf("open error\n"); exit(1); } fprintf(f,"%s\n",line1); fprintf(f,"%s\n",line2); fclose(f); g = fopen("a.b","wb"); if(g==NULL){ printf("open error\n"); exit(1); } fwrite(&line1,sizeof(line1),1,g); fwrite(&line2,sizeof(line2),1,g); fclose(g); return(0); }
>>35 >#defineによる定数と列挙型定数の、使い分けの指針みたいなものを教えてください。
The Practice of Programming(ブライアン カーニハン)には、
「マジックナンバーは#defineでなく、enumを使おう」
と書いてありました。
ですので、私はdefineをあまり使いません。
38 :
21 :2007/01/30(火) 21:46:17
>>35 指針?わかりません
私は、順序が必要かグループとして(関連性のある)くくりたい定数はenum、それ以外はdefine にしてる
>>36 文字列の場合はバイナリもテキストもほぼ一緒です
数値保存するさいはたとえば 4000 という数字を保存したい場合
テキストは4バイト、バイナリなら2バイトで済みます(パック10進数やゾーン10進数などはこの限りではありません)
39 :
21 :2007/01/30(火) 22:00:35
>>35 あっそーそー
あとその定数の値そのものが意味のあるものの場合はdefineで、数値そのものには意味はなくあくまで識別することが目的なら enum とか
たとえば
>>24 さんのenum{NVINIT = 1, NVGROW = 2}; で説明させていただきますが(
>>24 さんゴメンナサイ)
これがenum{NVINIT = 2, NVGROW = 1}; になってた場合意味が変わってしまいますよね
こういうときは define にします
enum{left=1,top=2,right=3,bottom=4}
これは enum{left=4,top=3,right=2,bottom=1}
だったとしても意味は変わりませんよね
enum week{ sunday=1,monday,・・・} などもそうですね
(インデックスから曜日を求めるとか演算の対象とする場合は意味が変わってしまいますが、それは除いて)
あくまで、<私は>ですのでね、公式にどうするのかは知りませんよ
40 :
36 :2007/01/30(火) 22:06:15
>>38 ありがとうございます。intだけを書き込んでみたら確かにバイナリのほうがサイズが小さくなりました。データ効率がよいといっても型によってはテキストよりもバイナリのファイルサイズのほうが小さいとは必ずしも言えないということですね。
41 :
35 :2007/01/30(火) 22:16:22
42 :
21 :2007/01/30(火) 22:19:40
>>40 そうです
それと
>>36 のプログラムで2バイトの差が出てますね
これはテキストの場合 分からん(改行)助けて(改行)
fprintf(f,"%s\n",line1); ←これが文字列のみ出力し次に改行を出力します
バイナリの場合 分からん(NULL)(改行)助けて(NULL)(改行) になっているからです
( fwrite(&line1,sizeof(line1),1,g); はsizeof(line1),による書き込み文字数にNULL(0)も含まれているため、そのNULL(0)も書き込んでいるためです
このプログラムの場合NULL(0)を含まないようにすればバイナリとテキストは同じサイズになります
>>39 まあ、普通はそういう使い分けは勧められないね。
44 :
21 :2007/01/30(火) 22:30:11
45 :
36 :2007/01/30(火) 22:41:49
>>42 なるほど!何度もありがとうございました。
>>44 プログラミング作法の41ページに書いてあるよ。
47 :
21 :2007/01/30(火) 22:55:18
48 :
デフォルトの名無しさん :2007/01/30(火) 23:07:41
if(true || F()){ //この時、関数F()の実行は保障されるのか? }
49 :
21 :2007/01/30(火) 23:09:22
trueってなんじゃい? if(1 || F()) {} ならF()が実行されないことは保証される。
30!のなんてどうやって求めればいいんだ? オーバーフローっていうレベルじゃねぇーぞ!
答えだけ教えてあげるね。 30!=265252859812191058636308480000000
53 :
デフォルトの名無しさん :2007/01/31(水) 03:51:59
#include <stduo.h> main(){ printf("5+5は%dです。\n",5+5); printf("5−5は%dです。\n",5-5); printf("5×5は%dです。\n",5*5); printf("5÷5は%dです。\n",5/5); printf("5÷3の余りは%dです。\n",5%d3); return 0; } これで、何故これらは宣言をしなくても、かってに代入されるのでしょうか? 普通なら int a = 5; など宣言をするはずですが・・・。
>>53 そのソースでは、
代入すべき変数はなさそうだけど、どこに代入するのん?
宣言すべき変数はなさそうだけど、何を宣言するのん?
それと、5%d3は5%3の間違い、stduo.hはstdio.hの間違いだよね?
>>53 C++なら一時オブジェクトなどと説明されるのだろうが、
Cなら関数の引数には値を取る事が出来るので、計算式の
結果が値として渡されるという事でよいだろう。
&(5 + 5) などとやると当然エラーになる。
56 :
デフォルトの名無しさん :2007/01/31(水) 04:43:43
レス、ありがとうごいます。
>>54 すみません、書き間違いでした
>>それと、5%d3は5%3の間違い、stduo.hはstdio.hの間違いだよね?
では、代入すべき変数や宣言がない時は、printf("5+5は%dです。\n",5+5);
で、かってに, 5+5 が代入されるのでしょうか?
>>55 何故、自動で計算結果が出るのでしょうか?
>>56 いや、代入っていうのは普通、
変数として用意されたメモリ領域に値をコピーすることをいうのだと思うよ。
printf("..", 5+5);における5+5は代入と呼ばれる操作ではなく、
printfという関数へ与える実引数の値を計算する式だ。
正確な説明でも何でもないけど、 代入という言葉は「変数=値」の形の時に使われて、 printf("5+5は%dです。\n",5+5)は関数呼び出しという別の操作。 関数呼び出しは、「関数名(値,値,...)」の形をしていて、 5+5というのは、その値を計算するための式、というのではどうかね? 5+5を計算した後の値は一般の変数ではなく、別のメモリ領域に置かれる。
59 :
デフォルトの名無しさん :2007/01/31(水) 05:08:37
ひ〜難しい… 頭を冷やしてから考え直してきます、サンクスですた。
ソース上の変数やリテラルはメモリのどこに配置されるか考えるといい でもその式は実行時じゃなくてコンパイル時に計算される
テキストファイル読み込んで、 ファイル内の指定した行を削除するにはどうしたらいい? 俺の頭の中では、 fp = fopen("2ch.txt","w+"); if(fp == NULL) printf("\aファイルをオープンできません。\n"); else { /*ここで何かするのかなって思ってるんだけど*/ fclose(fp); } どうすりゃいいのか分かんなくて。そもそも"w+"でいいのか? 誰か助けてください。
>>62 ファイルサイズを任意のサイズだけ小さくするような処理はできない
普通は一部分を除いたコピーを作る
65 :
デフォルトの名無しさん :2007/02/01(木) 01:57:09
#include <stdio.h>
main(){
int a = 15, b = 0x11;
printf("10進数の%dは16進数では%X\n",a,a);
printf("16進数の%Xは10進数では%d\n",b,b);
return 0;
}
これで質問なのですが、このソースを実行すると
書式に合わせた結果が表示されますが
これも>>58-
>>57 と同じ様な原理なのでしょうか?
かってに値が変わって表示されますが・・・。
66 :
デフォルトの名無しさん :2007/02/01(木) 02:22:35
#include <stdio.h> main(){ char c = 1; char s[10] = "Hello!"; printf("long型 = %dバイト\n",sizeof(long)); printf("char型変数 = %dバイト\n",sizeof(c)); printf("文字列変数 = %dバイト\n",sizeof(s)); return 0; } エラー E2206 samople2.c 12: 不正な文字 ' ' (0x8140)(関数 main ) 警告 W8004 samople2.c 12: 's' に代入した値は使われていない(関数 main ) 警告 W8004 samople2.c 12: 'c' に代入した値は使われていない(関数 main ) *** 1 errors in Compile *** これの何処が悪いかわかりませんので、ご指摘お願いします。
全角空白
今までボーランドのコンパイラ使ってたんんですが 最近Visual C++に変えました。 VCの場合実行ファイルはどこに作成されるんでしょうか?? 今まではexeファイルができてたんですが、見当たりません。
>>66 ×char c = 1;
○char c ='1';
70 :
デフォルトの名無しさん :2007/02/01(木) 03:21:10
#include <stdio.h> main() { double s; for(s=1.0; s<=1.5; s+=0.1) printf("s=%f\n", s); } これを実行するとs=1.50000が実行されません。 どうしてでしょうか? 教えてください。
>>70 for(s=10; s<=15; s+=1)
printf("s=%lf\n", s/10);
>>70 for(s=1.0; s<=1.5; s+=0.1) printf("s=%20.18lf\n", s);
にしてみると、本当は何をsに加えていたか分かるよ。
73 :
66 :2007/02/01(木) 03:51:36
ありがとうございました。
×%20.18lf ○%.20g
75 :
デフォルトの名無しさん :2007/02/01(木) 04:10:22
丸め誤差
×%.20g ○%.20a
77 :
デフォルトの名無しさん :2007/02/03(土) 00:51:17
#include <stdio.h> main(){ int i = 1; for(1<4; i++) printf("こんにちは%d\n",i); return 0; } c:\source>bcc32 sample3.c Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland sample3.c: 警告 W8019 sample3.c 6: コードは効果を持たない(関数 main ) エラー E2378 sample3.c 6: For文に ; がない(関数 main ) 警告 W8004 sample3.c 10: 'i' に代入した値は使われていない(関数 main ) *** 1 errors in Compile *** こう表示されてしまいますが、 #include <stdio.h> main(){ int i = 1; for(i =1; 1<4; i++) printf("こんにちは%d\n",i); return 0; } これだと実行できるのは、何故でしょうか?i = 1と宣言を先にしていますが・・・
for(; 1<4; i++)
79 :
デフォルトの名無しさん :2007/02/03(土) 00:54:50
文法ミスだろ
80 :
デフォルトの名無しさん :2007/02/03(土) 02:21:39
>>78-
>>79 ありがとうごいます。
あ〜ようするに省略の ; を付ければいいのでしょうか?
81 :
デフォルトの名無しさん :2007/02/03(土) 02:26:51
#include <stdio.h> main(){ while(a < 5){ printf("%d\n",a); a == a + 1; } これだと、何故無限ループになってしまうのでしょうか? 本の解説に依れば、a == a + 1 は aを増やすところを 誤って書いた。これでは a の値は変わらないので 無限ループになると書いてあります。 これは == の等しいだからいけなく = ならいいのでしょうか(ループにならない)? もしそうだとしたら、どうしてか解説をお願い致します。
82 :
77 :2007/02/03(土) 02:30:43
#include <stdio.h> main(){ int i = 0; for(;0<4; i++) printf("こんにちは%d\n",i); return 0; } これで実行すると無限になってしまいます。 どのようにすれば無限にならないでしょうか?
>>81 日本語でOK
==は関係演算子、=は代入演算子
a==a+1はaとa+1が等しいかどうかを判定して真偽値を返す
a=a+1はa+1の値をaに代入して、その値を返す
=と==は全くの別物だ
85 :
デフォルトの名無しさん :2007/02/03(土) 02:34:59
>>82 0<4
i<4だろ
そこは条件文だから
0<4なら一生trueだ
86 :
82 :2007/02/03(土) 02:38:27
ぐはぁーわけわかめです、サンクスでした、よく考え直します
>>86 for (A ; B ; C) D
は、A → B → D → C → B → D → C → B → D → C →...
とループする。ただし、Bの値で偽になった段階でループを抜ける。
0<4だといつまでたっても真だから無限にループする。
i<4ならループを回るたびにi++でiの値が1づつ増えるから、
いつかはi<4が偽になってループを終えることができる。
88 :
82 :2007/02/03(土) 03:57:27
>>87 要約わかってきました、0<4は最初から既に、4は大きくて当然で
真と言う事ですね。ありがとうごいます。
89 :
デフォルトの名無しさん :2007/02/03(土) 04:00:06
>>83 遅レス、もしわけありません。
>>a==a+1はaとa+1が等しいかどうかを判定して真偽値を返す
例えば等しくなければ偽と言うことでしょうか?
それで、>>a == a + 1; だと無限になってしまうかが
疑問です
90 :
82 :2007/02/03(土) 04:06:02
#include <stdio.h> main(){ int i = 0; for(;0>4; i++) printf("こんにちは%d\n",i); return 0; } これを実行しても、 c:\source>bcc32 sample3.c Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland sample3.c: 警告 W8066 sample3.c 7: 実行されないコード(関数 main ) 警告 W8004 sample3.c 4: 'i' に代入した値は使われていない(関数 main ) Turbo Incremental Link 5.00 Copyright (c) 1997, 2000 Borland c:\source>sample3 c:\source> と c:\source>に戻ってしまい、実行ができません。
>>81 無限ループになる以前にそのコード、コンパイルを通らないだろ。
aの宣言と初期化がない。
もし、int a = 5;とかにすれば、無限ループなんかせずにすぐに終了する。
aの値がループを回るたびにどう変化するか、もしくは、どう変化しないかを追ってみろ。
93 :
デフォルトの名無しさん :2007/02/03(土) 04:19:01
#include <stdio.h> main(){ int i ; for(i=0;i<4; i++) printf("こんにちは%d\n",i); return 0; } と書くことで 以下のようになりました D:\lsic330c\BIN>lcc ..\baka.c lld @link.i D:\lsic330c\BIN>..\baka こんにちは0 こんにちは1 こんにちは2 こんにちは3 D:\lsic330c\BIN>
>>90 実行できてるじゃん。
コンパイル時の警告は無視するとして、
何の文句も言わずsample3.exeは異常終了することなく実行を終えてシェルに制御を移している。
>>87 の説明をよく思い出して、0>4が何をやっているか考えろ。
95 :
デフォルトの名無しさん :2007/02/03(土) 04:25:03
96 :
82 :2007/02/03(土) 04:48:31
>>93 このソースでやればできました・・・
>>94 考えれば考える程、自分の頭の中がループしてしまいます
後日出直してきます。
皆さん、サンクスでした!!!
97 :
ビル ゲーシ(^▽^) ◆lHG3Yzo0a6 :2007/02/03(土) 05:03:53
>>96 ガンバレ!
ねぇねぇ、BCCじゃなく、マイクロソフトのVisualC++ 2005express使ってお
これFreeだし、BCCより良いから
やめとけやめとけ、入れたらIP抜かれるぞ
Cの学習用ならbccあたりで十分だ。 初心者のうちに下手にmicrosoftに手を出すと後から取り返しがつかないぞ。
IPを抜かれると何が困るのか具体的に説明してくれ。
101 :
ビル ゲーシ(^▽^) ◆lHG3Yzo0a6 :2007/02/03(土) 05:10:39
#include <windows.h> int main() { MessageBox(0, TEXT("ビル ゲーシ(^▽^) ◆lHG3Yzo0a6"), TEXT("VISTA"), MB_OK); main(); return 0 }
IP抜かれるっていうのはアラブでリチャードがやってくるぞというのと同じ古い時代の伝説的恐怖に基づく脅し文句じゃないかい? たぶん具体的脅威としての警告ではないだろう。
うんちー
104 :
デフォルトの名無しさん :2007/02/03(土) 06:24:26
構造体のポインタの中にあるポインタの実体ってどうやってとればいいのでしょうか? 例えば typedef struct{ int *num; }DATA; ってあって、 int i;DATA *dat; i=dat->num;//これではアドレスが渡されてしまう。 ここを i=*dat->num;にするとdatの実体という意味になってしまいますし。 i=dat->*num;だとエラーになります。
括弧つければ
106 :
104 :2007/02/03(土) 06:32:35
i=*(dat->num); でも 間接指定演算子 (*) の使い方が正しくありません。 ってエラーが出ます。。 i=dat->(*)num; i=dat->*(num); 全部だめでした。。 int i,*pi;DATA dat; pi=dat->num; i=*pi; ってやるしかないんでしょうか…。
i=*dat->num; で問題ないが・・・・・・
ホントにエラーになった?
違うところでエラー出てるんじゃない?datとnumはちゃんと初期化してる?
>>104 本当にint型?
なんとなく本当のプログラムでは別の型になってる気がする。
型キャストを伴うものだと、(hoge &)ってやらないといけない。
Webに接続してる以上 必ず接続先サーバに対してIP公開してるんだよね〜 私ゃ入門用にVSは勧めないなぁ プログラミング専用PCってなら入れるけど 実際は他にも色々やるから テキストエディタ+コマンドラインみたいな 気が向いた時サッと起動する軽い環境が好きだわー
随分古いPCをお使いのようでw
i = *(dat->num);
VS起動に5秒かかるぜ
115 :
デフォルトの名無しさん :2007/02/03(土) 14:10:15
最近C言語を始めて、やっとポインタを理解する段階まできたんだけど 現段階ではポインタの必要性がいまいち理解できない。 たとえば #include <stdio.h> main() { int *p; int a = 100; p = &a; printf("%d",p); return 0; } これで変数「a」に格納された「100」のアドレスを参照できるみたいだけど 何の役にたつの?
>>115 そんな処理じゃ必要ないね。分ってるなら聞くなよ。
何の役にって色々役立つからなぁ。 色んなソース読んでみ? どんな使い方をしてるか考えるといいよ
>>115 小さなデータしか扱わないなら、データ自体のコピーだけでなんとかなるかもね。
>>115 だいたいポインタの表示なら %p だろ
大きな構造体を引数として渡すときはポインタを使うといい。 データを全部コピーする時間が節約できる。 あとは関数から返り値以外になんらかのデータも受け取りたいとき 関数を呼び出すときにデータを格納する変数のポインタを渡す。 多分これらが一番多いポインタの使われ方。 主なもの他に何かあったっけ・・
関数ポインタ
・ リストや木を作るのに必須 ・ 動的にメモリを確保する時に使う
何に使うのかわからないうちは 理解できたとは言えない いずれそのことに気がつくと思う
構造体について質問があります struct HOGE { char name[30]; int number[20]; }; struct HOGE hoge[] = { { "田中","0001"}, { "鈴木","0002"}, }; たとえば、こんな構造体を定義したとして、 この構造体の配列の要素数を求めたい。 しかし、sizeof(hoge)を使っても、224としか出てきません。 どうやったら求められるのでしょうか?
>>124 sizeof a / sizeof a[0]
その手があったのかorz 勉強になります。 ありがとうございました
>>115 たとえば関数を跨ぐ時には使える。scanfなどで使っただろ。ほら、scnaf("%d", &a);のようにして。
128 :
デフォルトの名無しさん :2007/02/03(土) 18:19:49
129 :
デフォルトの名無しさん :2007/02/03(土) 18:23:04
関数の大きさって分からないんですか? int Kansu() { 〜略〜 } int main() { sizeof(Kansu()); sizeof(printf()); return 0; } これなんでできないの?
>>129 関数ってのは関数のコードがある最初のアドレスが入ってるだけ
関数全体のサイズなんて普通知る必要ないし
typedef struct { char* str; } foo; foo bar = {"hoge"}; ってやってもいいの? char* strの配列長は自動的に決めてくれるんでしょうか。
char *str="hoge"; と同じ。やっていいかはその後のstrの操作に拠るけど、変更は不可。 hogeの長さについては自動的に決まる
>112 だってVS以外はそれで充分なんだもの
134 :
131 :2007/02/03(土) 20:11:50
月蝕CDTがそんなに速くなっていたとは驚きだな
#include <stdio.h> struct student_data{ int a; int b; char x[100]; char y[100]; }test; void data_input() { printf("2つの値を入力してください。\n"); scanf("%s",&test.x); scanf("%s",&test.y); } int main(int, char*) { data_input(); printf("x = %s, y = %s, x + y = %d, x * y = %d",test.x,test.y,test.a,test.b); return 0; } に a = x + y; と b = x * y;ってゆう処理を入れたいんですけど どう書けばいいんでしょうか?
137 :
デフォルトの名無しさん :2007/02/03(土) 21:39:41
#include <stdio.h> main(){ int x; int y; printf("2つの値を入力してください。\n"); scanf("%d",&x); scanf("%d",&y); printf("x = %d, y = %d, x + y = %d, x * y = %d",x,y,x+y,x*y); return 0; }
>>136 x と y には何が入るの?
1.一般的な文字列?(氏名とか)
2.0〜9 の数字のみからなる文字列?
もし 2.なら
>>136 のしたいことは下記の事かもしれない
#include<stdlib.h>
test.a = atoi(test.x) + atoi(test.y);
test.b = atoi(test.x) * atoi(test.y);
要するに、何がしたいのかよく分からないのでエスパー回答しかできないってこった
すいません説明不足でした。 数字の文字列でint型のaとbに char型のx + y , x * yの計算結果を入れる処理がしたいです。
大域変数で値を持たしておくのと、関数を毎度毎度用いて値を生成するの、どちらが効率がいい方法なんでしょうか。 やはり、必要とするメモリ数、生成に必要とされる手間に応じて変わるものなのでしょうか。 必要とする間隔は20ミリ秒毎で、必要とするメモリ領域は100バイトほどです。手間に関してはちょっと図る術が分かりません。 アドバイスよろしくお願いします。
まずはベンチマークを取れ。
>>140 シングルスレッドでしか参照しないならどちらでもおk
マルチスレッドで参照するなら関数
個人的には関数のほうがイイと思う(値を保持する領域が固定であったとしても)
143 :
デフォルトの名無しさん :2007/02/03(土) 22:41:02
>>140 その関数にもよるしな
検索性をあげるためにインデックスフィールド持ったりとか
似たような手法はあるし
ディスクスペースが増えるのと矛盾が生じないための管理の手間と
比べてどっちが得かの比較だろう
144 :
デフォルトの名無しさん :2007/02/03(土) 22:43:24
無限ループである処理をしていて何かキーを入力したら 無限ループを抜けるプログラムを教えて下さい。
>>144 #include<stdio.h>
#include<conio.h>
int main(void){
int i;
for(i=0;!kbhit();i++) printf("%d ある処理\n", i);
while(kbhit()) getch();
return 0;
}
146 :
デフォルトの名無しさん :2007/02/03(土) 23:07:49
>>145 回答ありがとうございます。
しかし、私のPCにはconio.hがありません。どうすればいいですか?
ちなみにOSはvine4.0です。
>>140 効率というのがコーディングのことなのか実行時のことなのか分かりませんが
関数を使うにはそれに伴うオーバーヘッドも考える必要があると思います
ちょっとした内容(小さいもの)で頻繁に使用するのならオーバーヘッドによるロスは無視できないでしょう
ただその関数が何をするものなのかによると私も思います
ただ保存してある値を返すだけの関数なら必要ないんじゃないでしょうか
>大域変数で値を持たしておくのと、関数を毎度毎度用いて値を生成する
この内容によりますね
一度作成すれば次から作成する必要ないのならグローバルでもいいと思いますし
アクセスのたびに値が変わるなら関数のほうがいいでしょうし
148 :
デフォルトの名無しさん :2007/02/04(日) 00:06:57
>>146 リアルタイムで動くゲームを作りたいのか、
時間のかかる処理を途中で中断できるようにしたいのかによって違ってくる
>>146 ぐぐればいくらでもkbhitのlinuxポーツあるじゃねえか
>>148 無限ループの外で別の処理があるので
プログラムが終了したら意味がありません。
>>149 後者です。
>>150 初心者なので出来れば詳しくお願いします。
長い計算を中断したくて、途中までの計算結果も無駄にしたくないってことなら、 シグナルで処理するのがよくね?
>>152 シグナルはよく分からないんですが、とにかくキーボードから
入力があったら無限ループを抜けるようにしたいんですが・・・
154 :
デフォルトの名無しさん :2007/02/04(日) 00:59:20
#include <stdio.h> main(){ int i,n; for(i=1;i<=100;i++){ for(n=i-1;n>1;n--){ if(i%n == 0) break; } if(n==1)printf("%d\n",i); } printf("全部表示したぞ!この包茎が\n",i); } 1〜100の素数表示するプログラム書きました。 もっと簡潔なやつや効率いいのはどうすればいいですか。
>>153 「linux signal」とかで検索したら、いっぱいでてくると思われ。
156 :
154 :2007/02/04(日) 01:09:42
個人的に結構いいプログラムだと思う。どうよ
157 :
デフォルトの名無しさん :2007/02/04(日) 01:19:19
総当りっていうな 結局それが一番速かったりするが プログラムの価値はない
>>155 すみません、初心者なのでsignalが理解出来ません。
>>159 conio.hがない場合はどうすればいいですか?
#include<stdio.h> #include<pthread.h> #include<unistd.h> #include<fcntl.h> enum{ THREAD_RUNNING, THREAD_STOPPING, THREAD_FINISH }; int is_enter_pressed(void) { int fd_flag, ret=0; char buf[10]; fd_flag=fcntl(0, F_GETFL); fcntl(0, F_SETFL, O_NONBLOCK); while(read(0, buf, sizeof(buf))>0) /* 不要な入力はすべて読み飛ばす */ ret=1; fcntl(0, F_SETFL, fd_flag); return ret; }
void *aru_shori(void *arg){ int *thread_status; int i; thread_status=arg; *thread_status=THREAD_RUNNING; for(i=0;i<30;i++){ if(*thread_status!=THREAD_RUNNING) return NULL; printf("%s %d ある処理\n", __FUNCTION__, i); sleep(1); } *thread_status=THREAD_FINISH; return NULL; } int main(void){ pthread_t th; volatile int th_status; pthread_create(&th, NULL, aru_shori, (void*)&th_status); printf("Enter を押すと途中で終了します\n"); while(th_status==THREAD_RUNNING){ if(is_enter_pressed()){ th_status=THREAD_STOPPING; break; } sleep(1); } pthread_join(th, NULL); return 0; }
163 :
154 :2007/02/04(日) 01:30:38
>>160 >>161-162 をコピペして全角空白を削除(or 置換)
gcc 〜〜.c -lpthread
でコンパイル、リンク、実行してみて
あと名前とトリップを入れてくれると分かりやすいんだが
165 :
144 :2007/02/04(日) 01:50:58
>>164 ありがとうございます。
しかし、実行してみた所Enterを押しても終了しないのですが・・・
初版の独習Cを500円で買ったけど関数の書き方とかが違う・・・・ 3200円出して第3版の買ったほうがいいかな・・・
>>144 (
>>165 )
下のように変更して実行し、
「aru_shori 4 ある処理」が表示されたあたりで Enter を押した場合には、
どちらのメッセージが出ますか?
pthread_join(th, NULL);
↓
pthread_join(th, NULL);
if(th_status==THREAD_STOPPING)
printf("\n処理が中断されました\n");
if(th_status==THREAD_FINISH)
printf("\n処理は正常終了しました\n");
168 :
144 :2007/02/04(日) 02:10:33
>>167 Enter を押してみましたが1行改行されるだけで何も起きません。
>>144 (
>>168 )
>>161-162 がダメだったということは、多分これもうまくいかないんだろうけど
#include<stdio.h>
#include<unistd.h>
#include<fcntl.h>
int is_enter_pressed(void)
{
int fd_flag, ret=0;
char buf[10];
fd_flag=fcntl(0, F_GETFL);
fcntl(0, F_SETFL, O_NONBLOCK);
while(read(0, buf, sizeof(buf))>0) /* 不要な入力はすべて読み飛ばす */
ret=1;
fcntl(0, F_SETFL, fd_flag);
return ret;
}
int main(void){
int i;
printf("Enter を押すと途中で終了します\n");
for(i=0;i<30;i++){
if(is_enter_pressed()) break;
printf("%s %d ある処理\n", __FUNCTION__, i);
sleep(1);
}
return 0;
}
170 :
144 :2007/02/04(日) 02:20:09
>>169 上手く行きました!!
本当にありがとうございました!
171 :
デフォルトの名無しさん :2007/02/04(日) 02:49:56
mぅいやだあああああ わかねーーーーー
172 :
デフォルトの名無しさん :2007/02/04(日) 03:56:51
#include <stdio.h> main(){ int x,y;/*ループのカウンタ*/ char c;/*キャラクタ番号*/ for(x = 2; x < 8; x++) printf("16: 10:c | "); printf("\n"); for(x = 2; X < 8; x++) printf("---------\n"); printf("\n"); for(y = 0; y < 16; y++) { for(x = 2; X < 8; x++) { c = x * 16 + y; printf("%2x:%3d:%c |",c,c,c); } printf("\n"); } return 0; } エラー E2451 aaa.c 10: 未定義のシンボル X(関数 main ) *** 1 errors in Compile *** これの何が違うかわかりませんので、ご指摘お願い致します。
173 :
デフォルトの名無しさん :2007/02/04(日) 03:58:09
自己解決しマスタ
>>172 #include <stdio.h>
#include <ctype.h>
int main(void)
{
int c;
while ((c = getchar()) != EOF) {
putchar(tolower(c));
}
return 0;
}
このプログラムをコンパイルして実行ファイルを作り、
実行ファイル名 < aaa.c > aaaa.c
と実行して、作られたaaaa.cをコンパイルする。
>>154 >>156 良いかどうかは分かりませんが
#include <stdio>
#define MAX 100
int main()
{
unsigned char c[MAX]={0};
int i,k;
for(i=2;i<MAX;i++)
{
if(c[i]==1) continue;
for(k=i*2;k<MAX;k+=i)
{
c[k]=1;
}
printf("%d\n",i);
}
return 0;
}
#include<stdio.h> main() { int num1, num2, op; printf("number1:"); scanf("%d",&num1); printf("number2:"); scanf("%d",&num2); printf("0to add,1to multiply:"); scanf("%d",&op); if(op==0) printf("%d",num1 + num2); else printf("%d",num1 * num2); } 0を選んでも積を求めてしまうのは何故でしょうか?
177 :
デフォルトの名無しさん :2007/02/05(月) 00:35:53
printf("%d",op); ってみれば何かわかるんじゃない
自己解決しました コードを修正しても上書き保存をしてなかったようです
179 :
デフォルトの名無しさん :2007/02/05(月) 00:48:45
すいません複数のファイル合わせてコンパイルするやり方がわかりません。 くだらない質問ですが初心者に教えてくださいお願いします。
180 :
デフォルトの名無しさん :2007/02/05(月) 01:10:02
#include <stdio.h> main(){ int i; int a[] = {1,2,3,4}; for(i = 3; i >= 0; i--) printf("%d ",a[i]); printf("\n"); return 0; } 実行結果が 4 3 2 1 と表示されます #include <stdio.h> main(){ int i; int a[] = {1,2,3,4}; for(i = 3; i >= 0; i++) printf("%d ",a[i]); printf("\n"); return 0; } こうすると、予期せにエラーが出てしまいますが 何故、-を+に変えただけで、こうなってしまうのでしょうか? ご説明お願い致します、なるべく簡単に・・・・。
iが4以上だと配列aの領域を超えてるだろ。 しかも無限ループだし。
182 :
デフォルトの名無しさん :2007/02/05(月) 01:16:35
i=0だろ
3に1を足すと4になるからです。
184 :
デフォルトの名無しさん :2007/02/05(月) 01:21:53
では、4だと真になり続けてしまうからでしょうか?
>184 a[4]に何が入ってる?
186 :
デフォルトの名無しさん :2007/02/05(月) 01:57:52
無いです
187 :
デフォルトの名無しさん :2007/02/05(月) 02:17:02
質問です #include <stdio.h> main(){ int x,y; int a[2][3] = { {10,20,30}, {40,50,60} }; for(x =0; x < 2; x++){ for(y = 0; y < 3 ; y++) printf("a[%d][%d] = %d",x,y,a[x][y]); printf("\n"); } return 0; } c:\C>sample1 a[0][0] = 10a[0][1] = 20a[0][2] = 30 a[1][0] = 40a[1][1] = 50a[1][2] = 60 入門書の最初の解説では、int a[2][3] [2]がyの要素、[3]がxの要素となっていますが 現に上のソースでは、 [2]がxの要素、[3]がy と なっています、どうして変わっているのでしょうか? int x,y; こう宣言したからでしょうか?
これは関係ないでしょ int x,y; int y,x; ミスをしたんだな。 xは一般的にx軸のことであり横方向であり、 横1行の処理を終えたら次の行というのが多いパターンであり 配列のメモリ上の並び順は a[0][0] a[0][1] a[0][2] a[1][0] a[1][1] a[1][2] だから a[y][x] というのが一般的だと思う。 だから(推測だけど) 入門書の説明しているときは、a[y][x]にする予定だった。 でも実際にプログラムを作るときにミスしたんだよ。
190 :
187 :2007/02/05(月) 03:57:19
>>188 >>189 レス、ありがとうごいます。
>>これは関係ないでしょ
int x,y;
int y,x;
ミスをしたんだな。
そうですか・・・・因みに持っている参考書が二つとも
そうなっています・・・・。翔泳社のです。
191 :
187 :2007/02/05(月) 04:06:57
となると #include <stdio.h> main(){ int x,y; int a[2][3] = { {10,20,30}, {40,50,60} }; for(y =0; y < 2; y++){ for(x = 0; x < 3 ; x++) printf("a[%d][%d] = %d",x,y,a[y][x]); printf("\n"); } return 0; } c:\C>sample1 a[0][0] = 10a[1][0] = 20a[2][0] = 30 a[0][1] = 40a[1][1] = 50a[2][1] = 60 これが正解でしょうか? >>>for(y =0; y < 2; y++){ for(x = 0; x < 3 ; x++) printf("a[%d][%d] = %d",x,y,a[y][x]); を訂正してみました。
×printf("a[%d][%d] = %d",x,y,a[y][x]); ○printf("a[%d][%d] = %d",y,x,a[y][x]); 隙間なく繋がってしまうのもへんだね 以下では 最後にも", "がついてしまうので変だけど printf("a[%d][%d] = %d, ",y,x,a[y][x]); a[0][0] = 10, a[0][1] = 20, a[0][2] = 30, a[1][0] = 40, a[1][1] = 50, a[1][2] = 60,
193 :
誰か教えてください :2007/02/05(月) 16:07:26
自動販売機プログラム
>>193 同時押しに対するインターロックとか
つり銭・返却の取り扱いとか
在庫管理とか
(くじ管理)とか
そういうことを期待してるん?
195 :
187 :2007/02/05(月) 18:09:56
>>192 レス、ありがとうごいます、ですが幾つか疑問点が残ります
#include <stdio.h>
main(){
int x,y;
int a[2][3] = {
{10,20,30},
{40,50,60}
};
for(x =0; x < 2; x++){
for(y = 0; y < 3 ; y++)
printf("a[%d][%d] = %d",x,y,a[x][y]);
printf("\n");
}
return 0;
このソースと
196 :
187 :2007/02/05(月) 18:15:41
#include <stdio.h> main(){ int x,y; int a[2][3] = { {10,20,30}, {40,50,60} }; for(y =0; y < 2; y++){ for(x = 0; x < 3 ; x++) printf("a[%d][%d] = %d ",y,x,a[y][x]); printf("\n"); } return 0; } このソースの実行結果が a[0][0] = 10, a[0][1] = 20, a[0][2] = 30, a[1][0] = 40, a[1][1] = 50, a[1][2] = 60, と同じになりますが、前者の方のソースは入門書通りにです そっちの方のソースに誤りがあるんですよね? これ等のソースで、前者の方だと、yが3、xが2です 後者の訂正ソースだと、yが2、xが3となっています。 こっちが正しいと判断して宜しいでしょうか? 横がx、縦がyなので・・・・ そして、もう一つ質問があります 何故、微妙に違うソースなのに結果が同じになるのでしょうか? 最大の疑問です。
>>196 xとyを完全に入れ替えれば(コンパイラにとってxとyを区別する必要がないので)全く同じ振る舞いになる。
>195では外側がxであり、>196では外側がyというだけ。
つまり、配列aの使い方が>195と>196では違っていると言うことになる。
>>196 ループを回している順が変わらないから
変数A: [0 .. 2) で配列の先の添え字回し用
変数B: [0 .. 3) で配列の後ろの添え字回し用
>>195 のソースは 変数Aを x 変数Bを y に
>>196 のソースは 変数Aを y 変数Bを x に
してるだけ
199 :
197 :2007/02/05(月) 18:24:26
追記: xに横方向、yに縦方向と言う意味付けをしているのは人間であり、コンパイラはそんなことは頓着しない。 そもそも、Cの配列の配列は所謂二次元配列とは趣が異なるからa[x][y]かa[y][x]かは用途によってまちまちだったりする。 その上、実際によくある応用だと、二次元空間を仮想的に位置次元空間で表わす方法を取ることが多い。 その場合は、こんなコードになるかもしれない。 int main() { int a[] = {10, 20, 30, 40, 50, 60}; for (int y = 0; y < 2; ++y) { for (int x = 0; x < 3; ++x) { printf("a[%d][%d] = %d", y, x, a[y * 3 + x]); if (x < 3 - 1) putchar(','); } putchar('\n'); } return 0; }
200 :
187 :2007/02/05(月) 18:27:50
ありがとうごいます、とても厄介で難しいですね・・・
では、本の方も間違ってはいないのでしょうか?
>>197 >>>195では外側がxであり、>196では外側がyというだけ。
これだと、配列aの位置が変わり
a[0][0] = 10a[1][0] = 20a[2][0] = 30
a[0][1] = 40a[1][1] = 50a[2][1] = 60
の様に逆にはならないのでしょうか?
>>198 うががg、かなり混乱してしまっています
難しいです。
201 :
187 :2007/02/05(月) 18:32:47
>>199 こんな難しくも書けるのですね
>>int a[] = {10, 20, 30, 40, 50, 60};
だと、yが1ではないのでしょうか?
>>200 int a[2][3];
が 横2 x 縦3 なのか、横3 x 縦2 なのか、C言語においてはどっちにでも取れる。
だから、自分で [横2 x 縦3] か [横3 x 縦2] かを決めて、そのルールに合うように書くしかない。
[横2 x 縦3] の場合表示順は
横2個続けて表示後改行して次の行へ
となるから for (A=0; A<3; A++) for (B=0; B<2; B++) printf("", a[B][A]) ...
のようになるし、(a[ここは 0〜1までの値][ここは 0〜2までの値])
[横3 x 縦2] の場合表示順は
横3個続けて表示後改行して次の行へ
となるから for (A=0; A<2; A++) for (B=0; B<3; B++) printf("", a[A][B]) ...
のようになる (a[ここは 0〜1までの値][ここは 0〜2までの値])
あれだ、xとyって表現から暫く離れた方がいいよ。 >199が書いているように、xが横だとか縦だとかってのは人間の勝手な押し付けなんだから。
204 :
187 :2007/02/05(月) 19:29:06
>>202 わかり易いご返答、ありがとうごいます。
>>[横3 x 縦2] の場合表示順は
(a[ここは 0〜2までの値][ここは 0〜1までの値])
ではないのでしょうか?
a[][]の位置は、a[ここは 0〜1までの値][ここは 0〜2までの値]) 様に
位置が既に決まっていると言う事でしょうか?
>>203 そうします。
205 :
187 :2007/02/05(月) 19:31:40
斜め上な質問ばかり、すんまそです さっきも本屋で調べてきましたが、これらに関する内容が 載って無く困ります
>>204 表示内容として(a[ここは 0〜2までの値][ここは 0〜1までの値])を意味してるのではなくて
配列変数のアクセス範囲を括弧内に書いたつもり
int a[2][3] と宣言している以上 最初の添え字の範囲、次の添え字の範囲は変えようがない と
207 :
デフォルトの名無しさん :2007/02/05(月) 20:11:11
char x = 4,y; とは、char x1 = 2; char x2 = y; の事ですかね?
char x; char y; x = 4; のことです。
209 :
デフォルトの名無しさん :2007/02/05(月) 20:21:59
オレに聞け。 すべてはオレが基本だ。
日下部はsageなんて謙虚なことはしないぞ。
俺、ここの人たち大好きです。 こんな親切な方々は、何処の板にも存在しません。 何度となく挫折しそうになった俺を救ってくれました。 もし、オマイラがいなきゃ、俺はC言語続いてない。
213 :
デフォルトの名無しさん :2007/02/05(月) 20:53:56
質問なのですが、よろしくお願いします。 ポインタpが有効か否か調べるには、次の様にします。 NULLはポインタ版の「0」の様なものですが、 実は実際の値の0になっています。ですから、理論演算子の手法でも書けます。 pは有効? if(p != NULL)又は if(p) pは無効? if(p == NULL)又はif(!p) ※参考書抜粋 これで、“pは有効? if(p != NULL)又は if(p) pは無効? if(p == NULL)又はif(!p)” の意味を、助言して戴ければ幸いです。
214 :
デフォルトの名無しさん :2007/02/05(月) 20:55:03
>>212 そうですか、よかったね
C言語をある程度マスターしたら、ここでほかの人に教えてあげるといいよ
教えることによっては自分の未熟で不完全な部分がわかってくるものだから
自分のためにもいい
215 :
187 :2007/02/05(月) 20:56:18
>>206 ありがとうございました。
皆さんのお陰で大体は理解?できました・・・・。
216 :
デフォルトの名無しさん :2007/02/05(月) 20:58:44
>>213 if(p != NULL)又は if(p) は厳密にはヌルポインタかどうかのチェックだね
ポインタが汚れた値が入っている場合はチェックできないね
218 :
デフォルトの名無しさん :2007/02/05(月) 21:00:34
>>216 ご返答、ありがとうごいます。
“ポインタが汚れた値が入っている場合はチェックできないね ”
とはどういう事なのでしょうか?
>>218 *p とやって鼻から悪魔が出るような、でも非NULLなポインタ
# p=1; とか非0で適当なアドレス(?)を指し示した場合
>>218 そのポインタが実際に有効であるかどうかということ
たとえばプログラムがメモリ100番地から200番地の領域を確保したとします
ポインタはメモリの先頭番地をさすので通常なら100になっているわけです
仮に0だったなら 0番地にはメモリ領域を確保できないので実質「確保されたメモリはない」ということが分かります
ところがポインタが300番地をさしていたらどうでしょう?
if( p != NULL) や if(p) としては0で無い以上メモリアドレスを指定していることになりますが
実際には確保されていないアドレス(有効ではないアドレス)ということになります
>>216 がおっしゃっているのはこのことです
if( p != NULL) などのコードではポインタが実際に有効か無効であるかは調べようが無いんです
>>220 えーーーぇ
ポンタって注意しないと勝手に違うと所を指すことあるんですかー、怖えー
だから、ポインタって難しいのか
ポンタってたぬきですか
>>213 そこで言っている有効とはポインタがどこか*演算子などを使用して
そのポインタを逆参照(指し示す先を読み書き)できる状態のことだと思えばよい。
CではNULLをどこも指していないポインタ(の値)と定めているので、
逆にポインタ型の変数の値がNULLでなければ、そのポインタ型の変数はどこかの
変数(か何か)を指し示していると見なして処理することが多い。
しかし、>216>219-220の言うとおり実際にはポインタの値はNULLでないが、
逆参照してはならないという状態も存在する。ただしこの状態のポインタを逆参照するのは、
プログラマのミスであり、バグに過ぎないので、通常はNULLかどうかでポインタが有効かどうかの判断に代える。
パソコンなど現代的なOSの下で実行するプログラムでは、NULLなど無効な値を持つポインタを逆参照すると、
不正なメモリアクセスとしてプログラムの実行が停止される。Windowsではおなじみの
一般保護違反や「メモリがread/writtenになることはできませんでした」というダイアログが表示されるし、
Unix/Linux系だとsegmentation faultが表示される。
224 :
220 :2007/02/05(月) 21:37:54
>>221 いや、ポインタが「勝手に違うと所を指すこと」はないですよ
たとえばポインタの演算の時に間違って違うアドレスをさすような式を書いてしまったとかでしょう
あくまで書いた人のミスです
ポインタを0で初期化するのを忘れたとかもありますね
>>224 次点で
int a[3];
int* p = a;
int b[3];
a[3] = 1; とか b[3] =1; とかの配列範囲突破の副作用で p が書き換わる
とかね。
unionの初期化について教えてください。 C言語の学習サイトを調べてみると 「共用体の初期化はその最初のメンバの値で行わなければなりません」 とありましたが、絶対に不可能なのでしょうか? 下記のコードの st_hoge.un_point.pshort に 初期化で &s_area[0] を代入する方法があったら教えてください。 /*------------------------------------------------------*/ const short s_area[] = { 1, 2 ,3, 4, 5 }; /* 構造体定義 */ typedef struct _ST_Hoge { union { const long* plong; const short* pshort; } un_point; } ST_Hoge; /* 初期化 */ const ST_Hoge st_hoge = { ??? /* ←ここで un_point.pshort に &s_area[0] を入れたい! */ };
言葉足らずでした。 >C言語の学習サイトを調べてみると >「共用体の初期化はその最初のメンバの値で行わなければなりません」 >とありましたが、絶対に不可能なのでしょうか? unionの第二のメンバ pshort に初期化で値を入れることが絶対に不可能なのか? という意味です。
その構造体なら、キャストして放り込めばええやん。
はいはい。C99、C99。コンパイラがC99に対応してないという文句は却下ね。 const ST_Hoge st_hoge = { .un_point.pshort = &s_area[0] };
>>228 ポインタのキャストは、今回は無しでお願いします。
>>229 コンパイラがどうというのは、勉強不足で理解できていないですが
C99に対応していないコンパイラでは、最初のメンバ以外には
初期化で値を入れることはできないということですか?
勉強用に使っているbcc5.5.1では
const ST_Hoge st_hoge = {
.un_point.pshort = &s_area[0]
};
はコンパイルエラーでした。
231 :
デフォルトの名無しさん :2007/02/05(月) 23:36:01
C言語のアルゴリズムについての質問なんですが、 「2分木の先行順走査が、レベル順走査のキューより記憶領域を 多く使うような木の例」 とはどのようなものがあるんですか?
233 :
デフォルトの名無しさん :2007/02/06(火) 00:06:17
>>230 以下のやり方でソース書いて実行したら一応初期化されてる
けど、unionでconst使うの?
#include <stdio.h>
typedef struct{
union UNI{
const long* plong;
const short* pshort;
}uni;
}ST_Hoge;
int main()
{
int i;
const short s_area[] = { 1, 2 ,3, 4, 5 };
const ST_Hoge st = {(long *)s_area};
for(i = 0; i < 5; i++)
printf("%d ",st.uni.pshort[i]);
putchar('\n');
return 0;
}
234 :
デフォルトの名無しさん :2007/02/06(火) 00:08:35
>>233 >const ST_Hoge st = {(long *)s_area};
ポインタのキャストは
今回は使えないことになっているので。
なぜunionを使うかというと
書いていないですがST_Hoge構造体には他にもメンバがいて、
できるだけ構造体のサイズを小さくしたいので同時に使わないポインタは
unionで纏めたいのです。
constを使う理由は、静的なテーブルで ROM領域にデータを置いておく必要があるので constで定義しています。
>>231 二分木に 1〜10 の順で登録した時にはどうなる?
なんでキャストしたらあかんの?
unionで纏められるのがポインタなら、先頭をconst void*にでも しとけば。キャストは暗黙で済んじゃうから。
240 :
デフォルトの名無しさん :2007/02/06(火) 00:32:55
241 :
デフォルトの名無しさん :2007/02/06(火) 00:34:57
>>226 何かconstの用法間違ってる気がする...、unionメンバのconst要らんように思うが
ま、何したいのか、良くわからんのでなんとも言えんが
ST_Hoge st_hoge 変数で、ROM内の定数のアドレスを共有出来るようにしたいってこと?
>>238 >>239 ポインタのキャストはできません。
コーディング規約で縛られているので。
>>240 わかっていないと思います。
4byteバウンダリのことですか?
>>241 >>226 のグローバルの定義があって、その後に
void main() {
int i;
for( i=0; i < 5; ++i )
printf("st_hoge.un_point.pshort[%d] = %d\n", i, st_hoge.un_point.pshort[i]);
~~~~~~
↑pshortでアクセスすることが大事
}
で1, 2, 3, 4, 5と正確にアクセスしたいです。
243 :
デフォルトの名無しさん :2007/02/06(火) 03:07:46
>>242 これじゃだめあるか?
#include <stdio.h>
const long l_area[] = { 100, 200, 300, 400, 500};
const short s_area[] = { 1, 2 ,3, 4, 5 };
/* 構造体定義 */
typedef struct _ST_Hoge {
union {
const long *pLong;
const short *pShort;
} un_point;
} ST_Hoge;
int main()
{
int i;
ST_Hoge st;
st.un_point.pShort = &s_area[0];
for(i = 0; i < 5; i++)
printf("%d ",st.un_point.pShort[i]);
putchar('\n');
st.un_point.pLong = &l_area[0];
for(i = 0; i < 5; i++)
printf("%d ",st.un_point.pLong[i]);
putchar('\n');
return 0;
}
>>243 組み込みでROM領域ってことは代入はできないと思うんだ
コーディング規約で縛られているプログラムの面倒は見ません。
246 :
デフォルトの名無しさん :2007/02/06(火) 03:37:39
えっ、代入できないあるって st.un_point.pShort = &s_area[0]; これ駄目あるか、ROMの扱いって難しいあるね
そういや何で中国人?って〜あるって使うイメージなんだろ?
248 :
デフォルトの名無しさん :2007/02/06(火) 06:08:00
早上好!
老師、const ST_Hoge st_hoge、 このconst何のためにあるニダ?
中国3万年の歴史をもってしても不明あるニダ
>>242 努力加油!
へ〜
まとめ。 1.コーディング規約を無視してキャストする。 2.暗黙のキャストは許可されると解釈して、 const void *を共用体の先頭にもってくる。 というか暗黙のキャストが不可なら、void*は使えないってことか? 3.コンパイラをC99対応のものに換えて、>229 4.諦める
>247 多分漫画か何かでキャラ作りの為に中国人キャラがそう喋ってたんだろ んで在日中国人でそれを真似る奴も現れた 本場の中国人が日本語覚えたてだとアグネスみたいになる >248 一瞬、素が出ててヮロタw
リンカが型情報を捨ててしまうことを利用して、 定義の時だけ共用体の順序を弄るのはどうだ?(w a.c: struct st_hoge_impl{ const short *ps } st_hoge = { &s_area[0] }; b.c: extern ST_Hoge st_hoge_impl;
>>252 何気に日帝残滓
って日本なんだから当たり前かw
255 :
デフォルトの名無しさん :2007/02/06(火) 18:09:38
>>243 の
ST_Hoge st;
st.un_point.pShort = s_area;
は一応出来るだろ。
ただ、用件がconst ST_Hoge stになってるから困ってるんだと思う。
ついでに俺が思うのはunionでも構造体でも
ポインタ変数使ってるならmalloc()で領域確保しないと
後からバグの温床になるような気がする。
線形リストなりのリストにしたらどうなるんだろう。
静的な例えばchar *str = "abc"とかならコンパイル時に
メモリーにそのまま置かれるはずだと思ってるんだけど
構造体とかのメンバでのポインタ変数にオブジェクトの初期化で
constだからと言ってアドレスだけそのままわたして
でもC言語だからcont char *constなんてできないだろうし・・・・
わっかんねーや。
256 :
デフォルトの名無しさん :2007/02/06(火) 23:06:42
メニューに「1・入力 2・出力1 3・出力2」というのを作って、fgets()関数を用いて 入力はそのまま文字を入力してテキストに出力、メニューに戻る 出力1は、そのテキストをそのまま写し、メニューに戻る 出力2は、テキストに改行しかない行(要するに何もない行です)があった場合そこで出力を止めてメニューに戻る というのを作りたいのですが、最後の出力2だけができません。 ヌル文字で判断するようにしてら一番最初の行で出力終わっちゃうしorz どのように「文字が何もない」ことを判断させればいいのでしょうか?どなたかご教授お願いします。
str[0]=='\n'で判定すればいいんでそ
気がついたら上げてたことに今気づいたり OTLモウシワケナイッス
>>257 すばやい回答ありがとうございます。
(;´Д`)言われてみればそうですネ・・・
259 :
デフォルトの名無しさん :2007/02/06(火) 23:15:26
char *temp; char *token char *gDlim = " \t\n" temp = fgets() if((temp = strtok(temp,gDlim)) == NULL){ 文字無し else 文字有り
strtok()は使わないほうがいい。 ・使い方に癖がある。 ・スレッドセーフではない。 ・バグを発生させやすい。 ラッパ関数を用意すれば使い勝手は改善するが、 それ位ならsscanf()で%[](文字セット)を使うほうがマシ。
それもあるけど、 temp = fgets(); これも問題にして欲しいな、僕は。
int change_position(FILE *)という関数を作ろうとして このプロトタイプ宣言を自作ヘッダファイルに記述してインクルードしようとしたら エラー E2147 引数宣言は 'FILE' で始められない *** 1 errors in Compile *** と表示されてコンパイルできません。 何が問題なんでしょうか?
>>263 自作関数のプロトタイプ宣言の前に
#include<stdio.h>
してみては?
>>264 ありがとうございます。解決しました。
よくよく考えれば至極当然の事でしたorz
誰か俺を殴ってくれ。
sinとcosの関数を使用した値と、それらのマクローリン展開10項までの和の値を比較して、 誤差のある理由をレポートにしなきゃいけないんだが、なにか良い案はないか? 11項より後の項を切るんだから誤差が出るのはわかるんだが、もうちょっと詳しく知りたいのだ。
それマルチ
269 :
デフォルトの名無しさん :2007/02/07(水) 01:12:11
#include <stdio.h> main(){ char s[] = "I love dog and cat."; char c = 'a'; char *p = s; int n = 0; printf("\"%s\"の中から\'%c\'を探します。\n",s,c); while(*p != '0'){ if(*p == c){ printf("%d文字目で発見しました。\n"p-s+1); n++; } p++; } if(n == 0) printf("1個も見つかりませんでした。\n"); else printf("全部で%d個見つかりました。\n",n); return 0; } エラー E2121 sample13.c 12: 関数呼び出しに ) がない(関数 main ) *** 1 errors in Compile *** これが、どうしても見つからないので、ご指摘お願い致します。
270 :
269 :2007/02/07(水) 01:12:56
すみません、自己解決しました。。。。
>>269 p-s+1
の前にカンマ , が無いだけかな?
fgetsってfgets(hoge, size, *stream)のsizeで 読み取れる上限が決まるわけであって、 限界は1024までで設定されてるとかいうのは、デマだよな?
273 :
改めて質問させて戴きます-269 :2007/02/07(水) 01:20:11
#include <stdio.h> main(){ char s[] = "I love dog and cat."; char c = 'a'; char *p = s; int n = 0; printf("\"%s\"の中から\'%c\'を探します。\n",s,c); while(*p != '\0'){ if(*p == c){ printf("%d文字目で発見しました。\n",p-s+1); n++; } p++; } if(n == 0) printf("1個も見つかりませんでした。\n"); else printf("全部で%d個見つかりました。\n",n); return 0; } この、ソースでよくわからない部分が多数有ります。 参考書には解説が無く困っていますので、アドバイスの方を 宜しくお願いします。
>>272 デマ。もしそれが本当である処理系なんてあったら、そんなもの窓から投げ捨てろ。
>>273 多数であって無数ではないんだろ。
どこがわからないのか1つ1つ挙げてみろ。
275 :
改めて質問させて戴きます-273 :2007/02/07(水) 01:26:11
先ずは、一つ目なのですが char *p = s; は char s[] = "I love dog and cat."; を指しているのでしょうか? 二つ目は、whileの中にif文があるやつが、わかりませんので 解説をして戴ければ、ありがたいです。forの二重ループとは、違いますよね? 三つ目は、p-s+1 の意味です、これが何だかわかりません。 特にp-sとは・・・・? 四つ目は、n++とP++ です、これのp++の方は 参考書に、”探し当てた文字の次から探します。”と だけ書いてあります。なら、n++は何なんでしょうか? これらの、四つがわかりません。
#include <stdio.h> int main(){ char c = 'a'; char *p = "I love dog and cat."; int n = 0, k = 1; printf("\"%s\"の中から\'%c\'を探します。\n",p,c); while(*p){ if(*p == c){ printf("%d文字目で発見しました。\n",k); n++; } p++; k++; } if(n == 0) printf("1個も見つかりませんでした。\n"); else printf("全部で%d個見つかりました。\n",n); return 0; }
自己参照構造体がむずい。こんなん覚える必要あるのか
>>276 (1) pにはs[0]のアドレスが代入される
(2) pが指している文字がcに等しいかどうか判断
(3) pに入っているアドレスからs[0]のアドレスを引いて1を足す
pがs[0]に等しければp-s[0]+1は1になりprintf("%d文字目で発見しました。\n",p-s+1);は1文字目で〜と出力される
(4) printf("全部で%d個見つかりました。\n",n);を見れば分かるように配列sの中にあるcと同じ文字の個数
>>277 必要になってから覚えればいい
必要を感じないものは覚えにくいものだし面白くもない
>>277 世の中の少なくとも過半数の人は覚える必要が無い
自転車の運転が難しいっていうのと同じようなもの
できるようになれば、何で分からなかったのかが不思議なくらい
n++の意味か
(4) pが指している文字がcに等しいかどうか判断して等しければnの値を1増やす
最終的には
>>278 の(4)の通り
282 :
276 :2007/02/07(水) 02:13:00
自分は275と別人。 軽く書き直して説明つけようかと思ったけど めんどくせ!! って思ったから、書かなかった。 紛らわしい事してごめんね。
>>275 (2)whileになってるのは検索文字列の終端(〜cat\0)まで繰り返させるため。
全文字数が分っていればfor文でも出来るだろうが検索文字数が変わったときに
for文での上限の書き換えが必要になる。
その上でif文で検索文字'a'と同一か判定してる。
無ければif文を飛ばしてp++でwhile文に戻って次の文字との照合を行う。
あとは
>>278 の説明通りかと。
284 :
275 :2007/02/07(水) 02:23:05
皆さん、丁寧な質問ありがとうごいます。
>>276 >>278 >>281 >>283 皆さんの、アドバイスを読んで考えていますが
ちょっと、考えれば考えるほど混乱?してしまっているので
頭を冷やしてから、考え直し、再度質問させて戴きます。
285 :
デフォルトの名無しさん :2007/02/07(水) 02:39:36
数学的に完璧な世界観をもつCafeOBJによってこそで御座います。 かような仕儀にござりましょう。
どうでもいいんだが、0〜9を判定するとき (c >= '0' && c <= '9') とするのが多いの? 俺は ( '0' <= c && c <= '9') の方がわかりやすいと思うんだ。 ちなみに、K&Rは前者形式だった。
俺なら isdigit(c) かな?
>>286 後者を支持する人は、「数直線」を持ち出して「自然だ」と言い張る。
範囲を扱わないときには普通に>を使うのは全く気にならないらしい。
一方前者を指示する人は、「比較対照が常に前」ということで全て済ませてしまうらしい。
>>275 p-s+1を一度pにして実行してみて欲しい。
こちらの環境では12番目〜が2293459番目で〜になり
17番目で〜が2293464番目で〜と表示される。
あなたの環境でも同じ番号には成らずともdでもない桁数での表示なる。
s[]はs[0]をスタートにしてI love dog and cat.と終端文字'\0'の19個分、s[0]〜s[18]まで用意される。
p-s+1で行っているのはprintf("%d文字目で発見しました。\n",p-s+1);実行時の
pのアドレス番地からスタート地点s[0]のアドレス番地を引いた数+1を行う.
アドレス番地s[0]は必ずしも0番から始まっているわけではないので上記で表示されたdでもない番地は
実際に12番目と17番目の'a'が入っているアドレス番地になる。
上記での例で行くとs[0]の実際の番地は2293448番地となりここをスタート番地として動く。
p-s+1で実際に計算してみると
2293459番地(pの現在番地)-2293448番地(スタート番地)+1
で答え12を引き出すことが出来る。
>>288 なるほど、前者がそうなる理由を理解できないことはないと感じた。
でも、俺はずっと後者使うな。 前者はなんか気持ち悪いぞ。
>>289 ポインタ ≠ アドレス
なのに、その説明だと誤解しそう
#include<stdio.h>
int main(void){
int a[2];
printf("%p %p %d\n", &a[0], &a[1], (&a[1])-(&a[0]));
return 0;
}
ポインタとアドレスの正確な定義とかどうなってるんだろ?
>>292 質問の内容があいまいすぎて、わかんねーよ。
例えば
int *hoge = "abc";ってポインタ変数宣言して初期化してコンパイルしたら
hogeは、それ自身アドレス持ってるし
hogeは、"abc"で初期化されててコンパイル時にメモリーにそのまま置かれるし
コンパイルしてリンクずみのEXEを作ったとしたら
メモリーには変数のための領域、関数のための領域、スタックのための領域
ヒープのための領域が確保されて、EXEを実行してソース内でポインタ変数
をつかってヒープから領域確保して、ソース内でfreeせずじゃんじゃん
mallocでヒープから領域確保してたらメモリ足りなくなるし
再帰とかで関数スタックにつんでったらそのうちスタックオーバーフローするし
えーっと・・・
やっぱ、質問の意図がわかんね
アドレスを指し示すのがポインタ ポインタに入ってるのはアドレスの値 アドレスは機械語から使われている用語 ポインタは高級言語がアドレスを扱う為の概念の一つ ポインタはアドレスしか指さない アドレスは文字列や配列や関数にも存在する
って、ポインタの概念自体は機械語からあるか… アドレスは値でポインタは概念?俺も混乱してきた
これってpがaを指してるって事なの? 後ろから前の個数を数えて算出してるの?でも、+1が不明だ
+1しないと1文字目が0文字目になるって具合に一つずつずれちゃうから。
298 :
デフォルトの名無しさん :2007/02/07(水) 06:23:24
さんくす、S[0]から始まるからか!
299 :
デフォルトの名無しさん :2007/02/07(水) 06:30:00
p-s+1で pはaを指してるの?でsはs[0]?でしょうかね?
300 :
デフォルトの名無しさん :2007/02/07(水) 06:35:13
関数の引数でときどき…というのを見かけるのですがあれはどのように解釈すればよいのでしょうか?
>>300 ...は引数の型や個数が決められていない。好きに使えるってことだよ。
>>288 コーディング規約で何か決まってない限りは、おれは不等号に<と<=以外は使わないようにしているよ。
自然かどうかはしらんが、数直線を思い起こせばおれの足りない脳でもすぐ理解できるからね。
>>300 可変個引数を使う関数を自前で作るには
<stdarg.h>をインクルードヘッダを追加して
va_list
va_start
va_arg
va_end
の処理をその関数内でしなきゃならない。
最初は知って便利だと思って頻繁に使うかもしれないけど
正直そういう関数はあまり好ましくない
C++では、そういう関数はダメ
554 434 344 など3桁の整数が書かれてるテキストを読んで 344など4が2回出てくるやつだけ取り出すにはどうすればいいですか
>>305 4の数を数えればいい。
何がわからないんだ?
307 :
226 :2007/02/07(水) 23:11:56
共用体の初期化について質問をした者です。 結局、今回の初期化はコーディング規約を破って キャストして入れることになりました。 答えてくださった方 ありがとうございました。
308 :
275 :2007/02/07(水) 23:25:20
度々で、もうしわけありません
幾ら考えても、どうしても、
>>(3) pに入っているアドレスからs[0]のアドレスを引いて1を足す
がわかりません。
もう一度、解説お願い致します。
>>289 の解説を読む限りでは
>>(1) pにはs[0]のアドレスが代入される
これは、s[0] = Iのアドレスと解釈しても宜しいのでしょうか?
例、s[12]ならアドレスは1245059
やはり、p−s+1がいまいちピンときません
pとは何なのか、sが何なのか・・・・など。
>>289 実行したら、こうなりました
"I love dog and cat."の中から'a'を探します。
1245059文字目で発見しました。
1245064文字目で発見しました。
全部で2個見つかりました。
>>pのアドレス番地からスタート地点s[0]のアドレス番地を引いた数+1を行う.
もう少し詳細に説明して戴けると、幸いです。
309 :
デフォルトの名無しさん :2007/02/07(水) 23:29:14
アセンブラ詳しいかたいますか?
>>309 C言語じゃないし
何のアセンブラなのかもいわないし
汗ブラジャー
>>308 以下の文字列があるとします
文字列 s = "abcdefgh"
a のある位置は0でhは7ですね(s[0]=='a' であり s[7]=='h')
p−s+1
この式では s=0 となります
次にpについて考えますが p=4 としましょう
pは'e'をさしているのは分かりますね
では p - s はいくつでしょうか?4ですよね
ところで'e'は文字列 s において何文字目にありますか?
5文字目ですよね.とすると 式 p−s では文字列 s において 位置pがさす文字は何文字目であるか?という答えと一致しません
これは最初の0番目をカウントしていないからです
そこでp−s+1 と+1することで0番目の文字もカウントするようにしているのです
313 :
312 :2007/02/07(水) 23:43:10
>>308 訂正です
×この式では s=0 となります
○この式では s=0 とします
あっすいません↓アセンブラ言語のCASLUってやつです↓
315 :
275 :2007/02/07(水) 23:57:37
>>312 ご返答、ありがとうごいます。
>>p−s+1
この式では s=0 となります。
s=0 は配列が最初の値を指しているから"0"と
解釈してもいいのでしょうか?
>>ところで'e'は文字列 s において何文字目にありますか?
5文字目ですよね
自分なりの解釈では、>>これは最初の0番目をカウントしていないからです
そこでp−s+1 と+1することで0番目の文字もカウントするようにしているのです
が関係してるから'e'は4でなく、5だと思うのですが
普通は0から数えるから、'e'は4なのでは???
316 :
275 :2007/02/08(木) 00:06:55
'e'は文字列 s において何文字目か数えるので 0から数えるのではではないと、わかりました(ピンときました) 普通に数えていいみたいですね。
317 :
312 :2007/02/08(木) 00:07:48
>>315 それは配列のインデックスの話ですね
インデックスでは'a'は0番目であり、'e'は4番目ですが
表示上、'a'を1文字目とする場合、'e'は5文字目とならなければいけません
s[0]='a'; 1文字目
s[1]='b'; 2文字目
s[2]='c'; 3文字目
s[3]='d'; 4文字目
s[4]='e'; 5文字目
p−s+1 という式は上記の〜文字目を出す式です
s[〜]のインデックス値を出すだけなら p - s でいいんですけどね
あなたは「プログラム上のインデックス」と「日常のインデックス」を混同してませんか?
318 :
312 :2007/02/08(木) 00:09:56
>>316 リロード遅れました
そうです.普通に数えていいんですよ.
p−s+1 はその普通に数えた数を計算するための式です
みんな親切だね。 俺は、みんながこんなにレスしてる事に感激です。 俺の意見: もっと書籍読んで勉強しろよ 入門レベルだからこんな事言っちゃだめなんだろうけどよ
320 :
275 :2007/02/08(木) 00:18:38
>>317 丁寧な解説、ありがとうごいます。
何故、引けばその何文字目かが算出されるのかや
>>289 さんが、説明してくれたアドレス云々や(pのアドレスから??)
>>278 さんの>>(1) pにはs[0]のアドレスが代入される
などが、かなりごっちゃになってしまって、
考えても、今の段階(能力では)理解しがたいので
飛ばします・・・本当にありがとうございました。
321 :
275 :2007/02/08(木) 00:20:06
>>319 そうします、もっと簡単な参考書を探して勉強し直します。
自分がここを占領してしまったら、悪いですし
ありがとうございました。。。
単なる知識の指摘より、わかってない人をどうやってわからせるかの方が有益だし見てても面白いよ。
323 :
275 :2007/02/08(木) 01:15:41
くどくて、申し訳ないのですが
諦めきれず飛ばせず何度もレスを読み直しまし
80%とは何とか理解できました!!!
最後の質問に致しますので、ご返答戴ければ幸いです。
最後に3つだけ、質問させて下さい
”s=0” は決まってるのでしょうか?
決まっているとしたら、どうしてなのか?
>>278 さんの >> pにはs[0]のアドレスが代入される
は、今回はアドレスと切り離して考えてもいいでしょうか?
ポインタpはsの'I',' ','l','o','v','e'の各アドレスを指しているのでしょうか?
これがわかればもう悔いはありません。
324 :
312 :2007/02/08(木) 01:18:56
>>320 そうですか、一度に全部ではなく、少しずつ覚えるのがいいですよ.
それでは最後に・・・
文字列 "abcdefgh" があったとします.
仮に何も書かれていないカードが6枚あったとします.その後にa〜hまで書かれたカードが並んでるとして説明します
このカードを文字列として考えましょう.
空白 0番地
空白 1番地
空白 2番地
空白 3番地
空白 4番地
空白 5番地
s[0]='a'; 6番地
s[1]='b'; 7番地
s[2]='c'; 8番地
s[3]='d'; 9番地
s[4]='e'; 10番地
s[5]='f'; 11番地
s[6]='g'; 12番地
s[7]='h'; 13番地
↓続きます↓
325 :
312 :2007/02/08(木) 01:21:57
>>323 またリロード忘れましたorz
こちらの質問には再度レスします
↓先ほどの続き↓
まず、文字列とはなにか.上の文字列で説明します.文字列とは a を先頭にb,c,d,…と連続に続いたものですよね.
ではこの文字列を表現するためにはどうしますか?もっとも簡単なのは先頭の位置だけを記憶しておいて、後は順に隣を見る、という方法ですね
まずa〜hまでの文字列を s とします.文字列 s を表現するには文字列の先頭の位置を記憶すればいいんでしたよね
つまり s には文字列"a〜h"の先頭の文字 'a' の位置が記憶されているわけです.'a'の位置は 6番地 ですよね
では 'e' の位置は何番地でしょうか?そして文字列 s において何番目の文字でしょうか?
'e'は10番地ですね.では 'e' が文字列 s において何番目か計算してみましょう.
p−s+1 という式において p は'e'の位置 10 が、 s は文字列 s の先頭番地6が入っています.
10-6は4です.そこに1を足すと5になります.よって文字' e' は文字列 s の 5番目ということになります
実際に数えてみると、確かに5番目ですね.
では p-s とした場合どうでしょうか.答えは4になり実際の値とは違います.
先ほども説明しましたが、これは s[0]='a'; 自身が数えに含まれていないからです.
p-s とした場合常に s[0] が含まれないわけですから +1 とすればつじつまが合うようになります.
>323 s=0は間違い sは実際には適当なアドレスが入る。 pに初期値としてsを代入するからp-sが0から始まるってことで簡略化したんだろうが、 混乱させるからよくないな。 二つ目の質問の意味は良くわからん。 三つ目は、その通り。 pは'I'のアドレスから終端文字のアドレスまで順番に変化する。
327 :
312 :2007/02/08(木) 01:33:08
>>323 >”s=0” は決まってるのでしょうか?
決まってはいません.sの値は
>>324-325 の文字列の表現の仕方をみてください
私が書いたのは説明の便宜上のためです.
>
>>278 さんの >> pにはs[0]のアドレスが代入される
>は、今回はアドレスと切り離して考えてもいいでしょうか?
切り離す・・・のはよくないかと.どの問題と切り離すのかが分からないですが.
「pにはs[0]のアドレスが代入される」というのはp に文字列 s の先頭番地を入れておくということです
そして pが指している文字がcに等しいかどうか判断し、等しくなければ p を1つ隣に進めます( p++ と言う処理は p に 1を足している)
この操作によって 今度の p はs[1]のアドレスをさすことになります.
>ポインタpはsの'I',' ','l','o','v','e'の各アドレスを指しているのでしょうか?
そうですね.p++ と言う処理によって各アドレスをさすようになります
文字列操作、ポインタ、配列 本買ってもう少し自分で勉強しなさい。 ここまでくると他の人が質問しづらい
329 :
275 :2007/02/08(木) 01:38:38
>>324 >>325 >>326 何から何まで親切に、ありがとうございました。
よく、こんな難しいのがわかりますね。
あとは自力で考え込んで理解します。
でも参考書って入門向けや初心者対象とか 題名には謳っているけど、最初だけ簡単に説明して サンプルや練習問題でいきなり難しくなるのって多いと思う 俺もここで訊かなきゃ挫折していたよ by俺の経験談
どうにか基本情報合格できたレベルなんですが、何かオススメの書籍ありませんか? 月刊オープンソースマガジンとかいいのかな?
332 :
275 :2007/02/08(木) 02:27:55
遂にキターって感じでわかりました!!! 皆さんのお陰です!!!! すっきりしました!!!
333 :
デフォルトの名無しさん :2007/02/08(木) 03:00:57
プログラマの夢を諦めて大学中退したんだが1年振りにこのスレを見て・・・俺やっぱプログラマ目指すぜ! 専門行って無難なネットワークエンジニアに切り替えたんだがCCNAなんてつまんねぇ! てめーらに又教えてもらう
335 :
VoidNo2 :2007/02/08(木) 09:21:22
オレに聞け!
336 :
デフォルトの名無しさん :2007/02/08(木) 10:19:27
唐突にすいませんが、現在Cの研修中で「7桁の数字に,を付けて表示しろ」って言われたんですが 例)12345678 → 12,345,678 という風に これはint型の数字をchar型の配列に入れてfor文で3桁ごとに,を打つようにすればいいんでしょうか?
338 :
デフォルトの名無しさん :2007/02/08(木) 11:13:51
339 :
デフォルトの名無しさん :2007/02/08(木) 13:55:44
いきなりですみません。 倍精度整数型の配列a[100]にキーボードから入力された整数を順に格納する、ただし、今までに 入力された数を掛け合わせたものが1000万を超えれば、そこで終了し、結果と そこまでの配列aの内容を逆順に出力するプログラムをC言語で作れ。 この問題解いていただけませんか?お願いします
341 :
デフォルトの名無しさん :2007/02/08(木) 14:08:36
小数点を表示させたいのですけど、 %.2fのようなやり方だと、1.1とか20みたいな数値にまで0が付いちゃいますよね そのようにならないようなやり方とかありませんか?
1.23 → "1.23" 1.1 → "1.1" 20 → "20" っつーこと? %.2g でうまくいくかも だめなら自作(sprintf した後、後ろから 0 を潰す)
おまん幸太郎
>>339 簡単じゃね?
#include <stdio.h>
int main(){
long int a[100];
int i,j,total=1;
puts("100個の整数格納しろやボケ");
for(i=0;i<100;i++){
scanf("%d",&a[i]);
total *= a[i];
if(total > 10000000){
printf("今までに入力された数を掛け合わせたもの:%d\n",total);
for(j=i;j>=0;j--)
printf("a[%d]=%d\n",j,a[j]);
break;
}
}
printf("終了だ包茎野郎");
return 0;
}
345 :
デフォルトの名無しさん :2007/02/09(金) 00:01:19
超初心者で申し訳ないです・・・・・・ Hell World!って文字がでる基本的なサンプルの.exeファイルを開いても ウィンドウが一瞬でてすぐ消えてしまいます。 自分で試しに作ってみたやつもそうなりました。 これは仕様なんでしょうか? これだとちゃんとできてるかわからないのですが・・・・・・
getchar();
100個の整数格納しろやボケ 1 2 3 4 5 6 7 8 9 10 11 今までに入力された数を掛け合わせたもの:39916800 a[10]=11 a[9]=10 a[8]=9 a[7]=8 a[6]=7 a[5]=6 a[4]=5 a[3]=4 a[2]=3 a[1]=2 a[0]=1 終了だ包茎野郎 -- Press any key to exit (Input "c" to continue) --
>>345 デバッガで実行して、最後の行にブレイクポイント設定。
>345 Windowsの仕様。 プロンプトから実行するコマンドアプリを 直接ダブクリ起動するとそうなる。 すぐ消えないようにするには ・ブレークポイント ・コマンドプロンプトから実行 ・バッチファイルでPAUSEコマンド ・最後に getchar() する などなど。
350 :
デフォルトの名無しさん :2007/02/09(金) 00:24:11
質問させて下さい。OS:windows xp sp2で、コンパイラはBorland C++ Compiler 5.5です。 書店で本(10日でおぼえるC言語入門教室 / 坂下夕里著 / 翔泳社発行)を買ってきて、第1日目でつまづきました。コンパイルすると、コマンドプロンプト画面に Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland sample1.c: エラー E2209 sample1.c 1: インクルードファイル 'stdio.h' をオープンできない 警告 W8065 sample1.c 4: プロトタイプ宣言のない関数 'printf' の呼び出し(関数 main ) *** 1 errors in Compile *** とエラーが出てしまうのです。どうすればよいのかご教授下さい。sample1.cのソースは以下です。 #include <stdio.h> main() { printf("Hello!"); return 0; } よろしくお願いします。
本を読めばわかるよ
>>351 >>353 なのですが、あれこれと試していったら解決しました。ありがとうございました。
コンパイラをインストールし直してみたら直ったのです。
お騒がせしました。
356 :
デフォルトの名無しさん :2007/02/09(金) 01:14:23
>>351 俺も初めての時、これで挑戦したよ・・・
357 :
デフォルトの名無しさん :2007/02/09(金) 01:16:15
>>355 因みに、一ヶ月かかったが
俺的な評価は10点中5点かな
実はperlを先に覚えてしまったんで、変数定義?のいるC言語は覚えるのが億劫なのです。
でも仕事で必要なのでおぼえます。
>>357 さんは、何をどういう基準で評価したんですか?
>仕事で必要なので 大丈夫、仕事はあなたを必要としていません。
360 :
デフォルトの名無しさん :2007/02/09(金) 01:47:46
初心者向きか否かで評価しました 説明も薄い感じがした、プログラミング入門書としては、 ちゃんとした解説があってほしかったし、図もいまいちだった
C言語3級受かる実力まで俺をしごいてくださいつきっきりでハァハァ
C言語3級とかあんの!? じゃ、2級1級ときて、次は初段とかか!? でも、マジでそんなC言語に特化した資格有るならとろうかな。
C言語3級ろじかる?ぽか〜ん
構造体内のポインタにgets()で文字列等を代入できるのでしょうか? #include<stdio.h> #include<string.h> struct{ int num; char word; }*str; main(){ char temp[10]; gets(str->word); gets(temp); str->num=(int)atoi(temp); (以下省略) という感じでやっているとコンパイルエラーは無いのですが強制終了してしまいますorz ご教授お願いします
毎回すべてのインクルードファイルを含んでいてはいけないんですか 使い分けるの面倒だから
>364 gets()の使い方間違ってる。
>>364 軽く書き直した。コンパイルして無いけど、まぁいけると思う。コメントは面倒なので書いてない。
まず始めに、構造体にタグ名が無い。ついでにその中のwordってのは、ただのchar型の変数。
なのでstr->word = getchar();で一文字だけしか所持できない。ただ、それも無理。
しかし*strは、ポインタでありそのまま使うなら領域確保が必要になる。
色々と書籍、ネット等で知識を蓄える必要がたくさんあるようです。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct{
int num;
char *word;
}MyStrct;
main(){
MyStrct *ms;
char *temp;
char buff[256] = {'\0'};
ms = malloc(sizeof(MyStrct));
fgets(buff,sizeof(buff),stdin)
if((temp = strchr(buff,'\n') != NULL)
*temp = '\0';
ms->word = malloc(strlen(buff)+1);
strcpy(ms->word, buff);
memset(buff,'\0',sizeof(buff));
fgets(buff,sizeof(buff),stdin)
if((temp = strchr(buff,'\n') != NULL)
*temp = '\0';
ms->num=atoi(buff);
>>364 ・質問する前に本当にコンパイルエラーが出ないか確認する
・ポインタとポインタが指す先との区別を理解する
・struct{…} str;とstruct{…} *str;がint x;とint *xに対応していることを理解する
・char word[10];とする場合とchar *word;とする場合の違いを理解する
・できればgetsよりfgets使う、無闇に(int)とかしない
って書いてる間に
>>366 が先に答えてくれました。
俺のこのレスはどこに捨てればいいですか?
369 :
デフォルトの名無しさん :2007/02/09(金) 10:38:16
2000円の商品の消費税を計算するプログラム 半径20CMの円の面積を求めるプログラム を作成しなさい。初級問題です。 これができなきゃだめでしょう。
>369 ああ、だめだな。
371 :
デフォルトの名無しさん :2007/02/09(金) 11:16:46
#include<stdio> main() { double[問1]=3.14; /*円周率*/ double[問2]=20.0 ; /*半径*/ double[問3]; result=[問4]; printf;[問5] 円の面積は[問6]ですと表示させること return0; 初級だから簡単問題です
372 :
デフォルトの名無しさん :2007/02/09(金) 11:18:29
#include<stdio> main() { double[問1]=3.14; /*円周率*/ double[問2]=20.0 ; /*半径*/ double[問3]; result=[問4]; printf;[問5] 円の面積は[問6]ですと表示させること return0; 初級だから簡単問題です
[自己解決] ここはだめの集まりですね。
>371 それを解けるヤツはこのスレにはいないと思うぜ。 なんせ問題自身が間違ってるからな。
375 :
デフォルトの名無しさん :2007/02/09(金) 19:05:39
linuxでなんだけど、ソケットがcloseされたか知りたがってる。 selectで読み出し可能を待って、readして読み出しサイズがゼロなら 向こうにcloseされた ってわかるけど これを、getsockoptとか使ってcloseされたかどうかを readしないで知りたい と思ってる。 どうすればいいかな? かな?
レナ乙
>>369 Q. 2000円の商品の消費税を計算するプログラム
A. 入力された値をそのまま出すだけ。
理由: 内税方式のため、計算の必要なし。
>>378 そりゃ税込み価格のことだべ
消費税がいくらかを聞いてるんだべよ
>375 epollでEPOLLRDHUPも待てばいいんじゃないの
381 :
375 :2007/02/09(金) 20:29:29
>>380 ごめんね
selectとかなしで、いきなりソケットを検査して
相手からcloseされたかどうかを調べたかったの
epollソケット作って、ソケット巻き込んで、epoll_waitをタイムアウト0で呼ぶのは 「いきなりソケットを検査」と呼べないのはなぜ? 面倒くさいからか?
383 :
デフォルトの名無しさん :2007/02/09(金) 22:29:59
#include <stdio.h> int y; int z; void myfunc(int a){ int z; int x; x = a; y = a; z = a; } main(){ int x; x = 10; y = 10; z = 10; printf("x,y,zの値は%d,%d,%d\n",x,y,z); myfunc(5); printf("x,y,zの値は%d,%d,%d\n",x,y,z); return 0; }
384 :
デフォルトの名無しさん :2007/02/09(金) 22:31:43
実行結果 c:\language>sample15 x,y,zの値は10,10,10 x,y,zの値は10,5,10 これで、下のが"5"に、何故なるのかわかりませんので アドバイスをよろしくお願いします
myfuncの中でzとxはローカル定義されているので、 グローバルのzは隠され、関数から戻れば変数は消える。 yについてはグローバルのyをさわっているので全体に影響が及ぶ。
386 :
デフォルトの名無しさん :2007/02/09(金) 22:48:32
>>385 でも、どうして値が5になるのでしょうか?
ちょー処理系知りたい
むしろその質問の意味が分からん。 myfunc(5)で、呼び出して、y=aで代入したらy==5だろうが。 他になんになるって言うんだ?
389 :
デフォルトの名無しさん :2007/02/09(金) 22:57:19
>>388 レス、ありがとうございます
そしたら、yだけが5ではんく
x = 5;
y = 5;
z = 5;
と、なるのではないかと思いました。
>>389 ところで、もう解決した?
折角なので
変数を別の文字に例えると以下のようになるから
int y;・・・・・・・・・・int α;
int z;・・・・・・・・・・int β;
void myfunc(int a) {
int z;・・・・・・・int γ;
int x;・・・・・・・int δ;
x = a;・・・・・・δ = a;
y = a;・・・・・・α = a;
z = a;・・・・・・γ = a;
}
int main() {
int x;・・・・・・・int ε;
x = 10;・・・・・ε = 10;
y = 10;・・・・・α = 10;
z = 10;・・・・・β = 10;
//printf("x,y,zの値は%d,%d,%d\n",x,y,z);
・・・・・・・・・・・printf("x,y,zの値は%d,%d,%d\n",ε,α,β);
myfunc(5);
//printf("x,y,zの値は%d,%d,%d\n",x,y,z);
・・・・・・・・・・・printf("x,y,zの値は%d,%d,%d\n",ε,α,β);
return 0;
}
加速度的に出る確率が変わる乱数ってどう書けばいいの?
393 :
デフォルトの名無しさん :2007/02/09(金) 23:05:01
>>391 いえ・・・今も考えています・・・苦戦中です
>>392 >加速度的に出る確率
意味が分からない
どれも均一な確立でばらばらな値が出没するのが乱数だからな
あー、出る数値だ。スマン。
確率は2の32(+31) すれば十分ばらつきあるよ
つまり、最初0.1%次0.2%次0.4%,次0.7%、みたいなはなしか?
>>399 そう。解説thx。
俺の弱いおつむじゃさっぱり思いつかない。
401 :
375 :2007/02/09(金) 23:15:15
>>382 ごめんね
とりあえず言われたとおりにやってみるとしますぜ
乱数の最小値と最大値決めて使ってるだろ?
[0,1)を生成する乱数源rand()があったとして、 確率Kの事象は 式rand() < Kで生成できる。 あとはKを加速度的に増やしていけばOK. 力学的には加速度はa=d²p/dt²なので、 K=a*t²+b*t+cで導出するのが筋かな?
C言語を勉強しようと思い、参考書を買いに本屋に言ってきたんだけどたくさんあってどれがいいのかわからないです・・・ 真剣にやるつもりだから教材は良いやつ使いたいし なにかおすすめのってありませんか? 基礎をガッチリ学べるような・・・ PCは私生活で使うようなことなら大体わかるけどプログラミングなどの専門的なことに関しては初心者中の初心者です
405 :
デフォルトの名無しさん :2007/02/09(金) 23:24:53
C入門。
406 :
デフォルトの名無しさん :2007/02/09(金) 23:26:53
明日はCなろう
>>403 説明ありがとう。
読んだだけじゃ余り理解できてないから色々試してみる。
もう世話にならんよう勉強せな。
410 :
409 :2007/02/09(金) 23:41:24
411 :
409 :2007/02/09(金) 23:47:22
異なる関数で同じ変数名のローカル変数は無関係。 グローバル変数はどの関数からでも変更できる。 グローバル変数とローカル変数の変数名が同じときはローカル変数が優先される。 この3点さえ抑えとけば充分だろ。
>>404 おれはたくさん入門書買ったけど、結局は「C言語の切り札」だけで覚えた
他のは1回やってみれば分ることをダラダラ書いてあって自分には合わなかった。
資格用だけどもう基礎中の基礎から簡潔に書いてくれててすごい分りやすかった
文法編で基礎を覚えて問題編は分らないところはネットで調べながらやったら
ある程度分るようになったよ。
書いてるのをただ読むだけじゃなくて、ただ写すだけでもいいから自分で打って
コンパイルして実行してみていろいろ理解するといい
今は「Cプログラミング診断室」読んでる
414 :
デフォルトの名無しさん :2007/02/10(土) 02:59:08
>>411-
>>412 親切にありがとうございます!!!感無量の思いです
415 :
デフォルトの名無しさん :2007/02/10(土) 03:30:36
自分もC言語の入門書で、今三冊目(アルゴリズムの本を含めれば四冊目)に
なるのですが、ポインタや自作関数などが、どの本を読んでも理解できず
(なんとなくじゃ理解した?つもり)
四冊目の入門書、今日本屋で解り易い本を見つけました
入門書で何冊も買うのは、やはり向いてはいないんですかね?
>>406 で言われてる、Cの絵本読んでもポインタなどの説明がザッとしか
書いて無く微妙だと思いました・・・・
うん、向いてないよ。
417 :
デフォルトの名無しさん :2007/02/10(土) 03:43:02
理解したつもりなんだったらちょっと無理して自分より上のレベルの本を買った方がいい というか、作っていきながら分らないところがあったら調べる。とかの方がいい
興味があるのはいい事だから向いてなくてもやめろとは言わないけどさ。 どの入門書でもだいたい同じ内容が書いてるでしょ。 入門書を何冊も読んだりなんかしてて飽きない? 飽きない内は身についてないんだろうね。 しかしそろそろ次のステップを見てみたほうがいいかもね。 知識が不完全でも何か自分が作りたいものを作ってごらんよ。
使えば自然と身につく 使わなければ忘れる それだけの事
421 :
デフォルトの名無しさん :2007/02/10(土) 04:12:52
>>418 >>419 何となくイメージを掴む程度の理解では
満足できなく、完璧に理解するまで納得できないんです(人に説明できるくらい)
自分でも身に付いてはいないんだろうと思います
飽きはしませんし・・・・
作りたいのは、スパム対策のソフトを作ってみたいです
>>420 読んでると、前回よりは理解度が上がってる気がします
422 :
デフォルトの名無しさん :2007/02/10(土) 04:16:18
因みに、皆さんは入門レベルと言うか基礎レベルは 何冊くらい本を読んだりしましたか? 4冊読んで(ソースを書いたりもしました)理解できないとは 不向きなんですかね、やっぱり 独学だと非常に難しいと思います 向いていないと言うか、初めてのプログラミング言語が Cと言うのが間違いだったのでしょうか?
読んでるだけじゃいつまでたってもわかった気がするだけ。
自分は入門書は読まなかったよ。 Javascriptから始めたんだけどね。 そこらへんに落ちてる他人のソースを読んで改造するのから始めて。 次にC#とJavaをやったんだけど作りながら分からないところをネットで調べてた。 C#とかJavaやってる頃にもアルゴリズムを勉強するのに Cのソースはちょくちょく読んでたからCを書くようになるのは苦労しなかった
>>422 初めての言語がCっていうのはいいことだと思うが
>>421 お前さんの気持ちはよくわかる。
しかし理解の程度なんて言葉での説明は難しいし、
人によって理解の基準は違うのだから、完璧に理解…ったって
具体的に何をどうしたいのかさっぱり見えてこないよ。
取り敢えず今はそんなこと考えずに何かしら作ってみることを奨める。
俺もJavaを独学したとき、本を読んだ時点ではもやっとした部分があったけど
使ってるうちに徐々に霧が晴れていったものだよ。
大体、最初から完璧にしておく必要性なんてあるのかな?
入門書完璧に覚えて理解したくらいでは スパム対策ソフトを作れるようになるのはとても無理。 入門書がどれだけ説明を端折って簡単にしてるかも分かってないでしょ。 読んでるだけじゃ理解は深まらない。
スパム対策ソフトってかなり上級なんじゃないの? それこそ入門書なんかじゃなく百科事典みたいにぶ厚いのじゃ…
そこで入門書を読んだことがない漏れが来ましたよ。 つーか、当時はろくな本がなかったから手探りだったんだよ。
入門書2冊以上読む人ってほとんど居なくね? 多くて1冊だよね
431 :
421 :2007/02/10(土) 05:08:52
ネットだけで情報を漁っても説明が難しくて、本を買いました 凄いですね、ネットのソースなどで理解したなんて よく、初めてのプログミングがCだと難しいと聞きました たしかに、何を基準とかで理解したか判断はできませんが 自分としては"靄"が、すっきりしないのがイヤなんですよ スパム対策ソフは、かなり難易度が高いみたいなので、簡単なのに挑戦します でも、何をどうすれば良いのかがわからない
432 :
デフォルトの名無しさん :2007/02/10(土) 05:10:06
もやがすっきりするのはモノを作るようになった後。
>>430 たくさん買うことはあるよな
結局気に入った1冊しか読まないんだが
436 :
429 :2007/02/10(土) 05:16:20
当時はそもそもWebなんてないっての。
>>430 2冊以上買う人は多いだろうけど、ちゃんと読むのは精精1冊だろうね。
#つーか、入門書が1冊で足りないと思うのは理解が足りないから手を動かしてないからでしょ。
>>430 多くて1冊…かよw
まあ、俺も入門書を買ったわいいが、半分も読まなかったな。そういや。
>>431 じゃあ助言しておこう。
基準が分からない故俺の場合に重ねざるを得ないけど、
俺がCを完全に理解したと思ったのは、OSやCPUレベルで変数や処理の動き、
それとコンパイラの具体的な処理を理解してからだった。
前者はアセンブリ辺りから入った人なら最初から必要な知識として入ってくるものだから
もし自分の理解の基準がその辺りにありそうならば、アセンブリ言語を習ってみるのもいいかもしれない。
ただし、目的は見失わぬようにね。
ピーガガガガの時はググっても数件しか出てこなかったな HPもってる会社も殆どなかったし
439 :
431 :2007/02/10(土) 05:25:08
自分はCを完璧に理解したなーと思ったことはないが、 ほぼ理解したなーと思ったのはCコンパイラを作ったとき。
GUIってだいたいどのぐらいで作れるようになりますか? CでGUIはなかなか難しい?
前にも君みたいな人はどこかのスレに居たけど 入門書を何冊も読むのは恥ずかしい事だよ。
俺はむしろ彼みたいな真面目タイプが好きなんだが…。 ちゃんと話も聴いてくれるし、成長するよ。
>>445 ありがとう。
思ってたよりは難しくなくてホッっとした
ちょっとずつ勉強していくよ
他人の話を聞くのはいいことだね。 しかしそれを受け入れるかどうかが問題だ。 何かを作る段階に進むよう数人に言われてるが、 入門書を読み続けるのか言われたとおり何かを作り始めるのか。
SSL通信をする方法を教えてください
449 :
デフォルトの名無しさん :2007/02/10(土) 11:01:32
ポインタの理解はwebとの対比でかんがえてみてはどうかな?
URL -> ポインタ
ブラウザでURLを指定して中身を見る→ポインタの中身(実体)
掲示板の書き込み→ポインタの中身の書き換え
だから、
http://pc10.2ch.net/test/read.cgi/tech/1170064980/l50 をみているのはポインタの中身を見ている事になって、
書き込みはポインタの中身の書き換えという感じです。
ポインタ渡し、実体渡しの区別を言うと、ブラウザをオンライン
/オフライン作業に対応している。掲示板に書き込もうと思えば、
オフラインでは出来ないしソース(URL=ポインタ)に直接アク
セスする。要するにブラウザキャッシュは実体渡しを受けた状態。
webとの対比って分かりやすく無いかい?
>>449 たとえ話は素人を煙に巻くには使えるが、
真面目に理解しようとする者にとっては逆に障害になることもあるのではと。
指定された数値が示すメモリのアドレスに格納されている数値を取り出す、
CPUにそういう命令があるからという本質を教えたほうがよいと自分は思う。
ミもフタもないが。
5冊買ってようやく理解してきたよ
規格と人のソース読んでれば実用上は何とかなったから Cの本っていったら俺はK&Rしか読んでないな。
誰も聞いてないよ
アドレスなんて、普通に住所を例にすれば簡単だろ?
ヌルポはさしずめ住所不定無職ということか
いや、無職は関係ないだろ。
入門書は大概書いてるやつが初心者レベルだからなぁ。1冊読んだら次は 入門書以外の(初心者向けの手抜きがない)きっちりしたものを読んだほうがいいと思う。
今度LinuxでC言語を行う事になったのですが、Linuxの知識は全くという程ありません。 C言語はある程度できるのですが、Linux環境でC言語を扱う方法をご教授願います。
それぐらい自分で調べられんと 今後もLinuxは使いこなせないと思うぞ
こんなこと言う奴はCも初心者同然だろ
質問が漠然としすぎてるぞ・・・。とりあえず検索くらいしてからこいよ。
GCCっていうコンパイラ使えば? もしかしてLinuxのインストール方法も知らないの?
コンパイルの仕方がどうしても見つからなくて・・・
gcc -Wall -Werror -pedantic-errors -g hoge.c -o hoge でコンパイルして、 ./hoge で実行
gcc ファイル名.c rm -f ファイル名.c これでたぶん出来るだろ
構造体の練習で簡単なこんなのを書いてみてるんですが実行しても「scanf("%c",&kamoku[1].result);」 の部分が無視されてしまいます。何故でしょうか? 初歩的なことですみませんがおしえてください ↓
#include<stdio.h> main() { /* 構造体の練習〜 */ typedef struct{ char subject[10]; int score; char result; }TEST; TEST kamoku[2]; strcpy(kamoku[0].subject,"Engish"); kamoku[0].score=85; kamoku[0].result='A'; printf("科目名,点数,成績を入力してください。\n"); scanf("%s",kamoku[1].subject); scanf("%d",&kamoku[1].score); /* ↓何故かここが無視されてしまう */ scanf("%c",&kamoku[1].result); printf("代入した 科目名:%s ",kamoku[0].subject); printf("点数:%d 成績:%c \n",kamoku[0].score,kamoku[0].result); printf("入力した 科目名:%s ",kamoku[1].subject); printf("点数:%d 成績:%c \n",kamoku[1].score,kamoku[1].result); /* ↑成績が空白に */ }
前の%d入力時に残った\nが入ってるんじゃないの。
>>468 レスありがとう。
その前の「scanf("%c",&kamoku[1].result);」が入力を受け付けずに次に行ってしまう(´・ω・`)
実行するとこんな感じになってしまう
-----------------------------------------------------
科目名,点数,成績を入力してください。
Math
80
代入した 科目名:Engish 点数:85 成績:A
入力した 科目名:Math 点数:80 成績:
-----------------------------------------------------
だからscanf()は使わんほうがいいのよ。
>>467 >469
だから
>>468 の通りなんだってば。
C言語の標準入力関数は、基本的に
直接標準入力から読み込むのではなく
入力された内容を一度「バッファ」へ溜め
それを通して読み込む。
バッファが空の時はユーザへ入力を要求し
入力されたデータをバッファに溜め込み
そこから読み込みをする。
最初の scanf("%d",&score) は
バッファが空なのでユーザへ入力を要求。
80
と入力すればバッファに "80\n" という文字列が格納され
そこから数値である "80" が読み込まれる。
次の scanf("%c",&result) は1文字読み込みだが
バッファに "\n" という文字列が残っているので
ユーザへ入力を要求することなく1文字、つまり
'\n' を読み込む。
では、どうする?
>>471 ありがとう。それを参考にして
scanf("%c",&kamoku[1].result);の後にもう1つ「scanf("%c",&kamoku[1].result);」
入れたらちゃんとなるようになった
でもこれじゃ駄目だよね(´・ω・`) もうちょっと色々勉強してきます
scanfの代わりに、fgets+sscanfでラップしたgetscanfでも書けばいいんじゃないの。
>>474 で、長い入力が来たときに入力に改行が残るバグが発生と。
その長い、ってのはたとえば10万文字とかを言っているのか?
>>476 fgetsに渡すバッファサイズ以上の長さならいつでも起こりうるよ。
scanfの書式を使いこなせない馬鹿がいますね。
現実問題として、標準入力をリダイレクトしていなければ端末エミュレータ側の制限で 1行に1000文字も入れることはできない。 従って、char buf[1000]; fgets(buf, sizeof(buf), stdin); はそこそこ無難な選択だと思う。 #ビジネスユースなら勿論、長さと改行文字をチェックしてフォローすべきだが。
そんなでかい入力なんて来ねーよ。とバグを放置するんなら最初っからgets使えば? char buf[1000]; gets(buf); 『現実問題として、標準入力をリダイレクトしていなければ端末エミュレータ側の制限で 1行に1000文字も入れることはできない。 』らしいし。
そんなに心配なら、fgetsしたあとの最終文字が\nでなければ、 見つかるまでfgetcで空読みすりゃいいじゃん。
>>481 それだと入力列が
......[ここで'\0'文字]...'\n'
みたいにエスケープシーケンス等でNULをふくんでると改行見落とさね?
「最終文字」として、[strlen(buf) -1 ]を使えばそうなるけど、 [sizeof( buf ) - 2]を固定で調べるんだよ?もち、使う前には初期化してね。
>>483 あ、そうか。そうすれば問題ないね。ありがと。
strchr(buf,'\n')が脳内イメージにあったから思いつかなかったorz
>>479-480 そういえばなんかの規格で、1行の長さが1024文字(バイトだったかも)を
超える場合はテキストファイルではなくバイナリファイル扱いにするとか
どーとかってのを読んだ記憶がある。( http 関連の規格だった気がする
が思いだせん。 )
487 :
デフォルトの名無しさん :2007/02/11(日) 01:02:50
Cの絵本と言う書籍を読んでる方いないでしょうか? これの関数の説明が全然わからないので、ご教授お願いします。
>>487 4 人中、4人の方が、「このレビューが参考になった」と投票しています。
少なくとも最初に読む本ではない, 2006/12/14
レビュアー: カスタマ - レビューをすべて見る
この本の表紙と中身をちょっと見て買いました。
初めの印象は絵が見易くて理解しやすそうだなと思いました。でも実際には、説明がほとんどされていなく、非常に不親切だなと思いました。これで勉強をしていく人はいなのでしょうね。完璧に私の用途と違うなと。
文字列とか数字入力を求めて、たとえば「A」と打てば「A」をテキストファイルに出力させるんですが、 一度プログラムを終了させて、次の起動時に「B」と打った際に上書きをしないで A B という感じで前回入力した文字を保存したまま、1つ改行して文字を出力したいのですがこれはどうすればいいですか? 過去に入力した文字の履歴みたいのを作ってみたいんです。
>>489 こんな感じ?
#include<stdio.h>
main()
{
char moji[10];
FILE *fp;
fp = fopen("date.txt","a+");
printf("文字を入力してください\n");
scanf("%s",moji);
fprintf(fp,"%s \n",moji);
fclose(fp);
}
491 :
489 :2007/02/11(日) 01:37:50
>>490 なるほど・・・wとかwbとかrとかくらいしかマトモに使ってなかったんでa+とかすっかり忘れてました という言い訳をしてみる
ありがとうございます
参考書を見ながらこういうのを書いたんですが、実行してもa,b,cの値がちゃんと 代入されずにこうなってしまいます。なぜでしょうか? 入力するdate.txtには「1234」とだけ書いておいてるんですが、date.txtの書き方 が悪いのでしょうか? -----出力されたclax.txt------- a = 1245064 , b = 1245060 ,c = 1245056 のとき 2a+3b+5c = 25463 ------------------------------ #include<stdio.h> main() { int a,b,c,x; FILE *fp; fp = fopen("date.txt","r"); if(fp==NULL){ printf("ファイルがみつかりません。"); } else{ fscanf(fp,"%d %d %d",&a,&b,&c); fclose(fp); x =2*a + 3*b + 5*c; fp =fopen("clax.txt","w+"); fprintf(fp,"a = %d , b = %d ,c = %d のとき\n",&a,&b,&c); fprintf(fp,"2a+3b+5c = %3d\n",x); fclose(fp); } }
こうかな? fprintf(fp,"a = %d , b = %d ,c = %d のとき\n",&a,&b,&c); ↓ fprintf(fp,"a = %d , b = %d ,c = %d のとき\n",a,b,c);
>492 1234しか書いてないならbとcには値を読み込めないだろ。
>>493-494 ありがとう
でもこれでやっても無理だった
datae.txt を
1
2
3
にしても同じような結果(´・ω・`)
もう2時間ぐらい悩んでるんだけど分らない
基本的な質問ですみません
>>495 これを試した結果を晒してみて
#include<stdio.h>
int main(void) /* 変更 */
{
int a=-1,b=-2,c=-3,x; /* 変更 */
FILE *fp;
fp = fopen("date.txt","r");
if(fp==NULL){
printf("ファイルがみつかりません。");
}
else{
fscanf(fp,"%d %d %d",&a,&b,&c);
fclose(fp);
x =2*a + 3*b + 5*c;
fp =fopen("clax.txt","w+");
fprintf(fp,"a = %d , b = %d ,c = %d のとき\n",a,b,c); /* 変更 */
fprintf(fp,"2a+3b+5c = %3d\n",x);
fclose(fp);
}
return 0; /* 追加 */
}
>>495 fscanf(fp,"%d %d %d",&a,&b,&c);
じゃなくて
fscanf(fp,"%d%d%d",&a,&b,&c);
余計なものを書式指定に入れてはいかん
すみません。全部消してまた最初から書き直したらうまく出来ました。
(省略)のとき\n",&a,&b,&c); が (省略)のとき\n",a,b,c);
って初歩的なミスでした。ごめんなさい
>>496 20: 複合文に } がない(関数 main )ってでてコンパイルできなかったです。
ありがとうございました。ご迷惑おかけしました
>>498 あ、勘違いしてた
空白文字は問題ないね
追記:全角空白等はもちろん消しました
>>501 見てきたが、そのサイトは絶対に参考にしてはいけない
エラーの原因はデータを格納する領域が確保されていないこと
これは酷い。こんなところはみんなのために削除すべきだな。
実行時エラーの原因は
>>503 の言う通りだが、
全角空白を消してもコンパイルできないだろ。構造体の定義の最後のセミコロンがない。
自分で確認せずにこんなソースを出しているようなサイトは百害あって一利なしだな。
505 :
504 :2007/02/11(日) 05:37:07
あー 警告出してコンパイル通るのかw mainがintじゃなくて構造体を返すことになるww
端々に時代を感じさせるサイトだった・・・ 彼らが青春を謳歌した時代の残り火とでも言うのか・・・ 世代交代は否応無しに進んでいく・・・
世代交代は進むけど、これはさすがにこの世代の典型的プログラマ(もしくは元)の性能ではないと思うよ。 現役をある程度続けていればこんなことは書かないだろ。営業畑の人間でホビープログラマっぽいし。 力が無いのは仕方ないこととして、そういう能力の有無よりも悪質なのは、実行もできないプログラムの実行例があることだな。
508 :
501 :2007/02/11(日) 06:22:12
>>503 あー・・・なるほど、領域の格納とかありましたね・・・
>>504-505 セミコロンに関しては何か違和感があったんですがw
>>506-507 (´・ω・`)これは世代に関係なく間違ってた、ってことですかね
googleの上位に来るくらいのサイトだからある程度信頼してたんですが・・・
他にも結構実行できないケースに出くわしたりするんですよw
ありがとうございました
構造体のポインタのポインタ(下のコードの変数lpptail)から 構造体のメンバにアクセスすることはできますか? できるとすれば、どうやればいいのでしょうか? 今のところ構造体のポインタ変数にポインタのポインタの値を代入して メンバにアクセスしています。 typedef struct udlist { int data; struct udlist *next; } UDLIST; UDLIST *pushUDList( UDLIST *lp, UDLIST **lpptail, int data ) { UDLIST *lpnew; UDLIST *lpprev; /* 中略 */ lpprev = *lpptail; lpprev->next = lpnew; *lpptail = lpnew; return( lp ); }
こういうこと? (*lpptail)->next = lpnew;
>>510 おお、こんな単純なことだったのか!
ありがとうございます。
*lpptail->next と *(lpptail)->next を試してダメだったので
あきらめかけていたのですが、助かりました。
>>508 こうやって間違いがネタになるから検索上位に行っちゃうんじゃない?
つまり508のサイトのコレは main(){ struct personal *ps, ps_data[2],*a;/* (1) */ int i; a=(struct personal*)malloc(sizeof (struct personal)) 中略 free(a); }} でいいのかな
あれコンパイルエラー出た 27時間寝てない計算なんでマトモに文字が見れない('A` 後は頼んだ
>513 これはひどい。
まあしかし508のサイト主といいアレな人間もいるもんだな 管理人にメールでも送ったらサイト直すか潰すかしてくれるんだろうか やらないけどね?
517 :
デフォルトの名無しさん :2007/02/11(日) 08:59:28
Cを学び初めて、1月ほどの超初心者です。 #include <stdio.h> int main(void) {int i, N=5; char *pt[ ] = {"a", "b", "c", "d", "e" }; char **pp; char ***ppp; pp = pt; ppp = &pp; printf(" pt = "); for (i=0; i<N; i++) printf("%s ", pt[i]); printf("\n"); printf(" pp = "); for (i=0; i<N; i++) printf("%s ", pp[i]); printf("\n"); printf(" ppp = "); for (i=0; i<N; i++) printf("%s ", ppp[i]); printf("\n"); return 0; } これで、pt、pp の時は、a b c d e を表示するのに、ppp の場合は、うまく行かないのでしょうか? というか、なぜ pp の時にうまく行くのか分かりません。 本当なら、pp= の後に pt のアドレスが並ぶような気がするのですが。どなたか詳しい方、教えてください。
*pのポインタを*p++等でずらしていってすべき処理を終えたときに 一番最初のポインタを参照するにはどうすれば良くて? つまり、一番最初に読み込んだときの*pには文字列が指されていて printf("%s", p);でpが指しているものを全部書き出せますが、 ポインタをずらしてしまった後は全部の表示ができません。 どうにかprintf("%s", p);で再び表示させたいのですが、よろしくお願いします
>517 ppp[i] → (*ppp)[i] にすれば上手くいくぞ。 アドレス表示させたかったら%sじゃなくて%p。
>518 もう一つ変数用意してもとの*pを保存しとけばいいだろ。
>>519 レスありがとうございます。でも、さらに何故その記述が許されるのかが理解できないです。
(*ppp)[i] ってことは *(*ppp + i) ってことですよね。 そうすると、*ppp ってポインタ型の変数ってことなんですか?
定義してないんですけど。これが納得できないんです。
>アドレス表示させたかったら%sじゃなくて%p。
これは僕の書き方がまずかったです。アドレスを指すことになるから、それをもとに文字列表示したら、
文字化けしたアドレスが表示されるんじゃないかなと思ったのですが、何故か a b c d e だったってことです。
ポインタと文字列についてもう一度教科書読み直して。
まずはじめに int a[10]; int *p; p = a; はOKだよね?式中で配列名を書くと(例外はあるが)その配列の先頭要素を指す ポインタとして評価される。つまり p = &(a[0]); と同等。a[0]を囲む括弧は不要だけど優先順位を強調している。 最初の char *pt[ ] = {"a", "b", "c", "d", "e" }; char **pp; pp = pt; はちょうどこの関係になっているのでOK。 ptの型は「charを指すポインタの配列」なのでptだけを書くとそれは その配列の先頭要素を指すポインタとして評価される。 pt => &(pt[0]) このときのpt[0]の型は何かというとchar*。 &(char*)の型はchar**だから型があっているということです。 次にchar ***ppp = pp;自体は正当。これでppp,ppとも 同じ先を指すようになる。しかし型はchar***, char**で違う。 printf("%s ", ppp[i]); の部分の「ppp[i」]の型に注意。pppはchar***なのでppp[i]の型は char**になっている。たぶんpt, ppと同じような表示にさせたいなら 型をあわせなくてはならないので519さんのように (*ppp)[i]とするか、(本質的には同じだけど)ppp[0][i]と書く。 余談だけど(*ppp)[i]と*ppp[i]の違いがわかっていないなら今のうちに 確認しておくといいよ。
525 :
524 :2007/02/11(日) 10:09:26
>次にchar ***ppp = pp;自体は正当。これでppp,ppとも typoです。これは以下に訂正。 >次にchar ***ppp = &pp;自体は正当。これでppp,ppとも
>>524 ,525
ありがとうございます。printf で、%s のときは char* であわせる必要があるってことですね。
(*ppp)[i]と*ppp[i] は、前者が配列へのポインタ、後者がポインタの配列ってことであってますか。
なかなかややこしいけど、もう少しで完全理解できそうな気がしますので頑張ってみます。
ポインタ変数ってエロいよな
>>513 #include <stdlib.h>
...
ps=ps_data;/* (2) */
for(i=0;i<2;i++,ps++){/* (3) */
ps->name = malloc(100);
ps->adress = malloc(100);
ps->tel = malloc(100);
printf("name? -"); gets(ps->name);
printf("adress? -"); gets(ps->adress);
printf("tel? -"); gets(ps->tel); printf("\n");
}
...
ps=ps_data;
for (i=0;i<2;i++,ps++) {
free(ps->name);
free(ps->adress);
free(ps->tel);
}
そこのサイトの書き方に合わせるならこうかな?100は適当。もちろん構造体の定義の最後には;を付ける。
struct personal *ps, ps_data[2];/* (1) */で構造体そのものの領域は確保されているから、
各文字列のための領域を確保すればいい。
でも、gets()を使ってる時点でどんなに領域を確保しても安全とは言えないから、
gets()の代わりにfgets()を使って確保したサイズ以上を読み込まないようにしないとダメだ。
ここでは構造体のポインタの説明だから仕方ないけど、psなんて使わず素直にps_data[i].nameでいいかも。
あと、adressはaddressにした方がいいだろw
今日は人多いですね、日曜日だからかな?
>>513 struct personalの各メンバが領域確保されていないんですよ
530 :
529 :2007/02/11(日) 17:56:03
って真上ですでにレスあったり・・・・・
グローバル変数はstaticということでいいんですか?
532 :
529 :2007/02/12(月) 00:54:28
なんだそれ。
>>531 グローバル変数はグローバルなスコープを持ち、静的変数は(関数外で定義しても)ファイルスコープしか持ちません。
>>534 関数外で定義したのがグローバル変数じゃないの
他のファイルで使うときはexternで使わないとだめじゃないけ
>535 staticについてどう考えてる?
ファイルスコープ変数とグローバル変数は天と地程の(デバッグのしやすさの)差がある。
>>535 externは定義にはつけなくても、外部に公開される。
外部から利用するために、externをつけて宣言するわけだ。
だから、static は?
>>539 質問したいなら「staticは?」じゃなくて何を聞きたいのかきちんと書け。
で、staticをつけて定義した関数外の変数はファイルスコープだというの既出。
関数内の場合は関数スコープであり、静的であると言うこと。
>>540 ファイルa.cの中で
void abc(void)
{
static int a = 1;
...
}
void def(void)
{
a = 2;
}
は、可能か?
>>540 >関数外の変数はファイルスコープ
あっ、書いてあったのね。
>>542 寧ろこっちを嫁。
>関数内の場合は関数スコープであり、静的であると言うこと。
544 :
デフォルトの名無しさん :2007/02/12(月) 16:46:02
int addnum(int a, int b ){ と int main(int argc, char *argv){ これらの違いは何なんでしょうか? 前者はどういう時、後者はどういう時に使うのでしょうか? この二個の質問にお答え戴ければ幸いです。
前者はユーザ定義関数、後者はプログラムのエントリ関数。 但し、通常とは引き数が違うようなのでその辺りは処理系依存。
546 :
デフォルトの名無しさん :2007/02/12(月) 16:56:56
ありがとうございます エントリ関数とはコマンドフロンプトンから直接入力する事でしょうか?
>>546 プログラムのエントリ関数がどこからどう呼ばれるかも処理系依存。
まして、>544のような引き数を取るエントリ関数が(恐らくWindowsと思われる)
コマンドプロンプトからどう呼ばれるかなんて知るもんか。
>>547 Windowsのエントリでも
int main(int argc, char *argv[])
はあっても
int main(int argc, char *argv)
は無いんじゃないかな
549 :
547 :2007/02/12(月) 17:06:07
>>548 漏れもそう思う。だから「知るもんか」と書いた。
若しかしたら、そんな処理系があるかもしれない。
#少なくとも、こんな処理系があることは想定可能だ。
--
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow )
{
return main(1, lpCmdLine);
}
--
使いたくないがなw
550 :
デフォルトの名無しさん :2007/02/12(月) 17:06:37
dクスでした、難しい
>>550 判ってておちょくってる連中もなんだが、あんたも何で自分の環境を書こうとしないんだ?
それとも、あんたの環境や書き間違いまで全て推測しろとでも?
552 :
548 :2007/02/12(月) 17:12:35
>>549 あーーっ
それに近いコード書いたことあるorz VC6 の CRT0 から微妙に経由したときに。
>538 Cにおいてexternは、定義には付けられない
>>553 そんなことはない。
JIS X3010:2003でいいから一度見てみな。
あーたしかにC99なら合法だな
>>554 JIS X3010:2003 何これ?
で正解は "Cにおいてexternは、定義には付けられる" ということかな
たとえば、extern struct are { あれ、これ、}kore; って、どうなる?
これでおkかな? ----- hoge.h ----- extern struct are { int a; } kore; ----- hoge.c ----- #include"hoge.h" struct are kore;
どんなメリットがあるのか・・・あるから盛り込まれたんだろうけど。
>>555 え?C89とかでは駄目だったか?そんな覚えはないのだが。
先生!
>>557 の使い方で、正しいのでしょうか?
教えてくだはい
気持ち悪いので分けた方がいいと思います ----- hoge.h ----- struct are { int a; }; extern struct are kore; ----- hoge.c ----- #include"hoge.h" struct are kore;
>>561 先生!
この場合、自分はexternはなくて問題ないように思うんですが、やっぱり、必要でしょうか?
>>562 externがないとhoge.c以外のソースファイルからare koreにアクセスできない
are koreの実体はhoge.cにある
>>562 と、
extern struct are kore を無くすと
>>563 extern だけないとhoge.hをインクルードするソースファイルすべてにare kore;の実体が置かれる
hoge.c以外のソースからare kore; にアクセスしてもそれはhoge.cのare kore; とはベツモノ
hoge.cにいたっては2重で宣言したことになる
C言語初学者です。 4byteの文字列をfloat型のバイナリ値として 認識するにはどういった方法があるか教えてください。 例えば文字列が char c[] = {0x3f,0x00,0x00,0x00}; であれば、「0x3f000000(バイナリ)」→「0.5(float型)」のように変換したいと 考えてます。 よろしくお願いします。
お前のところのfloat型は4byteなんだとして、 *(float*)&c[0]あるいはもっと短く*(float*)c。 ただしエンディアンに要注意。
568 :
デフォルトの名無しさん :2007/02/13(火) 02:08:23
#include <stdio.h> #include <string.h> int main(int argc, char *argv[]){ char usage[] = "usage: tarsh <-d> filename\n"; int ret = 0 /*関数の戻り値*/ char newfilename[256] = ""; /*パラメータなし*/ if(argc <= 1){ printf(usage); return 1; } /* -d指定あり */ else if(strcmp(argv[1], "-d") == 0){ if(argc <= 2){ printf(usage); return 2; } ret = remove(argv[2]); if(ret == 0) printf("ファイルを削除しました。\n"); else printf("ファイルを削除できませんでした。\n"); }
569 :
デフォルトの名無しさん :2007/02/13(火) 02:09:26
/* -d指定なし */ else { sprintf(newfilename, "%s.bak", argv[1]); ret = rename(argv[1], newfilename); if(ret == 0) printf("ファイル名の最後に .bakを付加しました。\n"); else printf("ファイル名が変更できませんでした。\n"); } return 0; } Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland sample16.c: エラー E2141 sample16.c 8: 宣言の構文エラー(関数 main ) エラー E2451 sample16.c 31: 未定義のシンボル newfilename(関数 main ) *** 2 errors in Compile *** どこの箇所に誤りがあるのか、わからないので ご指摘、お願い致します。
>>568 =569
int ret = 0 /*関数の戻り値*/
int ret = 0; /*関数の戻り値*/
中身は一切見てないので、文法のみ指摘
571 :
570 :2007/02/13(火) 02:33:38
あ、書き忘れた × int ret = 0 /*関数の戻り値*/ ○ int ret = 0; /*関数の戻り値*/
572 :
デフォルトの名無しさん :2007/02/13(火) 03:54:44
573 :
デフォルトの名無しさん :2007/02/13(火) 04:00:34
結果って、これでいいんものですかね? c:\sm>bcc32 sample16.c Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland sample16.c: 警告 W8004 sample16.c 7: 'ret' に代入した値は使われていない(関数 main ) Turbo Incremental Link 5.00 Copyright (c) 1997, 2000 Borland c:\sm>sample6 0 1 2 3 4
>566 そういうときこそunionを使うんだ!
575 :
デフォルトの名無しさん :2007/02/13(火) 04:13:45
参考書の結果とは、だいぶ違いますが・・・・
>>573 ちょw 良く嫁ww
c:\sm>bcc32 sample16.c
c:\sm>sample6
>573 sample16じゃなくてsample6を実行してるように見えるけど、どうなの?
578 :
デフォルトの名無しさん :2007/02/13(火) 04:30:33
>>577 アー!!
とんだ、かんちがいを、やらかしていました
ですが、実行結果が参考書と、違うんですよね
自分のは
c:\sm>bcc32 sample16.c
Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland
sample16.c:
警告 W8004 sample16.c 7: 'ret' に代入した値は使われていない(関数 main )
Turbo Incremental Link 5.00 Copyright (c) 1997, 2000 Borland
c:\sm>sample16
usage: tarsh <-d> filename
になってしまいます。
c:\sm>sample16
usage: tarsh <-d> filename
が
c:\sm>trash a.txt
ファイルの最後に .bakを付加しました。
にならないといけないんです、何がいけないのか
さっぱりです
>>578 問題なくコンパイル出来てる。
「main関数の引数」とかに関する記述をよく嫁
あとついでに、「コマンドライン」とか「コマンドプロンプト」とかググって、詳しく理解することもオヌヌメする。
てっとりばやく説明するなら、
1) c:\sm>sample16
→ usage: tarsh <-d> filename
ファイルを指定してないので何もしない
2) c:\sm>sample16 hoge.txt
→ファイル名〜
sample16.exe と同じフォルダ(ディレクトリ)内の「hoge.txt」を「hoge.txt.bak」に名前変更する
3) c:\sm>sample16 -d hoge.txt
→ファイルを削除〜
sample16.exeと同じフォルダの「hoge.txt」を削除する
※2,3) で「hoge.txt」が存在しなければメッセージのみ出力して何もしない
つまり、「sample16」という命令で sample16.exe を起動してるわけだが
その後に続く文字列 = main()への引数によって動作が変わる訳で。
580 :
デフォルトの名無しさん :2007/02/13(火) 05:17:57
>>579 できました!!!夜分と言うか黎明ですが、ありがとうございました!!
「hoge.txt」を「hoge.txt.bak」に名前変更した、ファイルは何故か削除できないんですね。
何故なのでしょうか? でも、別に新しく作った hoge-hoge.txt と言うファイルは削除できました
「コマンドライン引数や」とか「コマンドプロンプト」とかググったら
http://homepage1.nifty.com/toshio-k/prog/c/ と解説ページが出てきました、
しかしコマンドライン引数( int main(int argc, char *argv[]) )
は、どういう意味があるのか、これで何がしたいのか、ピンときません
581 :
デフォルトの名無しさん :2007/02/13(火) 05:21:21
例えば、コマンド上で削除などしたければ 別にint main(int argc, char *argv[])を使わなくても delやrmなどで削除できると思いますが・・・
>580 ちゃんと変更した名前でやってるか?
583 :
デフォルトの名無しさん :2007/02/13(火) 05:33:33
よし、ここで俺がエスパーしておく。
> c:\sm>sample16 hoge.txt
> ファイル名の最後に .bakを付加しました。
> c:\sm>sample16 -d hoge.txt
> ファイルを削除できませんでした。
hoge.txtはrenameされてhoge.txt.bakになってるんだから、
既に存在しないhoge.txtは削除出来んわなあ。
まあ低レベルエスパーだったが。。。
結論としては、
>>580 はプログラミング向いてないかプログラミングの独学に向いてないかのどちらかだろう。
>>581 むしろ、オマイはCで何をしたいのかと。
delやrmが目的なら、別にCやらなくても良いんと違うかと
と書き込む前にリロードしたら、ちゃんと出来たようだが
>>583 質問した人は是非名乗って欲しいな。
もし
>>578 =
>>580 =
>>583 なんだったら、それこそもう(以下略
585 :
580 :2007/02/13(火) 05:44:45
すみません、ですができたので、とても嬉しいです。
プログラミング用チートシートってなんですか? 柴田望洋の入門書が一番詳しいけど 学校の問題とは出題傾向が違うので困る 望洋全然数学関係ないけど実際は数学使う問題だしてくるし
>>586 チートシート(=カンニングペーパー)
持ち込み可の場合には制限がつく場合が多い
本人の手書きに限る
A4二枚まで
など
プログラミング用チートシート
ポケットリファレンスみたいなもの?
標準関数一覧とヘッダリファレンスぐらいか? 多少は記憶していても、qsort とか、どっちが要素数でどっちが1要素あたりのサイズか忘れたりするし
入門書の次って何を買ったらいいですか? 「ポインタの極意」買っちゃっても理解できるかな?
ポインタはやってるうちにわかる。 辞書的に調べられるものや、実践で何かを作るために特化したものとか。
柴田望洋のポインタ本より前橋和弥のポインタ本のほうが初心者向け
>>591-593 ありがとうございます
今はとりあえずポインタは触りだけ理解したけど、どういうふうに有効に利用
したらいいのか分らない状態
薦めてくれたポインタ本買ってみることにします
595 :
568 :2007/02/13(火) 23:49:12
最後に質問なのですが 普通、printf("usage")ではないのでしょうか? どうして""が省略されているのでしょうか? そして、もう一つは return 1; や return 2;を返すとは どういう事なのでしょうか? よく、成功すれば0を返すとは聞きますが
>>595 成功すれば0、失敗(不正なパラメーター)してるから
それ以外を返してるんだろ?
bash なら実行したあと echo $? とでも実行してみろ。
>>595 >普通、printf("usage")ではないのでしょうか?
>どうして""が省略されているのでしょうか?
char usage[] = "usage: tarsh <-d> filename\n";
printf(usage);
は文字列へのアドレスをいったんポインタに格納してそれをprintfの引数として指定している
printf("usage: tarsh <-d> filename\n");
の引数は文字列であり、実際はその文字列への直接のアドレスが指定されている
つまり式としてはと等価
printf(usage); よりは printf("%s", usage); の方が良い作法のような気がする。 けど強くは主張しない。
>>598 いや、ある程度強く主張したほうがいいぞ。
usageの中に%sとか入れたくなるやつがきっと出る。
600 :
デフォルトの名無しさん :2007/02/14(水) 00:17:25
配列を使わず入力された正整数の最小値を求めるプログラムを教えてください。
601 :
568 :2007/02/14(水) 00:19:41
>>596->>597-
>>598 ありがとうございました、あとは自分で試行錯誤して考えます。
>>600 入力されるたびにそれまでの最小値と比較して小さいようなら最小値を更新する
>>600 EOF (Ctrl+D or Ctrl+Z) で入力終了
#include <stdio.h>
int main(void){
int minimum, num, is_first=1;
while(scanf("%d", &num)==1){
if(is_first || num<minimum)
minimum=num;
is_first=0;
}
if(!is_first)
printf("\nminimum : %d\n", minimum);
return 0;
}
604 :
デフォルトの名無しさん :2007/02/14(水) 00:29:02
>>602 ありがとうございます。
そのなかで次に小さい値を出力する場合にはどうすればいいですか?
605 :
1 :2007/02/14(水) 00:31:02
c言語でチャットや掲示板ってつくれますか? webで使えるようなやつ作りたいんですが
>>605 作れますよ。作れますけど、多分PerlやPHPなどを使った方がはるかに楽に作れます。
>>604 /* EOF (Ctrl+D or Ctrl+Z) で入力終了 */
#include <stdio.h>
#include <limits.h>
int main(void){
int min1=INT_MAX, min2=INT_MAX, num;
while(scanf("%d", &num)==1){
if(num<min2)
min2=num;
if(min1>min2)
{
num=min1;
min1=min2;
min2=num;
}
}
printf("\nmin1=%d\tmin2=%d\n", min1, min2);
return 0;
}
>>605 2chは確か一部にC言語も使っていたと思う
609 :
605 :2007/02/14(水) 01:13:35
>>606 >>608 解答ありがとうございました!
まずはチャットを作ることを目標にがんばります!
無理に作らんでもPerlで作っとけって・・・・
611 :
デフォルトの名無しさん :2007/02/14(水) 02:38:32
612 :
デフォルトの名無しさん :2007/02/14(水) 03:43:01
#include <stdio.h> #include <string.h> int wtoji(int, char *, int *); int main(){ int wyear = -1, jyear = 0; char nengo[16]; printf("西暦→和暦に変換を行います。終了するには0を入力して下さい。\n"); while(wyear != 0){ printf("西暦を入力して下さい(1868-2050)) : "); scanf("%d", &wyear); if(wtoji(wyear, nengo, &jyear) == 0) printf("西暦%d年は、%s%d年です\n", wyear, nengo, jyear); } return 0; } /********************************* wtoji() 西暦から和暦へ変換する [引数] wyear -- 西暦 nengo -- 和暦の年号文字列へのポインタ jyear -- 和暦へのポインタ [戻り値] 変換できたら0、範囲外なら1 ***********************************/
613 :
612 :2007/02/14(水) 03:44:04
int wtoji(int wyear, char *nengo, int *jyear){ if(wyear >= 1868 && wyear <= 1911){ strcpy(nengo, "明治"); *jyear = wyear-1868+1; return 0; } else if(wyear >= 1912 && wyear <= 1925){ strcpy(nengo, "大正"); *jyear = wyear-1912+1; return 0; } else if(wyear >= 1926 && wyear <= 1988){ strcpy(nengo, "昭和"); *jyear = wyear-1926+1; return 0; } else if(wyear >= 1989 && wyear <= 2050){ strcpy(nengo, "平成"); *jyear = wyear-1989+1; return 0; } return 1; }
614 :
612 :2007/02/14(水) 03:49:41
このソースで、幾つか疑問点がありますので ご返答、宜しくお願い致します。 一個目は、>>if(wtoji(wyear, nengo, &jyear) == 0) の、if(()〜 == 0)の部分です、これは0と等しいと言う事でしょうか? もし、違うのであれば指摘と助言お願いします。 二個目は、>>int wyear = -1, jyear = 0; 何故、-1と0なのか? 三個目は、>>*jyear = wyear-西暦+1; 何故、+1が必要なのかが疑問です。
>>614 (2)
wyearは0以外なら何に初期化しても構わない。
jyearは使われる前に値が代入されるので、ここで初期化する必要はない。
(3)
和暦は1年から始まるから。
明治元年が1868年だとすると、
入力した西暦が1869年なら1869-1868=1となり1を足さないと明治1年となる。
何が変数に入ったらどうなるのかを一文一文頭の中で追いかけてシミュレートしてみることを勧めるよ。
616 :
デフォルトの名無しさん :2007/02/14(水) 04:05:35
wtoji()の中が気持ち悪い・・・ if 、 else if を使っているならわざわざ return 0; を あちこち入れなくても、最後に入れて、入力範囲の条件にあわないところで return 1; をすりゃええがな。
617 :
612 :2007/02/14(水) 04:29:20
叩いておくからその参考書を教えてくれたまえ。
なんじゃこのアルゴリズムは?って思える本はいくらでもあるよね・・・
if 〜 else if で終わらしていいの? 最後はelse で終わらないと警告発するんじゃなかったっけ?
>>620 おまえは普通のif分にもelseを書くのかと。
っつか、条件分岐させる必要がない残りの部分を else { } で囲んでも 字下げがまんどっちぃ
>623 メモ帳でも使ってんのか?
いや、自動的に字下げしてくれるエディタ使っているけど?それでもまんどっちぃっつーか 見づらい
int x[8]; int *y; y = (int *)malloc(sizeof(int)*8); printf("x: %d\n", sizeof(x)/sizeof(int)); printf("y: %d\n", sizeof(y)/sizeof(int)); 実行結果 x: 8 y: 1 配列はsizeofでサイズを取得できるけれど、ポインタ変数を代用するとできません。 変数yから確保した領域のサイズを取得することはできないのでしょうか?
>>626 できない。
# だからかもしれんが、配列を受ける関数は要素数を引数に要求する作りになる。
>>627 この問題を解決できるライブラリがあるのではと期待していたのですが
甘かったですねorz
ご回答、ありがとうございました。
>626 っていうかmallocで確保するときにサイズを指定してるんだから、もともとサイズはわかってるだろ。
>>630 君は何を言っているんだね?質問の内容が分かってないなら黙っとけ。
>>626 の *y についてだろ
>631
634 :
本日のバカ一覧表 :2007/02/14(水) 14:01:28
630 名前:デフォルトの名無しさん 投稿日:2007/02/14(水) 13:07:30
>626
っていうかmallocで確保するときにサイズを指定してるんだから、もともとサイズはわかってるだろ。
632 名前:デフォルトの名無しさん 投稿日:2007/02/14(水) 13:56:49
>631
633 名前:デフォルトの名無しさん 投稿日:2007/02/14(水) 13:58:59
>>631
635 :
デフォルトの名無しさん :2007/02/14(水) 14:02:22
>>626 の質問の要点
> 変数yから確保した領域のサイズを取得することはできないのでしょうか?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
自前で malloc ラッパ- のようなものを書くという手もあるが、 void * hoge(size_t size) { size_t* r = malloc(size + sizeof(size_t)); *r = size; return r+1; } それ以外で得られたポインタが渡る可能性もあるから、結局ムリポ
質問の意味は分かってるよ。 ただ質問自体に意味がないって言ってるの。 yが指す領域はmallocで自分でサイズを指定してるわけ。 それをわざわざyから求めなおすことは無意味だろ。
>>637 俺、質問者じゃないんだけど?お前がそう思うにしても論点が違うから
質問内容が分かってないなら 黙ってろ な?
こんな感じかな? 適当なリストに malloc で確保したアドレスとサイズを記録していく void *hoge(size_t size){ void *ptr; ptr=malloc(size); hash_add(malloc_size_hash, ptr, size); return ptr; } size_t malloc_size_get(void *ptr){ return hash_search(malloc_size_hash, ptr); }
必死だな
ヘッダを参照しようとして*((char*)y-(char*)定数)とか鼻から悪魔ですよね、やっぱり
みんなは メモリ領域確保 と言われて一番最初に頭に出てくる関数なに?
GlobalAlloc
そもそもsizeof は実行時じゃなくてコンパイル時に決定する
#include<stdio.h> #define OFFSET(type, member) (size_t)(&((type *)0)->member) struct hoge{ char hoga[13]; double fuge; char fuga; }; #define offset_print(member) printf("Offset of %s : %d\n", # member, OFFSET(struct hoge, member)) int main(void){ struct hoge a, *b; void *p; offset_print(hoga); offset_print(fuge); offset_print(fuga); p=&a.fuga; b=(struct hoge *)((char *)p-OFFSET(struct hoge, fuga)); printf("&a=%p b=%p\n", &a, b); return 0; }
これで無限ループを作りたいのですが無限ループしません。 環境に依存しているのですか? knoppixのgccを使ってます。 #include <stdio.h> main () { char c; while (1){ c = getchar(); if(c == '\n') { break; } printf("%c", c); } return 0; }
breakしなきゃいいじゃん。
>>647 break外したらできました。
ありがとうございました!
649 :
デフォルトの名無しさん :2007/02/14(水) 17:55:58
ファイルで読み込んだ値を構造体で初期化できないので、初期化するにはどうしたらいいか教えてください。
初期化できないなら代入すれば良いじゃない by マリーアントワ.NET
freadで直接読ませてもいいし、memcpyでもいいじゃん。 1つずつセットしてもいいけど。 同じマシンで丸ごと、てのじゃ無ければパッキングに注意
652 :
デフォルトの名無しさん :2007/02/14(水) 18:49:00
直接入力しないで初期化したいんですよ。。。
は?それって >ファイルで読み込んだ値を これ関係ないじゃん { } と , でくくればおk
それとも読み込みたいのか? fread() のバッファに構造体のポインタ入れればいい そのための size とcount 別指定だぜ
655 :
デフォルトの名無しさん :2007/02/14(水) 19:18:27
初心者です。ごく基礎的なことでお尋ねします。以前に別板で上げましたが、誘導されました。 昔、NECの9801のDOS環境で、MS-C6で組み上げた自作のデータベースソフトがあります。 3つのソースを(ソースは合計2000行を超えるので、ちょっと晒せませんが)分割コンパイルし、LinkしてEXEを作成しています。 DOS-v6からWin95及びWin98環境に変えても、EXEファイルをコピーしておけば、コマンド入力で動いてくれました。(データファイルはa+なんで自動で) しかしWin2000とXP上では、全く起動さえしてくれません。 16bit環境と32bit環境の違いかな推測しているのですが、どうなのでしょうか? もし16と32のFATの違いなんかが原因であれば、下記の対処策のどれで解決できるのでしょうか。 @コンパイラ&リンカーを32bitのものと変えてコンパイル・リンクすればOK。 AMS-C全体を、32bitのC言語に取替え、ソースはそのままで、OBJやEXEファイルを32bit環境で再作成する。 B16bit時のグラフ関数等は使用不能。で、ソーステキストから書き換えが必要。その上でMS-Cを32bitのC言語に取替え、再作成。 Cそれとも原因は全く別の所に有って、そんなことをやっても所詮は無理。 もしよろしければ教えてください。 時々このソウトを使っているんで、これが有る限り9821vxというPC&CRTがリサイクルに出せません。 長文失礼しました。
ソースの内容次第としか答え様がない 環境依存部とロジック部を切り分けて 環境依存部を書き直すのがセオリー 2000行程度なら全部書き直してもいいんじゃまいか
> B16bit時のグラフ関数等は使用不能。で、ソーステキストから書き換えが必要。その上でMS-Cを32bitのC言語に取替え、再作成。 DOSの時代のグラフィックライブラリとか使ってるなら、それが、やばそうな気がするなぁ。 (よくしらんけど) FATの16とか32は関係なさそうな気がする。
>>655 1. int で宣言してある部分をすべて short に置き換え必須
2. 構造体のパディング部分の確認
3. グラフィック関係はおそらく全て書きなおし
お手軽なのは PC98エミュレータを使うこと
>>655 1と2は同じじゃ?
コンソールとファイルの入出力を標準関数でしてるだけなら、まんま通ります。
NEARとか使ってたりするならそこは直さないとダメかも。(NEAR,FAR,HUGEを消せばおk)
9801の画面にグラフを描いてたんですか?それはそのまんまは無理ですね。
それやるとなると、Windowsアプリを書くことになりますね。
MS-Cってのが分からないのでググって見たら
>MS-C(Microsoft C/C++) - Microsoft Visual C++の前身。
というのが見つかったけど、これのこと?
まあ、
>>657-659 の通りなんだろうけど。
取り敢えず標準Cではなさそうなので@Aが不可なのは確定
>合計2000行を超える
どっかのロダに晒せば、興味本位で書き直してくれる人も居そうな気がするけど
それともソース流用がイヤなのか?
>>659 MS-C6は__near, __farとかだったような。HUGEはまず使わないだろうとは思うけど、
何ともいえんなまあ、
#define __near
#define __far
でokかな。
グラフィックライブラリは、リファレンスを見ながら関数群を
WindowsのAPIにマップするようにするしかないかね。
voidの意味がいまいちわかりません
そのへんの参考書とかだと値を返さない とかだな まんまか。
>>662 どれが分からないのか、こっちも分からない。
1) 値を返さない関数の、返り値の型
2) 引数を取らない関数の、仮引数リスト
3) いわゆる汎用ポインタ
どっちにしろ参考書良く嫁としか
665 :
デフォルトの名無しさん :2007/02/14(水) 22:31:34
655です。回答レスありがとうございます。 やはりソースの書き直し、が必須となりそうですね。
ウーンしかし、ぶっちゃけて言うと我がソートながらも書き直しできるか不安です。 何せスキルが衰退してまして。
恥ずかしながら、ソフ開の試験を午前合格・午後敗退を繰り返してるような頼りないレベルなので。
>>656 これを書いたのが平成の最初のほう。 以来幾春秋!
当時でも2000行でかなり迷ったのに、歳を経た今となっては、自分のアルゴさえ思い出せない可能性が....
>>657 graph.hは当然includeしてます。それがやばいのなら、ご臨終のソースですね。
FATが関係なさそうなら、いよいよソース自体の問題ですね。
>>658 intは沢山使用。longさえ使用してます。
これはデータが長くなると予想して、その中からデータの位置を計算するために使う変数です。
shortに変えるとなると、データ構造を根元から変えないといけないし(涙)
グラフィク関連は657さんと同様のご指摘。本当にご臨終のようですね。
>>659 入出力関数は標準関数を使いました。
9801でグラフは描いてないんですが、データの画面文字縦表示にこだわりまして。
で、それを強調するために当時16色の色をフルに使って、画面広く塗り込んだんです。
当時はそれで良かったのですが、1677万色が標準の時代が来るとは思いませんでした。
>>660 そのMicrosoftCです。
流用されるほどのレベルの物ではないのですが、ソース全文を晒すのは、ボロクソに言われそうなんでね。
他人に徹底的に叩かれるのは、そうそう経験したくないので、遠慮したいですねー。
>>661 グラフィクはWindowsのAPIにマップ... 当方その根気&スキルが今は薄れておりまして。
どうもすみませんでした。 結局、このソフトは前時代の遺物に成り下がったのがよくわかりました。
壊れるまで9821と付き合っていくほかなさそうです。
初心者の問いに皆さんありがとうございました。 長文でごめんなさい。
>>662 void は値を返さない、もしくは引数が無い
void *は汎用ポインタを返す、使うときはキャストする
>>665 DOS (16bit)のintは2バイトだったが、Win32/64 (32/64bit)のintは4バイトだから
intをshortに直せと言われるわけ。というわけでとりあえず
つ#define int short
shortとlongはそれぞれ2バイト、4バイトで変わっていない。
>>662 なんかそのウィルスに感染するとコミュニティが荒れるらしいよ。
あと kusokabe だか kusakabe だかってエイリアスがあるらしい。
幸運な事に俺は直接遭遇したことないからよくは知らんけど。
669 :
デフォルトの名無しさん :2007/02/14(水) 23:23:46
他のファイル中に宣言している const 配列を、別ファイルから参照して sizeof() でサイズを知りたいんですが、 普通に extern foo[] だけだとsizeof()で知ることが出来ませんよね? これって解決方法はありますか?
>>669 解決方法
1. extern int foo[100]; のように要素数まで書く
2. 変数 foo の実体のあるファイルで要素数を返す関数を書く size_t foo_size(void){return sizeof(foo);}
3. foo の大きさを決めるマクロをヘッダに書く
エスパーによると 2. の方法がいいよ
672 :
612 :2007/02/15(木) 01:02:01
考えても、よくわからない点がまだあるのですが
*jyear = wyear-年号+1; の*jyearは
和暦のポインタとの事ですが、何処の事を指しているのでしょうか?
>>618 正永社の書籍です。
>671 なんで関数にするの?変数でいいじゃん。
>>672 main関数の中でwtoji(wyear, nengo, &jyear)というようにwtoji関数を呼び出している。
wtoji関数の方はwtoji(int wyear, char *nengo, int *jyear)と定義されているので、
wtoji関数内のjyearにはmain関数内のjyearのアドレスが入っている。
だから、wtoji関数内で*jyearに値を代入すると、main関数内のjyearにその値が入る。
676 :
671 :2007/02/15(木) 01:18:26
>>673 思いつかなかった
そう言われれば変数でもOKだね
でも、一押しは関数
変数のサイズについて質問です。バイナリファイルを読み込んで、処理を 行うさい、8bit、16bit、32bitといったバッファサイズをとりたいと考えています。 ただ、プラットフォームによって変数のサイズが変わってくると聞きました。 (int型が16bitだったり32bitだったり) とあるサイトのglibというライブラリの紹介の中で、全てのプラットフォームで 8 ビットであることを保証する符号つき整数として下記のものが定義されていると 紹介されていました。下記の書き方だと、サイズは一定ということが保障される のでしょうか? typedef signed char gint8; よろしくお願いします。
一定になるように、適切にgint_8をtypedefする、というか。 あなたが定義すべきか、glibが定義してくれるかは、 その処理系がどれだけマイナーかによっているけれど。 ちなみに、Cの規格としては、charが8bitであることは保証されていない。
679 :
671 :2007/02/15(木) 01:30:21
>>677 char は 1byte であることが保証されているが、
1byte が 8bit であるかどうかは C言語では規定されていない
って友達の友達が言ってた
普通のパソコンでは 1byte=8bit だろうけど、組み込みとかだと違ってくる可能性もある
>>672 【【【
>>612 の場合には 】】】
wtoji 関数の引数で与えられた jyear は
main 関数の中の int 型変数 jyear のアドレスを指しています
C言語もVisual Studioとか使ったら作りやすいんですか? まだそんな域まで達してないけど
682 :
612 :2007/02/15(木) 02:03:25
683 :
デフォルトの名無しさん :2007/02/15(木) 02:24:00
if(!(fp = fopen(buf_r, sizeof(int), 10, fp) != 10); fclose(fp) return; これは、どういう意味でしょうか? もし、10((buf_r, sizeof(int), 10, fp))でないなら閉じると言うのでしょうか?
fopeはそんな引数はとらんが… それがfread or fwriteだったとしても、ファイルポインタ壊すし…
いや、ファイルポインタを壊さないよ。 壊す前にコンパイルを通らない。 1行目の括弧のバランスが…… それにしても、どこをどう間違えるとこんなものを書くことになるんだろ。
686 :
デフォルトの名無しさん :2007/02/15(木) 04:10:38
#include <stdio.h> main(){ FILE *fp; char filename[] = "bintest.dat"; int buf_w[10], buf_r[10]; int i; for(i = 0; i < 10; i++) buf_w[i] = (i+1) * 10; if(!(fp = fopen(filename, "wb"))) return; if(fwrite(buf_w, sizeof(int), 10, fp) != 10){ fclose(fp); return; } fclose(fp) if(!(fp = fopen(filename, "rb"))) return; if(fread(buf_r, sizeof(int), 10, fp) != 10){ fclose(fp) ; return; } fclose(fp); for(i = 0; i < 10; i++) printf("%d", buf_r[i]); }
687 :
デフォルトの名無しさん :2007/02/15(木) 04:11:33
c:\source>bcc32 C-language.c Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland c-language.c: 警告 W8060 c-language.c 11: おそらく不正な代入(関数 main ) エラー E2379 c-language.c 19: ステートメントにセミコロン(;)がない(関数 main ) 警告 W8070 c-language.c 30: 関数は値を返すべき(関数 main ) *** 1 errors in Compile *** これらが、どうしても改善されませんので、指摘お願いします。
688 :
デフォルトの名無しさん :2007/02/15(木) 04:14:44
一つは発見しましたが c:\source>bcc32 C-language.c Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland c-language.c: 警告 W8060 c-language.c 11: おそらく不正な代入(関数 main ) 警告 W8060 c-language.c 19: おそらく不正な代入(関数 main ) 警告 W8070 c-language.c 30: 関数は値を返すべき(関数 main ) Turbo Incremental Link 5.00 Copyright (c) 1997, 2000 Borland c:\source>C-language 102030405060708090100 変な結果が出てしまいます。
689 :
デフォルトの名無しさん :2007/02/15(木) 04:25:26
#include <stdio.h> main(){ FILE *fp; char filename[] = "bintest.dat"; int buf_w[10], buf_r[10]; int i; for(i = 0; i < 10; i++) buf_w[i] = (i+1) * 10; if(!(fp = fopen(filename, "wb"))) return; if(fwrite(buf_w, sizeof(int), 10, fp) != 10){ fclose(fp); return; } fclose(fp); if(!(fp = fopen(filename, "rb"))) return; if(fread(buf_r, sizeof(int), 10, fp) != 10){ fclose(fp) ; return; } fclose(fp); for(i = 0; i < 10; i++) printf("%d ", buf_r[i]); }
690 :
689 :2007/02/15(木) 04:32:28
お騒がせして、申し訳ありませんでした。 質問が改めてあります。 上のソースはバイナリの読み書き出しですが 書き出したら、何処かに10 20 30 40 50 60 70 80 90 100 という ファイルができないのでしょうか? あと、これは読み込みと書き出しの両方をやっているのでしょうか? この2つの質問のご返答、宜しくお願い致します。
>>686 エラー:
二つ目の fclose(fp) の後に;が無い。
警告:
void main()
{
…
}
にするか
int main()
{
…
return 0;
}
にする。
あ、686はもう済んでるのか
お前はもう、済んでいる ひでぶぅ〜
【審議中】 ∧,,∧ ∧,,∧ ∧ (´・ω・) (・ω・`) ∧∧ ( ´・ω) U) ( つと ノ(ω・` ) | U ( ´・) (・` ) と ノ u-u (l ) ( ノu-u `u-u'. `u-u'
>>690 bintest.datというファイルにデータを書き出して、
bintest.datというファイルからデータを読み出して、
最後にそのデータの内容を標準出力に書き出している。
>>694 このブタ風情が、いっちょ前に審議なんてしてんじゃねぇ〜〜〜
697 :
677 :2007/02/15(木) 07:23:39
>678, 679 レスありがとうございます。やはり処理系によって場合分けするのが 適切なんですね。ありがとうございました。
>>681 メモ帳でプログラムを書いたり
毎回コマンドラインからコンパイルとかしているなら
Visual Studioの方が便利。
699 :
671 :2007/02/15(木) 07:53:04
>>671 >>673 関数化が良さそうですね。変数で持つのはRAM容量が無いので厳しそうです。
ありがとうございました。
>>699 なぜRAM容量?
関数のほうがオーバヘッドあるから変数よりメモリ食うぞ
関数がいいのは別のファイルからその内容を変更されないこと
変数の場合は別のファイルからも書き込みが出来るので誤って変更してしまうことがある
変数をconstで宣言しとけばある程度は安全だけど
702 :
デフォルトの名無しさん :2007/02/15(木) 15:07:10
符号無し整数xを右にnビット回転した値を返す関数rrtotateと、 左にnビット回転した値を返す関数lrotateを作成する っていう問題をやっているんですが、やり方がわからないので 少し教えていただけないでしょうか。 最下位ビットが1かどうか調べて1だったら シフトしてから最上位ビットを1にするんだと思ってるんですが 最上位のビットをONにする方法が思いつきません。
|
>>703 いや、端的過ぎるわそれw
>>702 >最下位ビットが1かどうか調べて1だったら
最上位じゃなくて?
705 :
デフォルトの名無しさん :2007/02/15(木) 16:05:19
00101110100110100101011001011011 ↑ここを調べて 00010111010011010010101100101101 右にシフトして 00010111010011010010101100101101 ↑ここをONにすると思ったんですが根本的に間違えてるんでしょうか・・・
>>702 #include <limits.h>
unsigned rrotate(unsigned x, int n) {
static const unsigned width = sizeof(unsigned) * CHAR_BIT;
return x << n % width | x >> (width - n % width);
}
unsigned lrotate(unsigned x, int n) {
static const unsigned width = sizeof(unsigned) * CHAR_BIT;
return x >> n % width | x << (width - n % width);
}
707 :
助けて・・・ :2007/02/15(木) 16:11:20
■プログラム課題:最小値を算出するプログラムを作る 3つの整数を入力し,その内の最小値を出力するプログラムを作成せよ. 但し,最小値を算出する関数,"min3"を自分で作成し用いなさい. また,最小値の出力はメイン文で行うこと. ------------------------------------------- "表示結果の例" 3つの整数を入力してください。 整数1:5 整数2:-4 整数3:0 最も小さい整数は-4 ------------------------------------------- <条件> 0.各自の課題であり,それぞれが自力でソースプログラムを作ること. 1.プログラム冒頭にプログラムの説明を入れる. (どうやって作ったかの説明を記述下さい.) 2.各ポイントにコメントを挿入し,内容が分かるようにしておく. 3.ソースが綺麗になるようにVCのタブ機能を使うこと. 誰かお助けください!!!!!
708 :
デフォルトの名無しさん :2007/02/15(木) 16:12:49
>>706 柴田望洋の明解C読みながら独学でやってるんですが
stdioだけではやっぱムリでしょうか?
>707 どうやっても条件0は満たせないんだが。
>>708 limits.hのこと?
中見てみるといいとおもうよ
>>707 宿題スレ向きだな
てか、
> 各自の課題であり,それぞれが自力でソースプログラムを作ること
って釘刺されてるじゃないかww
>>710 頑張って解読してみます。
ありがとうございます。
713 :
助けて・・・ :2007/02/15(木) 16:48:14
■プログラム課題:最小値を算出するプログラムを作る 3つの整数を入力し,その内の最小値を出力するプログラムを作成せよ. 但し,最小値を算出する関数,"min3"を自分で作成し用いなさい. また,最小値の出力はメイン文で行うこと. ------------------------------------------- "表示結果の例" 3つの整数を入力してください。 整数1:5 整数2:-4 整数3:0 最も小さい整数は-4 ------------------------------------------- <条件> 1.プログラム冒頭にプログラムの説明を入れる. (どうやって作ったかの説明を記述下さい.) 2.各ポイントにコメントを挿入し,内容が分かるようにしておく. 3.ソースが綺麗になるようにVCのタブ機能を使うこと. 条件変えました!!!!
714 :
706 :2007/02/15(木) 16:58:06
>>712 CHAR_BITを使ってるだけ。汎用的でなくてもいいならば、1byteは通常
8bitなんで、8と置換すれば動くけど。
ていうか|の意味すらわかってなさそうなんだが。
#include <stdio.h> int min3(int a, int b, int c) { if(a <= b) if(a <= c) return a; else return c; else if(b <= c) return b; else return c; } int main(void) { int a, b, c; printf("3つの整数を入力してください。\n"); printf("整数1\n"); scanf("%d", &a); printf("整数2\n"); scanf("%d", &b); printf("整数3\n"); scanf("%d", &c); printf("最も小さい整数は%d\n", min3(a, b, c)); } 面倒だから scanf のエラーチェックをしていない。 そもそも scanf を使うなとかいう突っ込みはしないでね。
>>716 一応ビット単位の論理演算子は分かってるつもりです・・・
全くわからないのでそこら中にprintf入れまくってます
>>713 int min3(int a, int b, intc){
return a>b?(b>c?c:b):(c>a?a:c); // ★
}
でいいと思うけど、★はあと5バイトくらい余裕でちぢめられる気がする。
ソースが縮んでも実行コードは変わらんよ
ソースが縮んだときにロジックが変わればコードも変わるよ
ロジックが変わればね
そこでどっちが短いとかどっちが速いとか議論するのが学問だろ
ソース上でなら縮むけどw a=b>a?a:b;return a>c?c:a;
それは学問というより最適厨のオナニーだろ
[ν] コンパイル自に最適化する
なるほどその手があったか。6文字縮んだのね。
今時のPCなら、目指すべきは速度より可読性の向上じゃない?
移植性は?
コンパイルしたあと ソースファイルの他に.exeと.tdsと.objファイルができますけど これは消すとき普通に消していいんですか?
よく swap(int *x, int *y) とかってあるけけど この「swap」って勝手に名づけただけで「xxx」とかでも問題ない? 好きな名前( ○ , ○ ) が書式と思っていいの?
∩___∩ | | ノ\ ヽ | / ●゛ ● | | | ∪ ( _●_) ミ j 彡、 |∪| | J / ∩ノ ⊃ ヽ ( \ / _ノ | | .\ “ /__| | \ /___ /
int minX(int a[], int x) // int x は配列a の要素数 { for (x--; x>0; x--) a[0] = (a[0] < a[x]) ? a[0] : a[x]; return a[0]; } 敢えて拡張性をw
>>733 比較関数のポインタを引数にしそうな勢いだなっ
……敢えてw #define N 3 long minX(int a[], int x) { long temp; if (x==N) return 2147483647; temp = minX(a,++x); return (temp < a[n]) ? temp: a[n]; }
736 :
730 :2007/02/15(木) 20:41:40
俺は・・・・質問・・・できるレベルにさえなってないってことなのか・・・! ここは一番初心者向けのスレじゃなかったのかちきしょー
>>730 あー複数ソースを個別コンパイル→まとめてリンクなら.objがあるとラクダよー
.tdsはよく知らない何だっけ、bcc専用でデバッグがなんたら?
まずはググればよいものをねえ。
自力で探すことを知らない人は、いつまで経ってもHelloWorldレベルだよ。
>>735 鼻から悪魔参照してるおー
>>730 使っているソースとヘッダ(と makefile 等のファイル)以外消しても桶だと思うぞ。
使っているソースとヘッダあれば、同じ手順で生成できるだろ?
実行に必要なのは、おおよそ exe だけ。(コンパイラ次第でもっといるかもしんない。
環境(コンパイラ)わからなきゃなんとも胃炎
739 :
デフォルトの名無しさん :2007/02/15(木) 22:15:46
配列の長さをしらべるうまい方法はありますか?Javaだと配列名.lengthで調べられたりします。 C言語で数値配列を扱う際、最初に全部0で初期化してwhileループの条件判断文でwhile(array[i]) としたところ、実際扱うデータの数値で0があるので、本来0で抜けてはいけないのに0で抜けてしまいます。 0以外の番兵(ありえない数値)をおくしかないんでしょうか?新しい言語見たいにスマートな方法などないですか?
sizeof 関数に渡す時は無理なので長さも一緒に渡す
741 :
738 :2007/02/15(木) 22:20:58
>>740 どうもありがとうございます。
sizeofでできるんですか。また、関数に渡すときはやはりむりなんですね。
どうもありがとうございました。感謝します。
>>736 tdsもobjももうコンパイル(またはmake)しないならいらないです
obj , tds ともにコンパイル時に生成されますので
特に気にする必要はないです
bprは消してはダメです(もしあるなら)
int arr[32]; sizeof(arr)/sizeof(arr[0]); こんな感じで取得ね
744 :
738 :2007/02/15(木) 22:59:33
>>743 どうもありがとうございます。よくわかりました。
int array[64];としてsizeof (array) / sizeof (array[0])。 適当な名前を付けて#defineでマクロにするのがいいと思う。
とはいえ、ポインタに適用して「(;´Д`)??」となるのは誰もが一度は通る道。
747 :
689 :2007/02/16(金) 02:25:56
>>695 ご返答、ありがとうございます。
bintest.dat というデータを予めメモ帳で拡張子変換で
作っておかなければならないのでしょうか
それと、本の解説に依れば
>>for(i = 0; i < 10; i++)
buf_w[i] = (i+1) * 10;
書き出し用のデータを作成と書いてありますが
どういう意味なのでしょうか?
>bintest.dat というデータを予めメモ帳で拡張子変換で作っておかなければならないのか 本の「ファイル入出力」とか「ファイルシステム」とかの項で、 「ファイルアクセスのモード」みたいな単語を探す(索引とか) で、そのプログラムで使用してる > fp = fopen(filename, "wb"))) "wb" というモードの動作を読む もし書いてないならば、そんな本は窓から(ry ……・ということで。 マジで、ちゃんと調べるべき。ソース見る限り、その本信用していいのか若干悩む まあ、"bintest.dat"を作ってない状態でそのプログラムを実行してみれば、サクッと理解できるさ。 >書き出し用のデータを作成 fwrite(buf_w, sizeof(int), 10, fp) で、「buf_w」に格納されてるデータをファイル"bintest.dat"に出力している。 そのためのデータを作成してるってこと
749 :
689 :2007/02/16(金) 03:11:05
>>748 ありがとうございます。
作らない状態でやったら、とんでもない事が起こりました・・・・
>>737 何故だか知らないが「HelloWorldレベル」という言葉に感動した
751 :
デフォルトの名無しさん :2007/02/16(金) 04:06:30
fgetcとfgetcharは同じなのでしょうか? 違うとしたら何が違うのでしょうか? ご教授お願いします。
>>751 それぞれの関数が受け取る引数が違う
int fgetchar(void);
int fgetc(FILE*);
fgetc(stdin) と fgetchar() なら等価
753 :
デフォルトの名無しさん :2007/02/16(金) 04:25:19
754 :
デフォルトの名無しさん :2007/02/16(金) 05:34:36
参考書のサンプルが、if〜、else if〜、else if〜 で終わっていますが 良いのでしょうか? if〜、else if〜、else、で終わるならわかりますが…
>>754 問題ない。
最後の else〜 部分に特定の処理を入れる必要が無ければ、書く必要は無い
>>754 べっ、別に if だけで終わっても問題ないんだから(ツンデレ風に)
if〜elseも理解できてないのに参考書が間違ってると思える根拠を知りたいよ。
そういや俺もC言語を習い始めた頃、if の後すべてのコードを else { } で囲っていた時期もありました
俺は、いまだに{}で囲むな〜 まぁ、ひとそれぞれネストさせるだけとか ネストもさせないとか
760 :
これ教えて :2007/02/16(金) 14:39:18
ringo 100 mikan 50 nashi 130 banana 70 kiui 80 上記のデータをファイル(kudamono.dat)に記述し、ファイルから読み込んだデータを値段で降順に並べ替えて出力するプログラムの作成。 ただし、データ構造は構造体を使用すること。
初心者をビビらせるためにC++で 関数ポインタ、汎用ポインタ、ビット操作、三項演算子、オブジェクト・アジャイル指向、共用体、STL を魅せるオナニープログラムを書こうかと思ったんだけどどうよ
中途半端に混ざってる感があるな。
>>761 初対面の人に恫喝してからじゃないと会話もできないDQNとなんら変わらん
>>763 恫喝と言うか?脅しじゃないだろw
すごさを見せつけることによる驚きの方じゃね?
普通のCでも、API叩きまくっとけば?
オブジェクト・アジャイル指向 (ただし、テンプレート無し) の構造を C で実現すれ
>764 初心者にはどこがすごいかわからない。 熟練者にはハッタリだけで全然すごくないのが丸わかり。
>>768 すごいと初心者が分かるか分からないかなんてどうでも良い。
それが 脅し じゃないってことを言いたかっただけ。
下らん突込みを入れる粘着ほど理解力がなくて困るよw
770 :
デフォルトの名無しさん :2007/02/16(金) 18:26:22
自分に合うすげー良い本を見つけましたo(^-^)o "自分ペースでゆったり学ぶC超入門"という書籍です
771 :
デフォルトの名無しさん :2007/02/16(金) 18:34:43
#include <stdio.h> int main(void) { int array[3][3] = { 1,2,3, 4,5,6, 7,8,9 }; int *p=(int *)array; int i; for(i=0; i<3; i++) { printf("%p ", p); p++; } return 0; } 上記ソースですが、どうしてキャスト(int *)arrayとしなくてはいけないのかが わかりません。 キャストしないとコンパイルエラーがでますが、そのエラーもわかりません。。 配列の先頭アドレスを取得するためには配列名(この場合はarray)をかけばいいと 本に書いてあるんですが。。 よろしくお願いします。
int *p = &array[0][0]; とすればよろし
773 :
デフォルトの名無しさん :2007/02/16(金) 18:43:54
どうもありがとうございます。なるほど。その方法があったんですね。 そっちの方が初心者にはわかりやすいですね。その方法で行きます。 独習Cを見てやっているんですが、解説もわけわからない解説が2行あるだけです。。 やる方法は&array[0][0]で納得できたんですが、配列の名前を指定する場合はキャストが 必要という意味合いがどうしても理解できません。どうしてなのか? できれば教えてほしいです。お願いします。
多次元配列は一次元配列とは型が違うから。
775 :
771 :2007/02/16(金) 19:04:24
>>774 なるほど。ありがとうございます。型がちがうんですね。
キャストしないでありのままの型を使う場合、左辺(この場合だとint *p)は
どういう風に書いたらいいんでしょうか?
わかっててわざと聞いてるように見えるのは気のせい?
>>760 #include <stdio.h>
#include <stdlib.h>
typedef struct a{char b[99];int c;struct a*d,*e;}f;char c[99];int d;void b(f*a)
{if(a){if(a->e)b(a->e);printf("%s %d\n",a->b,a->c);if(a->d)b(a->d);}}void a(f**
b){if(*b){if(d<(**b).c)a(&(**b).d);else a(&(**b).e);}else{*b=(f*)calloc(sizeof(
f),1);(**b).c=d;for(d=0;((**b).b[d]=c[d]);d++);}}int main(){f*e=0;for(freopen(
"kudamono.dat","r",stdin);scanf("%98s%d",c,&d)!=EOF;)a(&e);b(e);return 0;}
何処の七行スレ住人ですかあなたw
779 :
771 :2007/02/16(金) 20:59:27
>>776 いや。本当にわかっていないんです。Javaは経験あるのである程度予想はつきますが、
C言語に関しては本当の素人です。
二次元配列 int array[5][3] があるとき
ほにゃらら=array; といった式をなりたたせるためにはどうしたらいいのでしょうか?
暇な人でいいので回答をくだされば、ありがたいです。ないようなら、勉強を続けていきますので
スルーしてもらえるとありがたいです。
ああ、俺が途中で諦めたことをなしとげた人がいるw すげえよw
>779 arrayを右辺値にすることで何を求めたいの?
>779 int (*p)[3]
783 :
デフォルトの名無しさん :2007/02/16(金) 21:20:01
いま高校でC言語を習ってるんですが 将来役に立ちますか?
785 :
デフォルトの名無しさん :2007/02/16(金) 21:24:12
>>784 たとえばどういう仕事がありますか?
C言語教える教師しか思いつきません
( д) ゚ ゜ 俺、何のためにCやってるんだろう……
・質問1 指定されたディレクトリ内のファイル名を全て取得したいのですが、どのようにしたら良いでしょうか? ・質問2 以下のような構造体があるとします。 struct CELL{ int *pt; }CELL; さらにこの構造体の配列を作成し CELL *cp; *cp=(CELL*)malloc(sizeof(CELL)*size); この構造体内のptにさらに領域を確保したとします。 for(i=0;i<size;i++){ cp[i].pt=(int*)malloc(sizeof(int)*size2); } このとき free(cp); を実行すると、 cp内のptの領域も開放されますか?
・質問1 環境によって方法が違うので答えられない ・質問2 されない というかそれコンパイル通るのか
>>785 ・プログラマ
・ハッカー
・クラッカー
・ニートな人
FILE *fp; char s[256]; char name[50][50]; int i=0; if ((fp = fopen("smpl.txt", "r")) == NULL) { printf("file open error!!\n"); exit(1); } while (fgets(s, 256, fp) != NULL) { strcpy(name[i], s); i++; } fclose(fp); よくあるファイル操作のプログラムなのですが nameが改行部分を含まない、もうしくは、改行部分を取り除くやり方を教えてください。
s[ strlen(s) -1 ] = '\0';
791の方法だと1行が255文字以上あった場合のことを考えればよくない。 そこまで考えない、それは仕様ですと言う手もあるが。
793 :
779 :2007/02/16(金) 21:52:43
>>781 ただ単に興味本位だけです(;^^
>>782 サンクスです。思った以上に気抜けした答えでした。。ありがとうございまつ
795 :
デフォルトの名無しさん :2007/02/16(金) 21:58:58
char *temp=NULL; if(temp = strchr(s,'\n')) *temp = '\0';
/* buff を buf と書く人もいるみたいだが */ /* 個人的にはbuffの書き方の方が好きだ */
// 私は buf と書きます
C言語の標準関数、用例が全て書かれたC言語ライブラリ辞典みたいなのがほしいのですけど、 どこかに売られてます? ネットで調べればわかるのは確かなのですが、本じゃないと煩わしいのですよ。
用例が全てかかれてるのは無いだろう・・・・ 例に限度はない・・・
802 :
デフォルトの名無しさん :2007/02/16(金) 23:35:36
#include <stdio.h> #include <string.h> int main(){ FILE *fpr, *fpw; //読み書きファイルポインタ char bufr[256], bufw[256]; //読み書きバッファ char str1[] = "dog"; //置換文字列 char str2[] = "rabbit"; //置換後文字列 char *p, *q; if(!(fpr = fopen("dog.txt", "r"))) { printf("読み込みファイルオープンに失敗しました。"); return 1; } if(!(fpw = fopen("rabbit.txt", "w"))) { printf("書き込みファイルオープンに失敗しました。"); return 1; } while(1){ fgets(bufr,256,fpr); strcpy(bufw, bufr); p = strstr(bufr, str1); if(p){ q = bufw + (p - bufr); strcpy(q, str2); strcpy(q+strlen(str2), p+strlen(str1)); }
803 :
798 :2007/02/16(金) 23:37:50
>>801 俺はそのサイトをワードに写して自分で本にしようと思ったけど本がありそうな気がしてやめた。
やっぱ本だよな。
本離れの時代だからこそ。
804 :
802 :2007/02/16(金) 23:37:54
fprintf(fpw,"%s", bufw); if(feof(fpr)) break; } fclose(fpr); fclose(fpw); return 0; } 何故、これは書き換えなのに、読み込み作業も行っているのでしょうか? メモ帳に新しく書き出しているので書き込み作業だけでは、ダメなのでしょうか?
805 :
802 :2007/02/16(金) 23:48:10
これは、一旦読み込んで置換してから書き込んでいるのですかね?
>>804 if(!(fpr = fopen("dog.txt", "r"))) {
if(!(fpw = fopen("rabbit.txt", "w"))) {
読み込みでdog.txtを書き込み用でrabbit.txtを開いてる
dog.txt内で dog が見つかった場合rabbitに置換してその結果をrabbit.txtに書き込んでいる
元ファイルdog.txt、置換結果rabbit.txt ということ
txtから対象物を読み込まずして、比較も置換も糞もできないだろ?
808 :
802 :2007/02/17(土) 00:00:41
>>806 if(!(fpr = fopen("dog.txt", "r"))) {
if(!(fpw = fopen("rabbit.txt", "w"))) {
は"!"が付いてるから、読み込まなければ
printf("読み込みファイルオープンに失敗しました。");
ではないのでしょうか?
>>807 仰る通りで・・・
テキストファイルを開き、数値を変更し保存するプログラムについてですが、 fseek関数でちょこちょこ移動するのは面倒なので、テンポラリファイルを作成し、"w"で 開き、テキストファイルからデータを読み取り修正してテンポラリファイルに書き込む。 そして再openした後、テンポラリファイルから元のファイルへ書き戻すという方法は 間違い、というか危険な行為でしょうか?
>>798 ANSI C言語辞典はどう?
さすがに用例までは全て網羅していないが、
最悪でも簡単な説明以上は全ての関数その他に対して載っている。
>>808 if(!(fpr = fopen("dog.txt", "r"))) {
開けなければ終了
if(!(fpw = fopen("rabbit.txt", "w"))) {
開けなければ終了
ですよ
指定しているファイル名が違うことを見てください
>>809 おkです
>テンポラリファイルから元のファイルへ
書き込み上書きで開けば問題ないです
>>812 サンクス!それを聞いて安心しました。
テンポラリファイルから元のファイルへ書き戻すため、元のファイルを"w"
で開いた直後にPC落ちたら、ファイルのデータを失う!!と思っていましたが、
よく考えたらテンポラリファイルがあるから、ファイルの内容が消える心配は
ありませんね。
fseekとどっちが早いの?
815 :
802 :2007/02/17(土) 00:34:24
>>811 あ〜そう言う事だったんですね!!
勘違いしていました。
それと
while(1){
fgets(bufr,256,fpr);
strcpy(bufw, bufr);
p = strstr(bufr, str1);
if(p){
q = bufw + (p - bufr);
strcpy(q, str2);
strcpy(q+strlen(str2), p+strlen(str1));
}
上記のソースが、ちんぷんかんぷんです。
この中で、わからない事が多々あります。
1つ目は、while(1){ とは1(真)の間、繰り返すだと思うのですが
この場合は何が真の間なのでしょうか?全部がrabbitに置き換わる間でしょうか?
2つ目、p = strstr(bufr, str1); これがどういう意味なのか?
3つ目、if(p){ 繰り返しの間のif文です、繰り返してる間
もし〜ならこう〜なのでしょうか?
4つ目、q = bufw + (p - bufr); と strcpy(q+strlen(str2), p+strlen(str1));
もう解説がなく何が何だかさっぱりです。
>>815 > 1つ目は、while(1){ とは1(真)の間、繰り返すだと思うのですが
>この場合は何が真の間なのでしょうか?全部がrabbitに置き換わる間でしょうか?
この場合1ですので常に真です.
最後のほうに if(feof(fpr)) break; がありましたね.このif文が真になったときにループを抜けます
feof(fpr)というのはファイル(fpr)の最後まで来たということです
> 2つ目、p = strstr(bufr, str1); これがどういう意味なのか?
bufrの中にstr1と同じ文字列があった場合、そのbufrでstr1が現れる最初のポインタを返します
つまり文字列の検索です
> 3つ目、if(p){ 繰り返しの間のif文です、繰り返してる間
>もし〜ならこう〜なのでしょうか?
そうですね.
p = strstr(bufr, str1);
if(p){
p = strstr(bufr, str1); はstr1と同じ文字列が見つかった場合ものポインタを返します.見つからなかったらNULLを返します
もし見つかったら
q = bufw + (p - bufr);
strcpy(q, str2);
strcpy(q+strlen(str2), p+strlen(str1));
を実行しなさい.ということです
> 4つ目、q = bufw + (p - bufr); と strcpy(q+strlen(str2), p+strlen(str1));
>もう解説がなく何が何だかさっぱりです。
ここの説明は長くなるので↓で
817 :
816 :2007/02/17(土) 01:30:21
>>815 続きです
q = bufw + (p - bufr);
p - bufrで p が bufrから見て何文字目かが分かります(最初の文字は0番)
bufw から〜文字目にstr1と同じ文字列があるかを足すのでqにはbufw にあるstr1と同じ文字列の先頭ポインタが入ります
strcpy(q+strlen(str2), p+strlen(str1));
ここはややこしいです
q+strlen(str2)
bufwのstr1が見つかった最初のポインタにstr2の文字数を足した位置に
p+strlen(str1)
bufrのstr1以降(str1は除く)の文字列をコピーします
これで置換が成立するわけです
818 :
816 :2007/02/17(土) 01:40:27
>>815 そろそろ寝ます
暇があったらデモンストレーションのプログラムでも作ってみます
819 :
802 :2007/02/17(土) 02:05:56
>>818 本当に、ありがとうございます。
>>この場合1ですので常に真です.
最後のほうに if(feof(fpr)) break; がありましたね.このif文が真になったときにループを抜けます
feof(fpr)というのはファイル(fpr)の最後まで来たということです
これは常に真ですが、ifも真になったら抜けると言う事でしょうか???
特に
>>817 は難し過ぎます、後はじっくり自分で考えてみます
お休みなさいませ
820 :
802 :2007/02/17(土) 02:26:12
>>817 >>bufw から〜文字目にstr1と同じ文字列があるかを足すのでqにはbufw にあるstr1と同じ文字列の先頭ポインタが入ります
>>strcpy(q+strlen(str2), p+strlen(str1));
ここはややこしいです
q+strlen(str2)
bufwのstr1が見つかった最初のポインタにstr2の文字数を足した位置に
p+strlen(str1)
bufrのstr1以降(str1は除く)の文字列をコピーします
これ等が、どうしても理解できないです。
もしお暇があれば、再度ご教授お願いします。
例えばstrcpy(q, str2);の時点で 文字列が bufr = "12345dog6789" bufw = "12345rabbit9" になってる。 そのときp は 'd'の文字の場所を、q は'r'の文字の場所を指してる。 最終的にbufw = "12345rabbit6789"としたいからbufrのp + strlen("dog")の位置('6'の場所) から最後まで(文字列"6789")を bufwのq + strlen("rabbit")の位置('9'の場所)から上書きしなきゃいけない。
822 :
802 :2007/02/17(土) 04:52:34
>>821 >>例えばstrcpy(q, str2);の時点で
文字列が
bufr = "12345dog6789"
bufw = "12345rabbit9"
になってる。
そのときp は 'd'の文字の場所を、q は'r'の文字の場所を指してる。
最終的にbufw = "12345rabbit6789"としたいからbufrのp + strlen("dog")の位置('6'の場所)
から最後まで(文字列"6789")を
bufwのq + strlen("rabbit")の位置('9'の場所)から上書きしなきゃいけない。
ピンと(☆∀☆) キタ━━━━━━━━━━━━━━━!!です
やっとこさっとこ理解できますた!!
あと、一歩このソースを理解できそうです。
どうしても q = bufw + (p - bufr); も
>>817 さんの説明理解できませんでした
>>p - bufrで p が bufrから見て何文字目かが分かります(最初の文字は0番)
と、どうして>(p - bufr)で-のかが、未だに考えていますが難しいです。
そして、もう一つ"12345rabbit6789"はアドレスの位置でしょうか?
823 :
802 :2007/02/17(土) 04:54:06
訂正、"もでなく,"の"でした
今数学の課題の計算問題ぐらいでしか役に立ってないんだけど、どこぐらいのレベル までいったら実用的なのを作れるようになるの?
実用的がどんなレベルを指すのかわからない。 計算問題でも充分実用的だと思うぞ。
>>819 while や if の仕組みを覚えるべし。
比較演算(== > < 等)は値を返す。
式が成り立つなら 0 でない数値(1 -1 等)
式が成り立たなければ 0 を返す。
while if 等の制御文は、与えられた数値が
0 なら偽、0 以外なら真と判断する。
結果的に比較式が成り立てば真
成り立たなければ偽と判断されるワケ。
だから、while に 1 を与えれば
0 でないので真とみなされ、永久にループする。
break について。
if(feof(fpr))が成り立った時に実行される break は
最も内側のループを強制的に抜ける命令。
(本当はループ以外にも抜ける制御文があるんだけどな)
>>824 どこまで行ったらって言うのが何を指すのか知らないけど…
プログラミング言語の基本的な仕組みを覚えたら
あとはやりたい事に合わせたライブラリの使い方を覚える。
例えばウィンドウアプリを作りたければ
ウィンドウ用のライブラリの仕組みと使い方を覚える。
Webサービスを作りたければWebサービスの仕組みを覚える。
そしてWebサービスで使うライブラリの使い方も。
C言語でWebサービスを作る例は少ないから別の言語も必要になるだろうな。
他の言語を習得する時もプログラミングの基礎は多いに役に立つぞ。
ゲームプログラミングがしたけりゃ
ゲーム用のライブラリの使い方を覚える。
2Dなら2Dのグラフィック処理ライブラリを、3Dなら3Dの。
サウンド処理のライブラリ、コントローラからの入力をするライブラリなんかもある。
WindowsならDirectX、またはDirectXをもう少し簡単に利用するライブラリの知識。
ゲーム機ならゲーム機の仕様。
高度な計算処理がしたければ数学ライブラリや数学そのものの知識。
プログラミングは生涯勉強が必要な分野。
新たにやりたい事があれば、その都度新たに覚えることは増える。
基本を覚えたら、やりたい事によって覚える事は大きく変わる。
>>822 >>そして、もう一つ"12345rabbit6789"はアドレスの位置でしょうか?
いや、例えば
bufw = "12345rabbit9" っていうのはbufwの中の文字列がってこと。
最初にfgetsでファイルからbufrに読み込むでしょ?
それをbufwにstrcpyしたりしてこんなbufwになりましたよってこと。
最終的にbufwの中身を"12345rabbit6789"にしたいよってこと。
>>と、どうして>(p - bufr)で-のかが、未だに考えていますが難しいです。
strstr()したからpはbufrに"dog"という文字列があったらその一文字めの'd'
を指してる。だから(p - bufr)はbufrの最初から"dog"の'd'までの文字列の長さ。
strstrする直前のbufrの中身が"uwxyzdog1234"だったら
p = strstr(bufr,"dog");すると
bufrが'u'の位置、p が'd'の位置だから (p - bufr)は5になる。
三 瀬川おんぷ 2CDDDCC アベレージヒッター 人気者 一 中島正義 1FFFFED 投 高木まなぶ 3DDEBDD 捕 平松部長 3ECEDDD 守備職人 遊 妹尾あいこ 4DBBBCD 中 春風どれみ 2FEEDGG 安定度2\ 左 藤原はづき 1FFDFBF バント職人 二 春風ぽっぷ 1FFBDAB 流し打ち 右 飛鳥ももこ 1GGDDGG エラー 三振 安定度2
プログラムは道具だ
プログラミングは趣味だ
プログラムはパスタの一種だ
833 :
816 :2007/02/17(土) 21:58:35
835 :
816 :2007/02/18(日) 00:06:01
>>834 覚えている関数はほんの、ほんのごく一部
必要になったら調べてる
もしくは自作する
うわ、ほとんどしらねえw
>>835-837 ありがとう。全部覚えなくてもどうにでもやっていけるんだね
英単語みたいに覚えてないと話にならないって感じじゃないのか。安心した
839 :
816 :2007/02/18(日) 00:58:51
840 :
802 :2007/02/18(日) 02:15:05
>>826 ありがとうございます!
while(1)の事まで、説明が載っていなかったのですが
そう言う事だったんですね!!!
>>828 >>833 考えに考え(勿論、皆さんのお陰です)
今、何とかようやくわかりました!!!
どの参考書よりも丁寧でわかり易い解説、ありがとうです。
特に
>>833 さん、なんとお礼を申し上げればいいのやら、この解説は今後も
役に立ちそうなので、永久保存させて頂きます。。。
皆さんの、解説は本にも載っていなく、最高のものです。
>>833 ここで、一つわからない事があります(質問ばかりで、ごめんなさい)
解説の中で
>>今 bufrには文字列 "gsnjdnjdfdoggfgffmmk" が格納されています
bufw のポインタは1244808番地です.
つまり文字列は 1244808番地から格納されていると言うことですね
bufw には文字列は格納されていませんが bufw のポインタは 1244552 番地です
bufr="gsnjdnjdfdoggfgffmmk" ポインタ=1244808
bufw=" " ポインタ=1244552
>>bufw のポインタは1244808番地です.は
>>"bufr" のポインタは1244808番地 ではないのでしょうか?
841 :
802 :2007/02/18(日) 04:22:38
>>840 の質問を含め、すみませんが最後に4つ質問があるので、宜しくお願い致します。
一つ目は、
>>840 に記述
二つ目は、
>>833 の解説にある"文字があるポインタ"、
これは、どうやって >> g は 1244552 等調べるのでしょうか?
因みに" 1244552" は振り当てられているメモリ(番地)と解釈して良かったでしょうか?
三つ目は、"文字があるポインタ"を使わずインデックス番号で位置を
何番目か調べる事はできないのでしょうか?
例、bufrの"d"の位置を調べる場合(インデックス番号で) [9]-[0] = 9で9番目
bufwも同じく [0] + ( [9]-[0]) = 9
四つ目は、もう一度だけ最後に
>>strcpy(q+strlen(str2), p+strlen(str1)); の解説を宜しくお願い致します。
これらが、わかれば100%理解できます。
スレの内容は見てないけど 非常に面倒くさそうな質問満載ですね
何を言ってるんですか。 ここは知ったかさんのガス抜き用隔離スレですよ?
>>834 ほとんど覚えてない。
が、何処を探せば見つかりそうかのネタ(サイトとか書籍とかね)の準備だけはしておくw
初歩的な質問ですみませんが、C++とかの方が楽にプログラム組めるのになんで みんなわざわざC使うの? 他の言語へステップアップするために勉強してるだけ?
>>845 CでもC++でもJavaでもJavascriptでも「アルゴリズム」の勉強は
どれも記述内容がほとんど同じだからどれでも良いが
手軽に扱えるものとして俺はBorland C++でC言語で勉強中だが
ありがとう。C言語がプログラミングの基礎を勉強しやすいからなのか ずっと疑問に思ってたよ
宿題スレを見るとC++も扱っているところはあるけど、Cを使う方が多いのかね。
そりゃ教える方がC++を知らないからだろ。
>>849 きめつけすぎ。教育機関が過去のものをほいほいと簡単に変えられるわけでもないだろ。
どっちが歴史が長い?
CからC++への移行って楽?
拡張子をcppなんかにしてコンパイル・リンクして、 コンパイルエラー・リンカエラーが出なければそれで移行完了。 ヘッダで関数をプロトタイプ宣言せずに使っているなどお行儀の悪いことをしていなければ、 せいぜいmallocまわりがエラーになるだけ。 とまあ、個人レベルだったらこれで済むだろう。
C++をベターCとして扱う、という意味なら 全く問題ない。 C→C++は(ほぼ)上位互換 オブジェクト指向について理解出来てるかは別の話だが。
>>852 いろんな便利な機能が使えなくなるから、逆はツライけどな。
856 :
デフォルトの名無しさん :2007/02/18(日) 11:41:30
初歩的な質問ですが、納得いかないんで…。 猫でもわかる(ryからなんですが。 printf("cの値は%dでこれに11を加えると%dとなります\n""eには\%cが代入されています\n",c,d,e); って文があるとします。 これは正常に表示されます。 それを printf("cの値は%dでこれに11を加えると%dとなります\n""eには\%cが代入されています\n"e,,c,d); と「e」を先頭にもってきて、変数の順番を入れ替えて記述してコンパイルすると、正確に表示されません。 変数を記述する順番はランダムじゃいけないんですか? 出来れば理由も教えてほしいです。
857 :
デフォルトの名無しさん :2007/02/18(日) 11:45:43
>>856 です。
訂正です。
コンパイルすると、正確に表示されません。 →両方ともコンパイルは成功しますが、実行すると文字化けしますって意味です。
いや、順番変えたら結果変わるのはあたりまえじゃ… int a=3, b=5; printf("%d,%d",a,b); printf("%d,%d",b,a); この2つが同じ結果だったら困るだろ? どう考えても前者は 3,5、後者は 5,3 と表示されるだろ?
「e」を先頭にもってきて、変数の順番を入れ替えて記述 が正しくできてないだけ。 エスパーしてみると、おまい エディタの置換使ったろ? d から c への置換の過程で printf内 %d を %c にしちまってる可能性大
ああ "%d,%d,%c" → "%c,%d,%d"
いや、、、引数が、、、
2つしかとらない(最後の %c は % がエスケープされてるしな)のに3つ渡してたり カンマの位置無茶苦茶だったり。 症状がでる最小限コンパイルの通るコードを貼れ と。
先日回転シフトについて教えてもらってなんとか解読できたのですが、
次の問題でまたまた詰まりました。
符号無し整数xのposビット目を、1にした値を返す関数set、
0にした値を返す関数reset、反転した値を返す関数inverseを作成する
という問題ですが、setとinverseはできたのですが、
resetがどうしてもわかりません。
教えて頂けないでしょうか?
ソースはこちらです。
http://eggrice.no.land.to/up/src/tohoh0133.txt
XORは、左辺値に対して、右辺値の内、立っているビットのみを 反転させる演算子であると考えることも出来る。
反転してAND
>>864-865 素早いレスありがとうございます。
ヒントをもとにもうすこし頑張ってみます〜
0にするにはそのビットだけ0と&を取ればいい。
キタ━━━━━━(゚∀゚)━━━━━━ !!!!! できました! ありがとうございました。
set()とinverse()ができているなら unsigned reset(unsigned x, int pos) {return inverse(set(x, pos), pos);} でいいよ。
構造体のメンバ参照の時に、アロー演算子って使います? hoge->piyo は、 (*hoge).piyo と等価ですよね? ・・・・typedefを使うか使わないか、そんな違いなもんなのかな。
>>870 *は極力避けた方が間違いが減る。
* (array + offset)と書かず、array[offset]と書くが如し。
ポインタで頭がこんがらかってしまったので質問させて下さい uchar c[4] ; struct aaa{ uchar a1 ; uchar a2 ; uchar a3 ; uchar a4 ; } ; struct bbb{ uchar b1 ; uchar b2 ; } ; struct aaa *pa = (struct aaa *)&c[0] ; struct bbb *pb = (struct bbb *)&c[0] ; とした時、 pa->a1 = 5 ; と pb->b1 = 5 ; と c[0] = 5 ; は全て一緒なのでしょうか?
そーいう使い方はやめなさい。
>>872 構造体のメンバをどのように確保するかはコンパイラ依存
で、uchar は unsigned char のこと?
#include <stdio.h> #include <ctype.h> #include <stdlib.h> int get_word(char *buf, int buf_size, FILE *fp) { int len; int ch; while ((ch = getc(fp)) != EOF && !isalnum(ch)); /*←この !isalnum(ch) ってどういう意味ですか?*/ if (ch == EOF) return EOF; len = 0; do { buf[len] = ch; len++; if (len >= buf_size) { fprintf(stderr, "word too long.\n"); exit(1); } } while ((ch = getc(fp)) != EOF && isalnum(ch)); buf[len] = '\0'; return len; } int main(void) { char buf[256]; while (get_word(buf, 256, stdin) != EOF) { printf("<<%s>>\n", buf); } return 0; }
isalnumは分ってるけど「!」がつくことで何が変るのかなって 逆になって、成立しなければ0以外の値(真)を返すようになるのかな
基礎からやり直せってか演算子なんか人に聞くことじゃないだろ
>>880 ありがとう「!」って!=とかだけでなく関数にも使えるんだね
・関数に使ってるわけじゃない、関数が戻した int 型の整数に対して使ってる ・ ! と != は別物、何の関係もない
883 :
872 :2007/02/18(日) 22:48:01
変に書いてしまってすみません。 ucharはunsigned charです。 struct aaa *pa = (struct aaa *)&c[0] ; struct bbb *pb = (struct bbb *)&c[0] ; このような、型は違うけど変数名が同じという表記がありまして、 この場合ポインタ変数pa,pbは両方ともc[4]の先頭アドレスを示していると 自分では思ってるのですが、解釈としては合ってますでしょうか?
884 :
816 :2007/02/18(日) 23:12:04
>>841 >一つ目は、
ゴメンナサイ.間違いです
訂正→
http://sa-wiki.com/upload/src/up0108.txt >三つ目は、
”インデックス番号”は”何番目か”と同じものです
”目的の文字のアドレス”から”先頭の文字のアドレス”を引いたものが”インデックス番号”もしくは”何番目か”となります
>bufrの"d"の位置を調べる場合(インデックス番号で) [9]-[0] = 9で9番目
では ”[9]- ” この 9 はどーやって求めますか?
できませんよね.
しかし、p - &bufr[0] = 9 という計算なら出来ます.
p = strstr(bufr, str1) がインデックスではなくポインタを返すことを思い出してください
そして、&bufr[0]は &を付けた場合、その変数のアドレスを表すんでしたね.
つまり、文字配列の先頭の文字のアドレス(&bufr[0])=文字列の先頭アドレス bufr は同じことです
p - &bufr[0] と p - bufr は 同じことをしています.
bufw も同じく、&bufw[0] + ( p - &bufr[0]) とすることが出来ます.( &bufw[p - &bufr[0]] も同じ意味です.)
まずは自分が分かりやすい表現で書くのが良いでしょう.
>二つ目は、
え〜と、また暇があったときに作ってみます
特に>四つ目
では
>>883 6行目は何を言いたいのか判らんが、8行目は(一応)間違ってはいない。
>>881 >882にもあるが、! はそれ一つで意味のある演算子だから誤解しないようにね。
887 :
816 :2007/02/19(月) 00:08:50
888 :
802 :2007/02/19(月) 00:42:21
889 :
デフォルトの名無しさん :2007/02/19(月) 00:47:52
c言語で動画ファイルを使うにはどうすればよいのですか? ゲームを作っているのですが動画を使いたいので教えてください。
>>889 環境依存なので自分の環境にふさわしいスレに移動
今更ながら、strcpyに関して strcpy(p, str)で、strは適当なポインタ文字列、 pはポインタで'\0'で初期化しておいたのよね。 だけども、これだとエラーが出る。 どうやら、\0で初期化したpにはコピーできない なして?
>>892 エラーが出るときはエラーメッセージを書きましょう。
p の指している領域は確保されてるの?
まさか p='\0'; とかやってない?
>>892 char buffer[256];
char *p = buffer;
strcpy(p, str);
これで理解してくれればいいんだけど・・・
p自体を\0で初期化してたりしないよな?
>>883 その場合、pa == c, pb == c は共に真だけど、
pa == &pa->a1, pb == &pb->b1 が真となる保証はどこにもない。
そういうわけで、((struct aaa *)c)->a1なんてすると鼻から悪魔
ああ、ついでに言っておくと
sizeof(struct aaa) == sizeof(unsigned char) * 4 が真になる保証もない。
すみません、 ポインタが返すとはどういう意味なんでしょうか?
ポインタは何も返すことをしないので、「ポインタが返す」ということはありません。
>>897 正確さを捨てて分かりやすさを優先してみる。
p は、どこかのアドレスを指す矢印のようなもの。
p=0; で、p は「どこも指していない状態」になっている。
そんな状態で、「p が指すアドレスに文字列をコピー」なんてできるわけがない。
それをふまえて
>>894
901 :
デフォルトの名無しさん :2007/02/19(月) 01:23:48
>>899 訂正 「ポインタを返すです」
ポインタの説明を読んでも意味不明です
&←を付ける事により、例えば&aなら
aはアドレスのやくわりを果たすのでしょうか?
それともaがアドレスになるのでしょうか?
&a = 「aのアドレス」 それだけ
>>903 間違えた
>>900 ね
ついでだけも、 *p = "" も結局何も指さないんですよね?
場所が確保できてなかったのか。
905 :
デフォルトの名無しさん :2007/02/19(月) 01:39:15
>>902 cha a ="h"e"l"l"o"だとして&hなら
"h"が置いてあるアドレス13001番を指すんでしょうかね?
>>904 その場合、"" という文字列がどこかに確保され、p はそこを指している。
"" は {'\0'} という1文字分の大きさしかないので、
str ををコピーしようとすれば、おそらくバッファオーバーする。
>>904 char *p = ""; は、
char *p = {'\0'}; に等しくて、
メモリのどこかに バイト列 '\0' を割り当てて、そのポインタで p を初期化する。
ただし、この場合、*p = '\0'; や strcpy(p, ""); は未定義動作になる。
初期化以外の文脈で *p = "" はコンパイルとおらない。
>>905 cha a ="h"e"l"l"o"
意味不明
910 :
デフォルトの名無しさん :2007/02/19(月) 01:46:05
>>909 char a = "h"e"l"l"o" ;
char *p;
p = &h
こうでした
>>905 &a = 「a という変数のアドレス」 だ
&h = 「h という変数のアドレス」 だ
その例の意味が不明だが、h という変数なんてどこにもないので、
&h なんていわれても、h って何だよってコンパイラに怒られる
>>910 "h"e"l"l"o" ; <- 意味不明
>>910 >char a = "h"e"l"l"o" ;
意味不明
低レベルエスパー char a[] = "hello"; char *p; p = &a[0];
>>910 お前さ、本だけ読んで、実際にプログラムしたことないだろ…
916 :
802 :2007/02/19(月) 01:51:48
>>887 今、読み終わりました。おかげさまで100%近く理解できました。
>>char bufr[256];
bufr = 100;
としてみましょう.何かしらエラーが出るはずです.割り当てたメモリ領域の先頭番地が
格納されている bufr を別の値に変えようとしているからです.
では、
char *p;
p = 100;
としてみましょう.何もエラーは出ませんね.ですが100番地 は割り当てた領域ではあり
ません.
ポインタ変数を扱う場合は必ず正しいアドレスを指すようにしなければいけません.(NUL
L を除く)
が理解しがたかったのですが、これらは時間をかけてでも考えてみたいと思います。
こんなに長く丁寧な解説、感謝致します。
持っている参考書より断然深く丁寧な解説でした。
ポインタの概念がこんなに深いとは知りませんでした。
917 :
デフォルトの名無しさん :2007/02/19(月) 01:59:05
>>912-
>>913 ごめんなさい、
>>914 でした
>>915 サンプルのを書き写しなら今入門書でやっています…
char a[] = "hello";
char *p;
p = &a[0];
p = &a[0]; は"h"だと思うのですが
"h"が置いてあるアドレス13001番を指すんでしょうか?
それがポインタのやくわりですよね?
13001ってどっからでてくるんだよ
>>917 "h" <- 文字列
'h' <- 文字
区別しような
>p = &a[0]; は"h"だと思うのですが お前の頭の中では、 「p」 が 「"h"」 でもなく 「a[0]」 が 「"h"」 でもなく 「&a[0]」 が 「"h"」 でもなく 「p = &a[0];」 が 「"h"」 なのか? 何も考えずに適当に書いてるから、 意味不明としか返しようがないんだよ
>>917 p は配列 a の先頭アドレスを指す。
そこには 'h' が格納されている。
p は 'h' ではないし、&a[0] が 'h' でもなければ、p = &a[0]; も 'h' ではない。
'h' なのは *p であり、a[0] だ。
それだけのことだよ。
923 :
デフォルトの名無しさん :2007/02/19(月) 02:09:00
924 :
デフォルトの名無しさん :2007/02/19(月) 02:12:16
>>922 とんすくです
配列と文字列が混同しているみたいです
925 :
924 :2007/02/19(月) 02:34:49
ポインタの概念て一回で解る奴と、何ヶ月教えても理解できない奴といるけど、なんでなんだろうな
その入門書名を晒せ 話しはそれからだ。
928 :
924 :2007/02/19(月) 02:43:13
>>926 自分は後者に入ります、はい
逆に一回でわかる方が不思議です
>>927 10日シリーズです
翔泳社のあのシリーズはいいって噂はあんまり聞かないけどなあ 既習言語なしでCを10日で理解しようってのがそもそも無謀だとおもうわ。
理解できないっていうか勝手にヘンな解釈して泥沼にはまるパターンが多い気がする。
>>926 メモリレイアウトをイメージできてるかどうかで分かれるんじゃないかな?
メモリレイアウトをイメージできてるヤツなら一回で即解るだろうし、
そうじゃないと何度聞いてもメモリレイアウトをイメージできん限り、理解できんだろ。
ということで、メモリレイアウトをイメージしろ、
>>928
932 :
924 :2007/02/19(月) 02:52:36
joelも、ポインタと再帰は難しいって書いてたな。 >ポインタと再帰には、ある種の推論力、抽象的思考力、 >そして何よりも問題を同時に複数の抽象レベルで見ると >いう能力が要求される。そしてポインタと再帰を理解できる能力は、 >優れたプログラマになるための能力と直接的に相関している。
934 :
924 :2007/02/19(月) 03:07:36
>>931 はい!ががります
というか
>>922 を読んで今現在わかったどーーーーー!!
理解できますた!!!こんなにわかりやすいサイトがあるんですね
自分で本でわからない部分はネットで調べたりしましたが
ちんぷんかんぷんでした
ポインタの概念なんて理解しなくても使えればそれでいい。 プログラミングで実際にポインタを使って試行錯誤する前に 理解しようとするのがすべての元凶だ。
936 :
924 :2007/02/19(月) 03:12:56
この図と家の本棚を照らし合わせてみました そしたらわかったーーー詰まっていたものが取れた気分です
>>935 >プログラミングで実際にポインタを使って試行錯誤
正しい姿勢だと思うよ。
にわか知識でポインタ使ってたまたま動いたとしても
変なとこでバグ残してたりして、後々の問題になったりするし。
938 :
924 :2007/02/19(月) 04:13:51
char a[] = "hello"; char *p; p = &a[0]; char a[] = "hello"; は配列にすればchar a[5] = {'h',e',l',l'o','\0'};になるので 例えば、 a に割り当てられたアドレスが アドレス 文字型 1000 h [0] 1001 e [1] 1003 1004 l 1005 o 1006 \0 こうだとし p;に割り当てられたアドレス 10010 空 だとします、そしたらポインタを使い pにaのアドレスを入れ(指す)たら 10010 1001 になるんですよね?
939 :
924 :2007/02/19(月) 04:14:41
1003に'l'が抜けてました(訂正)
1001じゃなくて1000
>>938 char a[6] = {'h','e','l','l','o','\0'}; な。
>>938 おおかた正しい。
実際にはポインタは4バイトとか8バイトとかだから、
10010-10013(10017)に1000と書き込まれることになる。
943 :
924 :2007/02/19(月) 04:32:53
サンクスです、1000でしたね
>>941 NULL忘れてた、含まなきゃダメでしたね
>>942 詳しく、ありがとうです
pに割り当てられたアドレス
10010 1000
になったら、'h'が入ったと思って宜しいのでしょうか?
>>943 ポインタ p が指してるのはあくまで a[0] で、その中身の 'h' を指してるわけじゃないよ。
たとえば、 a[0]='c'; とすれば *p は 'c' になる。
>>938 これで、「ポインタのポインタ」と「関数ポインタ」を理解できればC言語での
ポインタまわりはほぼ完璧に理解できたと思っていい。
C++だと、それらに加えて「メンバポインタ」やら「キャストでアドレスが
変わる(ずれる)こと」なんかを理解しておく必要がある。
946 :
924 :2007/02/19(月) 04:38:58
>>944 厳密に言えば、[]要素数を指すって事ですね
今日は初めて急にポインタが概ね理解できた
皆さんサンクスでした!
947 :
924 :2007/02/19(月) 04:41:10
>>945 C++って、かなり難しいイメージがあります
Cより複雑になったらきついです
>>943 細かいことだけど、ヌルポインタと紛らわしいから '\0' (ヌル文字) をNULLと表記しないほうがいいよ。
書くならNULかな。
>>947 C++はCを拡張したものだからより複雑になるのは当然だけど、
その分、便利だから将来的にはC++にも手を出すことをオススメする。
が、いまはC++のことは忘れてCをしっかり身につけることに専念してればおk
950 :
924 :2007/02/19(月) 04:45:03
951 :
924 :2007/02/19(月) 04:50:41
>>949 がんばってCを理解します
forの二重ループやforの中のif文とかが苦手なので
ポインタの次に克服をするのを目標にします!
ほんとおまいら親切だなあ 俺のときは、絵本でも読んでろハゲ、しか言ってくれなかったのに
953 :
デフォルトの名無しさん :2007/02/19(月) 05:20:06
ってか、Cの絵本か? ありゃ説明が薄っぺらいから入門者向けとは言い難い
>>952 同じスレでも、そん時の雰囲気とか書き込んでいる連中とか違うと
同じような書き込みに対し、反応が180度逆になるのも珍しい話じゃない。
>forの二重ループやforの中のif文とかが苦手なので 物事を抽象的に捉えられない香具師の典型だな。 ポインタの次なんて暢気なこと言ってないで頭取り替えた方がいいぞ。
努力する姿勢があるならいつか苦手じゃなくなるさ
努力するつもりがあるなら、もちっと幅広く様々な文献やソースに目を向けることだな。 ただし、くだらねぇわけのわからんソースばかり見ているとバカになるぜ?
住所だの電話番号だの、そういう説明の為の抽象概念だけ追っかけてた頃は全然頭に入らなかったなぁ
「がんばるぞ」という気持ちの持続が難しいんだよな、勉強って。 自分の好きなこと、たとえばゲーム作りして、悩んで悩んで悩み続けられれば、 きっと本当の意味でC言語が身に付くと思う。
学校で単位取得のために点数評価を得るためだけにやっている奴は 本当に横着をして済まそうって根性があって困る。そんなんだったら 勉強する価値もなければ授業に費やした時間が無駄だって気づいた方が良いだろうね。 どうせ限られた時間の中で生きている人間なんだし。
そのことに気づいて学校辞めたら酷い目に遭いますた 俺のばやいはなんとか仕事に就けたからよかったが
プログラムは楽しいものなんだけどなぁ・・・ いやなものだというイメージは悲しいなぁ # うっひょーオレ仕事でプログラムし放題さいこー # 仕様変更?うひゃーまたプログラムさせていただけるんですね # さいこーでーっっっっす # そんな毎日だけどw
それがマゾヒストだ。
プログラムって いわゆる努力家よりも 「楽をするための努力は厭わない怠け者」 がいいもの書けるようになるらしいぞ。
>>964 俺はまさにそれだけど、いいものが書けるようになるかどうかは別問題だぞ。
だって、飽くまで楽をする為の努力だからメンテナンスの必要がないと
判断したモノはそりゃもうグチャグチャなコード(当然コメントなんてない)を書く。
# でも、後からメンテナンスの必要が出てきたらその都度必要な範囲で段階的に
# リファクタリングしていく。リファクタリングが大変そうな時はバッサリ捨てる。
>>964 お前C言語ポインタ完全制覇読んだ事あるだろw
>>966 俺その本読んだこと無いけど、どっかで見たことあるぞそのフレーズ
そりゃ有名だもん
つうかITそのものがそうだろ
あの…スレ違いかもしれませんが… Cコンパイラは基本的にどっかのサイトからインストールしますよね? だけど、そうじゃなくてネット使わずに、CDロムか何からインストールできるようにしたいんです。 できますか?
CD-ROMか何かの形態で売っているものを買えばいい。 むしろそのほうが一般的だと思うぞ。 まあそこまでしなくてもダウンロードしたものをそのままCD-Rにでも焼けばいいと思う。 VC++ 2005 EEみたいにISOイメージなんて場合もあるけど。
>>970 君はCやる前にPCの基礎を頭に叩き込んだほうがいい。
いや煽りじゃなくて。PCの挙動わかってないとポインタの概念なんか絶対掴めない。
>>971-973 ありがとうございます
こういう質問むかつきますよね
すみませんすみません
怠惰を求めて勤勉に行き着く、か。
基本書なんかCD付きのが多くない? ネット環境が制限されるなら一冊買っといたほうがいいかも。
>>965 捨てられるならそれでいいじゃないか
捨てずに拡張拡張ってさせる頭悪いのが・・・・・・
>>966 読んでません
Cの前はアセンブラ使いだったからポインタで
困った記憶はあんまし無い
>>973 PCの基礎をダウンロードさせてください><
いやまぁ、PC関係なく勘のいいヤツなら何とかなるよ
ただ勘のいいヤツは質問する前に自分で気づいちゃったりするわけだが
ISOにはもう愛想が尽きた!ちうか仮想ディスクドライブ使えばおk
入門書の次ってどの本がオススメ? よく自分でいろいろ作ってみろって言ってるけど何を作ればいいのかまったく分りません
WinRAR があれぱ ISO ファイル解凍できるよ
ウィンドウアプリでも作ってみたら?
自分で作ったところでvectorに類似ソフトがアップされているし 自分で作るより誰かが作ったソフトをダウンするほうがよい
>979 目的がないならプログラムの勉強する必要なくね?
>>981 入門書で一通りの基本的な関数の使い方を覚えただけだからまだそんなレベル
に達してないと思うけどネットで調べながらやったら出来るかな?
>>983 将来的につまらないアプリやらゲームやら作りたいけどどう作ればいいのか
とかサッパリ分らないレベルなんだ(´・ω・`)
>>979 LinuxでもBSDでもなんでもいいからコードを読んでみることかなあ。
お勧めはNetBSD、「デーモン君のソース探検」て本をガイドにコードを読んでみるといいと思う。
もちろんそれ以外にもいいソースはあると思うけどね。
お前ら見てると、 ひらがな覚え立てで本が読んでみたーいって言ってる幼稚園児に いきなり太宰治の本とか薦めたりしてそうだな
なんでこれmojiに1足したら(アドレス000061に1を足したら)a→bになるの? #include<stdio.h> int main(void) { char *moji='a'; printf("%c\n",moji); printf("%p\n",moji); moji=moji+1; printf("%c\n",moji); printf("%p\n",moji); return 0; }
>>987 そういうことはやめなさい
以下のように読めば自分が何をしてるか分かるだろう
#include<stdio.h>
int main(void)
{
char *moji;
moji = (char *)'a';
printf("%c\n", (char)moji);
printf("%p\n", moji);
moji = moji + 1;
printf("%c\n", (char)moji);
printf("%p\n", moji);
return 0;
}
>>987 無茶なヤツだなww
普通は、
char *moji='a';
でなく、
char moji='a';
だろう。
char *moji='a';であっても、
printf("%c\n",moji);はmojiというcharへのアドレスに入っている値を文字として表示するんじゃなく、
mojiに入っている値(='a'=0x61)を文字として表示するから、当然最初はaが表示される。
次にmojiに1を加えるんだから、0x62='b'が表示される。
なんにせよ、コンパイラがchar *moji='a';の段階で警告を出すはずだぞ。
もしくは、こうしたかった? #include<stdio.h> int main(void) { char *moji="a"; printf("%s\n",moji); printf("%p\n",moji); moji=moji+1; printf("%s\n",moji); printf("%p\n",moji); return 0; } これなら、moji=moji+1;のあとは文字列"a"を2文字目('\0')から表示しようとするから、 空文字列を表示することになる。
ごめん分らない つД`) *mojiのアドレスに無理矢理'a'のコードを代入させてるってこと?
書き込む前にリロードしてなかった。 やっとわかったよ。どうにか理解できたような気がする(・∀・) ありがとう
実行してみてprintfの実行結果を見れば分かるだろう
>>984 ウィンドウ作りはある程度のC++環境ならライブラリが付いてくるぞ。
あとCを真似た言語で標準でウィンドウライブラリ付いてる言語ではJavaとか。
純Cで、ってならTcl/Tkとして有名なTkでもやってみる?
>>984 あとゲーム用ライブラリならゲーム製作板で色々見つかると思う。
URL忘れたが Wiki がある。
>>994 1時間悩んだ結果
'a'(97)ならccがa(97)〜z(122)のどれであっても宣言したalphas[27]の中に納まる
から'a'を使ってるだけ。97じゃなくわざわざ'a'を使ってるのは練習の為
と解釈したんだけど合ってるかな?
'a'の方が分かりやすいから
>>997 'a'が97でない環境があるかもしれないから、普通、文字の即値を整数で書くことはしない
1000げt
1001 :
1001 :
Over 1000 Thread このスレッドは1000を超えました。 もう書けないので、新しいスレッドを立ててくださいです。。。