C言語なら俺に聞け( ..
[2ch|▼Menu]
263:デフォルトの名無しさん
08/06/05 02:47:02
>>261
あー、自分の手元のソースの方ではヌル文字を意識した配列していたのですが…
問題点を抽出化したサンプルを作成する際に、手落ちしてしまったみたいです…
ようするに、まだヌル文字分まで意識して文字列配列を宣言することを、意識しなれていない、ということですね
繰り返さないように精進します

ありがとうございました!

264:デフォルトの名無しさん
08/06/05 02:51:37
>>251
'1' は文字定数である。
Cでは文字はすべてそのマシン上での文字セットに対応する整数値と等価である。
そしてこれが通常 char 型の変数に格納される。

連続したchar 型からなるデータ領域に任意の文字の値を並べて格納し、
最後にヌル文字( '\0' )を加えたものが文字列と呼ばれるデータ構造である。
文字列は通常、その先頭の文字へのポインタを使って操作される。
配列の場合はその配列名が先頭の文字へのポインタに変換されるので、
つまり大抵の場合は文字列を格納した配列の名前を使って文字列を操作する。
この場合、配列 tmp に文字列を格納し、tmp という名前を通じて操作しようとしている。

"1" は「文字列リテラル」と呼ばれる、固定の文字列である。
コード上では配列名同様に '1' へのポインタに変換される。

コンパイラによる自動的な変換がある限られた場合を除き、
どんなときも == 演算子で互いに比較する対象は
「同種の」データオブジェクトでなければならない。
この場合 tmp[0] は char 型つまり整数型であるのに対し、
"1" はその文字列リテラルの先頭を指すポインタ型であるから
正しく比較できるわけがない。文字定数 '1' を使え。

265:デフォルトの名無しさん
08/06/05 02:52:32
もう四半世紀近くやってきて思ったこと。
経験は絶対的に必要だが、努力や熟練とは異質の世界だなと最近痛感。
足を洗うヨテイ

266:デフォルトの名無しさん
08/06/05 02:56:02
>>263
if (tmp[0] == "1"[0])
とか
if (tmp[0] == *"1")
でもコンパイルが通らない事は無いがオススメはしない

文字列が指すのがポインタってのはこれが一番わかりやすいかも?

267:デフォルトの名無しさん
08/06/05 02:58:04
&tmp[0]は絶対に蛇足(tmpと同じ)ということも覚えておくこと

268:デフォルトの名無しさん
08/06/05 03:06:25
C++だとvectorと合わせるために&tmp[0]とかやるけどな
趣味で好きな方を選べばいいと思う

269:デフォルトの名無しさん
08/06/05 03:12:41
&(tmp[0])はtmpと等価だがtmpをポインタ変数と同一視するのはCでもやめたほうがいい。
Cでは変更不能なポインタ変数というのが無い(C++ではある)から。
仮に実際にそうであっても、変更不能なポインタ変数であるとtmpをコード上で見なすこと
はしないほうがいい。
*(tmp++)とか書けないだろ?だからポインタ変数とまぎわらしい書き方はしないほうがいい。
char配列をchar*型引き数に渡す場合は、(char*)&(tmp[0])とか(char*)&tmpというキャスト
をして値渡し(アドレス値は、ポインタ変数にアサイン可能)する。

270:デフォルトの名無しさん
08/06/05 03:30:10
>>265
食っていくだけなら経験があればいい
腕を上げるには努力や熟練よりも好奇心が必要
と、八半世紀(ってなんだ)くらい思い続けてるんですがどうですか

271:デフォルトの名無しさん
08/06/05 08:09:27
>>249
なに、すべてはお金のため。あなたもその年になれば嫌でも理解するでしょう。

272:デフォルトの名無しさん
08/06/05 09:42:19
独学で先週から勉強してるんですが、引数だの返却値だののくだりで分からなくなりました
高校時代の数学の成績を聞いて一言返すだけのプログラムなんですが
seisekiがどんな値でも返事が「苦手なんすね」になります
どうしたら成績に合った返答ができるようになりますか?
どうやらこのスレで自分の質問だけかなり低レベルなようですがよろしくお願いします

#include <stdio.h>

int func ( int );
int seiseki ;

int main ( void )
{
printf("高校時代の数学の成績は5段階評価で言うと大体どのくらいでした? :");
scanf("%d",&seiseki);

switch(func(seiseki)) {
case 1 : printf("苦手なんすね\n"); break;
case 2 : printf("普通っすね\n"); break;
case 3 : printf("得意なんすね\n"); break;
default: printf("え?\n");
}
return 0;
}

int func ( int seiseki )
{
if(seiseki == 1 || 2) return 1 ;
if(seiseki == 3) return 2 ;
if(seiseki == 4 || 5) return 3 ;
else return 4 ;
}

273:デフォルトの名無しさん
08/06/05 09:45:46
int func ( int seiseki )
{
if(seiseki == 1 || seiseki == 2) return 1 ;
if(seiseki == 3) return 2 ;
if(seiseki == 4 || seiseki == 5) return 3 ;
else return 4 ;
}


if ( seiseki == 1 || 2 )
だと、seiseki == 1 もしくは 真(0以外) になるから
必ず真になってしまって条件の意味が無い

274:デフォルトの名無しさん
08/06/05 09:46:15
>>272
>if(seiseki == 1 || 2
if(seiseki == 1 || seiseki == 2


275:デフォルトの名無しさん
08/06/05 09:48:14
>>273-274
即レスありがとうございます!
引数とかの問題じゃない初歩的な間違いだったんですね・・・

276:デフォルトの名無しさん
08/06/05 11:22:54
>>269
正しく理解していれば混同することなどナイヨ
そんな冗長なキャスト使うほうが読んでて知識を疑うわ

277:デフォルトの名無しさん
08/06/05 12:00:54
>>269
もし君が配列名をポインタ値として扱うべきでないと真剣に考えるなら、
tmp の要素にアクセスするあらゆる場所で ((char *)&tmp)[0] のように書くべきである。
しかし前スレで書いたように、C規格はそのような冗長な書き方を避けるために、
配列はその先頭要素へのポインタ値に成り下がるという動作を規定した。
規格を正しく理解するかぎり、tmp[0] という書き方はまったく正当で安全である。
理解しないならどのような書き方をしたとて遅かれ早かれ間違いを起こすだろう。
1から10までアセンブラを叩くようなものの考え方を押し通すまえに、
高級言語というものがそもそも何のためにあるかを考え直すこと。

278:デフォルトの名無しさん
08/06/05 12:35:41
どっちも正しいんだから好きな方を選べばいい

279:デフォルトの名無しさん
08/06/05 12:41:45
>>265
俺も、アセンブラから始めて、pascal C++と4半世紀歩んできたが、今C++&boostで面白さが更に拡大してきた。これで10年は戦えそうだ。

280:ロベ
08/06/05 13:34:30
・BMPファイルの情報(画像サイズ、色数等)を表示する
・BMPファイルの画像を上下・左右反転させる
・BMPファイルの画像を回転させる
・BMPファイルのカラー画像をグレースケール化する
   式 Y=0.298912*R+0.586611*G+0.114478*B
・Windows形式とOS/2形式どちらにも対応できるようにする

このようなプログラムを作りたいのですが
ネットで調べてもほとんど参考になるものを見つけれませんでした
どこか参考にできるHPなどありますかね?

281:デフォルトの名無しさん
08/06/05 13:47:27
>>280
BMPファイルのフォーマット解説
URLリンク(www.kk.iij4u.or.jp)

282:デフォルトの名無しさん
08/06/05 13:49:23
あと>>56>>83>>92も参考に

283:ロベ
08/06/05 13:56:26
>>281 >>282
ありがとうございます
参考にします!!!

284:デフォルトの名無しさん
08/06/05 14:52:45
今まで
struct hoge __attribute__((aligned(16))) hogehoge[] =
{
    {-0.53878,5.12228,-0.46578},
    {-0.53878,5.62244,-0.05845},
    {-0.53878,5.12228,-1.13112},
    {-0.53878,6.47772,-0.82431},
    {-0.53878,6.55215,-0.05845},
          ・
          ・
}
とソースに組み込んできた情報が肥大してきたので
ファイルから読み込む予定なんですが
16バイト区切りで読み込みに必要なメモリをmalloc
させる方法ありますでしょうか?

285:デフォルトの名無しさん
08/06/05 15:21:06
ない。gccの拡張機能でもなかった気がする。

286:デフォルトの名無しさん
08/06/05 15:23:30
>>284
UNIX系だとmemalign()とかposix_memalign()があるかもしれない。
VC++だと_aligned_malloc()というのがあるかもしれない。

malloc()を使っても簡単にできますけどね。



287:デフォルトの名無しさん
08/06/05 15:25:42
malloc自体は16バイト境界に合わせてくれる保証がないから、
大きめに取って自分で境界調整するしかなかった気がする
なんにせよ処理系に依存する話

288:284
08/06/05 15:27:59
>>285
マジっすかorz

>>286
>UNIX系だとmemalign()とかposix_memalign()があるかもしれない。
>VC++だと_aligned_malloc()というのがあるかもしれない。
ちょっと調べてみます。
ちなみにCygwin + gcc 環境での開発になります。

>malloc()を使っても簡単にできますけどね。
これで思いついたのが、実際に必要なサイズ+16バイトでmallocで
確保した上でアドレスを16バイト区切りになるようにずらすというのもいけそうですかね?

289:デフォルトの名無しさん
08/06/05 15:34:37
>>288
>確保した上でアドレスを16バイト区切りになるようにずらすというのもいけそうですかね?

freeするときに元のアドレスに戻すのを忘れないように

290:デフォルトの名無しさん
08/06/05 15:41:13
戻すのは危険な香り
確保した領域の先頭を指すポインタと実際に使う領域の先頭を指すポインタを別に用意したほうがいいかも

291:デフォルトの名無しさん
08/06/05 15:42:59
>>289
そうですね。

>>290
ポインター2個の予定です。

こういうケースのアドレスのずらし方がわからないorz


292:デフォルトの名無しさん
08/06/05 15:49:58
ポインタの内部表現によるけど
基本的には整数値として見たときに
16の倍数になるように後ろにずらせばいいんじゃないの?

293:デフォルトの名無しさん
08/06/05 16:07:58
>>277
だからtmpは定数を表すマクロシンボルじゃないんだって。Cでは予約語や関数以外、識別子を定数と
みなすことはされない。(もしかして関数も変数なのかも知れないし)

Cでは、配列識別子は、実質ポインタ変数だよ。ただしポインタ変数として書き換え不能という属性がある。
書き換え可能なポインタ変数を、型は同じでも属性が異なるポインタ変数に値を複製する場合も、
明示的キャストが必要.本来的にはCではポインタの型(格)だけでなく変数属性にも煩いぞ。
異なる格や属性のポインタ変換が多用され、多用できるが故のメリットを享受するのに必要な当然の
危機管理文化だ。

Cは簡潔記述が目的で設計されたわけじゃない。この点、絶対誤解するな。
コードを簡潔かつ流麗にし記憶しやすくする為に、型/格/属性の相違をすべて型に吸収させいちいちそれ
にもっともらしい名前を付けることによる弊害(乱用され、乱造されるので、ちょっとしたコード書くの
にも、膨大な資料を参照しなければならなくなるハメになり、そのうち正しいコード(他人のバグに依存し
ない)を書く事すら不能になる)だけは避けたいというのが設計理念。
Cはキャストまみれの冗長記述になるのが自然だし、冗長に書いて真価を発揮する。

294:デフォルトの名無しさん
08/06/05 16:14:04
>Cはキャストまみれの冗長記述になるのが自然だし、冗長に書いて真価を発揮する
ありえない
そんな思想で作られたとしたら
そもそも配列がポインタに変換される仕様が入るはずがない

295:デフォルトの名無しさん
08/06/05 16:15:46
>>291
void *p = malloc(required_size + 16);
uintptr_t addr = (uintptr_t)p;
addr = (addr & ~0xf) + 16;
struct hoge *phoge = (struct hoge *)addr;
...
free(p);



296:デフォルトの名無しさん
08/06/05 16:27:30
>>293
ぜんっぜん逆。
Cはそういうわずらわしさを、ある一定の原則さえ守っていれば(そこがちょっと難しいが)
環境ごとの差異にさえ捕らわれずに排除できることを目指した。
だからそれぞれの型の複雑な格上げや符号拡張や変換や比較の法則があって、
そしてそれらが 自 動 的 に 行われる。
お前さんは単にそういう原則を正確に把握していないために、
コードの実際の動きを予想することができなくて、ガチガチに規定した冗長コードを書いてしまうだけ。

297:デフォルトの名無しさん
08/06/05 16:30:30
Cには配列という概念は無い
ポインタ(変数/値)に対する演算子[]が定義されてるだけ
pointer[integer_value]は無名変数(ポインタの型/属性/格に対応する型/属性/格を持つ)を
表す。

298:デフォルトの名無しさん
08/06/05 16:32:35
少なくとも strlen((char *)&array) はないだろ常識的に考えて

299:デフォルトの名無しさん
08/06/05 16:33:36
>>297
「概念」はあるよ。
オブジェクトがないだけ。

300:284
08/06/05 16:33:43
>>295
おーありがとうございます。

301:デフォルトの名無しさん
08/06/05 16:43:27
>ただしポインタ変数として書き換え不能という属性がある。
すくなくともこれは大間違い
配列に代入しようとしたときと
char*constに代入しようとしたときの
エラーメッセージを読めばわかるはず

配列識別子は配列全体そのものを表す
ただし一部の例外を除いてその先頭要素への
ポインタ値(変数ではなく)に変換される
だよ

302:デフォルトの名無しさん
08/06/05 16:47:00
>>296
言語仕様を勝手にガチガチに規定して、それに依存したコードを書いてると後で泣きを見るかも知れません
(俺モナー)

303:284
08/06/05 16:57:47
早速組み替えて思ったように動作しました。
感激!!ありがとうございます。

304:デフォルトの名無しさん
08/06/05 17:10:29
必要のないキャストが大量にあるコードを見たときの常人の反応は
「うわあ、この人はすごい厳密なコードを書くんだなぁ」じゃなくて
「うわあ、この人はC言語の仕様をよく知らないんだなぁ」だ

一方で、明示的なキャストが大量に必要なコードがあったとしたら、
たぶんそれは設計に問題がある

305:デフォルトの名無しさん
08/06/05 17:14:22
Cの経験がある常人って事か…

普通に考えてどっちであろうが
常人がコードを見たら「うわぁ…」としか思わないだろ
とか思ってしまったよ

306:デフォルトの名無しさん
08/06/05 17:16:15
ポインタを制するものはCを制すとはよく言ったものだ

307:デフォルトの名無しさん
08/06/05 17:29:01
特定のコンパイラは文句を言わないだけで本当は必要なキャストが大量にあるコードを
見たときの賢人の反応は
「うわあ、この人はC言語の仕様の良く知らない人なんだなぁ」じゃなくて
「うわあ、この人はC言語の仕様の流動的な部分に依存しない信用のおける人」だ

一方で、明示的なキャストが皆無に出来るほど、型やクラスが大量に作ってあるような
(その反面、根本改革は至難の技になる)コードは、CじゃなくてPASCAL系とかで書いた
ほうがいいんじゃないかという気がする。

というのは独り言

308:デフォルトの名無しさん
08/06/05 17:32:40
C++への移植のためにキャストは必要

309:デフォルトの名無しさん
08/06/05 17:36:42
キャストしたら負けかな、と思っている

310:デフォルトの名無しさん
08/06/05 17:49:44
>>307
>特定のコンパイラは文句を言わないだけで本当は必要なキャスト
具体例plz

311:デフォルトの名無しさん
08/06/05 17:59:54
少しでも心配だなと思うところには明示的にキャスト
そうじゃないところは面倒なのでスルー

そんな俺

312:デフォルトの名無しさん
08/06/05 18:29:04
char a = 2;
int b = a << 8;

こんな感じのプログラム書いてはまったことならあるな
格上げって処理系依存なんだっけ?

313:デフォルトの名無しさん
08/06/05 18:36:33
決まってるでしょ。
それでどんな風にはまったの?
その例じゃ出ないけど符号拡張?

314:デフォルトの名無しさん
08/06/05 18:37:12
規格では両オペランドが演算に先立って整数拡張されるはずだが。

315:デフォルトの名無しさん
08/06/05 18:43:32
両方ともunsinedで宣言してたかな?
VCだと512が求まるんだがとある環境だとキャストしないと0になった

316:デフォルトの名無しさん
08/06/05 19:04:06
なんか冷静に思い出してみると、16ビット環境で32ビットの計算をさせようとしてたのかも
typedefされてたのintじゃなくてlongだったような

勘違いスマソ >>312は忘れて下さい
そりゃキャスト必要だよな

317:デフォルトの名無しさん
08/06/05 19:17:05
基本型の型変換にはキャストに似た書式が使われるが、これはキャストとは言わないほうが
いいと思うような...
int m;
double d;
d=(double)m;

とかね。このコードをint変数をdouble変数にキャストするコードとは言わず、int値をdouble値に
型変換してアサインすると言って欲しい。本当は別の書式にしたいんだろうな。設計者は。

318:デフォルトの名無しさん
08/06/05 19:19:02
これは別に煽ってるとかじゃなくて本当に教えて欲しいんだけど
キャストと型変換はまったく違うものなのか?

319:デフォルトの名無しさん
08/06/05 19:25:43
C++ではいろいろ増やしたんだよね。型変換だとstatic_castかな。
dynamic_cast
static_cast
reinterpret_cast
const_cast


320:デフォルトの名無しさん
08/06/05 19:53:14
ビルトインの型変換(密かに関数が呼び出され、その関数が宣言されない)
を使う場合は、使う場所すべてに、わかるようにコメントを入れておくのが後々のことを考えると
ベターかと。(書式は一般的なキャスト演算子にするしかないが)
コンパイラが変るだけでも影響してくる可能性があるし...

321:デフォルトの名無しさん
08/06/05 20:11:45
c言語のスタックについての質問なんですが
int fibo_stack( int n )
{
int f =0;
push(n);
while(!empty())
{ n = pop();
if( n==0 ) f+=0;
if( n==1 ) f+=1;
if( n>=2 ) {push( n-1); push( n-2);};
show()
};
return f;
}
の振る舞いにつて説明する問題なのですが、f+=0やf+=1で何が行われているのか解りません。
スタック内部に影響するのでしょうか。ご教示ください。

322:デフォルトの名無しさん
08/06/05 20:13:40
f = f + 0;
f = f + 1;


323:デフォルトの名無しさん
08/06/05 20:13:51
f = f + 0
f = f + 1
の略

324:デフォルトの名無しさん
08/06/05 20:16:47
f = f + 0は理解してます。しかし、これがスタック内に影響があるのかが解りません。
説明不足ですいません

325:デフォルトの名無しさん
08/06/05 20:19:01
意味の分からないことをいわないでくださいおねがいします。

326:デフォルトの名無しさん
08/06/05 20:23:39
>317-318
本質的な動作は同じである。
キャストは型変換演算子であって、元の型の値をもとにして
指定したデータ型の右辺値を生み出す。ポインタかそうでないかは関係ない。
単に型変換という場合は、コンパイラによって自動的に行われるものを言う場合が多い。
たとえば>317のコードで言えば d=m; と書いた場合である。
(double) のキャストをつけようとつけまいと、コードのやることは変わらない。

327:デフォルトの名無しさん
08/06/05 20:27:00
自分の考えた振る舞いは
n=4の場合
4
_
3 2
3
3 1 0
3 1 f=0
3 f=1
_
2 1
2 f=2
_
1 0
1 f=2
_ f=3
となるのですがこのfが何なのか解りません

328:デフォルトの名無しさん
08/06/05 20:31:54
その関数だけ見せられてもわからん
全部貼れ

329:デフォルトの名無しさん
08/06/05 20:32:56
つーかこの関数おもいっくそ間違ってるんじゃねぇか?

330:デフォルトの名無しさん
08/06/05 20:32:57
>>328
これで全部です

331:デフォルトの名無しさん
08/06/05 20:36:22
関数の処理が正しいかどうかは知らんが
フィボナッチ数列ならf(0) f(1)は固定でいれなきゃじゃない?

332:デフォルトの名無しさん
08/06/05 20:36:25
>>330
なら答えはひとつしかない

「わからない」

fの値がなんになるかはnの値のほかpush()、pop()、empty()、show()の仕様に依存する
fの値がどう使われるかはこの関数を呼んだ場所のコードに依存する
つまりこの関数だけ見せられてfがなにものであるか答えられるわけがない

333:デフォルトの名無しさん
08/06/05 20:38:12
>>329
少なくともこのままコンパイルにかけたら構文エラーだな

334:デフォルトの名無しさん
08/06/05 20:38:51
>>327
それであってるし0から始まるフィボナッチ数列の四番目は3だからおk

335:デフォルトの名無しさん
08/06/05 20:45:03
push()は()内をプッシュ、
pop()はポップしてその値を返す、
empty()はタックが空かどうか判定する、
show()は現在のスタック内表示です


336:デフォルトの名無しさん
08/06/05 20:46:54
>>334
fはスタックとは別のところで計算されてると考えてよろしいんでしょうか?

337:デフォルトの名無しさん
08/06/05 20:47:18
int fibo_stack( int n )
{
vector<int> x;
int f =0;
x.push_back(n);
while(!x.empty()) {
n = x.back();
x.pop_back();
if( n==0 ) f+=0;
if( n==1 ) f+=1;
if( n>=2 ) {x.push_back( n-1); x.push_back( n-2);};
}
return f;
}

極普通のスタックだと思うのですが因縁つけてくる人が多いので
C++になっちゃいますが動くようにしました。
引き続きお答え願います

338:デフォルトの名無しさん
08/06/05 20:49:07
そこまでわかっててなぜわからんのかわからん

339:デフォルトの名無しさん
08/06/05 20:49:44
単にフィボナッチ数列というものを知らないのでは

340:デフォルトの名無しさん
08/06/05 20:55:23
このプログラムのfを足していく理由がわからないんです。
スタックを計算する上で必要な事なんでしょうか


341:デフォルトの名無しさん
08/06/05 21:03:35
fって言う時点でフィボナッチと関連あるとか想像付かないかな・・・
Wikipedia項目リンク

342:デフォルトの名無しさん
08/06/05 21:09:37
解りました!!fはn番目のフィボナッチ数を計算するためにあったんですね!!
ずっとスタック内に影響するものだと思ってました。
ありがとうございました。

343:デフォルトの名無しさん
08/06/05 21:10:51
なぜこれで正しく計算できるかまではわかったのかなー?
そこが意図のはずだが

344:デフォルトの名無しさん
08/06/05 21:11:56
>343
どっちかっつーと数学板の仕事だし…
実用でこんなタコなアルゴリズム書いたら殴られるわ

345:デフォルトの名無しさん
08/06/05 21:12:14
やってることは再帰と同じくらい効率悪いなw

346:デフォルトの名無しさん
08/06/05 21:14:47
スタックを使う理由がわからん

347:デフォルトの名無しさん
08/06/05 21:17:10
数学的な数列の再帰証明をプログラムに変換するために必要だったんだろう
こんなことやる意味がそもそもあるのかと思うけど

348:参考
08/06/05 21:28:29
再帰呼び出し関数で、フィボナッチ数列を計算するコードを定義した際にn=0,1の条件で関数が何回
呼ばれるかを計測するプログラム。奇しくもこれはフィボナッチ数列そのものを与えるという
トリック

unsigned int fib(unsgined int n){
static unsigned int m=0;
static unsigned int result=0;
if(m==0)
m=n;
if(n<=1)
result++;

else{

fib(n-1);
fib(n-2);

}
if(m==n)
return result;
}
(この関数は1回しか呼び出せないのがイタいが)

349:参考
08/06/05 21:33:06
mなんていらねぇな。
unsigned int fib(unsgined int n){
static unsigned int result=0;
if(n<=1)
result++;
else{
fib(n-1);fib(n-2);
}
return result;
}


350:デフォルトの名無しさん
08/06/05 21:33:08
当たり前って言えば当たり前の結果だよな

351:デフォルトの名無しさん
08/06/05 21:35:29
つーか、IT関連の授業教えてる先生ってこんなのばっかり出題してるのか?
大学院とか行って研究するやつなんてすくないんだからもうちょっと実用的
な問題だせよ。

昨日もBMPの読み込みとかなかったっけ?

352:デフォルトの名無しさん
08/06/05 21:40:15
この件については議論せずにスルーしような

353:デフォルトの名無しさん
08/06/05 21:46:10
>>326
キャストは左辺値にも出来ますが何か?
char *p;
void *q;

(char*)q=p;

354:デフォルトの名無しさん
08/06/05 21:48:42
フィボナッチ理解できない人間が結構いることに驚き

355:デフォルトの名無しさん
08/06/05 21:49:57
>>353
それはだめじゃないのか?

356:デフォルトの名無しさん
08/06/05 21:51:39
>>353
間違いである。少なくともANSI/ISO規格の保証する動作ではない。

357:デフォルトの名無しさん
08/06/05 22:00:43
固定長のフィールドからなるレコードを
fgetsした後にsscanfでバラバラにして
フィールド毎にprintfで表示したいんだが
うまくsscanfでバラせてないみたい・・・

AAAAA
BBB
CCCC
こうなって欲しい。

入力ファイル(固定長5、3、4の3フィールドからなる)
AAAAABBBCCCC



358:デフォルトの名無しさん
08/06/05 22:01:14
禁止しても、抜け穴が幾らでもありそうだな。

359:デフォルトの名無しさん
08/06/05 22:04:01
>>357
それって区切りになる文字が無いから失敗するんじゃないの?


360:デフォルトの名無しさん
08/06/05 22:04:15
>>357
sscanf(s, "%5s%3s%4s", a, b, c);
これで済まないのか?


361:デフォルトの名無しさん
08/06/05 22:06:17
>>342
だから>>331でフィボナッチだっつってんじゃん
関数名見ても分からないとか大丈夫か?

362:デフォルトの名無しさん
08/06/05 22:07:53
>>357
ばらせてるけどNULL終端じゃないから残りが出てるだけに5ペリカ

363:デフォルトの名無しさん
08/06/05 22:07:54
>>361
まーそういうなって。
初めてのころは「自分が何にはまってるかそれがわからない」
ということもあるよ。

あることをきっかけにどんどん進むのさ・・・

364:デフォルトの名無しさん
08/06/05 22:10:26
わかってないのに見当違いのレスつけてるヤツらよりはマシだけどな

365:デフォルトの名無しさん
08/06/05 22:10:34
>353

4.5
質問:charのポインタがあって、そのポインタがたまたまintを指していた。
intの次へポインタを進めたい。なぜ以下の式ではうまくいかないのか。

 ((int *)p)++;

回答:C言語でキャスト演算子は「ビット列が別の型を持っているふりをして、
そういう風に扱ってやろう」ということを意味しているわけではない。
キャストは変換演算子であって、それは右辺値を生みだすと定義されている。
右辺値であるとするなら、代入することも++で足し算することもできないことになる
(古いコンパイラやgccの拡張機能が上のような式を受け付けることは例外である)。

References: K&R2 §A7.5 p.205 / ANSI §3.3.4(とくに注14) / ISO §6.3.4 / Rationale §3.3.2.4 / H&S §7.1 pp.179-80

366:デフォルトの名無しさん
08/06/05 22:28:22
公開された定義に基づいて
再解釈可能なものについては再解釈し、そうでないものは絶対に通さないというのが
基本だったのだが...
いつのまにやら処理系に依存する話になってしまった。

367:デフォルトの名無しさん
08/06/05 22:55:01
こう書けばとおるが、
*(char**)&q=p;
そもそもvoid *へ/からの変換はキャストが不要なのでこの例なら
q=p;
でよい。

368:デフォルトの名無しさん
08/06/05 22:55:55
- キャストが不要なので
+ 明示的なキャストが不要なので

369:デフォルトの名無しさん
08/06/05 22:56:40
((struct hoge*)p)->fuga

370:デフォルトの名無しさん
08/06/05 22:58:00
**a と a[][] って、同じ?

371:デフォルトの名無しさん
08/06/05 22:58:40
仮引数でなら

372:デフォルトの名無しさん
08/06/05 23:00:54
仮引数でも違う。
というか、不完全型の配列型は存在しない。

373:デフォルトの名無しさん
08/06/05 23:01:33
コンパイルは通るよ。

374:デフォルトの名無しさん
08/06/05 23:02:23
通らんかった。二次元はダメか。

375:デフォルトの名無しさん
08/06/05 23:06:05
>>370
仮引数に限ってT**とT*[]は同じ。T[][]はT[]が不完全型だから許されない。

376:デフォルトの名無しさん
08/06/05 23:07:39
仮引数の[]は、識別子に最初に結合する一回だけポインタ扱い

377:デフォルトの名無しさん
08/06/05 23:20:18
>>369
-> の結果は左辺値になりうる。

378:デフォルトの名無しさん
08/06/06 00:04:07
多次元配列はC/C++の最もクサいところ。使わないでね。なるべく。
(普通の1次元配列を工夫して使って)

379:デフォルトの名無しさん
08/06/06 00:07:57
int main(int argc, char** argv)


int main(int argc, char argv[][])


380:デフォルトの名無しさん
08/06/06 00:08:46
>>379
悪い例ですね、わかります

381:デフォルトの名無しさん
08/06/06 02:21:47
メモリの動的確保とポインタについて勉強したのですが、
分からないところがあったので質問します

・mallocで確保したメモリは、プログラムの終了と同時に解放されることは保証されているのか
・関数内でmallocで確保したメモリは関数が終了しても解放されず、
 別の関数から参照できることは保証されているか

両方、正常に動くことは確認できたのですが、あらゆる環境・状態で成り立ちますか?

382:デフォルトの名無しさん
08/06/06 02:25:13
・プログラムが終了すれば解放はされる
・別の関数にアドレスを渡せばそりゃ参照できる

383:デフォルトの名無しさん
08/06/06 02:25:20
>>381
Cの規格では保証されてない、プログラム終了後の処理はOS頼み
ただし、間違いなく解放されると思って問題ない。(されないOSが昔あるにはあったが)

二番目は保証されてる、こっちはそう決まってる

384:デフォルトの名無しさん
08/06/06 02:27:49
関数からポインタを返すときって混乱しやすいところだよね。

385:デフォルトの名無しさん
08/06/06 04:34:47
あんまりC言語関係ないけど
#include <stdio.h>
#include <stdlib.h>
void main(){
int a[25];
int i,j;
for(i=0;i<25;i++){
a[i] = rand()%25+1;
for(j=0;j<i;j++){
if(a[j]==a[i]){
a[i] = rand()%25+1;
j=0;
}
}
printf("a[%d]は%dです。\n",i,a[i]);
}
}

↑のは
a[0]〜a[24に]1〜25の乱数を生成し、且つどれも一致しないというモノなんだけど
乱数が何度やっても決まった値しかでないんだけどどうすればいいのかな?
あと、j=0;とかやってたりソースかなり読みにくいので、訂正などあったらガンガンお願いしますmm

その際解説もつけてくれるとありがたいです

386:デフォルトの名無しさん
08/06/06 04:37:29
#include <time.h>

srand(unsigned)time(NULL));

を足す

387:デフォルトの名無しさん
08/06/06 04:37:53
括弧抜けた
srand((unsigned)time(NULL));


388:デフォルトの名無しさん
08/06/06 04:46:41
あー解説か…まあ細かい話はおいておいて
乱数発生させるには最初に種みたいなのが要るんだけど

srand((unsigned)time(NULL));
はプログラムを実行させた時の現在時刻を拾ってきて
それを種にするように設定する関数なわけ

>>385のプログラムだと何もして無いのでsrand(1);
と設定した事とみなされて
常に同じ乱数が生成されてるのよ

389:デフォルトの名無しさん
08/06/06 06:06:42
Cのプログラムの中で、
system("hoge")で起きたコマンドの結果を文字配列に格納したい場合、何かいい方法は無いですかね?
コマンドライン上ならls > fileで一発なのに・・・orz

390:側近中の側近 ◆0351148456
08/06/06 06:21:52
>>389
(っ´▽`)っ
popen, pclose
標準ライブラリ関数ではないが、unix系OSだと使える。

391:デフォルトの名無しさん
08/06/06 06:29:17
>>390
感謝。さっそく調べて試してみるっすー。

392:デフォルトの名無しさん
08/06/06 08:34:52
>>381
まあmallocも関数でvoid*ではあるけどポインタ返ってくるよね?

393:デフォルトの名無しさん
08/06/06 10:48:52
#include <stdio.h>
#include <float.h>
int main(void)
{ float f;
double x;
long double ld;
printf("\nTesting the precision of float, double, and long double : \n");
f = 1.0f + 1.0e-7;
printf(" 1.0 + 1.0e-7 = %.10f\n", f);
f = 1.0f + 1.0e-8;
printf(" 1.0 + 1.0e-8 = %.10f\n", f);
x = 1.0l + 1.0e-15;
printf(" 1.0 + 1.0e-15 = %.20lf\n", x);
x = 1.0l + 1.0e-16;
printf(" 1.0 + 1.0e-16 = %.20lf\n", x);
ld = 1.0L + 1.0e-19;
printf(" 1.0 + 1.0e-19 = %.30Lf\n", ld);
ld = 1.0L + 1.0e-20;
printf(" 1.0 + 1.0e-20 = %.30Lf\n", ld);
printf("\nThe experiment above is explained by constants from float.h :\n");
printf(" precision of float : %e\n", FLT_EPSILON);
printf(" precision of double : %.15le\n", DBL_EPSILON);
printf(" precision of long double : %.30Le\n", LDBL_EPSILON);
return 0; }
表示された結果のうち、
1.0 + 1.0e-7 が 1.0000001 にならず、同様に
1.0 + 1.0e-15 が 1.000000000000001 にならず、
1.0 + 1.0e-19 が 1.0000000000000000001 という、きれいな数にならない理由を、FLT_EPSILON, DBL_EPSILON, LDBL_EPSILON との関係から説明してもらえないでしょうか。
よろしくお願いします。

394:デフォルトの名無しさん
08/06/06 11:07:42
宿題丸投げは宿題スレへ

自分で考えるヒントが欲しいなら、まずそこに出てくる制限定数の意味やIEEE浮動小数点数フォーマットについて調べること

395:デフォルトの名無しさん
08/06/06 11:33:43
板違いごめんなさいッ
ありがとうございます。

396:デフォルトの名無しさん
08/06/06 12:42:40
問03
学科の出席簿作成。
15人分の学生を表示し、入力により内容を変動させる。

表示順番:
出席表
<入力>学生番号0〜14
<入力>曜日番号0〜6
<入力>時限番号0〜3
<入力>出欠番号0〜1


<入力>学生番号0〜14の時に99を入力するとプログラム終了。
誰かこの問題教えてください。

397:デフォルトの名無しさん
08/06/06 12:44:01
>>396
氏ね

398:デフォルトの名無しさん
08/06/06 12:59:39
>>396
/* stdio.h をインクルード */
int main(void)
{
  /* 必要な変数を宣言し、出席簿の初期値を設定 */

  /* 学生番号を入力から一時変数に取り込み、それが妥当な値である間、以下の処理を繰り返す */
  {
    /* 曜日を入力から一時変数に取り込み、もし妥当な値でなければエラーメッセージを表示して continue する */
    /* 時限を入力から一時変数に取り込み、もし以下略 */
    /* 出欠を入力から以下略 */
    /* 入力された一時変数の値を出席簿に反映する */
    /* 出席簿の現在の内容を表示する */
  }

  return 0;
}

399:デフォルトの名無しさん
08/06/06 13:02:11
>/* 学生番号を入力から一時変数に取り込み、それが妥当な値である間、以下の処理を繰り返す */
親切そうに見せて性格悪いなお前

400:デフォルトの名無しさん
08/06/06 13:23:10
出席簿のデータ構造くらいは教えてやったほうがよくね?

int book[15][7][4]={0};

まあcharにするほどのサイズではあるまい

401:デフォルトの名無しさん
08/06/06 13:23:58
日曜日に授業あんのかよ

402:デフォルトの名無しさん
08/06/06 13:25:40
たまに・・・・・

403:デフォルトの名無しさん
08/06/06 13:28:03
>398
必要な変数ってこれでいい?
データ形式:
(一人分のデータ)
学生番号<int>
名前<char*>
性別<char*>
曜日番号<int[]>
時限番号<int[]>
出欠番号<bool>
変更番号<bool>

404:デフォルトの名無しさん
08/06/06 13:30:25
Cにboolはありません

405:デフォルトの名無しさん
08/06/06 13:31:02
396のどこに名前と性別があるんだよ

406:デフォルトの名無しさん
08/06/06 13:32:38
じゃあ _Bool で

407:デフォルトの名無しさん
08/06/06 13:34:00
学生の名前も含めて構造体で表すなら
struct{
 char name[NAMELEN_MAX];
 int sex;
 int attend[7][4];
}student[15];
ってとこか

408:デフォルトの名無しさん
08/06/06 13:38:20
>>403
学生番号は不要。要素15の配列の添字で扱えば済む。
名前は動的割付するほど大きなデータじゃない。適当な大きさの配列で十分。
性別は整数でいい。男か女かそれ以外しかないのだから。
曜日、時限、出欠を別々に宣言しても意味がない。多次元配列を使え。
Cにbool型は無い。メモリを節約したいならchar型を使え。
変更番号ってなんだ説明しろ。

409:デフォルトの名無しさん
08/06/06 13:41:19
> char name[NAMELEN_MAX];
そこは NAMELEN_MAX+1 にしとけよ
一応

410:デフォルトの名無しさん
08/06/06 13:45:44
>>408
退学とかで、欠番の可能性は?

411:デフォルトの名無しさん
08/06/06 13:47:18
>>410
問題の前提が番号は0〜14まで15人ってなってる

412:デフォルトの名無しさん
08/06/06 13:47:40
そこで性別をenumですよ

413:デフォルトの名無しさん
08/06/06 13:48:43
>408
>名前は動的割付するほど大きなデータじゃない。適当な大きさの配列で十分。
初期化したあと変更しないならconstポインタのほうがいいんじゃね?

414:デフォルトの名無しさん
08/06/06 13:52:11
後出しの条件はともかく、まずは>398を作れ
話はそれからだ

415:デフォルトの名無しさん
08/06/06 14:03:48
入力はgetchar?99を入力するとプログラム終了ってどうやんだっけ?

416:デフォルトの名無しさん
08/06/06 14:06:50
本当はfgetsを使うんだがこのレベルの問題ならscanfでいいだろう

417:デフォルトの名無しさん
08/06/06 14:07:31
>>415
おいおいそこから教えなきゃいけないのかよ
もう一回最初から本を読み直せ

418:デフォルトの名無しさん
08/06/06 14:10:57
どうやんだっけ?じゃねーよw
素直に全く分かりませんって言えよ

419:デフォルトの名無しさん
08/06/06 14:14:51
すまぬがちょっと質問。

MinGWとVC++でDLL連携をしようと思って下記みたいなソース書いたんだ。
GeoOpen関数に「1」を渡してるのに
返ってくる値は何故か「63」。
printfで出力される値も「63」。
なんぞこれー


DLL作成側cpp(MinGW)
extern "C" __declspec(dllexport) int __stdcall GeoOpen(string strLicence, string strGeoDBDir, string strNormalize, int intA) {
printf("%u", intA);
return intA;
}

DLL呼び出し側cpp(VC++)
// GeoOpen関数のポインタ取得
GEOOPEN geoOpen = (GEOOPEN)GetProcAddress(hGEOCODERDLL, "GeoOpen@16");

int testInt = 1;
// GeoOpen関数のポインタ取得成功
if (geoOpen != NULL)
{
// GeoOpen関数呼び出し
int intRes = (*geoOpen)(strLicence, strGeoDBDir, strGeoDBDir, testInt);
}

420:デフォルトの名無しさん
08/06/06 14:15:34
エラーメッセージって表示しなきゃなんないのか?

421:デフォルトの名無しさん
08/06/06 14:17:05
>420
「そんなの問題に書いてないじゃないですか」で押し通せるならしなくていい
常識的にはする

422:デフォルトの名無しさん
08/06/06 14:17:13
>>419
MinGWとVC++のstd::stringの内部構造が異なるんじゃないのかたぶん

423:デフォルトの名無しさん
08/06/06 14:19:51
というか完璧スレ違い

424:デフォルトの名無しさん
08/06/06 14:28:13
>>422
試しにintを第一引数にしたらちゃんと1が返ってきたよ。
stringが邪魔してたのか、、、これは気づかなんだ。
サンキュー助かった。

>>423
あぁC++はスレチか。すまん


425:デフォルトの名無しさん
08/06/06 14:28:58
異なるコンパイラ、コンパイラが同じでもバージョンが違う場合、モジュール間でのクラス渡しは御法度。
クラスで渡したければCOM使うしかない。

426:デフォルトの名無しさん
08/06/06 14:35:16
COMってなんぞえー!?

427:デフォルトの名無しさん
08/06/06 14:37:39
C++つかわず、CだけでCOM(ActiveX)のプログラムするのは死ぬほど辛い

428:デフォルトの名無しさん
08/06/06 15:48:13
素直にポインタを使え

429:デフォルトの名無しさん
08/06/06 21:35:24
strtokを使ってカンマ区切りの文字列を分け、それぞれの文字配列に格納する関数を作ってるのですが、
関数の中で正常に表示される文字配列が、関数の外だと化けるんですよ!

何が原因なのでしょうか?お手上げです。どなたかどうか、教えてくださいm(_ _)m

430:デフォルトの名無しさん
08/06/06 21:36:24
ローカル変数を外に持ち出そうとしてるのか?

431:デフォルトの名無しさん
08/06/06 21:41:00
ソースうp

432:デフォルトの名無しさん
08/06/06 21:45:23
B木の話なんですが質問させてください、二分木でも同じと思いますが
ノードに入るkeyの値は自然数としています

現在の木に例えば3という値が入っているときにさらに3を挿入する場合は
すでに入っている3の手前と後ろのどちらに入れるかは決まっているんですか?

433:デフォルトの名無しさん
08/06/06 21:49:14
比較の仕方によるけど、だいたい後ろになるんじゃね?

434:デフォルトの名無しさん
08/06/06 21:54:38
>>430
文字配列はmainで宣言していて、関数の中では、char*型で引数宣言しています。

>>431
今携帯なので、うち帰ってからまたソースうpさせていただきますね。

すみません、また来ます。ありがとうございます。

435:デフォルトの名無しさん
08/06/06 21:57:55
>>434
たぶん、その引数のポインタにstrtokの戻り値を代入してるだけだろう?
ちゃんとstrcpyしろ

436:デフォルトの名無しさん
08/06/06 22:03:51
>434
こういうことをやってないかどうか

#include <stdio.h>
void hoge(char *str)
{
  str="STRING"; /* 間違い */
/* こっちが正解
  strcpy(str, "STRING");
*/
}

int main(void)
{
  char str[]="string";
  hoge(str);
  puts(str);
  return 0;
}

437:デフォルトの名無しさん
08/06/06 22:04:41
>>436
まてそれは大丈夫だろw

438:デフォルトの名無しさん
08/06/06 22:06:36
>>437
落ち着け

439:デフォルトの名無しさん
08/06/06 22:08:22
>>438
ごめんおちついた、ごめんなさい
mainみないで条件反射してしまいました・・・

440:デフォルトの名無しさん
08/06/06 22:10:46
435の解釈が妥当そう。
strtokの戻り値は次のstrtokの呼び出しで破壊されるから、
strdupしておくべし。


441:デフォルトの名無しさん
08/06/06 22:11:29
>440
お前も落ちつけよ

442:デフォルトの名無しさん
08/06/06 22:14:59
>strtokの戻り値は次のstrtokの呼び出しで破壊されるから
されんされん

443:385
08/06/06 23:01:23
>>386-388
なるほど、ありがとうございます

444:デフォルトの名無しさん
08/06/06 23:08:26
>>443
for(i=0; i<25; i++) {
j = rand() % (i + 1);
a[i] = a[j];
a[j] = i + 1;
}
こうやるとムダなチェックが必要なくなるよ

445:デフォルトの名無しさん
08/06/07 00:45:33
URLリンク(ytteter.so.land.to)

446:デフォルトの名無しさん
08/06/07 02:50:52
>>444
ぱっと見では、なんでうまくいくのか分からなかったけど面白い方法だ

447:デフォルトの名無しさん
08/06/07 03:23:54
わからん

448:デフォルトの名無しさん
08/06/07 03:49:22
確かに重複は回避できるけどシャッフルの度合いとしてはどうなんだろう……
前方にかたよる気がするが

449:デフォルトの名無しさん
08/06/07 04:56:54
シャッフルの度合いw
前方にかたよるw

450:デフォルトの名無しさん
08/06/07 08:03:17
もっといい擬似乱数がほしければメルセンヌ・ツイスターでも使えばいいよ。


451:デフォルトの名無しさん
08/06/07 09:00:24
>>448
くじ引きは最初と中間と最後のどこで引くのが有利だと思う?

452:デフォルトの名無しさん
08/06/07 09:08:43
>>451
商店街のクジ引きなら最後のほうw

453:デフォルトの名無しさん
08/06/07 09:12:39
>>452
当たりが1つで残りn個全部ハズレのクジとした場合、

1)引いたクジを戻す場合は常に確率は一緒
2)引いたクジを戻さない場合はそのときによる。

2)は最初に引く人はかなり確率は低いけど当たりも引ける。
後に引く人は当たりを引く確率は上がるが、最初に当たりを引かれると残りは
ハズレのみになる・・・・・

454:デフォルトの名無しさん
08/06/07 09:26:24
>>453
マジで言ってる?
2)の場合
1回目は 1/n
2回目は (n-1)/n*1/(n-1) = 1/n

最初から最後まで確率は一定だよ。


455:デフォルトの名無しさん
08/06/07 10:33:49
たぶん>>452
商店街とかだと当たりを前半に出すわけにはいかないから、
後半にしか入ってないことをいってるんだと思うぜwww

456:デフォルトの名無しさん
08/06/07 13:25:48
>>444のやり方はこのスレや宿題スレなんかではよく出る中身がある配列のシャッフル
for(i=0; i<N; i++) {
j = rand() % (i+1);
temp = a[i];
a[i] = a[j];
a[j] = temp;
}
と同じ理屈だろ。
これが偏ってるとか思うヤツはセンスないな。

>>450
擬似乱数の精度の話なんかしてない

457:デフォルトの名無しさん
08/06/07 13:30:52
>>454
それは違うな。
あらかじめ引く順番が決められてるなら(2)でも(1)と同じ確率になるが、
自分でいつ籤を引くか決められるなら、(1)とは異なった確率にできる。

たとえば当たり籤が一本しかなかったとして、
当籤が出るまでは誰かが籤を引くたびに当たり確率が高くなっていくが、
当たりが出た途端に当たり確率は0になる。

458:デフォルトの名無しさん
08/06/07 13:31:42
数学的な話か実際の話かの差だから論じても意味が無いと思うけど

459:デフォルトの名無しさん
08/06/07 13:53:49
>>456
マジレスすると、センスないのはお前だ。それは偏る。

<Proof>
N=3とすると、置換の可能性は3^2=27。
一方、3つの要素の並べ方は3!=6。
27/6は整数ではない。故に、偏る。q.e.d.

実際に列[0,1,2]に対して、6万回の試行をしてみると、
[0,1,2]:9063
[0,2,1]:10843
[1,0,2]:11236
[1,2,0]:11121
[2,0,1]:8719
[2,1,0]:9018
この程度のばらつきが出る。

数学的に考えれば、9000前後の数字が出ている列は、
それぞれ並べ替え方27のうち4を占めていて、
11000前後のはそれぞれ27のうち5を占めている。

正確にシャッフルしたければ、並べ替え方が6!のKnuthシャッフルを使うべし。

460:デフォルトの名無しさん
08/06/07 13:56:32
>>459
j = rand() % N;
じゃなくて
j = rand() % (i+1);
になってるんだよ

461:デフォルトの名無しさん
08/06/07 13:57:15
>>458
数学的には、確率を考えているか条件つき確率を考えてるかの違い。
数学vs実際の違いじゃないぞ。

462:デフォルトの名無しさん
08/06/07 14:01:54
暗号化に関する質問です

char str[] = hairetu //暗号化する文字列
int j = 0; //暗号化する文字列の現在位置

strとjが上記の場合

while(*(str+j) != ’\0’)

このwhileの条件ってどういう意味ですか
なぜ文字列に位置を示す数を加算できるのですか??

463:デフォルトの名無しさん
08/06/07 14:04:08
それのどこに暗号化が関係してるの?

464:デフォルトの名無しさん
08/06/07 14:07:01
暗号化のところで出てきたので暗号化特有の構文かと思ったわけです

465:デフォルトの名無しさん
08/06/07 14:07:19
>>459
恥ずかしいヤツw

466:デフォルトの名無しさん
08/06/07 14:08:02
>>462
配列はその先頭の要素を指すポインタになるから
char str[] = ... ;
char *p = str;
while (*(p + j) != '\0')
と書くのと同じ


次ページ
最新レス表示
スレッドの検索
類似スレ一覧
話題のニュース
おまかせリスト
▼オプションを表示
暇つぶし2ch

5031日前に更新/203 KB
担当:undef