トップページ⇒tech
1001コメント247KB

C言語なら俺に聞け(入門編)Part 66

■ このスレッドは過去ログ倉庫に格納されています
0001デフォルトの名無しさん2010/06/12(土) 19:36:52
C言語の*入門者*向け解説スレッドです。
★前スレ
C言語なら俺に聞け(入門編)Part 65
http://pc12.2ch.net/test/read.cgi/tech/1274976173/
★過去スレ
http://makimo.to:8000/cgi-bin/search/search.cgi?q=%82b%8C%BE%8C%EA%82%C8%82%E7%89%B4%82%C9%95%B7%82%AF&andor=AND&sf=0&H=&view=table&D=tech&shw=5000
★初心者、初級者の方は他の質問スレのほうが良いかもしれません。
例えば
【初心者歓迎】C/C++室 Ver.73【環境依存OK】
http://pc12.2ch.net/test/read.cgi/tech/1274395127/

とか
★教えて欲しいのではなく宿題を丸投げしたいだけなら
↓宿題スレ↓へ行ってください。
C/C++の宿題片付けます 136代目
http://pc12.2ch.net/test/read.cgi/tech/1274827528/
★C++言語については避けてください。C++対応明記スレへどうぞ
★分からない事をなるべく詳しく書いて下さい。
★ソースコードを晒すと答えやすくなるかもしれません。
  # 抜粋/整形厳禁、コンパイラに渡したソースをそのまま貼ること
  # サイズが大きい場合は宿題スレのアップローダ等を利用してください
★開発環境や動作環境も晒すと答えが早いかもしれません。
★質問者は最初にその質問をした時のレス番号を名前欄に書いて下さい。
0232デフォルトの名無しさん2010/06/18(金) 21:47:40
おい馬鹿教えるなよ
0233デフォルトの名無しさん2010/06/18(金) 21:50:04
>>231
どういう事ですか?
0234デフォルトの名無しさん2010/06/18(金) 22:01:57
>>233
関数・変数などの全ての識別子は、そのソースファイルにおいて最初に*使われる*までに
宣言されている必要がある。

例えば、以下のソースをコンパイルすると、そのメッセージがでる。
---ここから---
void foo() { x = 5; }
int x;
int main(void) { return 0; }
---ここまで---

1: error: ‘x’ undeclared (first use in this function)

これは1行めで変数xが*使われて*いるにも関わらず、この時点ではxの宣言がなされていないことを
意味する。
2行めのxの宣言を1行めより先に書けばエラーにならない。

---ここから---
int x;
void foo() { x = 5; }
int main(void) { return 0; }
---ここまで---

この場合は、xは同じファイルで定義されているが、別のファイルで定義されている場合も
宣言は必要。そのときは、以下のように書く。

extern int x;




0235デフォルトの名無しさん2010/06/18(金) 22:04:00
意味がわからない
他の人説明してくれませんか?
0236デフォルトの名無しさん2010/06/18(金) 22:04:24
使う前に宣言してください。
0237デフォルトの名無しさん2010/06/18(金) 22:10:50
>>235
ソースコードとerror: ‘hoge’ undeclared (first use in this function)のhogeを晒せや
0238デフォルトの名無しさん2010/06/18(金) 22:17:04
>>237
ソースコードさらしたら別にエラー内容なんていらんだろ
0239デフォルトの名無しさん2010/06/18(金) 22:23:58
>>238
よく分からんマクロとかかも知れんだろ
0240デフォルトの名無しさん2010/06/18(金) 22:27:23
ふつうソースコードなんて晒せないだろ
家にソースを持って帰ったり会社で2chにアクセスできたりするクソ会社じゃあるまいし
0241デフォルトの名無しさん2010/06/18(金) 22:28:26
>>240
え?意味が分からない
0242デフォルトの名無しさん2010/06/18(金) 22:37:10
>>235が業務用のプログラムをいじってるなら怖いな
0243デフォルトの名無しさん2010/06/18(金) 22:37:47
エラーの内容から判断してこいつは学生だってわかるだろ
変数の宣言忘れてエラーの意味もわからないプロがいたら怖いわ
0244デフォルトの名無しさん2010/06/18(金) 22:45:11
>>240
どう考えても仕事絡みの質問じゃないだろ
0245デフォルトの名無しさん2010/06/18(金) 22:48:34
学生とは限らんだろ
0246デフォルトの名無しさん2010/06/18(金) 23:01:29
そうだな趣味かもしれないしな
0247デフォルトの名無しさん2010/06/18(金) 23:22:16
友愛数のペアを出力するプログラムを作ってみました

自分の思いつく限りの事はしたのですが、これ以上に速くなりますか?
ご指摘お願いします。

http://codepad.org/u2IDYxvs
0248デフォルトの名無しさん2010/06/18(金) 23:32:41
n/mが複数回出てくるけどこういうのはコンパイラが取り計らってくれるのだろうか。
0249デフォルトの名無しさん2010/06/18(金) 23:33:54
こんなスレで質問するって職業プログラマじゃないだろ
普通、職業プログラマなら職場のよくわかっている奴に聞くだろ
0250デフォルトの名無しさん2010/06/18(金) 23:35:49
意外に聞かないわ
0251デフォルトの名無しさん2010/06/18(金) 23:36:48
職場によくわかってない奴がいっぱいいるから?
0252デフォルトの名無しさん2010/06/18(金) 23:37:27
>>248
どういう意味ですか?
0253デフォルトの名無しさん2010/06/18(金) 23:39:48
>>247
なんでここまで遅くできるのかわからんw

普通に約数の和を関数化して戻り値と引数を比較すればいいのに
0254デフォルトの名無しさん2010/06/18(金) 23:40:28
職業プログラマじゃないと質問してはいけないんですか?
0255デフォルトの名無しさん2010/06/18(金) 23:40:36
n/mの結果を一度変数に入れてその変数を使い回したらって、ことじゃ
0256デフォルトの名無しさん2010/06/18(金) 23:45:24
なるほど!
こういう事ですね


http://codepad.org/RI5MDSCC


それ以外にはありますか?
0257デフォルトの名無しさん2010/06/18(金) 23:49:39
#include <stdio.h>

int divsum(int n)
{
int sum = 1, i;

for(i = 2; i * i < n; i++) if(n % i == 0) sum += i + n / i;

return i * i == n ? sum + i : sum;
}

int main(void)
{
int i, j, c = 0;

for(i = 220; i < 1000000; i++) {
if((j = divsum(i)) <= i) continue;
if(i == divsum(j)) {
printf("%d %d\n", i, j);
c++;
} }

printf("%d\n", c);

return 0;
}
0258デフォルトの名無しさん2010/06/18(金) 23:57:47
友愛数を配列に保存して比較するのは意味がなくて無駄
0259デフォルトの名無しさん2010/06/19(土) 00:06:09
作り変えちゃったか。仕方のないことかもな。
0260デフォルトの名無しさん2010/06/19(土) 00:08:05
>>257
凄いですね・・・。
以前に作った事がありますか?

>>258
自分の作ったプログラムだと、
それが無いと同じペアを2回表示する事になるので・・・。
0261デフォルトの名無しさん2010/06/19(土) 00:10:57
>>260
多分自分でそこまで作るのにあれこれ苦労したと思うんだけど、その苦労が経験となり、身につく。
おつかれさま。
0262デフォルトの名無しさん2010/06/19(土) 00:20:15
>>260
if(n < s) があるから、同じの2回表示されないと思うけど。
0263デフォルトの名無しさん2010/06/19(土) 00:23:58
>>262
ありがとうございます
0264デフォルトの名無しさん2010/06/19(土) 00:32:58
>>260 もう少し高速化
#include<stdio.h>

long calc_yuai(long value){
long i, j, yuai=1, tmp, sum, value_org;

value_org=value;
for(i=2;value/i>=i;i++){
sum=1;
tmp=1;
for(j=0;value%i==0;j++){
value/=i;
tmp*=i;
sum+=tmp;
}
yuai*=sum;
}
if(value>1) yuai*=(value+1);
return yuai-value_org;
}

int main(void){
long i, yuai;

for(i=2;i<1000000;i++){
yuai=calc_yuai(i);
if(i<yuai && calc_yuai(yuai)==i){
printf("%ld %ld\n", i, yuai);
}
}
return 0;
}
0265デフォルトの名無しさん2010/06/19(土) 00:41:58
一応プロだけど同僚よりGoogleとMSDNに聞いた方が速くて確実だわ
0266デフォルトの名無しさん2010/06/19(土) 00:44:58
ふーん
0267デフォルトの名無しさん2010/06/19(土) 01:05:41
>>264
速いな
今度からこれ使うことにしよう
0268デフォルトの名無しさん2010/06/19(土) 07:07:03
自演乙
0269デフォルトの名無しさん2010/06/19(土) 07:35:38
横からだけど、アルゴリズムの出典があったらおながいします。
ぐぐったけど互除法の変形とも違うし何やってるんだ、これ?
0270デフォルトの名無しさん2010/06/19(土) 07:41:15
(1 + a + a^2 + ... + a^m) * (1 + b + b^2 + ... + b^n)
= 1 + a + ... + a^m + a * b + a^2 *b + ... + a^m * b + .... + a^m * b + ... a^m + b^n
0271デフォルトの名無しさん2010/06/19(土) 07:42:35
= 1 + a + ... + a^m + b + a * b + a^2 *b + ... + a^m * b + .... + b^n + a * b^n + ... a^m + b^n
だった
0272デフォルトの名無しさん2010/06/19(土) 07:43:38
また違った。
最後はa^m * b^nだ。
0273デフォルトの名無しさん2010/06/19(土) 08:57:21
>>269
アルゴリズム名は知らないけど、例えば220の約数は1,2,4,5,10,11,20,22,44,55,110。
1を無視して、両端から数字をひとつづつ取って掛け合わせると、以下のように220になる。
2*100=220
4*55=220
5*44=220
10*22=220
11*20=220

約数の和sumを得るためには、a=2,3,4,5,6,...で割ってみるが、
割りきれたらsum=sum+a+220/a
a<=220/aの間、aをカウントアップして割りきれるか試す。
それ以上続けても、既に見つけた約数しかないので、無駄になるから計算しない。
0274デフォルトの名無しさん2010/06/19(土) 08:59:05
>>273
X:2*100=220
○:2*110=220
02752692010/06/19(土) 10:36:30
>>273
理解しました!

>>270
言いたいことはたぶん理解しました!
0276デフォルトの名無しさん2010/06/19(土) 10:47:13
アホだw
0277デフォルトの名無しさん2010/06/19(土) 10:51:18
>>264のアルゴリズムを聞いてたんじゃないの?
>>273の説明は全然関係ないと思うんだが。
0278デフォルトの名無しさん2010/06/19(土) 11:26:10
>>277
だから、>>264のアルゴリズムのfor(j=0以降は
>>270がヒントになってると思いますよ?
0279デフォルトの名無しさん2010/06/19(土) 11:28:53
だから、>>273関係ないじゃんwってことなんだけど
0280デフォルトの名無しさん2010/06/19(土) 11:33:28
俺がアホだwと煽られるのは結構だけど、
>>273が叩かれる筋合いはないのでは?
>>273の説明のおかげで>>264のiのforループも理解し易くなると思うんだが。
0281デフォルトの名無しさん2010/06/19(土) 11:42:27
素因数分解したときに
1210=2^1*5^1*11^2
であるとき
全ての約数の和は
(2^0+2^1)*(5^0+5^1)*(11^0+11^1+11^2)=2394
ここから元の数を引けば
2394-1210=1184
となる
0282デフォルトの名無しさん2010/06/19(土) 11:57:50
>>280
じゃあ遠慮なく・・・アホ!
0283デフォルトの名無しさん2010/06/19(土) 12:06:30
関係ない説明すれば、煽られても仕方ないだろ
0284デフォルトの名無しさん2010/06/19(土) 12:10:10
数学的な解方をそのままプログラムに置き換えると効率が悪いから、
コンピューターの性質を踏まえた上でもう一工夫するんだよ
0285デフォルトの名無しさん2010/06/19(土) 12:18:58
今の女子って、正直、生理的に汚いよね。
0286デフォルトの名無しさん2010/06/19(土) 12:54:11
はい
0287デフォルトの名無しさん2010/06/19(土) 13:39:32
度々世話になります

#define RAKKA_SPEED 8.0
#define BLOCK_TATE 32.00

(略)
double rakka_calc=BLOCK_TATE/RAKKA_SPEED;

(略)
board[i][j][2][player_flag]+=double(rakka_calc*rakka_flag[player_flag]+shot_calc*shot_flag[player_flag]);


で計算が上手くいかないというか、
rakka_calkの値の小数点以下が計算されてないみたいで、
どうすれば小数点以下を反映できますか?

board[][][][]をdouble宣言ってのはなしの方向で。
0288デフォルトの名無しさん2010/06/19(土) 14:01:46
なしの方向なら答えもなし
0289デフォルトの名無しさん2010/06/19(土) 14:04:50
>>287ですが解決しました、ありがとうございました
0290デフォルトの名無しさん2010/06/19(土) 14:45:17
いまどき、C言語のコンソールアプリの求人ってあるの?
0291デフォルトの名無しさん2010/06/19(土) 15:07:38
ない
0292デフォルトの名無しさん2010/06/19(土) 17:05:28
質問です。
穴掘り法で迷路を作成しようとしたのですが、参考にしたソースと同じ様に動かすつもりで
書いたのに、なぜか、掘られていない穴が残ってしまいます。
ソースを載せますので、自分のソースのどこに問題があるのか教えてください。
参考にしたもの
ttp://codepad.org/9iaa2YAs
自分で書いたヤツ
ttp://codepad.org/DYLuK5Ca

よろしくお願いします。
02932922010/06/19(土) 17:08:18
すいません。掘られていないのは穴ではなくて、壁でした//
0294デフォルトの名無しさん2010/06/19(土) 17:19:02
そこで穴があったら入りたいとか言っとけよ
0295デフォルトの名無しさん2010/06/19(土) 17:19:26
アッー!
0296デフォルトの名無しさん2010/06/19(土) 18:44:21
穴があったら入れたい
0297デフォルトの名無しさん2010/06/19(土) 21:57:15
穴があったら塞ぎたい
0298デフォルトの名無しさん2010/06/19(土) 23:56:17
>>264
前後もコードもちゃんとみてないんで、
何するコードか分からんのだけど、
jをインクリメントしてんの、何で?
0299デフォルトの名無しさん2010/06/20(日) 00:01:48
>>298
途中で書き直した名残
j はいらない
0300デフォルトの名無しさん2010/06/20(日) 00:32:45
jを使って等比級数の公式利用して
for(j = 1; value % i == 0; j++, value /= i);
yuai *= (pow(i, j) - 1) / (i - 1);
とか書くと笑えるくらい遅くなるなw
0301デフォルトの名無しさん2010/06/20(日) 00:53:01
for(i = 2; i * i <= n; i++) {
for(j = 1; n % i == 0; j = j * i + 1) n /= i;
yuai *= j;
}
これなら計算回数変わらずに変数節約できる
0302デフォルトの名無しさん2010/06/20(日) 01:45:17
プロプライエタリなライブラリを一部で呼び出してるソースコードを、GPLとして公開することは合法ですか?
具体的にはフォトショップSDKで書いたプラグインです。
03033022010/06/20(日) 01:48:44
BSDとして公開することは合法ですか?
0304デフォルトの名無しさん2010/06/20(日) 02:16:54
GPLは無理だったような
BSDは別にいいんじゃないかな
0305デフォルトの名無しさん2010/06/20(日) 02:37:28
GPL違反ではあるけど、法的にはグレーじゃないっけ?
まぁあえて危ない橋渡る人が居ないだろうけど。
0306デフォルトの名無しさん2010/06/20(日) 06:10:19
>>292
http://codepad.org/v5IiMN8I
/* これ */
03072922010/06/20(日) 10:56:53
>>306
ですね。
デバッグするっていうのはなかなか難しいです。
ありがとうございました。
0308デフォルトの名無しさん2010/06/20(日) 11:59:40
>>307
たいしたこと教えてないからお礼はいらないよ
0309デフォルトの名無しさん2010/06/20(日) 14:40:40
>>308
お礼?ふざけんな
2chでちょっと投稿したからと言って何かもらえるという考えは甘い
0310デフォルトの名無しさん2010/06/20(日) 14:44:44
回答者でもないのに毎回お礼に反応する頭のおかしい人が常駐してるからなw
0311デフォルトの名無しさん2010/06/20(日) 14:48:24
>>307
いえいえ
0312デフォルトの名無しさん2010/06/20(日) 18:01:02
VC++ 2008です

いったんプログラムを止めて
エンターキーを1回押して再開させたいのですが

fprintf(stdout,"Push Enter\n");
getchar();

と書いたらエンターキーを2回押さないと再開しません
仕方ないのでしょうか?
0313デフォルトの名無しさん2010/06/20(日) 19:51:08
>>311
どうもどうも
0314デフォルトの名無しさん2010/06/20(日) 20:37:23
getch()の結果が\nか判定
03153122010/06/20(日) 23:50:26
while(getch()!=10);

でいいのでしょうか?
これにするとエンターを何回押しても進みません。

エンター1回で進むようにする方法はないのでしょうか?
0316デフォルトの名無しさん2010/06/21(月) 01:03:01
#include <stdio.h>
#include <conio.h>

int main(void)
{
  puts("before");
  while(getch() != '\r'){
  }
  puts("after");
  return 0;
}
0317デフォルトの名無しさん2010/06/21(月) 01:16:40
>>312
俺の環境だと、その書き方でenter一回押したら再開されるんだが。
03183122010/06/21(月) 01:32:11
できました。
2回押さなければ進まなかった原因は
他の関数で入力待ちしている部分があったためでした。
ありがとうございました。
0319デフォルトの名無しさん2010/06/21(月) 01:33:09
>>318
いいよ別に
0320デフォルトの名無しさん2010/06/21(月) 21:59:08
int a = ( int )( 3 * 1.0f );

aは3であることが保証されるのでしょうか??
浮動小数点数は誤差とか怖いので気になりました・・・
0321デフォルトの名無しさん2010/06/21(月) 22:07:10
>>320
保険をかけるなら四捨五入すべし
0322デフォルトの名無しさん2010/06/21(月) 23:11:17
普通の浮動小数点数なら整数は(表現可能精度内でなら)誤差なしに表現できるので、
一旦循環小数や精度オーバーを経由して
整数に戻ってくるような演算でない限り、誤差は発生しない
(Cの規格で保証されているわけではないが)
0323デフォルトの名無しさん2010/06/21(月) 23:16:30
0.5足しとけばいいじゃん
0324デフォルトの名無しさん2010/06/21(月) 23:42:00
>>320
誤差が出るのは小数点イカでゲソ
0325デフォルトの名無しさん2010/06/21(月) 23:45:07
>>320
http://ja.wikipedia.org/wiki/%E5%BA%8A%E9%96%A2%E6%95%B0%E3%81%A8%E5%A4%A9%E4%BA%95%E9%96%A2%E6%95%B0#C.E8.A8.80.E8.AA.9E.E3.81.AE.E6.BC.94.E7.AE.97.E5.AD.90_.28int.29
03263202010/06/21(月) 23:46:34
みなさん、ありがとうございます。
>>320のケースは大丈夫なようですが、大事をとって0.5f足してからの丸め(四捨五入)をする方針でいくように
したいと思います。
0327デフォルトの名無しさん2010/06/21(月) 23:47:20
>>326
round 使ったほうがいいかも
0328デフォルトの名無しさん2010/06/22(火) 00:16:01
>>326
0.5f足して四捨五入しちゃだめー
0329デフォルトの名無しさん2010/06/22(火) 00:34:01
>>328
ああああわわわてててるななな
0330 ◆Jo8oQAGh3M 2010/06/22(火) 01:34:54
3次元の実数ベクトルを、要素がfloat型で要素数3の配列を用いて表すものとする。
二つの3次元ベクトルに対して、それらの和を求める関数を定義する。
和を計算する関数はaddvec関数定義の頭部は
void addvec(const float x[3], const float y[3], float z[3])とする。
プログラムの動作は、二つの3次元ベクトルaとbの各成分を順次に入力して、それらの和を求めて出力する。

というものをつくりたいです、そこで
#include <stdio.h>

void addvec(const float x[3], const float y[3], float z[3])
{
int i;
for(i = 0; i < 3; i++) z[i] = x[i] + y[i];
}
これに続くmain関数を作りたいのですがどうすればいいのかわからないので教えてください。


int main (void)
{
float x1,y1,z1,x2,y2,z2;

puts("各成分を入力してください.");
printf("ベクトルa:"); scanf("(%d,%d,%d)", &x1, &y1, &z1);
printf("ベクトルb:"); scanf("(%d,%d,%d)", &x2, &y2, &z2);

printf("和%d \n", addvec(わからない));
return (0);
}
上のように作ろうとしたのですが、どうも的外れな気がして…
0331デフォルトの名無しさん2010/06/22(火) 02:12:27
#include<stdio.h>

void addvec(const float a[3], const float b[3], float c[3])
{
int i;
for(i = 0; i < 3; i++) c[i] = a[i] + b[i];
}

int main (void)
{
float a[3], b[3], c[3];//x,y,z成分

puts("各成分を入力してください.");
printf("ベクトルa:"); scanf("%f %f %f", &a[0], &a[1], &a[2]);
printf("ベクトルb:"); scanf("%f %f %f", &b[0], &b[1], &b[2]);
addvec(a, b, c);
printf("a+b:%f, %f, %f\n",c[0], c[1], c[2]);
return (0);
}
■ このスレッドは過去ログ倉庫に格納されています