C言語なら俺に聞け(入門篇) Part 8
■ このスレッドは過去ログ倉庫に格納されています
0001デフォルトの名無しさん
2007/02/20(火) 13:44:34・C++言語はスレ違いです。
・分からない事をなるべく詳しく書いて下さい。
・ソースコードを晒すと答えやすくなるかもしれません。
・質問者は最初にその質問をした時のレス番号を名前欄に書いて下さい。
前スレ
C言語なら俺に聞け(入門篇) Part 7
http://pc10.2ch.net/test/read.cgi/tech/1170064980/
過去スレ
Part 1 http://pc8.2ch.net/test/read.cgi/tech/1146700389/
Part 2 http://pc8.2ch.net/test/read.cgi/tech/1153818463/
Part 3 http://pc8.2ch.net/test/read.cgi/tech/1160682950/
Part 4 http://pc8.2ch.net/test/read.cgi/tech/1162999861/
Part 5 http://pc8.2ch.net/test/read.cgi/tech/1165022193/
Part 6 http://pc10.2ch.net/test/read.cgi/tech/1167325490/
関連スレ
C/C++の宿題を片付けます 83代目
http://pc10.2ch.net/test/read.cgi/tech/1170830498/
くだすれC言語(初心者用)
http://pc10.2ch.net/test/read.cgi/tech/1153542424/l50
【ISO/ANSI/JIS】 C言語なら俺に聞け! Part 131
http://pc10.2ch.net/test/read.cgi/tech/1170338926/
【初心者歓迎】C/C++室 Ver.35【環境依存OK】
http://pc10.2ch.net/test/read.cgi/tech/1171888583/
【C 関数検索 man on WWW】 http://www.linux.or.jp/JM/index.html
0153デフォルトの名無しさん
2007/02/22(木) 01:30:12やる気があるならC言語が最適
0154デフォルトの名無しさん
2007/02/22(木) 01:36:48みんなありがとう
0155デフォルトの名無しさん
2007/02/22(木) 01:43:43なければ自分で作ります
0156デフォルトの名無しさん
2007/02/22(木) 01:54:550157デフォルトの名無しさん
2007/02/22(木) 02:09:19文字列とポインタがわかりません、説明は読みました
前の変数と配列のポインタは理解できました
>>>10−3.ポインタと文字列
普通ポインタを用いるときには、配列などのアドレスをポインタに設定して用いますが、
文字列の場合には、配列を使わずにメモリ上に取られた文字列のアドレスを
直接ポインタに指定することができます。
これがわかりませんので、解説よろしくお願いいたします。
0158157
2007/02/22(木) 02:15:12ポインタと文字列で
>>>>>>10−3.ポインタと文字列
普通ポインタを用いるときには、配列などのアドレスをポインタに設定して用いますが、
文字列の場合には、配列を使わずにメモリ上に取られた文字列のアドレスを
直接ポインタに指定することができます。
これで、普通の"変数や配列のポインタ"と、"ポインタと文字列 "の違いがわかりませんです。
0159デフォルトの名無しさん
2007/02/22(木) 02:34:05→ ありません。全てアドレス値です。そもそも文字列というのはchar型配列(の先頭のポインタ)
"ABC"みたいのでもメモリ上に変数が作られると考えればいい。文字列は配列なので先頭のポインタを取得すればいい
""で先頭のポインタが取得できるのでポインタ変数にあたかも文字列を代入しているように見える
よってconst char *hoge[N]みたいなので文字列定数の配列が作れます。
0160デフォルトの名無しさん
2007/02/22(木) 02:34:35int *array = { 1, 2, 3, 4, 5 }; // エラー
こういうことはやったらおこられるが、
文字列ならおkとかそういう意味。
char *p = "ABC"; // おk
別にポインタそのものには違いはない。
0161デフォルトの名無しさん
2007/02/22(木) 03:18:34サンクス自分で作る
0162デフォルトの名無しさん
2007/02/22(木) 03:23:01その説明だと、
char *p = "ABC";
*p = 'D';
とか平気でやるようになりそうだ。
0163デフォルトの名無しさん
2007/02/22(木) 03:32:47は前スレの人だな
未だまともな本買わずに、サイトとか見てるのか。
0164デフォルトの名無しさん
2007/02/22(木) 03:46:10それがダメなのはchar *pが暗黙にconstとして宣言されているからですか?
0165157
2007/02/22(木) 03:59:51では、大した違いが無く気にせずでいいんですね。
サンクスでした
>>163
良い本が見つからず、どれを買うか悩んでいます
ここで紹介された本は書店では見当たりません
今のところ、上で挙げたサイトが最良です
0166157
2007/02/22(木) 04:12:50直接ポインタに指定することができます
この解説が
>>>"ABC"みたいのでもメモリ上に変数が作られると考えればいい。文字列は配列なので先頭のポインタを取得すればいい
""で先頭のポインタが取得できるのでポインタ変数にあたかも文字列を代入しているように見える
>>int *array = { 1, 2, 3, 4, 5 }; // エラー
こういうことはやったらおこられるが、
文字列ならおkとかそういう意味。
char *p = "ABC"; // おk
この二つでいいのですよね?
もう一度だけ、例文を用いて解説して戴けると、ありがたいです。
0167デフォルトの名無しさん
2007/02/22(木) 04:13:33その場合の挙動が標準規格で未定義だからです。
0168デフォルトの名無しさん
2007/02/22(木) 05:02:54ありがとうございます。
足を踏み入れてはいけないところに行ってしまったみたいで
ちょっとびびりますた。
0169デフォルトの名無しさん
2007/02/22(木) 06:05:450170デフォルトの名無しさん
2007/02/22(木) 06:09:12OSは?
0171デフォルトの名無しさん
2007/02/22(木) 06:09:340172デフォルトの名無しさん
2007/02/22(木) 06:10:42Win32API質問箱 Build50
http://pc10.2ch.net/test/read.cgi/tech/1171721448/
0173デフォルトの名無しさん
2007/02/22(木) 06:14:540174デフォルトの名無しさん
2007/02/22(木) 11:36:45char name[20]; char name2; int No; int time; char nurupo[10];・・・・
}
みたいな感じでcharやintなんかがごっちゃになってる構造体を
ポインタ操作か何かで
順番に指定していくことってできますか?
0175デフォルトの名無しさん
2007/02/22(木) 11:50:340176デフォルトの名無しさん
2007/02/22(木) 11:58:59>構造体を順番に指定
struct nannka a, b, c;
struct nannka p[] = {&a, &b, &c};
>構造体の要素を順番に指定
struct nannka a;
void * p[] = {a.name, & a.name2, & a.No, & a.time, a.nurupo};
0177デフォルトの名無しさん
2007/02/22(木) 12:13:48ありがとうございます。
早速試させていただきます。
0178デフォルトの名無しさん
2007/02/22(木) 12:22:010179デフォルトの名無しさん
2007/02/22(木) 14:07:52こういう型の異なる構造体のメンバにポインタを使って順番にアクセスする意味があるのだろうか?
結局、そのメンバが文字列なのか整数型なのか判断する必要があるわけだし
名前でアクセスしたほうがソースも見やすいと思うけど
0180デフォルトの名無しさん
2007/02/22(木) 16:19:21sscanf(buff, "%s", buff);
これは反則技ですか?
0181デフォルトの名無しさん
2007/02/22(木) 16:24:40むしろ一般的(?)。これだけで十分だな。最後に\nがくっ付くので注意
0182デフォルトの名無しさん
2007/02/22(木) 16:29:03sscanf(buff, "%s", buff); の方。
同じものにsscanfをしていいのかどうか
0183デフォルトの名無しさん
2007/02/22(木) 16:38:44領域が重なっていると鼻から悪魔
0184デフォルトの名無しさん
2007/02/22(木) 16:49:570185デフォルトの名無しさん
2007/02/22(木) 16:54:47反則技
あぶないコーディング
0186デフォルトの名無しさん
2007/02/22(木) 16:55:38別に buff[strlen(buff)-1] = '\0'; 等でも
やりたい事はできるのだけど、
sscanf使ったらどうなるのかな、って思っただけ。
0187デフォルトの名無しさん
2007/02/22(木) 16:56:55実用上問題ないけど、かなり危険な気がする
でも、その例が思い浮かばない
ループで\nを取り除いたほうがいい気がする
>>184
\nを取り除きたいんじゃないの?
0188デフォルトの名無しさん
2007/02/22(木) 16:59:220189デフォルトの名無しさん
2007/02/22(木) 17:38:36それやるなら
fgets(buff, sizeof(buff), stdin);
sscanf(buff, "%s", command);
でいいんじゃない?
buffは入力データを格納する領域の名称
入力データを加工したらもうbuffではないでしょう
0190デフォルトの名無しさん
2007/02/22(木) 17:58:26httpsの使い方を教えてください
0191デフォルトの名無しさん
2007/02/22(木) 18:19:34目的の環境に合わせて適切なライブラリを入手せよ。
C言語自体には、それらの取り扱いは規定されていない。
0192デフォルトの名無しさん
2007/02/22(木) 22:33:450193デフォルトの名無しさん
2007/02/22(木) 22:38:56#include <time.h>
time_t time(time_t *timer);
0194デフォルトの名無しさん
2007/02/23(金) 00:35:51と
char [10] = "ABC";
char *p;
p = s;
の違いは何なのでしょうか?
0195デフォルトの名無しさん
2007/02/23(金) 00:41:17前者はコンパイルができて後者はエラーになってコンパイルが通らない。
0196194
2007/02/23(金) 00:42:34どうしてなんでしょうか?
同じポインタですよね?
0197デフォルトの名無しさん
2007/02/23(金) 00:44:43↑変数名がないからエラーになる。ポインタは関係ない。
0198デフォルトの名無しさん
2007/02/23(金) 00:46:450199194
2007/02/23(金) 00:47:28char *p = "ABC";
と
char s[10] = "ABC";
char *p;
p = s;
の違いでした。
0200デフォルトの名無しさん
2007/02/23(金) 00:47:290201デフォルトの名無しさん
2007/02/23(金) 00:50:03pの指しているものが文字列リテラルか文字配列かの違い。
0202194
2007/02/23(金) 00:54:10もう少し簡単にお願い致します
”リテラル”、入門書にも載っていません(索引も調べましたが)・・・・
文字列リテラルか文字配列とは・・・?
0203デフォルトの名無しさん
2007/02/23(金) 00:56:410204デフォルトの名無しさん
2007/02/23(金) 00:57:21char *p = "ABC"; ←"ABC"という文字列を指しています。普通はこのポインタを介しての変更はしません。
char s[10] = "ABC";
char *p;
p = s; ←今は"ABC"の入った配列の先頭を指しています。指してる配列の中身を変更できます
0205デフォルトの名無しさん
2007/02/23(金) 00:58:58記憶クラスやらスコープやらの説明をする前に、変数を宣言すると
メモリ上に型に応じた領域が確保されるというのをちゃんと教えて
くれないといかん。
あと、初期値の設定なんて0/NULLにしておくくらいしか普通使わなく
ないか?
0206194
2007/02/23(金) 01:07:15>>204
>>205
ありがとうございます
char s[10] = "ABC";
char *p;
p = s;
は、a[0] A を指していて
char *p = "ABC"; pの中に"ABC"が入るって事でしょうか?
0207デフォルトの名無しさん
2007/02/23(金) 01:12:00あくまで"ABC"っていう文字列リテラルの先頭を指しているだけで、
中に入っているわけじゃない。
こういうのって実行時にプログラムが、どんな風に展開されてるかを
イメージできないと理解しにくいんでない?
0208デフォルトの名無しさん
2007/02/23(金) 01:15:05ヒープにおかれた "ABC" の先頭アドレスが p に代入される。
char s[10] = "ABC"; だと、
スタックに s がつまれ、"ABC" で初期化される。
0209デフォルトの名無しさん
2007/02/23(金) 01:15:28(こいつだめだ・・・まるでわかってない・・・俺が教えてやんよ!)
前者はそんな感じ(中身のAを指してるわけじゃないが)
後者は例えば文字列リテラルという型LITERALがあったとしよう。
char *p = "ABC";っていうのはいわば前者と同じ感じで
LITERAL lite = "ABC"
char *p = &lite; //&liteはアドレス
こんな感じで、配列だろうと文字列リテラルだろうとメモリ上にあるからアドレスがあるわけだ
0210194
2007/02/23(金) 01:16:53難しいです、というかイメージが付きにくいです
>>文字列リテラルの先頭を
は"ABC"の{'A',B',C,','\0'};リテラルの先頭とは
\0←を指しているのでしょうか?それとも'A'でしょうか?
0211デフォルトの名無しさん
2007/02/23(金) 01:18:570212デフォルトの名無しさん
2007/02/23(金) 01:18:59矢印に 'A' が入るんじゃない。
矢印のさしている先に 'A' があるんだよ。
0213デフォルトの名無しさん
2007/02/23(金) 01:19:210214デフォルトの名無しさん
2007/02/23(金) 01:19:590215デフォルトの名無しさん
2007/02/23(金) 01:28:190216デフォルトの名無しさん
2007/02/23(金) 01:30:56堂々とした間違い。
0217デフォルトの名無しさん
2007/02/23(金) 01:31:54int か double か
0218194
2007/02/23(金) 01:32:10ヒープやスタック、とか説明が高度で付いていけません
双方共に同じ先頭を指してるのに何が違うのかイメージがつかないです
もう一度だけ>>char s[10] = "ABC"; だと、
スタックに s がつまれ、"ABC" で初期化される。
の>>スタックに s がつまれ、"ABC" で初期化される。
というのを解説お願い致します。
あとは出直してきます
0219デフォルトの名無しさん
2007/02/23(金) 01:33:27int abs(int);
double fabs(double);
0220デフォルトの名無しさん
2007/02/23(金) 01:34:02そこ間違ってるから気にする必要はない
0221194
2007/02/23(金) 01:34:36ヒープやスタック、とか説明が高度で付いていけません
双方共に同じ先頭を指してるのに何が違うのかイメージがつかないです
もう一度だけ>>char s[10] = "ABC"; だと、
スタックに s がつまれ、"ABC" で初期化される。
の>>スタックに s がつまれ、"ABC" で初期化される。
というのを解説お願い致します。
あとは出直してきます
0222194
2007/02/23(金) 01:35:18ありがとうございました、出直してきます
0223デフォルトの名無しさん
2007/02/23(金) 01:38:01分解して考えると分かるかも
char s[10] = "ABC";は
char s[10];
strcpy(s, "ABC");
この場合は、char s[10]の領域の内容を s[0]='A' s[1] = 'B' s[2]='C' s[3]='\0' s[4]〜以下不定
で初期化。
char *p = "ABC";
これを分解すると
char *p;
p = "ABC";
こうすれば、pは単なるポインタだってわかるはず。"ABC"はコンパイル時に
プログラム(exeファイルとか)内のどこかにおかれる文字列定数の先頭
のアドレスの意味になる。
022436
2007/02/23(金) 02:12:00どのことでしょうか?要素とは何でしょうか?
0225デフォルトの名無しさん
2007/02/23(金) 02:29:08"米飯", 150.3 ←要素
"中華麺", 57.1 ←要素
"蕎麦", 133.3 ←要素
"うどん", 100.0 ←要素
"素麺", 133.3 ←要素
"食パン", 250.3 ←要素
要素数=6
022636
2007/02/23(金) 02:45:37さんkすです!
要素だから[]だと思っていました
0227デフォルトの名無しさん
2007/02/23(金) 04:10:56それとも構造体配列でないとポインタは使えないでしょうか?
0228デフォルトの名無しさん
2007/02/23(金) 04:22:18022936
2007/02/23(金) 04:35:43CALORIE cal[500] = {
{"米飯", 150.3}, {"中華麺", 57.1}, ←アドレス:1000: cal[0]
{"蕎麦", 133.3}, {"うどん", 100.0}, ←アドレス:1001: cal[1]
{"素麺", 133.3}, {"食パン", 250.3} ←アドレス:1002: cal[3]
};
なのでしょうか?
或いは、これら全体でアドレス:1000: cal[0]なのでしょうか?
{"米飯", 150.3}, {"中華麺", 57.1},
{"蕎麦", 133.3}, {"うどん", 100.0},
{"素麺", 133.3}, {"食パン", 250.3}
}
023036
2007/02/23(金) 04:45:12{"米飯", 150.3}, ←アドレス:1000: cal[0]
{"蕎麦", 133.3}, ←アドレス:1001: cal[1]
{"素麺", 133.3}, ←アドレス:1002: cal[3]
{"中華麺", 57.1}, ←アドレス:1003: cal[4]
{"うどん", 100.0}, ←アドレス:1004: cal[5]
{"食パン", 250.3} ←アドレス:1005: cal[6]
0231デフォルトの名無しさん
2007/02/23(金) 04:51:100232デフォルトの名無しさん
2007/02/23(金) 04:54:46ポインタに代入することが出来る。
指しているのはcalの先頭要素。
ポインタに加減算をすることで次/前の要素をポイントできる。
023336
2007/02/23(金) 05:06:020234デフォルトの名無しさん
2007/02/23(金) 05:09:160235デフォルトの名無しさん
2007/02/23(金) 05:10:52023636
2007/02/23(金) 05:22:03では違っているのでしょうか?
>>235
え?そうなんですか?
ポインタはアドレスが重要と思っていましたが
では、アドレスでなくインデックス番号を重視すべきですかね?
0237デフォルトの名無しさん
2007/02/23(金) 05:37:31実現するためにCではアドレスという機械寄りの概念を露出させ
てしまっているだけ。Pascalではもっと抽象化されているし、ポ
インタ=アドレスという理解だとJavaにはポインタがないという勘
違いも生む。
場所さえ指せればよいのだから、使い手にとっては、それがメモリ
上のアドレス値であるというのは余計な情報。
023836
2007/02/23(金) 05:41:47初めてのプログミングがCだったのが間違いでしたかね
Javaの方が簡単と聞きますし
0239デフォルトの名無しさん
2007/02/23(金) 05:43:37○「Cではポインタをデータのあるメモリ上のアドレスとして表現している」
と理解してればいいんじゃね?
0240デフォルトの名無しさん
2007/02/23(金) 05:49:550241デフォルトの名無しさん
2007/02/23(金) 06:11:30CALORIE *hoge=cal; int i; for(i=0;i<cal_num;i++){printf("%6s(%3.0f) %p\n",hoge->name,hoge->value,hoge);hoge++;}
(int mode = 0; の直後)
で、表示されたモノは一旦忘れてw
真面目な話、例として↑のコードで
CALORIE *hoge(CALORIE型のポインタ)はメモリのどこかに格納されているデータ、CALORIE型の変数(配列)にアクセスできる。
この場合、最初に設定されているアクセス先は配列cal[500]の先頭(つまり要素cal[0])で、
hoge++ で、次々とcal[1], cal[2], cal[3] ... とアクセスして表示している。
冗談で %p で番地を表示しているけど、実際のコーディングでこのアドレスを意識する必要性は無い(と思う
と偉そうに言う俺もほぼ初級者。。。
0242デフォルトの名無しさん
2007/02/23(金) 07:16:17{
char a[4] = "ABC";
char *p = "ABC";
printf("&a = %p\n", &a);
printf("a = %p\n", a );
printf("&a[0] = %p\n", &a[0]);
printf("\n");
printf("&p = %p\n", &p);
printf("p = %p\n", p);
printf("&p[0] = %p\n", &p[0]);
return(0);
}
// 3つとも配列aの先頭アドレス
&a = 0x22cce4
a = 0x22cce4
&a[0] = 0x22cce4
&p = 0x22cce0 // ポインタ変数pのアドレス
p = 0x402000 // ポインタ変数pの値
&p[0] = 0x402000 // "ABC"が格納されている場所の先頭アドレス=ポインタ変数pの値
0243デフォルトの名無しさん
2007/02/23(金) 07:25:55そう書くと&a、a、&a[0]どれも同じに見えてしまう。
0244デフォルトの名無しさん
2007/02/23(金) 09:34:35リテラル使って初期化したら初心者には余計わかりづらいと思うんだが。
0245デフォルトの名無しさん
2007/02/23(金) 12:33:20&a、a、&a[0]は、どれも同じ。
a も p も表示させるとアドレスだが、a は配列aの先頭アドレスであって、
&a の示すアドレスに0x22cce4というアドレスが格納されているのではない。
そのため、a = p という代入はできない。
一方で、p は変数pのアドレスではない。
&p の示すアドレスに0x402000というアドレスが格納されている。
この0x402000は "ABC" というデータが格納されている領域の先頭アドレスに
なっている。
変数p にはアドレスを格納できるので、p = a という代入はできる。
0246デフォルトの名無しさん
2007/02/23(金) 12:37:12間違ってるぞ
0247デフォルトの名無しさん
2007/02/23(金) 12:57:00間違ってるとは言えない
0248デフォルトの名無しさん
2007/02/23(金) 13:02:59型が違う。
p = &a と代入すると警告が出るはず。
0249デフォルトの名無しさん
2007/02/23(金) 14:26:12#include <stdlib.h>
#include <time.h>
#define MAX_LINE 79
void main(void)
{
char s[] = "0123456789"
"abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"[]@;:-+*^~|_,.\\/\"\'%%$#&()!";
char ps[MAX_LINE];
int si = sizeof(s);
int i;
srand(time(NULL));
for( i = 0; i < MAX_LINE; i++ )
ps[i] = s[rand() % si];
printf(ps);
}
なんとなく思いつきでランダムな文字列を79個配列にコピーして
それを表示するプログラム作ってみたんですが、実行する毎に79文字表示されなかったり
エラーが出たりします。
間違いを教えて頂けないでしょうか?
0250デフォルトの名無しさん
2007/02/23(金) 14:37:2779文字表示されないのはs[si-1]が'\0'だから。
0251デフォルトの名無しさん
2007/02/23(金) 14:40:13printf("%s", ps);
でやってみ
0252デフォルトの名無しさん
2007/02/23(金) 14:41:17rand() % si のとりうる範囲は[0,sの文字列長+1]
よって ps[i] の途中に ¥0 が入る可能性がある。
■ このスレッドは過去ログ倉庫に格納されています