|
Name: a.k.a.dRESSING ..ぴよぴよ(317ポイント)
Date: 2006/12/14(木) 21:37
No:2776
|
|
Title: BCC Developer のエラーについて
|
|
BorlandC++ Compiler 5.5の使い方で
@ BCC Developer のメニューから[プロジェクト]→[メイク]を選択。
エラーが起きなければ実行するためのソフトがこれで作成されます。
エラーがあった場合は画面下のウインドウにエラー内容が出てきます
ので指示にしたがって修正してください。
A 次に[実行]→[実行]を選択してソフトを起動します。
まで手順通りに行いましたが、
エラー E2209 C:\Documents and Settings\裕樹\デスクトップ\bccdev1221\裕樹\test\DrawPixel.cpp 1: インクルードファイル 'DxLib.h' をオープンできない
エラー E2141 C:\Documents and Settings\裕樹\デスクトップ\bccdev1221\裕樹\test\DrawPixel.cpp 3: 宣言の構文エラー
というのが出てきて実行できません。どうすればいいのでしょうか?お願いします
317ポイント を手に入れた。
|
|
|
|
Name: box ..上級者(20,501ポイント)
Date: 2006/12/14(木) 22:14
No:2778
|
|
Title: Re:BCC Developer のエラーについて
|
|
> エラー E2209 C:\Documents and Settings\裕樹\デスクトップ\bccdev1221\裕樹\test\DrawPixel.cpp 1: インクルードファイル 'DxLib.h' をオープンできない
作成しようとしているプログラムがインクルードしている
ヘッダーファイルが、Borland C++ Compilerの環境に
含まれていない、ということです。
もしかすると、Microsoftの開発環境で作成することを
前提としているプログラムなのかもしれません。
> エラー E2141 C:\Documents and Settings\裕樹\デスクトップ\bccdev1221\裕樹\test\DrawPixel.cpp 3: 宣言の構文エラー
DrawPixel.cppの3行目に何らかの文法エラーがある、ということです。
89ポイント を手に入れた。
|
|
|
|
|
Name: バグ ..上級者(15,599ポイント)
Date: 2006/12/14(木) 23:07
No:2788
|
|
Title: Re:BCC Developer のエラーについて
|
|
BCC用のDXLibファイルでないとか、プロジェクト内にヘッダーファイルが登録されてない可能性もありますね。
2倍のポイントを手に入れた! 98ポイント を手に入れた。
|
|
|
|
|
Name: 管理人 [URL] ..ハッカー(129,501ポイント)
Date: 2006/12/14(木) 23:21
No:2789
|
|
Title: Re:BCC Developer のエラーについて
|
|
バグさん、お久しぶりです^^
>BCC用のDXLibファイルでないとか・・
そうですねぇ、、しかしオープンできないとなると、それ自体ないような気もします。
・フォルダ内にヘッダファイルがあるか
・Bcc用とVS用の2種類のものがありますので、Bcc用のものをきちんとダウンロードしているか
確認してみてください。
110ポイント を手に入れた。
|
|
|
|
Name: ジミー ..ぴよぴよ(120ポイント)
Date: 2006/12/14(木) 15:39
No:2761
|
|
Title: 再帰関数ノ使い方がよくわかりません。
|
|
Q、再機呼び出しを利用して、1から7までの階乗を表示するプログラムを作成せよ。
という問題なのですが、よくわかりません。
どういったプログラムをつくればよいのか教えて下さい。
ちなみに、表示例は、、
1!=1
2!=2
3!=6
4!=24
5!=120
6!=720
7!=5040 です。
よろしくおねがいします。
120ポイント を手に入れた。
|
|
|
|
Name: box ..上級者(20,412ポイント)
Date: 2006/12/14(木) 15:56
No:2763
|
|
Title: Re:再帰関数ノ使い方がよくわかりません。
|
|
階乗の定義より、
0! = 1
n! = n * (n-1)! (ただし、nは1以上)
です。
これに従って、どんな関数を作ればよいか考えてみてください。
nの階乗を計算するために、1つ小さい数の階乗を必要としている、
ここが再帰関数のキモです。
62ポイント を落としてしまった。
|
|
|
|
|
Name: 管理人 [URL] ..ハッカー(127,693ポイント)
Date: 2006/12/14(木) 16:14
No:2764
|
|
Title: Re:再帰関数ノ使い方がよくわかりません。
|
|
再帰関数はどんなものか最初は難しいと思うので、
入力した値までの自然数の和を求めるプログラムをここに紹介します。
#include <stdio.h>
int calc(int n){
if (n > 1) return(n + calc(n - 1));
else return 1;
}
int main(void){
int x;
scanf("%d",&x);
printf("%dまでの自然数の和 = %d\n", x, calc(x));
return 0;
}
ここで「2」と入力した時に「3」と表示されるまでのアルゴリズムを追ってみてください。
しかし再帰関数はアルゴリズムを追わなくても作ることが出来るすばらしい関数です。
つまり
nまでの自然数の和というのは、
n + ○
を何度も繰り返した合計の値で、○には「n-1」が入ります。
nの値は呼ばれるたびに1ずつへっていき、結局nから1まで全て足し合わせることになります。
途中にprintfをはさめばどう処理が進んでいるのかわかります。
2を引数に呼ばれたcalc関数は
n=2から始まります。
2は1より大きいのでif文にはいります。
int calc(int n){
if (n > 1) return(n + calc(n - 1));
else return 1;
}
ここで
return (2+calc(1));
となってまたcalc関数が呼ばれます。
n=1となりcalc関数が始まります。
1は1より大きくないのでelseに入ります。return 1より1が帰ります。
関数は呼んだところにかえりますから
return (2+calc(1));
のcalc(1)の部分が1になりますね。つまりreturn (2+1);となります。
だから結局返る値は「3」!
わかりますか?
200ポイント を手に入れた。
|
|
|
|
|
Name: 管理人 [URL] ..ハッカー(128,581ポイント)
Date: 2006/12/14(木) 16:38
No:2767
|
|
Title: Re:再帰関数ノ使い方がよくわかりません。
|
|
4までの自然数の和を求めるために、4を引数にしてこの関数を呼んだとすると、
4を引数に呼ばれたcalc関数は
n=4から始まります。
4は1より大きいのでif文にはいります。
int calc(int n){
if (n > 1) return(n + calc(n - 1));
else return 1;
}
ここで
return (4+calc(3)); ☆1
となってまたcalc関数が呼ばれます。
n=3となりcalc関数が始まります。
3は1より大きいのでまたif文に入り、
return (3+calc(2)); ☆2
となってまたcalc関数が呼ばれます。
n=2となりcalc関数が始まります。
2は1より大きいのでまたif文に入り、
return (2+calc(1)); ☆3
となってまたcalc関数が呼ばれます。
n=1となり、calc関数が始まります。
1は1より大きくないのでelseに入ります。return 1より1が帰ります。
関数は呼んだところにかえりますから
この関数が最後に呼ばれたところは☆3ですから
return (2+calc(1));
のcalc(1)の部分が1になりますね。
つまりreturn (2+1);で「3」が返ります。★2
この関数が最後から2番目に呼ばれたところは☆2ですから
return (3+calc(2));
のうち、さきほど★2からcalc(2)は「3」であることがわかったので、
☆2の返り値は結局return (3+3)つまり「6」になります。★1
この関数が最後から3番目に呼ばれたところは☆1でした。
return (4+calc(3));
このうちcalc(3)は★1より「6」でしたから
return (4+6)となり結局10です。
この関数が呼ばれたのは最初ですから、最終的に呼ばれたところに返る値は「10」です。
つまり4+3+2+1の計算が出来たことになります。
しかし、こんな風に処理を追ってたんじゃ、面倒でしかたありません。
そこでソースを見直すと、定義通りに式を書けば、すんなりそのまま処理が行われていることがわかります。
int calc(int n){
if (n > 1) return(n + calc(n - 1));
else return 1;
}
自然数の和は1よりも大きな数がある時、その一つ下の値を足し合わせていった数字です。
式を書けば、アルゴリズムを追わなくても、勝手に計算をやってくれる。
それが再帰関数の利点です。
では、階乗を求めるには?
自然数を求めるためにはこのように書きました。
******自然数の和*******
int calc(int n){
if (n > 1) return(n + calc(n - 1));
else return 1;
}
自然数の和は1よりも大きな数がある時、その一つ下の値を足し合わせていった数字です。
******階乗計算*********
int calc(int n){
if ****;
else ****;
}
階乗は0よりも大きな数がある時、その1つ下の値とかけあわせていった数字です。
このように比べたらどのように変更を加えたらいいかわかりますね。
713ポイント を手に入れた。
|
|
|
|
|
Name: ジミー ..ぴよぴよ(0ポイント)
Date: 2006/12/16(土) 03:56
No:2839
|
|
Title: 返信おくれてすみません。一通り読ましてもらいました。
|
|
とても丁寧で親切な回答、どうもありがとうございます。
C言語が不得意な私でも、一応理解することができました。
わがままですみませんが、calc関数という関数は習っていないので、
できれば違う形でひょうげんしたいのですが。
何関数を使えば良いですか?
129ポイント を落としてしまった。
|
|
|
|
|
Name: box ..上級者(22,460ポイント)
Date: 2006/12/16(土) 07:36
No:2840
|
|
Title: Re:返信おくれてすみません。一通り読ましてもらいました。
|
|
> 何関数を使えば良いですか?
関数の名前は、その関数の機能を端的に表現したものに
するのがよいでしょう。
名前は、その関数を作成する人が考えて付けるものです。
習っているかいないかという話ではありません。
今回の例は、「何かの計算をする」という意味で、
「計算する」の英単語(calculate)を省略した「calc」という
名前を付けていたのです。
108ポイント を手に入れた。
|
|
|
|
|
Name: ジミー
Date: 2007/01/08(月) 13:57
No:27611168232272
|
|
Title: Re:返信おくれてすみません。家のインターネットの調子が悪くてとうとう年を越してしまいました。
|
|
どうもありがとうございました。
宿題のほうは、無事に提出できました。
また、よろしくお願いします。
|
|
|
|
Name: メントス ..ぴよぴよ(50ポイント)
Date: 2006/12/15(金) 11:36
No:2812
|
|
Title: 画像の質問です。
|
|
初めて投稿します。よろしくお願いします。
C言語の質問ではないんですけど、いいでしょうか。
もしふさわしくなかったら投稿を消してください。
いつも掲示板を拝見しています。
上の C言語何でも質問掲示板 と書かれた画像がここの掲示板に来るたびに変わると思うのですが
これはどういう風にプログラムされてらっしゃるんでしょうか?
ソースを拝見しても、そのような記述が見当たらず・・。
もしよければこの技術を私のHPでも使わせてもらいたいなと思い質問しました。
場違いでしたらごめんなさい。
50ポイント を手に入れた。
|
|
|
|
Name: 管理人 [URL] ..ハッカー(131,940ポイント)
Date: 2006/12/15(金) 11:44
No:2814
|
|
Title: Re:画像の質問です。
|
|
メントスさん、こんにちは^^
>C言語の質問ではないんですけど、いいでしょうか。
もちろん結構ですよ^^
>ソースを拝見しても、そのような記述が見当たらず・・。
それはメニューの「表示」から「ソース」を選択してご覧になったのでしょうか?
ここは「フレーム」で出来ているので、そのソースでは実際のソースが見れません。
自分の見たいフレーム内の部分で右クリックして「ソースの表示」を選んでください。
画像をアクセスするたびに変更する方法ですが、JAVAスクリプトを使っています。
私が使っているコードはこんな感じです。
<SCRIPT language="JavaScript">
<!--
// ランダムに画像を表示する
img = new Array();
img[0] = "http://dixq.net/img/keijiban_top.png";
img[1] = "http://dixq.net/img/keijiban_top2.png";
img[2] = "http://dixq.net/img/keijiban_top3.png";
img[3] = "http://dixq.net/img/keijiban_top4.png";
img[4] = "http://dixq.net/img/keijiban_top5.png";
img[5] = "http://dixq.net/img/keijiban_top6.png";
img[6] = "http://dixq.net/img/keijiban_top7.png";
img[7] = "http://dixq.net/img/keijiban_top8.png";
img[8] = "http://dixq.net/img/keijiban_top9.png";
n = Math.floor(Math.random()*img.length);
document.write("<img src='”+img[n]+"' border='0'>");
//-->
</SCRIPT>
最後の行のダブルコーテーションを1つ全角にしてあるので注意してください。
自分の用意する画像ぶんだけ、配列要素を増やし、リンク先の画像を変更すれば、
このままコピペで使えますから使ってみてください^^
444ポイント を手に入れた。
|
|
|
|
Name: 初心者 ..入門者(3,710ポイント)
Date: 2006/12/05(火) 13:29
No:2343
|
|
Title: 加減剰余の演算機の作成
|
|
大学で次のような課題がでたんですがどのようにやればいいかわかりません。
もしわかる方がいれば教えてください。
[1] 授業単元: プロフラミング実習II
[2] 問題文(含コード&リンク):
コマンドライン版 加減乗除 演算機の作成
※必ずコマンドラインから入力データを与えてください.本課題の必須要件です.
使い方: calc 数値1 [+|-|*|/] 数値2
(例)calc 4 + 2 <enter>
6.00
上記の例に示すようなコマンドライン版の超簡単な加減乗除演算機を作成してください.
加減乗除ですから,+ - * / の4つのオペレータ(加減乗除演算子)を考えるだけで十分です.
括弧の処理はなくて構いません.
括弧による優先順位や四則演算の優先順位を考慮すると格段に難しい問題になります.
したがって本課題では考慮の必要はありません.
コマンドラインから与える「数値1」と「数値2」は実際には文字列として main 関数に渡されます.ご注意ください.
例にあるように,コマンド名calcと数値1の間には半角スペースを入れます.同様に数値1とオペレータの間にも半角スペースを入れます.もちろんオペレータと数値2の間にもスペースが必要です.
例では小数点以下2桁で結果を表示しています.表示方法は各自で工夫してください.
[3] 環境
[3.1] OS: WindowsXP
[3.2] コンパイラ名とバージョン:gcc
[3.3] 言語: C
よろしくお願いいたします。
418ポイント を手に入れた。
|
|
|
|
Name: box ..中級者(11,714ポイント)
Date: 2006/12/05(火) 13:50
No:2348
|
|
Title: Re:加減剰余の演算機の作成
|
|
サンプルです。
#include <stdio.h>
#include <stdlib.h>
void error_msg(char *s);
int main(int argc, char *argv[])
{
double a, b, c;
char op;
if (argc != 4)
error_msg(argv[0]);
a = atof(argv[1]);
b = atof(argv[3]);
switch (op = argv[2][0]) {
case '+':
c = a + b;
break;
case '-':
c = a - b;
break;
case '*':
c = a * b;
break;
case '/':
c = a / b;
break;
default:
error_msg(argv[0]);
break;
}
printf("%f %c %f = %f\n", a, op, b, c);
return 0;
}
void error_msg(char *s)
{
fprintf(stderr, "%s 数値1 [+|-|*|/] 数値2\n", s);
exit(1);
}
202ポイント を手に入れた。
|
|
|
|
|
Name: keichan ..初心者(5,750ポイント)
Date: 2006/12/05(火) 13:56
No:2349
|
|
Title: Re:加減剰余の演算機の作成
|
|
エラー処理をまったくしていないサンプルコードです。
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char* argv[])
{
/// argcは4が入力されていることを前提として作成(エラー処理省く)
double lp = 0.0, rp = 0.0;
double ret = 0.0;
lp = atof(argv[1]);
rp = atof(argv[3]);
switch( argv[2][0] ) {
case '+':
ret = lp + rp;
break;
case '-':
ret = lp - rp;
break;
case '*':
ret = lp * rp;
break;
case '/':
ret = lp / rp;
break;
}
printf("%.2f", ret);
return 0;
}
344ポイント を手に入れた。
|
|
|
|
|
Name: 初心者 ..入門者(3,741ポイント)
Date: 2006/12/05(火) 14:24
No:2355
|
|
Title: Re:加減剰余の演算機の作成
|
|
すみませんがまだあまりC言語について理解できてない部分もあるのでソースの説明もしていただけねいでしょうか?
31ポイント を手に入れた。
|
|
|
|
|
Name: box ..中級者(12,334ポイント)
Date: 2006/12/05(火) 14:44
No:2361
|
|
Title: Re:加減剰余の演算機の作成
|
|
先ほどのソースにコメントを付けてみました。
#include <stdio.h>
#include <stdlib.h>
void error_msg(char *s);
int main(int argc, char *argv[])
{
double a, b, c; /* 計算用の数値 */
char op; /* 加減乗除の演算子 */
/* このプログラムは、
* プログラム名 数値1 演算子 数値2 <Enter>
* という形式で実行する。コマンドライン引数の数は、
* プログラム名を含めて4個。
* 想定どおりの形式でない場合、エラーメッセージを出力する。
*/
if (argc != 4)
error_msg(argv[0]);
/* コマンドライン引数の文字列には、
* 0番目:プログラム名
* 1番目:数値1
* 2番目:加減乗除の演算子
* 3番目:数値2
* の順に格納してある。1番目と3番目の文字列を、atof関数で
* 浮動小数点数に変換する。
*/
a = atof(argv[1]);
b = atof(argv[3]);
/* コマンドライン引数の文字列の2番目の先頭文字(先頭文字以外は無視)が
* 加減乗除の演算子である。演算子の内容に応じて、適切な計算を行なう。
* 演算子が正しくなければ、エラーメッセージを出力する。
* switch〜case構文では、switch文のカッコ内の内容に応じて、適切なcase文の
* ところの内容を実行する。
*/
switch (op = argv[2][0]) {
case '+':
c = a + b;
break;
case '-':
c = a - b;
break;
case '*':
c = a * b;
break;
case '/':
c = a / b;
break;
default:
error_msg(argv[0]);
break;
}
/* 「数値1 演算子 数値2 = 演算結果」の形式で出力する。 */
printf("%f %c %f = %f\n", a, op, b, c);
return 0;
}
/* エラーメッセージを出力する関数
* メッセージ出力後、exit関数でプログラムを終了する。
*/
void error_msg(char *s)
{
fprintf(stderr, "%s 数値1 [+|-|*|/] 数値2\n", s);
exit(1);
}
620ポイント を手に入れた。
|
|
|
|
|
Name: シンゴ ..ぴよぴよ(346ポイント)
Date: 2006/12/08(金) 15:42
No:2496
|
|
Title: Re:加減剰余の演算機の作成
|
|
boxさんのソースは理解できたんですがコマンドプロンプトでやってみてもちゃんと動きません。
わかるかたがいれば教えてください。
42ポイント を手に入れた。
|
|
|
|
|
Name: box ..中級者(14,938ポイント)
Date: 2006/12/08(金) 15:54
No:2498
|
|
Title: Re:加減剰余の演算機の作成
|
|
> コマンドプロンプトでやってみてもちゃんと動きません。
「ちゃんと動かない」という現象を、具体的に説明してください。
途中経過を省略して最後の結果だけ報告されても、どうしようもありません。
コマンドプロンプトでどんな風に実行したとき、どうなったので
「ちゃんと動かない」と判断されましたか?
何かエラーメッセージが出たのでしたら、すべて見せてください。
8ポイント を手に入れた。
|
|
|
|
|
Name: keichan ..初心者(7,321ポイント)
Date: 2006/12/08(金) 15:56
No:2499
|
|
Title: Re:加減剰余の演算機の作成
|
|
>boxさんのソースは理解できたんですがコマンドプロンプトでやってみてもちゃんと動きません。
どういったオペレーションをされました?
ちゃんと動きません。ってどう動かないんですか?
具体的に書いてください。
101ポイント を手に入れた。
|
|
|
|
|
Name: シンゴ ..ぴよぴよ(404ポイント)
Date: 2006/12/08(金) 21:01
No:2514
|
|
Title: Re:加減剰余の演算機の作成
|
|
すいません。コマンドプロンプトで実行すると
Usage:
calc num1 [+|-|*|/] num2
とは表示されるのですがそこで終わってしまい最初に書いてあるような
(例)calc 4 + 2 <enter>
6.00
とゆう感じに入力することができません。
58ポイント を手に入れた。
|
|
|
|
|
Name: 管理人 [URL] ..ハッカー(120,798ポイント)
Date: 2006/12/08(金) 21:14
No:2516
|
|
Title: Re:加減剰余の演算機の作成
|
|
calc num1 [+|-|*|/] num2 とは表示されるのですが
ということですが、boxさんのプログラムもkeichanさんのプログラムも
そのような記述はありません。
コンパイルしているファイルが違うのじゃないのですか?
後、初心者さんとシンゴさんは同じ方ですか?
100ポイント を手に入れた。
|
|
|
|
|
Name: シンゴ ..ぴよぴよ(491ポイント)
Date: 2006/12/08(金) 21:35
No:2517
|
|
Title: Re:加減剰余の演算機の作成
|
|
いえ初心者さんとは一緒に問題を解いてただけです。
えっと違うのをコンパイルしていました。すみません。
でも、もう一度確認してやってみたら
数値1 [+|-|*|/] 数値2
とでただけで数値を入力できませんでした。
87ポイント を手に入れた。
|
|
|
|
|
Name: box ..上級者(15,043ポイント)
Date: 2006/12/08(金) 21:42
No:2518
|
|
Title: Re:加減剰余の演算機の作成
|
|
> 数値1 [+|-|*|/] 数値2
このメッセージを表示したということは、
コマンドプロンプトでの実行方法が正しくないということです。
実行ファイル名がcalc.exeで、4+2の計算を行ないたければ、
コマンドプロンプトで
calc 4 + 2 <Enter>
のように実行してください。
calcと4と+と2の間に、各々1個以上の空白をあけてください。
105ポイント を手に入れた。
|
|
|
|
|
Name: シンゴ ..ぴよぴよ(531ポイント)
Date: 2006/12/08(金) 21:54
No:2520
| 解決!
|
Title: Re:加減剰余の演算機の作成
|
|
できました!!ありがとうございます。
boxさんの言うとおりやりかたが違ってました。
親切に教えてくださってありがとうございました。
40ポイント を手に入れた。
|
|
|
|
|
Name: c言語頑張る ..ぴよぴよ(3ポイント)
Date: 2006/12/12(火) 13:52
No:2652
|
|
Title: 加減剰余の演算機の作成
|
|
はじめまして!!
このプログラムの問題に興味をもちました!!
このプログラムを見て、このプログラムは理解できたのですが、
他に別解ってのはないでしょうか??
参考までに教えてもらえないでしょうか???
是非C言語の勉強(特にコマンドライン)になると思うのでお願いします!!
3ポイント を手に入れた。
|
|
|
|
|
Name: box ..上級者(16,461ポイント)
Date: 2006/12/12(火) 14:32
No:2656
|
|
Title: Re:加減剰余の演算機の作成
|
|
こんなのはどうでしょう。
#include <stdio.h>
#include <stdlib.h>
void usage(char *s);
int main(int argc, char *argv[])
{
double a, b, c;
char op;
if (argc != 4)
usage(argv[0]);
a = atof(argv[1]);
b = atof(argv[3]);
if (sscanf(argv[2], "%1[+-*/]", &op) != 1)
usage(argv[0]);
c = (op - '+') ? (op - '-') ? (op - '*') ? a / b : a * b : a - b : a + b;
printf("%f %c %f = %f\n", a, op, b, c);
return 0;
}
void usage(char *s)
{
fprintf(stderr, "%s 数値1 [+|-|*|/] 数値2\n", s);
exit(1);
}
250ポイント を手に入れた。
|
|
|
|
|
Name: Justy ..熟練のプログラマー(42,487ポイント)
Date: 2006/12/12(火) 14:56
No:2659
|
|
Title: Re:加減剰余の演算機の作成
|
|
sscanfの使い方が素晴らしいです(w
では、私はこんなかんじで。
#include <stdio.h>
#include <stdlib.h>
typedef double (*op_func)(double, double);
static double op_add(double a, double b) { return a + b; }
static double op_sub(double a, double b) { return a - b; }
static double op_mul(double a, double b) { return a * b; }
static double op_div(double a, double b) { return a / b; }
static double op_none(double a, double b){ return 0; }
static op_func get_op(char c)
{
return c=='+'? op_add: c=='-'? op_sub: c=='*'? op_mul: c=='/'? op_div: op_none;
}
int main(int argc, char* argv[])
{
if(argc >= 4)
{
char *p, *q, c = *argv[2];
double l = ((p = argv[1]), strtod(p, &q)),
r = ((p = argv[3]), strtod(p, &q));
printf("%f %c %f = %f\n",
l, c, r, get_op(c)(l, r));
}
return 0;
}
327ポイント を手に入れた。
|
|
|
|
|
Name: box ..上級者(16,845ポイント)
Date: 2006/12/12(火) 16:46
No:2664
|
|
Title: Re:加減剰余の演算機の作成
|
|
sscanfの使い方を上級者に笑われてしまったので、書き換えてみました。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void usage(char *s);
int main(int argc, char *argv[])
{
double a, b, c;
char *op, *ops = "+-*/";
if (argc != 4)
usage(argv[0]);
a = atof(argv[1]);
b = atof(argv[3]);
if ((op = strpbrk(argv[2], ops)) == NULL)
usage(argv[0]);
c = (*op - '+') ? (*op - '-') ? (*op - '*') ? a / b : a * b : a - b : a + b;
printf("%f %c %f = %f\n", a, *op, b, c);
return 0;
}
void usage(char *s)
{
fprintf(stderr, "%s 数値1 [+|-|*|/] 数値2\n", s);
exit(1);
}
224ポイント を手に入れた。
|
|
|
|
|
Name: box ..上級者(17,498ポイント)
Date: 2006/12/12(火) 19:57
No:2678
|
|
Title: Re:加減剰余の演算機の作成
|
|
関数ポインタを使った例です。
#include <stdio.h>
#include <stdlib.h>
typedef double (*Func)(double, double);
double Add(double a, double b);
double Sub(double a, double b);
double Mul(double a, double b);
double Div(double a, double b);
void usage(char *s);
int main(int argc, char *argv[])
{
Func funcs[] = { Add, Sub, Mul, Div };
double a, b, c;
char op, ops[] = "+-*/";
int n, i;
if (argc != 4)
usage(argv[0]);
a = atof(argv[1]);
b = atof(argv[3]);
n = sizeof(ops) / sizeof(ops[0]);
for (i = 0; i < n; i++)
if ((op = argv[2][0]) == ops[i])
break;
if (i == n)
usage(argv[0]);
c = funcs[i](a, b);
printf("%f %c %f = %f\n", a, op, b, c);
return 0;
}
double Add(double a, double b)
{
return a + b;
}
double Sub(double a, double b)
{
return a - b;
}
double Mul(double a, double b)
{
return a * b;
}
double Div(double a, double b)
{
return a / b;
}
void usage(char *s)
{
fprintf(stderr, "%s 数値1 [+|-|*|/] 数値2\n", s);
exit(1);
}
574ポイント を手に入れた。
|
|
|
|
|
Name: C言語頑張る ..ぴよぴよ(21ポイント)
Date: 2006/12/14(木) 23:45
No:2791
|
|
Title: Re:加減剰余の演算機の作成
|
|
BOXさんにお願いがあるのですが、BOXさんのプログラムのソース説明を、
お願いしてもいいですか??本当に申し訳ないです。。。
21ポイント を手に入れた。
|
|
|
|
|
Name: box ..上級者(20,549ポイント)
Date: 2006/12/15(金) 00:11
No:2793
|
|
Title: Re:加減剰余の演算機の作成
|
|
> BOXさんのプログラムのソース説明を、
3つ書きましたが、全部ですか?
いずれにしましても、これから寝るところであります。
何時間かお待ちください。
48ポイント を手に入れた。
|
|
|
|
|
Name: C ..ぴよぴよ(12ポイント)
Date: 2006/12/15(金) 00:49
No:2794
|
|
Title: Re:加減剰余の演算機の作成
|
|
sscanfの使ったものと、使ってないものでお願いしてもいいですか??
12ポイント を手に入れた。
|
|
|
|
|
Name: 管理人 [URL] ..ハッカー(130,395ポイント)
Date: 2006/12/15(金) 01:37
No:2796
|
|
Title: Re:加減剰余の演算機の作成
|
|
どの辺がわかりませんか?ちょっと複雑なところは
c = (*op - '+') ? (*op - '-') ? (*op - '*') ? a / b : a * b : a - b : a + b;
この辺だけだと思いますけど。
x=10;
y = (x==1) ? 1 : 2;
この構文はxが1ならyに1を代入し、違うなら2を代入すると言う意味です。
このxは1ではないので、実際2が入ります。
(*op - '*')ここまでを最初に見ましょう。
足し算でもなく、引き算でもなく、かけ算でもないときは、
割り算。
足し算でもなく、引き算でもなく、かけ算であるときは
掛け算
足し算でもなく、引き算であるときは
引き算
足し算であるときは
足し算
と言う意味です。
a = atof(argv[1]);
b = atof(argv[3]);
if ((op = strpbrk(argv[2], ops)) == NULL)
usage(argv[0]);
c = (*op - '+') ? (*op - '-') ? (*op - '*') ? a / b : a * b : a - b : a + b;
printf("%f %c %f = %f\n", a, *op, b, c);
数字がはいっているはずの[1],[3]をatofで数値に変換し、strpbrkでopsに入っている文字を探索します。
探索した所でポインタを返し、opに格納。
そこの文字がたすなのか、ひくなのか、かけなのか、わるなのかで計算を変えます。
条件にあった計算方法で計算された結果をcに格納しています。
308ポイント を手に入れた。
|
|
|
|
|
Name: 管理人 [URL] ..ハッカー(130,704ポイント)
Date: 2006/12/15(金) 01:49
No:2797
|
|
Title: Re:加減剰余の演算機の作成
|
|
ですから、エラー処理などを行わない最小のプログラムはこのように成ると思います。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[]){
double a, b, c;
char *op, *ops = "+-*/";
a = atof(argv[1]);
b = atof(argv[3]);
op = strpbrk(argv[2], ops);
c = (*op - '+') ? (*op - '-') ? (*op - '*') ? a / b : a * b : a - b : a + b;
printf("%f\n",c);
return 0;
}
strpbrkについては
http://www9.plala.or.jp/sgwr-t/lib/strpbrk.html
この辺を読んでみるとよくわかりますよ。
boxさんのプログラムなのに、横から失礼しましたm(_ _)m
309ポイント を手に入れた。
|
|
|
|
|
Name: box ..上級者(21,152ポイント)
Date: 2006/12/15(金) 09:41
No:2804
|
|
Title: Re:加減剰余の演算機の作成
|
|
> sscanfの使ったものと、使ってないものでお願いしてもいいですか??
if (sscanf(argv[2], "%1[+-*/]", &op) != 1)
usage(argv[0]);
argv[2]という、文字列のポインタから、四則演算子を取り出します。
argv[2]の先頭1文字を取り出し、char型の変数opに格納します。
argv[2]の先頭1文字の形式は、sscanfの第2引数で指定しているとおり、
+-*/のいずれかであることを想定しています。
opに正しく格納できたら、sscanfの戻り値は1(格納した変数の個数)となります。
+-*/以外を指定したなどの理由でsscanfの戻り値が
1以外の(つまり、opに正しく格納できなかった)場合は、
usageで使用法を表示して、プログラムを終了します。
sscanfのかわりにstrpbrkを使う場合の解説は、管理人さんの回答をごらんください。
ところで、今回の三項演算子の使い方は、わかりにくいかもしれません。
足し算かどうかの判定と実際に足し算を行なうところとが
大きく離れているためです。
カッコを補ってみると、少しはわかりやすくなるかもしれません。
実際にやってみましょう。
c = (op - '+') ? ((op - '-') ? ((op - '*') ? a / b : a * b) : a - b) : a + b;
あるいは、こんな風に書く方がもっとわかりやすいかもしれません。
c = (op == '+') ? a + b :
(op == '-') ? a - b :
(op == '*') ? a * b : a / b;
いずれにせよ、あまりにも技巧に走りすぎると、コードは短くなるけれど
理解するのに時間がかかってしまう、ということがあるかもしれません。
今回、いくつかサンプルを紹介しましたが、いちばんわかりやすいのは
最初に挙げた、switchで分岐する例ではないかと思います。
一見、愚直な感じがするかもしれませんが、
自分以外の人(注:「将来の自分自身」を含む。コードを書いたときの自分と
保守するときの自分は別人とみなす)が後で保守することなどを
考えると、多くの人がパッと見てすぐに理解できるコードを書いておくことが
重要であります。
603ポイント を手に入れた。
|
|
|
|
|
Name: 管理人 [URL] ..ハッカー(131,496ポイント)
Date: 2006/12/15(金) 11:26
No:2811
|
|
Title: Re:加減剰余の演算機の作成
|
|
プログラムに書きなれてくると、難しい構文も別に抵抗無く使える(書いている本人は難しい構文だと意識しなくなる)ようになってくるでしょうけど、
読む人のスキルが違うとすごく見にくかったり理解しづらかったりするときありますよね。
または、ソースを書く人のくせがでたりするものですよね。
私は最初
if(a==1){
printf("a=1");
}
このようにいつも処理文を書いていたので
if(a==1)
{
printf("a=1");
}
このような書き方を見ると何か抵抗がありました。
書いた本人に言わせると、後者の方が括弧の対応がはっきりわかってわかりやすいじゃないかと
言います。
確かにその通りだと思いますけど、理屈なしで、前者でなれちゃってるので違和感はぬぐえませんでした。
全ての人が見てわかりやすいコードっていうのはなかなか書きにくいものですよね!
359ポイント を手に入れた。
|
|
|
|
Name: かっちゃん ..ぴよぴよ(190ポイント)
Date: 2006/12/15(金) 07:13
No:2800
|
|
Title: ゲームプログラミングの館のサンプルについて
|
|
はじめまして、かっちゃんと申します
ゲームプログラミングの館を見て勉強させていただいております
このサイトのサンプルについて
すべてのサンプルにおいて一度しか描画しないイメージやフォントは
その他のプログラムウィンドウに隠されると欠けて行き
プログラムに支障をきたしてしまうんですが
描画したイメージやフォントを欠けさせないためには
どのような処理が必要になるのでしょうか?
190ポイント を手に入れた。
|
|
|
|
Name: かっちゃん ..ぴよぴよ(256ポイント)
Date: 2006/12/15(金) 08:25
No:2802
| 解決!
|
Title: Re:ゲームプログラミングの館のサンプルについて
|
|
すいません、自己解決しました
裏画面に描画すれば消されないんですね
つまらないことで掲示板汚してすいませんでした
この質問は削除しておいてください
66ポイント を手に入れた。
|
|
|
|
|
Name: 管理人 [URL] ..ハッカー(131,063ポイント)
Date: 2006/12/15(金) 11:17
No:2809
|
|
Title: Re:ゲームプログラミングの館のサンプルについて
|
|
かっちゃんさん、こんにちは^^
>つまらないことで掲示板汚してすいませんでした
いえいえ、全然そんな事ないので、気軽に聞いてくださいね^^
最初は何かと難しいでしょうから☆ あまり高度な質問になると答えられないかもしれませんが
出来る限りお答えします♪
2倍のポイントを手に入れた! 260ポイント を手に入れた。
|
|
|
|
Name: fumu ..ぴよぴよ(170ポイント)
Date: 2006/12/14(木) 11:04
No:2757
|
|
Title: 動的メモリ確保
|
|
動的メモリ確保で悩んでます。
ちなみに、ポインタの知識は少ないです。
下記に記したように、main上で動的メモリ確保はできたのですが、
<pre>
#include <stdio.h>
#include <stdlib.h>
int main(){
int i;
int *a;
int totala = 5;
a = (int*)malloc(totala * sizeof(int));
for(i=0; i<totala ;i++){
a[i]=i;
}
for(i=0; i<totala ;i++){
printf("a[%d] = %d\n",i,a[i]);
}
return 0;
}
</pre>
実行結果
a[0] = 0
a[1] = 1
a[2] = 2
a[3] = 3
a[4] = 4
一旦他の関数へいき、そこでメモリ確保をし、
main上で使用する事ができませんでした(下記)。
<pre>
#include <stdio.h>
#include <stdlib.h>
void Read(int *a, int *totala);
int main(){
int i;
int *a;
int totala = 0;
Read(a, &totala);
printf("totala %d in main\n",totala);
for(i=0; i<totala ;i++){
printf("a[%d] = %d in main\n",i,a[i]);
}
return 0;
}
void Read(int *a, int *totala){
int i;
*totala = 5;
printf("totala %d in Read\n",*totala);
a = (int*)malloc(*totala * sizeof(int));
for(i=0; i<*totala ;i++){
a[i]=i;
}
for(i=0; i<*totala ;i++){
printf("a[%d] = %d in Read\n",i,a[i]);
}
};
</pre>
実行結果
totala = 5 in Read
a[0] = 0 in Read
a[1] = 1 in Read
a[2] = 2 in Read
a[3] = 3 in Read
a[4] = 4 in Read
totala = 5 in main
上記に記したように、グローバル変数を用いずに、
一旦他の関数へいき、そこでメモリ確保をし、
main上で使用するという事はできないのでしょうか?
また、こういうやり方は間違っているのでしょうか?
グローバル変数を使用したほうがいいのでしょうか?
書き方のアドバイスも宜しくお願います。
ご指導宜しくお願いします。
170ポイント を手に入れた。
|
|
|
|
Name: Yuki ..ぴよぴよ(190ポイント)
Date: 2006/12/14(木) 12:54
No:2758
|
|
Title: Re:動的メモリ確保
|
|
サブ関数で領域確保する際はダブルポインタを使います。
malloc関数で返されたアドレスをmain関数に返すためです。
int と int* の違いと同じように考えてください。
>void Read(int *a, int *totala){
void Read(int **a, int *totala){
>a = (int*)malloc(*totala * sizeof(int));
*a = (int*)malloc(*totala * sizeof(int));
>a[i]=i;
(*a)[i]=i;
グローバル変数は膨大なソースで開発者が複数いる場合など
「いつ」「どこで」「だれが」値を変えるかわからないので、
使わなくて済むほうが良いです。
145ポイント を手に入れた。
|
|
|
|
|
Name: box ..上級者(20,362ポイント)
Date: 2006/12/14(木) 13:19
No:2759
|
|
Title: Re:動的メモリ確保
|
|
> Read(a, &totala);
Read(&a, &totala);
> printf("a[%d] = %d in Read\n",i,a[i]);
printf("(*a)[%d] = %d in Read\n",i,(*a)[i]);
main関数でreturn 0;する前にfree(a);
も追加修正すれば大丈夫でありましょう。
36ポイント を手に入れた。
|
|
|
|
|
Name: fumu ..ぴよぴよ(298ポイント)
Date: 2006/12/14(木) 18:18
No:2768
| 解決!
|
Title: Re:動的メモリ確保
|
|
二人の回答を見て、書き直したところ見事に
解決しました。
少し、自分にはややこしいダブルポインタですが、
いい勉強になりました。
また、違う質問もありますので、
次も宜しくお願いします。
ぴよぴよさん、boxさんどうもありがとうございました。
128ポイント を手に入れた。
|
|
|
|
|
Name: fumu ..ぴよぴよ(336ポイント)
Date: 2006/12/15(金) 11:15
No:2808
|
|
Title: Re:動的メモリ確保
|
|
すいません。
初めてこちらにきたので間違えてしまいました。
改めて、boxさん、Yukiさん
ありがとうございました。
38ポイント を手に入れた。
|
|
|
|
Name: arekku ..ぴよぴよ(173ポイント)
Date: 2006/12/15(金) 10:50
No:2805
|
|
Title: for文について
|
|
初めて書き込みさせていただきます。よろしくお願いします。
現在、学校で出された問題をやっているのですが、for文のところで躓いてしまいました。
下のプログラムでiを0から3まで0.1ずつ増やし表示しているのですが、3.0を表示できません。
3.0を表示するにはiを0から3.1まで、みたいにしなければならないのでしょうか。
何かよい対策があれば、お願いします。
#include <stdio.h>
void main(){
double i;
for(i=0;i<=3;i+=0.1)printf("%lf\n",i);
}
173ポイント を手に入れた。
|
|
|
|
Name: box ..上級者(21,367ポイント)
Date: 2006/12/15(金) 10:59
No:2806
|
|
Title: Re:for文について
|
|
> 下のプログラムでiを0から3まで0.1ずつ増やし表示しているのですが、3.0を表示できません。
浮動小数点数の誤差が原因です。コンピュータで浮動小数点数を扱う際、
ごくわずかながら誤差が発生するのはどうしても避けられません。
0.1を繰り返し加えていくとき、30回でちょうど3.0になるとは限りません。
おそらく、3.0をわずかに超えた値(3.0000000001のような値)になったために、
printfで出力せずにループから抜けたのでありましょう。
解決策の例を挙げます。
ループ制御用の変数をint型にして、出力の際にdouble型に変換しています。
#include <stdio.h>
int main(void)
{
int i;
for (i = 0; i <= 30; i++)
printf("%f\n", (double) i / 10);
return 0;
}
215ポイント を手に入れた。
|
|
|
|
|
Name: arekku ..ぴよぴよ(225ポイント)
Date: 2006/12/15(金) 11:13
No:2807
| 解決!
|
Title: Re:for文について
|
|
早速の返信ありがとうございました!
無事完成させることができました。
また何かわからなくなったときは、よろしくお願いします。
52ポイント を手に入れた。
|
|
|
|
Name: アイス ..ぴよぴよ(57ポイント)
Date: 2006/12/14(木) 22:39
No:2779
|
|
Title: 初心者です
|
|
一番最初のBorlandC++ Compiler 5.5をダウンロードするところで、ダウンロードしたのですが、名前がfreecommandlinetools2に変わっているのですが、これはおかしいですか?
57ポイント を手に入れた。
|
|
|
|
Name: アイス ..ぴよぴよ(87ポイント)
Date: 2006/12/15(金) 01:05
No:2795
| 解決!
|
Title: Re:初心者です
|
|
ありがとうございます。
また、よろしくお願いします。
30ポイント を手に入れた。
|
|
|
|
Name: テル ..ぴよぴよ(37ポイント)
Date: 2006/12/14(木) 20:50
No:2774
|
|
Title: C言語始めました
|
|
c言語を初めてコンパイルしてみましたが?エラーE2209 sample1.c:インクールドファイル'stdio.h'をオープンできないと表示され警告w8065とでます。なにがおかしいのでしょうか。教えてください。
37ポイント を手に入れた。
|
|
|
Name: オルムント ..ぴよぴよ(235ポイント)
Date: 2006/12/14(木) 00:28
No:2742
|
|
Title: 割り切れるものを探すプログラム
|
|
こんにちは。
プログラムの作りかたをお聞きします。
整数をふたつ読み込み、どちらの数も割り切ることが
できる0 より大きい数でもっとも大きいものを見つける
プログラムの作り方を教えてください。
自分で試して
ひとつ読み込、割り切れる1より大きい数で一番小さいものを見つける
プログラムなら作ることが出来ました。
これを改造したら作れると思うのですが、
どこをどのように変えればいいのか教えてください。
おねがいします。
#include<stdio.h>
int
main()
{
int x,i;
scanf("%d",&x);
for(i=2;x%i;i++)
{
i==0;
}
printf("%d\n",i);
return 0;
}
176ポイント を手に入れた。
|
|
|
|
Name: 管理人 [URL] ..ハッカー(127,078ポイント)
Date: 2006/12/14(木) 00:46
No:2743
|
|
Title: Re:割り切れるものを探すプログラム
|
|
えぇと、つまり最大公約数を見つけるプログラムですか?
for(i=2;x%i;i++)
{
i==0;
}
ここのとこの処理のしたい事がよくわかりません。
i==0は何を意味しようとしたのですか?
2倍のポイントを手に入れた! 100ポイント を手に入れた。
|
|
|
|
|
Name: オルムント ..ぴよぴよ(314ポイント)
Date: 2006/12/14(木) 00:52
No:2745
|
|
Title: Re:割り切れるものを探すプログラム
|
|
読み込んだ2つ数字の最大公約数を見つけるプログラムです。
for(i=2;x%i;i++)
{
i==0;
}
は読み込んだ数字を2から割っていって
あまりが0になったらfor文をやめるように
しようと思い書きました。
79ポイント を手に入れた。
|
|
|
|
|
Name: オルムント ..ぴよぴよ(338ポイント)
Date: 2006/12/14(木) 00:54
No:2746
|
|
Title: Re:割り切れるものを探すプログラム
|
|
w←これ消してください。
気づかず投稿してしまいました。
すみません。
24ポイント を手に入れた。
|
|
|
|
|
Name: Justy ..熟練のプログラマー(43,343ポイント)
Date: 2006/12/14(木) 00:57
No:2747
|
|
Title: Re:割り切れるものを探すプログラム
|
|
>整数をふたつ読み込み、どちらの数も割り切ることができる
>0より大きい数でもっとも大きいものを見つける
最大公約数のことでしょうか。
最大公約数はユークリッドの互除法という方法で求めることができます(ググって見て下さい)。
その方法も減算方式と剰余方式とありますが、剰余方式だと下のようになります。
#include<stdio.h>
int main(void)
{
int v1, v2, t, result;
if(scanf("%d %d", &v1, &v2) == 2)
{
result = v1;
while(v2 != 0)
{
t = result % v2;
result = v2;
v2 = t;
}
printf("result = %d\n", result);
}
return 0;
}
244ポイント を手に入れた。
|
|
|
|
|
Name: 管理人 [URL] ..ハッカー(127,182ポイント)
Date: 2006/12/14(木) 01:01
No:2748
|
|
Title: Re:割り切れるものを探すプログラム
|
|
一番シンプルな形にするとこうなると思います。
#include <stdio.h>
int kouyakusu(int x, int y){
if (!y) return x;
return kouyakusu(y, x%y);
}
int main(){
int x,y;
scanf("%d %d",&x,&y);
printf("最大公約数 : %d\n",kouyakusu(x,y));
return 0;
}
これは再帰関数です。
後、
for(i=2;x%i;i++)
{
i==0;
}
これは確かに2から始まって割り切れる値まで来ると抜けていますが、
i==0はいらないんじゃないですか?
for(i=2;x%i;i++) ;
でいいと思います。
30ポイント を手に入れた。
|
|
|
|
|
Name: 管理人 [URL] ..ハッカー(127,274ポイント)
Date: 2006/12/14(木) 01:07
No:2749
|
|
Title: Re:割り切れるものを探すプログラム
|
|
約数の1以外の最小の値は
#include<stdio.h>
int main(){
int x,i;
scanf("%d",&x);
for(i=2;x%i;i++) ;
printf("%d\n",i);
return 0;
}
となります。
for文のx%iはいい考えですね。
92ポイント を手に入れた。
|
|
|
|
|
Name: オルムント ..ぴよぴよ(450ポイント)
Date: 2006/12/14(木) 01:10
No:2750
|
|
Title: Re:割り切れるものを探すプログラム
|
|
わかりやすい回答ありがとうございます。
こんな方法があったんですか!
参考にさせてもらい
do-while文でも作れると思い作って見ましたが
この書き方は正しいでしょうか?
#include<stdio.h>
int
main()
{
int x,i,y,k;
scanf("%d",&x);
scanf("%d",&y);
do{
k=x%y;
x=y;
y=k;
}
while(y !=0);
printf("%d\n",x);
return 0;
}
112ポイント を手に入れた。
|
|
|
|
|
Name: 管理人 [URL] ..ハッカー(127,375ポイント)
Date: 2006/12/14(木) 01:25
No:2751
|
|
Title: Re:割り切れるものを探すプログラム
|
|
後判定する意味があるんでしょうか?
k=x%y
0で割ってはいけませんよね。
せっかく上記の式がエラーにならないように判定しているのに一度計算してから判定したのでは
判定する意味がないです。
値を入力するとき、2つ目の値を「0」にしてみてください。
きっとエラーになるはずです。
101ポイント を手に入れた。
|
|
|
|
|
Name: オルムント ..ぴよぴよ(518ポイント)
Date: 2006/12/14(木) 01:32
No:2752
| 解決!
|
Title: Re:割り切れるものを探すプログラム
|
|
ほんとうですね!
0で割ったらエラーになってしまいました。
度々質問して
大切な時間を割いてもらい
さらに
親切な回答ありがとうございました。
68ポイント を手に入れた。
|
|
|
|
|
Name: yasu ..ぴよぴよ(335ポイント)
Date: 2006/12/13(水) 23:32
No:2741
| 解決!
|
Title: Re:クイックソート解説アプリに関して
|
|
Driverを更新したら文字化け直りました。どうもお騒がせしました。
…ドライバーの更新くらいちゃんとしとけって話ですよねw
申し訳ない。
今週はレポートに挟まれて圧死しそうな状態なので(笑
来週にでもやらせていただきます。
バブルソートっていうのはなんとなく分かりましたが、クイックソートは
イマイチわからなかったので、これで理解できるようにがんばります!
ありがとうございました。失礼します
145ポイント を手に入れた。
|
|
|
|
Name: ストレンジャー ..ぴよぴよ(345ポイント)
Date: 2006/12/11(月) 22:55
No:2630
|
|
Title: 二項定理?に関するもの
|
|
はじめまして、ストレンジャーといいます。
以後お見知りおきを^^
課題で、(課題の内容をとりあえず丸写しします。(汗
n個からr個を取る組合せの数nCrについて、次の関係がある。
・ nCr = n-1Cr-1 + n-1Cr
・ nC0 = 1, nCn = 1
上記の関係を用いて、プログラム中の記号定数Nについて、nCr (n = 1, 2, …, N)
の表を出力するプログラムをつくりなさい。たとえば、Nが5であるとき、
以下のように出力されることが期待される。
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
なお、このプログラムは二次元配列を利用すると簡単に作れる。
しかし、計算の手順を工夫することで、N + 1この要素を持つ1次元配列のみで行う方法、
両方について考えて見なさい。
こんなのがでたんですはい。
nCr = n! / {(n - r)! * r!}だから、
うえの公式を使って考えて、
nCr = (n - 1)! / { (n - r)! * (r - 1)! } + (n - 1)! / { r! * (n - r - 1)! }
だ!とか思いまして、階乗の部分の計算式を立てようとがんばっていたんですが、
なんかものすごーいことになってしまいまして、(汗
なんかわかんないのがなんなんだかわかんないです・・;
ということで答えていただきたいです^^
こういうことを掲示板に張るのが初めてなので、
何かいたらいいかわかんないんですが、
とりあえず、今まで習ったのはprintf(),scanf(),if,for,whileループ,do whileループ
配列変数(1次元、二次元),sqrt()とか、double型、float型,int型の変数くらいです。
後はいろいろなアルゴリズムです。
答えてもらえやすいように書き込みしたつもりです!!
お願いします!!
359ポイント を落としてしまった。
|
|
|
|
Name: Justy ..熟練のプログラマー(41,968ポイント)
Date: 2006/12/12(火) 02:01
No:2634
|
|
Title: Re:二項定理?に関するもの
|
|
nCrは
typedef unsigned int uint32;
static uint32 comb1(uint32 n, uint32 r)
{
if (r == 0 || r == n) return 1;
return comb1(n - 1, r - 1) + comb1(n - 1, r);
}
static uint32 comb2(uint32 n, uint32 r)
{
uint32 i, p = 1;
for(i=1; i<=r; ++i)
p = p * (n+1-i) / i;
return p;
}
で、comb1でも comb2のどちらでも解けます。
comb1は再帰関数で、comb2は繰り返しで処理しています。
配列を使う云々はよくわかりませんが、パスカルの三角形の法則とかを使うんじゃないですかね、きっと。
339ポイント を手に入れた。
|
|
|
|
|
Name: フリオ(元通りすがり) ..ぴよぴよ(687ポイント)
Date: 2006/12/12(火) 02:22
No:2637
|
|
Title: Re:二項定理?に関するもの
|
|
こういう意味でしょうか。
#include <stdio.h>
#define N 5
int main(void)
{
int n, r;
int combi0[N + 1][N + 1], combi1[N + 1];
for(n = 0; n <= N; n ++){
for(r = 0; r <= n; r ++){
if(r == 0 || n == r) combi0[n][r] = 1;
else combi0[n][r] = combi0[n - 1][r - 1] + combi0[n - 1][r];
}
}
for(n = 0; n <= N; n ++){
for(r = 0; r <= n; r ++) printf("%d ", combi0[n][r]);
putchar('\n');
}
for(n = 0; n <= N; n ++){
for(r = n; r >= 0; r --){
if(r == 0 || n == r) combi1[r] = 1;
else combi1[r] += combi1[r - 1];
}
for(r = 0; r <= n; r ++) printf("%d ", combi1[r]);
putchar('\n');
}
return 0;
}
406ポイント を手に入れた。
|
|
|
|
|
Name: フリオ(元通りすがり) ..ぴよぴよ(892ポイント)
Date: 2006/12/12(火) 04:12
No:2639
|
|
Title: Re:二項定理?に関するもの
|
|
少し整理しました。
#include <stdio.h>
#define N 5
int main(void)
{
int n, r;
int combi0[N + 1][N + 1], combi1[N + 1];
for(n = 0; n <= N; n ++){
combi0[n][0] = combi0[n][n] = 1;
if(n) printf("%d ", combi0[n][0]);
for(r = 1; r < n; r ++){
combi0[n][r] = combi0[n - 1][r - 1] + combi0[n - 1][r];
printf("%d ", combi0[n][r]);
}
printf("%d\n", combi0[n][n]);
}
for(n = 0; n <= N; n ++){
combi1[n] = combi1[0] = 1;
for(r = n - 1; r > 0; r --) combi1[r] += combi1[r - 1];
for(r = 0; r <= n; r ++) printf("%d ", combi1[r]);
putchar('\n');
}
return 0;
}
205ポイント を手に入れた。
|
|
|
|
|
Name: ストレンジャー ..ぴよぴよ(87ポイント)
Date: 2006/12/12(火) 19:24
No:2677
|
|
Title: Re:二項定理?に関するもの
|
|
回答ありがとうございます!
解決しました!といいたいところなのですが、
putcharとかcombiとかなどなどの意味がわかりません。
やはりそこは自分で調べて、
どういう形でプログラムを作ればいいかってことなんですかね?
自分が作ったプログラムを作りかけでも載せるべきだったんでしょうか。
反省しておきます。
87ポイント を手に入れた。
|
|
|
|
|
Name: ストレンジャー ..ぴよぴよ(178ポイント)
Date: 2006/12/13(水) 20:43
No:2739
| 解決!
|
Title: Re:二項定理?に関するもの
|
|
justryさん、フリオさん、管理人さん
ありがとうございました!!
すごいですね!
こんな計算方法があったんだと
パソコンの前でなんかうなづいてしまいました。(汗
ありがとうございました!!
解決いたしました。
またわからないところがあったらよろしくお願いします!
91ポイント を手に入れた。
|
|
|
|
Name: びす ..ぴよぴよ(18ポイント)
Date: 2006/12/13(水) 18:56
No:2731
|
|
Title: 何がおかしいのか・・・
|
|
コマンドライン引数の各々の文字列中の文字で、アルファベットの小文字を大文字に、大文字を小文字に変換して表示するプログラムを作成せよ。
のプログラムを作成しているのですが・・・
#include <stdio.h>
#include <ctype.h>
void encrypt(char *argv[]);
int main( int argc, char *argv[] )
{
int i;
for(i=1;i<argc;i++){
void encrypt(char *argv[i]);
}
printf("%s",argv[]);
return(0);
}
void encrypt(char *argv)
{
do {
if(isupper(*argv)) {
*argv =tolower(*argv);
} else
if(islower(*argv)) {
*argv = toupper(*argv) ;
}
} while(*++argv!='\0');
return;
}
エラー
重大度 記述 リソース フォルダー ロケーション
2 *** [ghk.o] Error 1 ghk
2 error: previous declaration of 'encrypt' was here ghk.c ghk 行 12
2 error: parse error before ']' token ghk.c ghk 行 15
2 error: conflicting types for 'encrypt' ghk.c ghk 行 21
となり意味がわからないです・・・
どなたか教えていただけると幸いです。
18ポイント を手に入れた。
|
|
|
|
Name: box ..上級者(20,277ポイント)
Date: 2006/12/13(水) 19:13
No:2732
|
|
Title: Re:何がおかしいのか・・・
|
|
encrypt関数の実行の仕方などに問題があります。
手を加えたサンプルです。
#include <stdio.h>
#include <ctype.h>
void encrypt(char *s);
int main(int argc, char *argv[])
{
int i;
for (i = 1; i < argc; i++) {
encrypt(argv[i]);
printf("%s\n", argv[i]);
}
return 0;
}
void encrypt(char *s)
{
for (; *s; s++) {
if (isupper(*s))
*s = tolower(*s);
else if (islower(*s))
*s = toupper(*s);
}
}
194ポイント を手に入れた。
|
|
|
|
|
Name: 管理人 [URL] ..ハッカー(126,978ポイント)
Date: 2006/12/13(水) 20:14
No:2737
|
|
Title: Re:何がおかしいのか・・・
|
|
void encrypt(char *argv[i]);
これは宣言する時の文であり、関数を呼ぶときの文ではありません。
呼ぶ先の関数が2次元配列の先頭アドレスを受け取る形でしたら
encrypt(argv[i]);
このように2次元配列の先頭アドレスを渡す形で呼んでやりましょう。
77ポイント を手に入れた。
|
|
|
|
|
Name: びす ..ぴよぴよ(77ポイント)
Date: 2006/12/13(水) 20:20
No:2738
| 解決!
|
Title: Re:何がおかしいのか・・・
|
|
本当にどうもありがとうございました!
理解できるように努めます。
お早い回答本当にありがとうございました!
59ポイント を手に入れた。
|
|
|
|
Name: 困ったさん ..かけだし(1,224ポイント)
Date: 2006/12/12(火) 16:17
No:2660
|
|
Title: ポインタについて
|
|
こんにちは。
大学の課題で「整数型変数a,b,cを定義し、それぞれに10,100,1000を代入する。次に整数型ポインタ変数pを
定義し、cのアドレスを代入する。pの値をp+0からp+9まで変化させて、*pの値を画面表示するプログラムを
作成しなさい。」というものをやっているのですが・・・これの実行結果はどのようなものになるでしょうか?
142ポイント を手に入れた。
|
|
|
|
Name: box ..上級者(16,533ポイント)
Date: 2006/12/12(火) 16:28
No:2661
|
|
Title: Re:ポインタについて
|
|
p+0のときの*pの値は1000(=cの値)ですが、p+1〜p+9のときの*pの値は
ゴミ(何が入っているかわからない)です。
出題の意図が理解できないです。
72ポイント を手に入れた。
|
|
|
|
|
Name: box ..上級者(16,621ポイント)
Date: 2006/12/12(火) 16:32
No:2662
|
|
Title: Re:ポインタについて
|
|
もしかすると、*(p+1)〜*(p+9)の値はゴミである、
ということを理解させるための課題かもしれませんね。
2倍のポイントを手に入れた! 88ポイント を手に入れた。
|
|
|
|
|
Name: 困ったさん ..かけだし(1,177ポイント)
Date: 2006/12/12(火) 16:46
No:2663
|
|
Title: Re:ポインタについて
|
|
よくわからないんですが、何が入っているか分からないということは具体的な表示は
ないということですか?
47ポイント を落としてしまった。
|
|
|
|
|
Name: box ..上級者(16,924ポイント)
Date: 2006/12/12(火) 16:51
No:2665
|
|
Title: Re:ポインタについて
|
|
printfで表示すれば何かの値を表示します。
しかし、今回は*(p+1)〜*(p+9)の値はゴミなので、
訳のわからない値である、ということです。
以下のコードを実行してみてください。
#include <stdio.h>
int main(void)
{
int a = 10, b = 100, c = 1000, i;
int *p = &c;
for (i = 0; i <= 9; i++) {
p += i;
printf("*p=%d\n", *p);
}
return 0;
}
79ポイント を手に入れた。
|
|
|
|
|
Name: 困ったさん ..かけだし(1,219ポイント)
Date: 2006/12/12(火) 16:59
No:2666
|
|
Title: Re:ポインタについて
|
|
なるほどp+0以外のときは本当にむちゃくちゃなんですね。
これはどういうことなんだろう・・・??
42ポイント を手に入れた。
|
|
|
|
|
Name: 困ったさん ..かけだし(1,236ポイント)
Date: 2006/12/12(火) 17:29
No:2669
|
|
Title: Re:ポインタについて
|
|
わかりました。
もう1問ポインタで聞きたいことがあるのですが、それはまた別にスレを立てさせてもらいます。
みなさんありがとうございました。
17ポイント を手に入れた。
|
|
|
|
|
Name: 困ったさん ..かけだし(1,653ポイント)
Date: 2006/12/13(水) 12:59
No:2709
|
|
Title: Re:ポインタについて
|
|
度々すいません(>_<)なぜp+1以降の値がゴミになるのか考察しなければならないんですけど
なぜゴミになるのかわかりやすく教えてもらえないでしょうか??
49ポイント を手に入れた。
|
|
|
|
|
Name: keichan ..初心者(8,369ポイント)
Date: 2006/12/13(水) 13:12
No:2711
|
|
Title: Re:ポインタについて
|
|
今回はint型の変数cを定義していますよね。
その変数cはメモリのどこかに4バイト分確保されます。
例えばcが10000番地〜10003番地で確保されているとします。
int *p = &c;
上記コードで pには10000が格納されることになります。
そして p+1 とすると結果は 10004 となるのは理解できますか?
10004番地にはプログラム内の別の変数が割り当てられているか
または全く割り当てられていない所なのかはわかりません。
つまり10004番地以降(10004, 10008, 1000C...)には不定な値(ゴミ)
が入っています。
要はcで確保したメモリ領域以降のアドレスに対して本来"やってはいけない"処理をしているということです。
227ポイント を手に入れた。
|
|
|
|
|
Name: 困ったさん ..かけだし(1,730ポイント)
Date: 2006/12/13(水) 13:17
No:2713
|
|
Title: Re:ポインタについて
|
|
なるほど。確保した領域を超えてしまったために正確な値が表示されることはないということですね?
わかりやすかったです!ありがとうございます。
49ポイント を手に入れた。
|
|
|
|
|
Name: box ..上級者(19,411ポイント)
Date: 2006/12/13(水) 13:18
No:2714
|
|
Title: Re:ポインタについて
|
|
ポインタ変数pの値をp+0〜p+9の範囲で変化させて、
そのときの*pの値を参照しています。
これは、*(p+0)〜*(p+9)の値を参照しているのです。
ここで、*(p+n)という表記は、一般にp[n]と同じです。
つまり、あたかも配列の要素を参照しているかのごとく
振る舞っています。
ということは、p[0]〜p[9]という、p[10]と定義した
配列の要素を参照しているのと実質的に同じです。
くだんのソースコードでは、p[0]にはcの値(1000)が
入っていますが、p[1]〜p[9]には明示的に値を
代入していません。これは、p[10]と定義した配列の
先頭要素だけに値をセットしているのと同じで、
先頭要素以外には何が入っているかわかりません。
何が入っているかわからない場所の値を出力するから、
訳がわからない値が出てしまったのです。
321ポイント を手に入れた。
|
|
|
|
|
Name: box ..上級者(19,493ポイント)
Date: 2006/12/13(水) 13:25
No:2715
|
|
Title: Re:ポインタについて
|
|
boxの先ほどの回答は誤りを含んでいます。
ソースの中でp[10]という配列に相当する
領域を確保しているわけではありませんので、
議論そのものが成立しません。
boxの回答は無視してください。
82ポイント を手に入れた。
|
|
|
|
|
Name: なぎ ..中級者(9,155ポイント)
Date: 2006/12/13(水) 15:55
No:2721
|
|
Title: Re:ポインタについて
|
|
上に上げられている、box さんのソースですが、一見すると、*(p + 1) // i じゃなくて、数字の 1
は、たまたま、変数 i をポイントするので、ここだけは、まともな値(具体的には、1)が表示されるのではないでしょうか……という疑問がわくのではと思いますが。
あのソースだと、*(p + 0) 以外は、でたらめな値になることが多いようですね。
これは、文法の話というよりは、具体的な処理系の動きになってしまうのですが、上述のソースだと、まず、a, b は、値が代入されただけで全く使われていない、故に、この変数自体が「なかったこと」にされてしまう。
変数 i は、使われているが、アドレスを通して参照されているわけでもないし、変数の数が少ないので、メモリ上には確保されない(やってみたら、レジスタに確保されていました)
変数 c だけは、アドレスを通して参照されているので、メモリ上に確保されている。
というように、実際の挙動がまた、「最適化」というもののおかげで、いろいろ予期しない動きをしてくれたりもします。
245ポイント を手に入れた。
|
|
|
|
|
Name: box ..上級者(19,545ポイント)
Date: 2006/12/13(水) 16:07
No:2723
|
|
Title: Re:ポインタについて
|
|
> 上に上げられている、box さんのソースですが、一見すると、*(p + 1) // i じゃなくて、数字の 1
> は、たまたま、変数 i をポイントするので、ここだけは、まともな値(具体的には、1)が表示されるのではないでしょうか……という疑問がわくのではと思いますが。
boxのところでは、こんなコードを実行して下記の結果を得ました。
iのアドレスはp〜p+9とは重なりませんでした。まあ、偶然でしょうけど。
#include <stdio.h>
int main(void)
{
int a = 10, b = 100, c = 1000, i;
int *p = &c;
printf("&i=%p\n", &i);
for (i = 0; i <= 9; i++) {
p += i;
printf("i=%d p=%p *p=%d\n", i, p, *p);
}
return 0;
}
【実行結果】
&i=0012FF84
i=0 p=0012FF88 *p=1000
i=1 p=0012FF8C *p=1245112
i=2 p=0012FF94 *p=1
i=3 p=0012FFA0 *p=-1
i=4 p=0012FFB0 *p=1245152
i=5 p=0012FFC4 *p=2011662757
i=6 p=0012FFDC *p=2011529823
i=7 p=0012FFF8 *p=4198400
i=8 p=00130018 *p=1048576
i=9 p=0013003C *p=0
52ポイント を手に入れた。
|
|
|
|
|
Name: box ..上級者(20,022ポイント)
Date: 2006/12/13(水) 16:18
No:2725
|
|
Title: Re:ポインタについて
|
|
先ほどの、アドレスを出力するコードの実行結果を見て、
ものすごいバグに気付いてしまいました。
ループの中でpに0を足して1を足して2を足して、...9を足して、
最終的には45要素分先を見てしまっていました。
いや、お恥ずかしい。何をやってたんでしょうか…。
#include <stdio.h>
int main(void)
{
int a = 10, b = 100, c = 1000, i;
int *p = &c;
printf("&i=%p\n", &i);
for (i = 0; i <= 9; i++) {
if (i != 0) p++; /* ここが間違っていた! */
printf("i=%d p=%p *p=%d\n", i, p, *p);
}
return 0;
}
【実行結果】
&i=0012FF84
i=0 p=0012FF88 *p=1000
i=1 p=0012FF8C *p=1245112
i=2 p=0012FF90 *p=4226254
i=3 p=0012FF94 *p=1
i=4 p=0012FF98 *p=20783560
i=5 p=0012FF9C *p=20784880
i=6 p=0012FFA0 *p=-1
i=7 p=0012FFA4 *p=1242452
i=8 p=0012FFA8 *p=2147348480
i=9 p=0012FFAC *p=2147348480
477ポイント を手に入れた。
|
|
|
|
|
Name: なぎ ..中級者(9,540ポイント)
Date: 2006/12/13(水) 17:03
No:2727
|
|
Title: Re:ポインタについて
|
|
雑談の追加になりますが……。
box さんの、最後のソースでは、
printf("&i=%p\n", &i);
で、&i が参照されているために、i は、メモリ上に確保されてしまいます。
そして、これがまた、ちょっとおもしろいのは、i は、c より「前」に確保されてしまうのですね。
ですから、
printf("&a=%p\n", &a);
printf("&b=%p\n", &b);
というコードを入れるだけで(こちらは、c より後ろにとられたりするので)
*(p + 0) -> c
*(p + 1) -> b
*(p + 2) -> a
を「たまたま」ポイントして、ここまでは、まともな値が出てきたりします。
このあたりも、コンパイラによって挙動が異なってきます。
「ゴミデータの表示」とはいえ、
printf("&a=%p\n", &a);
printf("&b=%p\n", &b);
の有無で挙動が異なってくるというのは、なかなか、パニックの元だと思います。
というわけで、ポインタがらみのバグは、最適化が絡むと、最悪の状態になります。
#しかし、最初のコードのバグには気づきませんでした、はい。
385ポイント を手に入れた。
|
|
|
|
|
Name: box ..上級者(20,054ポイント)
Date: 2006/12/13(水) 17:34
No:2728
|
|
Title: Re:ポインタについて
|
|
&iを参照しているからではなく、
int i;
で定義した時点でメモリ中の
どこかに配置します。
32ポイント を手に入れた。
|
|
|
|
|
Name: なぎ ..中級者(9,147ポイント)
Date: 2006/12/13(水) 17:45
No:2729
|
|
Title: Re:ポインタについて
|
|
> &iを参照しているからではなく、
> int i;
> で定義した時点でメモリ中の
> どこかに配置します。
それがですね、実は、C言語の規約上、「変数はメモリ上に存在する」というのは保証されていないわけです。
また、たいていのCPUは、メモリ上にアクセスするより、CPUの中のレジスタにアクセスするほうが速いわけです。
このために、「最適化」という手法で、宣言された変数がメモリ上に存在していないことはままあるわけです。
(変数をレジスタにおいてねという意思表示のために、 register という予約語も存在しますが)
一方で、&i と、アドレスが参照されてしまうと、この変数はメモリ上に存在している必要があります。
こんな訳で、数行程度のソースで、変数も数個程度であれば、その変数は実はメモリ上に存在していない可能性があります。
例えば、
int i, a, b, c; の順序で変数を定義して(この場合、i は確保されるとしたら、c の後に確保される可能性が高くなるので)&i という参照の有無で、 *(p + 1) の値がどう変化するかを見ると、&i があれば、*(p + 1) の値がゴミではなく、その時点での i の値になることが確認できるかもしれません。
(コンパイラの動作によるので)
そういう意味で、(このソースの場合は) &i で参照されたがために、メモリ上におかれてしまった という可能性があります。
手元にあった Boralnd の処理系では、&i を参照しない場合、i はメモリ上には存在しませんでした。
393ポイント を落としてしまった。
|
|
|
|
|
Name: box ..上級者(20,083ポイント)
Date: 2006/12/13(水) 18:32
No:2730
|
|
Title: Re:ポインタについて
|
|
> それがですね、実は、C言語の規約上、「変数はメモリ上に存在する」というのは保証されていないわけです。
それは全然知りませんでした。
> 手元にあった Boralnd の処理系では、&i を参照しない場合、i はメモリ上には存在しませんでした。
このことをどうすれば確認できますか?
29ポイント を手に入れた。
|
|
|
|
|
Name: Justy ..熟練のプログラマー(43,099ポイント)
Date: 2006/12/13(水) 19:35
No:2733
|
|
Title: Re:ポインタについて
|
|
>このことをどうすれば確認できますか?
コンパイル時にアセンブラの結果を出力するようにするか、デバッガでアセンブリ表示させれば確認できますが、機械語を読み解く必要があります。
コンパイル時の出力は MSVCだとプロパティの「C/C++」「出力ファイル」内に設定項目があります。
101ポイント を落としてしまった。
|
|
|
|
|
Name: なぎ ..中級者(9,527ポイント)
Date: 2006/12/13(水) 19:51
No:2735
|
|
Title: Re:ポインタについて
|
|
本当にチェックする場合は、アセンブラによる出力を確認する必要があります。
Borland のコンパイラだと、
bcc32 -S test.c
のように -S をつけると(このオプションは、わりと共通している気がしますが) test.asm というアセンブラのファイルが生成されます。
今回の場合では。
&i による参照がある場合、
?live1@16: ; ESI = &i
となり(この行はコメント)
lea esi,dword ptr [ebp-8]
と、esi レジスタに、[ebp-8] のメモリのアドレスがセットされます。
for() のループの終端で、9と比較する部分は
cmp dword ptr [esi],9
と、[esi] のポイントするメモリにアクセスして比較しています。
一方で、&i がない場合には、
?live1@64: ; EBX = i, ESI = p
となり(この行はコメント)
for() のループ終端で、9と比較する部分は、
cmp ebx,9
と、ebx レジスタが直接使われています。
といった感じです。
もちろん、これは、「コンパイラによってはこういうことになる」ということであって、必ずこうなるという意味ではありません。
380ポイント を手に入れた。
|
|
|
|
Name: hiro ..ぴよぴよ(135ポイント)
Date: 2006/12/12(火) 13:01
No:2648
|
|
Title: NULLを認識しません。
|
|
はじめまして。
下記のプログラムでNULLを認識してプログラムが入力行数を出力して終わるようにしたいのですが、
NULLを認識せずいつまでもループになってしまいます。
どこがわるいのでしょうか?
#include <stdio.h>
main()
{
char a[81];
int n = 0;
while(gets(a) != NULL)
{
n++;
puts(a);
}
printf("\n lines = %d\n",n);
}
135ポイント を手に入れた。
|
|
|
|
Name: box ..上級者(16,123ポイント)
Date: 2006/12/12(火) 13:22
No:2649
|
|
Title: Re:NULLを認識しません。
|
|
> NULLを認識せずいつまでもループになってしまいます。
Windowsをお使いでしたら、Ctrl+Z で入力を終了させてください。
32ポイント を落としてしまった。
|
|
|
|
|
Name: hiro ..ぴよぴよ(217ポイント)
Date: 2006/12/12(火) 13:33
No:2651
|
|
Title: Re:NULLを認識しません。
|
|
boxさん
返答ありがとうございます。
こちらも、Ctrl+Zで止めていました。
プログラム的にはどうでしょうか?
2倍のポイントを手に入れた! 82ポイント を手に入れた。
|
|
|
|
|
Name: hiro ..ぴよぴよ(260ポイント)
Date: 2006/12/12(火) 13:55
No:2653
|
|
Title: Re:NULLを認識しません。
|
|
先の返信でマークを雑談にいれていました。
どなたかプログラムの悪いところを教えてください。
43ポイント を手に入れた。
|
|
|
|
|
Name: Justy ..熟練のプログラマー(42,117ポイント)
Date: 2006/12/12(火) 14:14
No:2654
|
|
Title: Re:NULLを認識しません。
|
|
>どなたかプログラムの悪いところを教えてください。
NULLを認識していないとのことでしたが、特に悪いところは見あたりません。
正しく gets()の戻り値の NULLを認識しています。
だから Ctrl+Zでループをぬけることができるわけで。
76ポイント を落としてしまった。
|
|
|
|
|
Name: hiro ..ぴよぴよ(337ポイント)
Date: 2006/12/12(火) 14:26
No:2655
|
|
Title: Re:NULLを認識しません。
|
|
justyさん
返答ありがとう御座います。
てっきり、入力を何もせずにエンターキーを返せば終わるものと思っていました。
エンターキーで終わる方法はないのでしょうか?
77ポイント を手に入れた。
|
|
|
|
|
Name: Justy ..熟練のプログラマー(42,160ポイント)
Date: 2006/12/12(火) 14:34
No:2657
|
|
Title: Re:NULLを認識しません。
|
|
なるほど。ではこうして見てください。
while(gets(a) != NULL)
{
if(!strlen(a))
break;
n++;
puts(a);
}
43ポイント を手に入れた。
|
|
|
|
|
Name: GPGA ..中級者(14,686ポイント)
Date: 2006/12/12(火) 14:43
No:2658
|
|
Title: Re:NULLを認識しません。
|
|
では私はこんなプログラムで。
char* p;
while ((p = gets(a)) != NULL && *p != '\0')
{
n++;
puts(a);
}
39ポイント を手に入れた。
|
|
|
|
|
Name: hiro ..ぴよぴよ(157ポイント)
Date: 2006/12/12(火) 17:31
No:2670
|
|
Title: Re:NULLを認識しません。
|
|
justyさん
GPGAさん
いろいろと考えて頂きありがとうございます。
正常に動作致しました。
さらに、頂いた返事をもとに内容を考えてみました。
justyさんの回答では、NULLは無くても良いと分かりましたので下記のようにプログラムを変更しました。
#include <stdio.h>
#include <string.h>
main()
{
char a[81];
int n = 0;
while(!!strlen(gets(a)) != '\0')
{
n++;
puts(a);
}
printf("\n lines = %d\n",n);
}
また、GPGAさんに頂いた回答についても、同様にNULLの部分がいらないように思えたので下記のように変更してみました。
#include <stdio.h>
main()
{
char a[81];
int n = 0;
char* p;
while((p = gets(a)) && *p != '\0' )
{
n++;
puts(p);
}
printf("\n lines = %d\n",n);
}
結局、どちらについてもNULLは無くなってしまいました。
(プログラムの'\0'の部分をNULLにすると参照の型が違うと言うワーニングメッセージがでます。)
別に作ったデータファイルの内容を参照するプログラムではNULLは正常に動きましたが、キーボード入力ではなぜ正常に動かないのでしょうか?
NULLの扱い方についてさらに教えて頂ければ幸いです。
157ポイント を手に入れた。
|
|
|
|
|
Name: keichan ..初心者(8,097ポイント)
Date: 2006/12/12(火) 17:45
No:2672
|
|
Title: Re:NULLを認識しません。
|
|
NULLの使い方というよりはgets関数の使い方をきちんと確認してください。
MSDNでは
> gets関数は、stdin標準入力ストリームから行を読み取り、bufferに格納します。行は最初の改行文字(\n)までのすべての文字で構成されています。
> その後、getsは、改行文字をnull文字(\0)に置換してから行を返します。
とあります。
NULLが必要なのはgetsではなくfgetsの方だと判断できますね^^
54ポイント を手に入れた。
|
|
|
|
|
Name: GPGA ..中級者(14,927ポイント)
Date: 2006/12/12(火) 17:51
No:2675
|
|
Title: Re:NULLを認識しません。
|
|
> NULLの部分がいらないように思えたので
NULLチェックがなくなると Ctrl+Z で終了させることが
できなくなってしまいますが、いいのでしょうか?
> (プログラムの'\0'の部分をNULLにすると参照の型が違うと言うワーニングメッセージがでます。)
'\0'とNULLは別物です。
NULLは大抵の処理系では以下のように宣言されています。
#define NULL ((void *)0)
一方 \0 は文字列の終端コードです。
gets関数はエラーの場合はNULLを返しますが
正常終了したときは引数と同じポインタを指します。
つまり
p = gets(a);
が正常終了した場合、
p == a
が成り立ちます。
何も入力せずにENTERを押した場合、a[0]に 終端コードである '\0' が入ります。
a[0] == *(a + 0) == *a == *p
なので、whileのチェックで
*p != '\0'
の一文を入れているわけです。
> 別に作ったデータファイルの内容を参照するプログラムではNULLは正常に動きましたが、キーボード入力ではなぜ正常に動かないのでしょうか?
それは fgets関数を使用したプログラムですか?
そうである場合、fgets関数はファイルの終端に来た場合にNULLを返すからです。
キーボードからの場合、通常の入力では終端というものがありません。
Ctrl+Zが押されたときが、終端と考えてください。
241ポイント を手に入れた。
|
|
|
|
|
Name: hiro ..ぴよぴよ(237ポイント)
Date: 2006/12/13(水) 19:49
No:2734
| 解決!
|
Title: Re:NULLを認識しません。
|
|
keichanさん
GPGAさん
管理人さん
なんとなく分かった気がしてきました。
どうも、NULLとNULL文字を同じものとして、使い方を誤解していたようですね。
いろいろとありがとうございました。
これからも宜しくお願い致します。
80ポイント を手に入れた。
|
|
|
|
Name: 大介 ..ぴよぴよ(125ポイント)
Date: 2006/12/11(月) 22:12
No:2625
|
|
Title: 昨日はじめました。
|
|
基本的だと思いますが教えてください。
#include <stdio.h>
int main(void)
{
int na, nb:
puts("二つの整数を入力してください.");
printf("整数A:”); scanf("%d",&na);
printf("整数B:”); scanf("%d",&nb);
printf("それらの平均は%fです。\n,(na+nb)/2.0);
return(0);
}
これでintの形で最後のprintfが%fなのですがintは%dとなるはずなのですがこれは2。0という実数値で割るから答えは実数値になりますよ。という意味で%fとしたのでしょうか?確かにこうしないと正しい値がでてこないのです。教えてください。
125ポイント を手に入れた。
|
|
|
|
Name: box ..上級者(16,019ポイント)
Date: 2006/12/11(月) 22:30
No:2626
|
|
Title: Re:昨日はじめました。
|
|
おっしゃるとおりです。
なお、アップロードされたソースにはいくつか問題があって、
コンパイルできないです。
次回からは、コンパイルできたソースをコピー&ペーストしてください。
その際、字下げを活かすために、ソースの前後を<pre>と</pre>タグで
はさんでください。便宜上ここでは<と>を全角で書いていますが、
実際は半角です。
108ポイント を落としてしまった。
|
|
|
|
|
Name: 大介 ..ぴよぴよ(249ポイント)
Date: 2006/12/11(月) 22:47
No:2628
|
|
Title: Re:昨日はじめました。
|
|
ミスありましたこれです。
#include <stdio.h>
int main(void)
{
int na, nb;
puts("二つの整数を入力してください.");
printf("整数A:"); scanf("%d",&na);
printf("整数B:"); scanf("%d",&nb);
printf("それらの平均は%fです。\n",(na + nb)/2.0);
return(0);
}
124ポイント を手に入れた。
|
|
|
|
|
Name: たろう ..ぴよぴよ(435ポイント)
Date: 2006/12/12(火) 00:42
No:2631
|
|
Title: Re:昨日はじめました。
|
|
整数A,Bの合計が奇数の時、平均の値は小数点になるから%fを使うと思う。
ちなみに%.1fとかにしとけばOK!
46ポイント を手に入れた。
|
|
|
|
|
Name: なぎ ..初心者(8,910ポイント)
Date: 2006/12/13(水) 09:00
No:2706
|
|
Title: Re:昨日はじめました。
|
|
> 2。0という実数値で割るから答えは実数値になりますよ。という意味で%fとしたのでしょうか?
その理解で間違いではありません。
C/C++の計算規則では、
・int と int の計算結果は int
・int と double の計算結果は double
という規則があります。
さらに、
・小数点を伴わない数値定数は int
・小数点を伴う数値定数は double
という規則があります。
これを適用して、
(na + nb) の 結果は int
(na + nb) / 2 の結果は int (小数点無し)
(na + nb) / 2.0 の結果は double (小数点有り。 int / double の計算)
となります。
122ポイント を手に入れた。
|
|
|
|
|
Name: 管理人 [URL] ..ハッカー(126,901ポイント)
Date: 2006/12/13(水) 16:22
No:2726
|
|
Title: Re:昨日はじめました。
|
|
たろうさんのご回答
>ちなみに%.1fとかにしとけばOK!
を補足させて頂くとすると、
%f と %.1f との違いは小数点何位まで表示するかの違いです。
%fのままでは大量に不必要な小数まで表示されていると思います。
しかし%.nfのnの部分に数字を入れることで、小数点第n位まで表示することが出来ます。
小数点の無い表示の時も、これは結構使えます。
#include <stdio.h>
int main() {
printf("%5d\n",1234);
printf("%5d\n",12);
printf("%5d\n",123);
return 0;
}
これを実行してみてください。
綺麗にそろってひょうじされるはずです。
これは5スペース分の領域を使って表示するという意味なので、値がすくなくても5スペース分で表示されるので
値に関係なく綺麗にそろって表示されるのです。
色々試してみてください。
388ポイント を手に入れた。
|
|
|
|
Name: たくみ ..ぴよぴよ(54ポイント)
Date: 2006/12/07(木) 20:09
No:2445
|
|
Title: 入力値の和を求めるには
|
|
こんばんわ 「配列に文字を入力し、その配列全て足し合わせ、文字と和をファイルに保存する」 という課題をいただいたのですが、どうしていいかまったくわからず悩んでいます 教えてくださいおねがいします
68ポイント を落としてしまった。
|
|
|
|
Name: 管理人 [URL] ..ハッカー(115,123ポイント)
Date: 2006/12/07(木) 20:35
No:2447
|
|
Title: Re:配列
|
|
たくみさんこんばんは。
管理人です。
>配列に文字を入力し、その配列全て足し合わせ、文字と和をファイルに保存する
数値を入力するんじゃなくて文字なんですか?
それとも数値を文字として読み込んで、数字に変換し、たしあわせて、さらに文字として出力するということですか?
どこで躓いていますか?
120ポイント を手に入れた。
|
|
|
|
|
Name: 管理人 [URL] ..ハッカー(115,434ポイント)
Date: 2006/12/07(木) 23:47
No:2448
|
|
Title: Re:配列
|
|
キーボードから文字を入力するのに、初心者のうちによく使われる関数は
scanf
getchar
だと思いますが亜、
「配列に文字を入力し」
という言葉からしても
scanf("%d",&a);
とするのはダメみたいですね。
getchar関数で1文字ずつ読み取って配列にいれていく方法が思いつかれますけれども、
たとえばgetchar関数を使用して
1234
と入力した際に
st[0]=1
st[1]=2
st[2]=3
st[3]=4
st[4]=\0
と格納し、atoi関数という文字列をint型関数に変換する関数を使って
整数型にし、そこから和を求める方法です。
出力は%dを使って整数型として出力するほうが一般的だと思いますが、文字列にまた直して
ファイルに出力したほうがいいんですか?
このプログラムは主に3つに分かれると思います。
・文字入力
・和を求める
・ファイル出力
このどの辺でつまづいていらっしゃいますか?
311ポイント を手に入れた。
|
|
|
|
|
Name: たくみ ..ぴよぴよ(128ポイント)
Date: 2006/12/08(金) 02:30
No:2462
|
|
Title: Re:配列
|
|
正直にいえばすべてでつまずいてしまっています ごめんなさい。
先生におききしたところ、数値を文字として読み込んで、たしあわせて、文字とそのたしあわせた値2つを出力して保存するということらしいです
74ポイント を手に入れた。
|
|
|
|
|
Name: 管理人 [URL] ..ハッカー(116,832ポイント)
Date: 2006/12/08(金) 02:51
No:2466
|
|
Title: Re:配列
|
|
まず、入力するというプログラムを考えましょう。
scanfという関数を使えば、キーボードからの入力が格納できます。
http://www5c.biglobe.ne.jp/~ecb/c/c00.html
こちらのサイトでscanfについて勉強してください。
文字列
char st[100];
と宣言すれば、99個最大で文字が格納できます。
というのも文字列というのは最後に文字列の最後である終端記号\0が必要だからです。
実際に数字が格納できるのは準備した要素数-1になるわけです。
ところで、関数の書き方は
scanf("%s",st);
です。
するとこの関数に差し掛かったとき、stに入力文字列が格納されます。
実際に表示されたかどうか確認するのはprintfでできますから
printf("%s\n",st);
で表現できますね。
では、これらを使って、まず
・文字列宣言
・キーボードから1文読み取り
・入力結果表示
を行うプログラムを自分で作ってみてください。
出来たら投稿してください。
233ポイント を落としてしまった。
|
|
|
|
|
Name: たくみ ..ぴよぴよ(42ポイント)
Date: 2006/12/08(金) 22:06
No:2521
|
|
Title: Re:配列
|
|
すみませんサイトをみたり教科書や図書館でしらべても、わかりませんでした。授業についていくのがやっとで、落ちこぼれの自分にはこの課題はどうしていいか皆目検討がつきません
86ポイント を落としてしまった。
|
|
|
|
|
Name: 管理人 [URL] ..ハッカー(121,212ポイント)
Date: 2006/12/08(金) 22:46
No:2522
|
|
Title: Re:配列
|
|
C言語を書き始めるときは
#include <stdio.h>
と書きます。
これは入門のうちは「C言語のはじまり」という意味として覚えておけばいいでしょう。
プログラムにはすべてメイン関数というものが必要です。
void main(){
と書き始めます。
このメイン関数の中にすべての処理をかいていきます。
処理がおわれば
}
で閉じます。
これで、わかりますね?
自分の思うプログラムが出来るかと思いますが、どうでしょうか。
ちょっと自分の力でやってみてください。
162ポイント を手に入れた。
|
|
|
|
|
Name: たくみ ..ぴよぴよ(166ポイント)
Date: 2006/12/09(土) 03:49
No:2523
|
|
Title: Re:配列
|
|
そこまで無知なわけではなく、文字列を関数にわたすような
#include<stdio.h>
void strout(char ss{[]);
int main (void)
{
char st[]="ABCDEF"
strout(st);
strout("ABab12");
return0;
}
というようなものなら簡単にできるのですが、この問題は特別課題らしく調べられるものすべてを使ってよい
というかんじで学校の先生もあまり教えてくれず悩んでいるのが現状です
124ポイント を手に入れた。
|
|
|
|
|
Name: Justy ..プログラマー(34,561ポイント)
Date: 2006/12/09(土) 04:26
No:2524
|
|
Title: Re:配列
|
|
結局何をするプログラムを作りたいのかよくわからないのですが、推測すると
1 数値を入力させ、文字列として受け取る
2 文字列を数値化し、整数の配列に入れる
3 1と2を複数回繰り返し、配列を埋める(回数不明)
4 配列の中身の全要素を全て足す
5 ファイルに配列内の数値の羅列と、4の結果を書き出す
か若しくは
1 charの配列に文字列を入力させる。
2 その配列の各 char値を加算する
3 1の文字列と2の結果をファイルに出力する
のどちらかかな、と思いますが・・・。
(と、書いてる途中で後者の可能性が高そうな気がしてきました)
243ポイント を手に入れた。
|
|
|
|
|
Name: 管理人 [URL] ..ハッカー(121,385ポイント)
Date: 2006/12/09(土) 05:32
No:2525
|
|
Title: Re:配列
|
|
結局何がやりたいのかよくわかりませんし、
少しずつ解説していくと、全て解らないし検討もつかないといわれ、1から解説するとそこまで無知じゃないと
言われましても困ります・・。
>調べられるものすべてを使ってよいというかんじ
どういう感じかよくわかりませんが、標準関数や特定のライブラリ関数の使用制限がないということでしょうか。
・文字入力
・文字>数値変換
・和を求める
・ファイル出力
という処理ではだめなんですか?
それとも文字コードの質問なんですか?
173ポイント を手に入れた。
|
|
|
|
|
Name: バグ ..上級者(15,424ポイント)
Date: 2006/12/09(土) 08:58
No:2526
|
|
Title: Re:配列
|
|
一通り読んでみたのですが、質問者の意図が分かりませんね…これでは答えようがないのでは?(^_^;)
36ポイント を手に入れた。
|
|
|
|
|
Name: たくみ ..ぴよぴよ(258ポイント)
Date: 2006/12/10(日) 03:20
No:2549
|
|
Title: Re:配列
|
|
今日先生にメールでしつこく聞いたところ今の自分たちのクラスのレベルでは解けないもんだいで、どのように考え答えを見つけ出してくるかがみたかったようです Justyさんの
1 charの配列に文字列を入力させる。
2 その配列の各 char値を加算する
3 1の文字列と2の結果をファイルに出力する
という考えで正解みたいでした。
92ポイント を手に入れた。
|
|
|
|
|
Name: 管理人 [URL] ..ハッカー(124,217ポイント)
Date: 2006/12/10(日) 03:27
No:2552
|
|
Title: Re:配列
|
|
>どのように考え答えを見つけ出してくるかがみたかったようです
難しい問題をどこまで解いてくるかみるというのならわかりますが、
よくわからないことする先生ですね・・。
>その配列の各 char値を加算する
つまり、文字コードの合計をだしたいわけでしょうか。
出力は
char型で、文字を出力
int型で文字コードの合計値を出力
でいいんでしょうか?
102ポイント を手に入れた。
|
|
|
|
|
Name: 管理人 [URL] ..ハッカー(124,371ポイント)
Date: 2006/12/10(日) 03:39
No:2554
|
|
Title: Re:配列
|
|
入力した文字コードの合計を求めるプログラムです。
#include <stdio.h>
int main(){
int x[100],i=0,j,sum=0;
while((x[i]=getchar())!='\n' && i<100)
i++;
for(j=0;j<i;j++)
sum+=x[j];
return 0;
}
単純に配列の中身をたしているだけです。
154ポイント を手に入れた。
|
|
|
|
|
Name: たくみ ..ぴよぴよ(303ポイント)
Date: 2006/12/10(日) 18:22
No:2568
|
|
Title: Re:配列
|
|
わがままばかりいってしまいごまんなさい。
管理人さんにしめしていただいた部分にあらたにつけたす感じで考えてゆけばいいんですよね
45ポイント を手に入れた。
|
|
|
|
|
Name: たくみ ..ぴよぴよ(347ポイント)
Date: 2006/12/11(月) 01:13
No:2592
|
|
Title: わかりません
|
|
管理人さんに示していただいたものを自分なりに本を見たり友達と相談しながらどう手を加えればよいのかいろいろ試してみましたが、思いどうりのものができません。 やはりむりなのでしょうか・・・・・ だれか助けてください
44ポイント を手に入れた。
|
|
|
|
|
Name: ま〜く ..ぴよぴよ(196ポイント)
Date: 2006/12/11(月) 01:49
No:2593
|
|
Title: Re:わかりません
|
|
初めて質問の回答をします♪
いままでの流れを呼んでいて思ったのですが、たくみさんの質問
>「配列に文字を入力し、その配列全て足し合わせ、文字と和をファイルに保存する」
がそのままの課題の内容だとすると仕様が不明確ですよね。
(授業の流れ(この課題の出される授業の前回や前々回の授業)からある程度絞れるかもしれませんが・・・)
こんな課題が出されるか分からないけど、「仕様を詰める」と言うのが答えだったりして^^;
あ〜でも
>1 charの配列に文字列を入力させる。
>2 その配列の各 char値を加算する
>3 1の文字列と2の結果をファイルに出力する
が正解と言ってるしなぁ〜
247ポイント を落としてしまった。
|
|
|
|
|
Name: Justy ..プログラマー(38,205ポイント)
Date: 2006/12/11(月) 01:49
No:2594
|
|
Title: Re:わかりません
|
|
実際問題、後は管理人さんのコードにファイルに保存する機能をつけるだけで完成すると思うのですが、具体的にどこで詰まっているのでしょうか。
>いろいろ試してみましたが
いろいろ試してみてどうなったのでしょうか。
その最終版というか、たくみさんなりに正解に近いと思うコードを見せてください。
100ポイント を手に入れた。
|
|
|
|
|
Name: たくみ ..ぴよぴよ(367ポイント)
Date: 2006/12/11(月) 02:05
No:2595
|
|
Title: Re:わかりません
|
|
justy さんへ 保存する機能とは単にprintfをつけくわえる感じでよろしいのでしょうか
20ポイント を手に入れた。
|
|
|
|
|
Name: Justy ..プログラマー(38,245ポイント)
Date: 2006/12/11(月) 02:15
No:2597
|
|
Title: Re:わかりません
|
|
>単にprintfをつけくわえる感じで
いえ、コンソール上のテキストへの出力ならそれでいいのですが、ファイルを対象にしているので fopen〜fprintf/fputsなど〜fcloseの一連のファイル操作処理を付け加える感じになります。
40ポイント を手に入れた。
|
|
|
|
|
Name: たくみ ..ぴよぴよ(441ポイント)
Date: 2006/12/11(月) 03:05
No:2598
|
|
Title: Re:わかりません
|
|
今まで単にprintfとかいていたのですが、それが間違いであったのかもしれません。fprintf(" "); というようなものをどのあたりに加えれば大丈夫なのでしょうか
74ポイント を手に入れた。
|
|
|
|
|
Name: mas ..入門者(3,037ポイント)
Date: 2006/12/11(月) 08:30
No:2602
|
|
Title: Re:わかりません
|
|
fopen, fprintf等を検索してみましたか?
ファイル入出力に関しては数多くのサンプルが見つかるはずなので、
それを見たり、試しに実行してみると理解しやすいと思います。
もし解からないことがあるなら、どこが解からないかをはっきりさせてから、ここに質問すればよいでしょう。
133ポイント を手に入れた。
|
|
|
|
|
Name: たくみ(ダメ人間) ..ぴよぴよ(237ポイント)
Date: 2006/12/12(火) 23:46
No:2694
|
|
Title: Re:わかりません
|
|
fopen, fprintf両方ともまだ学校でならっていないものでした。検索してみて ファイルのオープン→ファイルの読み書き→ファイルのクローズという感じでつながっていくということを勉強させていただきました。fopenの式として、fopen(char filename,char openmode)とかくみたいでした。 fcloseというものもあわせてのっていましたが、
#include <stdio.h>
int main(){
int x[100],i=0,j,sum=0;
while((x[i]=getchar())!='\n' && i<100)
i++;
for(j=0;j<i;j++)
sum+=x[j];
return 0;
}
このプログラムにもfopenとfclose両方いるのでしょうか
237ポイント を手に入れた。
|
|
|
|
|
Name: 管理人 [URL] ..ハッカー(125,489ポイント)
Date: 2006/12/13(水) 00:11
No:2695
|
|
Title: Re:わかりません
|
|
ファイル操作をしていないので、fopenはいりません。
ファイルを開いていないのならfcloseは必要ありません。
上記のプログラムはファイルからデータを取ってくる処理をしていません。
getcharでキーボードからの1文字ずつをとってくる処理になっています。
文字コードの合計を出したらそのまま終わっています。
121ポイント を手に入れた。
|
|
|
|
|
Name: たくみ(ダメ人間) ..ぴよぴよ(328ポイント)
Date: 2006/12/13(水) 00:25
No:2696
|
|
Title: Re:わかりません
|
|
他の方々から「後は保存する部品を組み込むだけだよ」というアドバイスと「fopenを使ってみたら」というアドバイスを受けたのですが、fopenは他の場所にtxtファイルがある時に呼んでくるのに使うとものっていました。 管理人さんに作っていただいたものはポインタというものなのでしょうか
91ポイント を手に入れた。
|
|
|
|
|
Name: GPGA ..上級者(15,555ポイント)
Date: 2006/12/13(水) 01:06
No:2697
|
|
Title: Re:わかりません
|
|
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE* fp = NULL;
int num = 10;
fp = fopen("test.txt", "w");
if (fp == NULL) {
printf("ファイル書き込みエラー\n");
exit(1);
}
fprintf(fp, "今日は%d才の誕生日だよ\n", num);
fclose(fp);
return EXIT_SUCCESS;
}
上記のプログラムは、テキストファイルを作成しそこに文字列を書き込むサンプルプログラムです。
順番に解説します。
FILE* fp = NULL;
ファイルを扱う場合は、ファイルポインタを宣言します。
ファイルポインタ一つに付き、一ファイルを扱うと考えてください。
fp = fopen("test.txt", "w");
上記はファイルを開くプログラムです。
fopenの第一引数には対象になるファイルのパスを指定します。
第二引数には対象のファイルの扱いを指定します。
"w" はテキストファイルを新規に書き込むという意味です。
これは、test.txtが存在しなければ、新規に作成し
存在していれば、中身を全て消して新しく作るという意味です。
fopen関数は失敗するとNULLを返します。
したがって、fopenの後fpをチェックし、NULLであればエラー表示を行ってプログラムを終了します。
fprintf(fp, "今日は%d才の誕生日だよ\n", num);
fprintfは対象のファイルに文字列を書き込みます。
第一引数が対象となるファイルポインタとなり、第二引数以降は
printfと同じ扱いです。
fclose(fp);
使い終わったファイルは閉じましょう。
以上となります。
何かわからないところはありますでしょうか?
628ポイント を手に入れた。
|
|
|
|
|
Name: たくみ(ダメ人間) ..ぴよぴよ(474ポイント)
Date: 2006/12/13(水) 01:25
No:2698
|
|
Title: Re:わかりません
|
|
丁寧な解説ありがとうございます
今回の配列に文字を入力し、その配列全て足し合わせ、文字と和をファイルに保存する
1 charの配列に文字列を入力させる。
2 その配列の各 char値を加算する
3 1の文字列と2の結果をファイルに出力する
というもんだいではGPGAさんが解説してくださったtxtの部分を置き換える感じで管理人さんのプログラムに当てはめて考えていく感じでしょうか
146ポイント を手に入れた。
|
|
|
|
|
Name: GPGA ..上級者(15,576ポイント)
Date: 2006/12/13(水) 01:59
No:2699
|
|
Title: Re:わかりません
|
|
> GPGAさんが解説してくださったtxtの部分を置き換える感じで管理人さんのプログラムに当てはめて考えていく感じでしょうか
今回の場合に関しては、そう考えてもらってかまいません。
21ポイント を手に入れた。
|
|
|
|
|
Name: 管理人 [URL] ..ハッカー(125,841ポイント)
Date: 2006/12/13(水) 03:27
No:2703
|
|
Title: Re:わかりません
|
|
おぉ、ま〜くさん、回答お初ありがとうございます♪
たくみさん、もうそのまんま答えが皆さんの回答に載ってます。
ちょこっとだけ付け足したらいいだけで。
明日が提出締め切りということで、もっとほとんど答え状態のものをお教えしますから、
是非完成させてください(というか付け足すだけです)
まず、文字コードを数えるだけならint型でも出来ますが、
xの宣言はここはchar型でやっておきましょう。
宣言は全部でこうです。
FILE* fp = NULL;
int i=0,j,sum=0;
char x[100];
文字列というものは最後に終端記号を入れる必要があります。
これは最後に%sで文字列を一括出力するためです。
x[?]='\0';
?の部分はどこになるか考えてみてください。
fprintfで使う表現指示文字は
・int型は%d
・char型文字列は%s
でしたね。もうここまで聞けば出来たでしょう。
なお、カウントの仕方は
for(j=0;j<i;j++)
sum+=(int)x[j];
このようにするのが理想的☆
がんばってください!
352ポイント を手に入れた。
|
|
|
|
|
Name: たくみ(ダメ人間) ..ぴよぴよ(745ポイント)
Date: 2006/12/13(水) 13:32
No:2716
| 解決!
|
Title: Re:わかりません
|
|
今朝先生に提出してきました、今回は課題の文章もわかりずらかったため出した先生も少し後悔していました。あっているかどうかわかりませんが、こんな感じになりました
#include <stdio.h>
int main(){
FILE* fp = NULL;
int i=0,j,sum=0;
int x[100],i=0,j,sum=0;
char x[100];
while((x[i]=getchar())!='\n' && i<100)
i++;
for(j=0;j<i;j++)
sum+=(int)x[j];
return 0;
}
自分では間違っているかどうか判断できないので
正解のプログラムを教えていただけませんでしょうか
230ポイント を手に入れた。
|
|
|
|
|
Name: GPGA ..上級者(16,051ポイント)
Date: 2006/12/13(水) 14:01
No:2718
|
|
Title: Re:わかりません
|
|
#include <stdio.h>
#include <stdlib.h>
int main(){
FILE* fp = NULL;
int i = 0, j, sum = 0;
char x[100];
// キーボードからの文字列を取得する
while ((x[i] = getchar()) != '\n' && i < 100) {
i++;
}
x[i] = '\0'; // 文字列の終端コードを代入
// 文字コードの値を足す
for (j = 0; j < i; j++) {
sum += (int)x[j];
}
// ファイルを開く
fp = fopen("out.txt", "w");
if (fp == NULL) {
printf("ファイル作成エラー\n");
exit(1);
}
// out.txtに書き込む
fprintf(fp, "配列の文字:%s\n", x);
fprintf(fp, "char値の合計:%d\n", sum);
// ファイルを閉じる
fclose(fp);
return 0;
}
模範解答です。
一行一行のプログラムが何を行っているのかを考え
わからない所があれば質問してください。
447ポイント を落としてしまった。
|
|
|
|
|
Name: 管理人 [URL] ..ハッカー(126,421ポイント)
Date: 2006/12/13(水) 16:00
No:2722
|
|
Title: Re:わかりません
|
|
たくみさん、失礼ですが、自分の事をダメ人間と書く前に、自分で努力した姿勢が感じられません。
皆さんがあれだけわかりやすく答え同様の回答をしてくださっているにもかかわらず、
最後のプログラムにはファイル操作にかかわる処理が一つもありませんし、投稿されたソースは全角文字が含まれているので、コンパイルされたソースではないでしょう。
昨日からプログラムを勉強し始めた という事ではないですよね。
そこまで無知ではありませんという投稿のプログラムを見ても、少し考えたら理解できるレベルのはずです。
GPGAさんが、ファイル処理のソースはどうかくか、説明も詳しく書いてくださっています。
たくみさんは、それを読みましたか?
自分でも「fopen」「fclose」などと検索してみたり、本で読んで勉強してみたりしましたか?
普段であれば、最後にまだ解決されてない方には模範ソースと並べて詳しく説明を書くところですが、
すでに全て説明はされているので、もう説明は書くことがありません。
たくみさんも、きっと興味があって情報系を専攻されているんでしょう。
その授業料や貴重な時間を無駄にしないように、しっかり頑張ってください。
嫌味で言っているのだと捉えられてはそれまでですが、もう少ししっかり気合をいれて頑張っていただきたくて言いました。
努力してぶつかった壁はみんなで一生懸命あなたを支えて乗り越えさせてくれるはずです。
頑張ってください。
580ポイント を手に入れた。
|
|
|
|
Name: 困ったさん ..かけだし(1,434ポイント)
Date: 2006/12/12(火) 17:41
No:2671
|
|
Title: ポインタについて・・・その2
|
|
先程はありがとうございました。
今度は「倍精度実数型変数aと倍精度実数型ポインタ変数pを定義し、以下の動作を
行なうプログラムを作成しなさい。
@キーボードから実数aの値を読み込み、aに格納する
Aaの値とaのアドレスを画面表示する
Baのアドレスをpに代入しておき、pを通じてキーボードから実数を読み込む
Cpの指し示す先の要素の値とpの値を画面表示する」というものです。
今現在では
#include<stdio.h>
int main(void){
double a,*p=&a;
printf("実数aを入力 ->");
scanf("%lf",&a);
printf("a=%f &a=%p\n",a,&a);
return 0;
}
というところどまりでBとCの意味がよくわからなくて困っています。
この後どうすればいいのでしょうか?
198ポイント を手に入れた。
|
|
|
|
Name: 困ったさん ..かけだし(1,604ポイント)
Date: 2006/12/13(水) 12:38
No:2708
|
|
Title: Re:ポインタについて・・・その2
|
|
つまりこういうプログラムで大丈夫でしょうか?
#include<stdio.h>
int main(void){
double a;
double *p;
p=&a;
printf("実数aの値を入力 ->");
scanf("%lf",&a);
printf("a=%f &a=%p\n",a,&a);
printf("実数を入力 ->");
scanf("%lf",p);
printf("*p=%f p=%p\n",*p,p);
return 0;
}
154ポイント を手に入れた。
|
|
|
|
|
Name: 困ったさん ..かけだし(1,770ポイント)
Date: 2006/12/13(水) 14:06
No:2719
|
|
Title: Re:ポインタについて・・・その2
|
|
はい。そうなりました。みなさんありがとうございましたm(__)m
2倍のポイントを手に入れた! 40ポイント を手に入れた。
|
|
|
|
Name: Justy ..熟練のプログラマー(42,733ポイント)
Date: 2006/12/13(水) 02:36
No:2701
|
|
Title: <off> MSVC7.1の atof
|
|
どーでもいい話なんですが。
Visual C++ (MSVC7.1)付属のライブラリの atofって内部で strlen()がコールされています。
つまり、んMBものテキストの先頭で atofを何度も何度も使った日には、呼ばれるたびにテキストの終端までチェックするので、結構処理負荷が高くなります。
実際ずっと前作っていた大容量のテキストを扱っていたアプリで何十万とある浮動小数の読みとり処理に atofが使われていたことがあり、処理に数分かかっていたものがここを改善しただけで2,3秒まで短縮されました。
元々 atoX系はエラーチェックができないという致命的な欠陥がありますし、すこーし避けたほうがいいのかもしれません。
246ポイント を手に入れた。
|
|
|
|
Name: Justy ..熟練のプログラマー(42,960ポイント)
Date: 2006/12/13(水) 03:32
No:2704
|
|
Title: Re:MSVC7.1の atof
|
|
>atoX系の代わりといえばstrtoX系ですかね、エラーチェックもできますし。
困ったことに double版の strtod()も内部で strlenが使われているんです。
さらなる代替手段となると sscanfくらいだと思うんですが、わざわざ %fとか指定するのも・・・って思います。
上記の時は結局自作しました。
>高木信尚さんのブログ内に
あ、こちらは巡回 RSSでチェックしてます。
標準関数の中は結構考えられて作られてるなぁ、としみじみ。
227ポイント を手に入れた。
|
|
|
|
|
Name: Justy ..熟練のプログラマー(43,200ポイント)
Date: 2006/12/13(水) 03:32
No:2705
|
|
Title: Re:MSVC7.1の atof
|
|
最近は数値は boost::spiritで処理していたりします。
一応 spiritは数値が文字列内のどこからどこまでかを正しく判定しているので速いかな、と勝手に妄想しています。
ちゃんと調べたことはないですが・・・。
240ポイント を手に入れた。
|
|
|
|
|
Name: GPGA ..上級者(16,498ポイント)
Date: 2006/12/13(水) 11:40
No:2707
|
|
Title: Re:MSVC7.1の atof
|
|
簡単タグ入力がこの掲示板に存在していると今頃気づきました。orz
> 困ったことに double版の strtod()も内部で strlenが使われているんです。
う、それは困りますね。
> 最近は数値は boost::spiritで処理していたりします。
boostですか。
噂を聞いた程度で実際に使用したことは一度もないです。
STLもほとんど使ったことありませんし。
ここ半年ほどJavaをやっている毎日であります。
仕事とは別で、勉強するべきなんでしょうけど
そういう場合は、大抵C#やったりほかのことをやったりするんですよね。
最近仕事がいそがしすぎて、仕事以外のことをやっていないが実際のところですが。
仕事だけの日が続くと、boostやSTLを勉強する日が来るのは、仕事で必要になったとき
以外ありえないという考え方にだんだん変わってきます。
2倍のポイントを手に入れた! 636ポイント を手に入れた。
|
|
|
|
Name: ☆ ..かけだし(2,397ポイント)
Date: 2006/12/12(火) 22:06
No:2682
|
|
Title: 2点間の距離を求める
|
|
質問です!!
お願いします。
以下の3つの条件を満たすプログラムを作成せよ.
* x座標およびy座標のペアとして構成されるPOINT構造体を以下に示すように定義せよ.
* 2つ以上5つまでの任意の数の座標p1(x,y)~pn(x,y)の入力を受け付け,構造体配列に代入せよ.
* 任意の二つの座標を選び,その座標間の距離を出力せよ.
という問題です。
自分で作ったのが、
#include <stdio.h>
#include <math.h>
#define range(v1,v2,w1,w2) (sqrt((v1-w1)*(v1-w1)+(v2-w2)*(v2-w2)))
int main()
{
double x[2], y[2];
printf("2次元空間の点の座標を入力して下さい ");
scanf("%lf %lf", &x[0], &x[1]);
printf("もう1つの点の座標を入力して下さい ");
scanf("%lf %lf", &y[0], &y[1]);
printf(" 2つの点の距離は %f\n", range(x[0],x[1],y[0],y[1]));
return 0;
}
です。一応、距離はできたんですが・・構造体を使わなければいけないので・・・・
しかも、『2つ以上5つまでの任意の数の座標p1(x,y)~pn(x,y)の入力を受け付け,構造体配列に代入せよ.』
というところもプログラミングに反映されていませんよねぇ。。
もーこれ以上分からない状況に陥っています。。御指導お願いします。
85ポイント を手に入れた。
|
|
|
|
Name: box ..上級者(17,910ポイント)
Date: 2006/12/12(火) 22:28
No:2683
|
|
Title: Re:2点間の距離を求める
|
|
サンプルです。
#include <stdio.h>
#include <math.h>
#define range(v1,v2,w1,w2) (sqrt((v1-w1)*(v1-w1)+(v2-w2)*(v2-w2)))
typedef struct {
double x;
double y;
} POINT;
int main(void)
{
POINT p[5];
int n, i, a, b;
do {
printf("いくつの点を入力しますか?(2〜5):");
scanf("%d", &n);
} while (n < 2 || 5 < n);
for (i = 0; i < n; i++) {
printf("p%dのx,y座標を入力してください:", i + 1);
scanf("%lf%lf", &p[i].x, &p[i].y);
}
do {
printf("2つの点を選んでください(1〜%d):", n);
scanf("%d%d", &a, &b);
} while ((a == b) || (a < 1 || n < a) || (b < 1 || n < b));
printf("%f %f\n", p[a-1].x, p[a-1].y);
printf("%f %f\n", p[b-1].x, p[b-1].y);
printf("この2点間の距離は\n");
printf("%f\n", range(p[a-1].x, p[a-1].y, p[b-1].x, p[b-1].y));
return 0;
}
412ポイント を手に入れた。
|
|
|
|
|
Name: ☆ ..入門者(2,636ポイント)
Date: 2006/12/12(火) 22:35
No:2684
|
|
Title: Re:2点間の距離を求める
|
|
返信ありがとうございます。
それで、質問なんですが、自分で書いといて、悪いんですが、
#define range(v1,v2,w1,w2) (sqrt((v1-w1)*(v1-w1)+(v2-w2)*(v2-w2)))
ってなんですか??授業で今日やったので、使ってみたんですが、意味が分かりませんでした。
あと、
typedef struct {
double x;
double y;
} POINT;
のところは、単に、
struct POINT{
int x;
int y;
};
でもいいんでしょうか??
typedefは使わないこと!!!って言う条件なんですよねぇ。。
239ポイント を手に入れた。
|
|
|
|
|
Name: box ..上級者(19,090ポイント)
Date: 2006/12/12(火) 23:01
No:2685
|
|
Title: Re:2点間の距離を求める
|
|
> #define range(v1,v2,w1,w2) (sqrt((v1-w1)*(v1-w1)+(v2-w2)*(v2-w2)))
#defineは、コンパイル時に、文字の置き換えを行ないます。
今回は、コード中に
range(p[a-1].x, p[a-1].y, p[b-1].x, p[b-1].y)
という記述があります。
したがって、
v1→p[a-1].x
v2→p[a-1].y
w1→p[b-1].x
w2→p[b-1].y
という置き換えを行ないます。つまり、
range(p[a-1].x, p[a-1].y, p[b-1].x, p[b-1].y)
は、
(sqrt((p[a-1].x-p[b-1].x)*(p[a-1].x-p[b-1].x)+(p[a-1].y-p[b-1].y)*(p[a-1].y-p[b-1].y)))
と書いたのと同じです。
typedefを使わないコードの例です。
#include <stdio.h>
#include <math.h>
#define range(v1,v2,w1,w2) \
(sqrt((double)(v1-w1)*(v1-w1)+(double)(v2-w2)*(v2-w2)))
struct POINT {
int x;
int y;
};
int main(void)
{
struct POINT p[5];
int n, i, a, b;
do {
printf("いくつの点を入力しますか?(2〜5):");
scanf("%d", &n);
} while (n < 2 || 5 < n);
for (i = 0; i < n; i++) {
printf("p%dのx,y座標を入力してください:", i + 1);
scanf("%d%d", &p[i].x, &p[i].y);
}
do {
printf("2つの点を選んでください(1〜%d):", n);
scanf("%d%d", &a, &b);
} while ((a == b) || (a < 1 || n < a) || (b < 1 || n < b));
printf("%5d%5d\n", p[a-1].x, p[a-1].y);
printf("%5d%5d\n", p[b-1].x, p[b-1].y);
printf("この2点間の距離は\n");
printf("%f\n", range(p[a-1].x, p[a-1].y, p[b-1].x, p[b-1].y));
return 0;
}
2倍のポイントを手に入れた! 1,180ポイント を手に入れた。
|
|
|
|
|
Name: ☆ ..入門者(2,718ポイント)
Date: 2006/12/12(火) 23:04
No:2686
| 解決!
|
Title: Re:2点間の距離を求める
|
|
なるほど!!!!
やっとのことで、今日の授業もわかりました★^^;
ありがとうございます。
これは、ライブラリー関数なので、cc -lm test.cという風にコンパイルするんですよね!!
本当に分かりやすい、説明、ありがとうございました。
82ポイント を手に入れた。
|
|
|
|
|
Name: 管理人 [URL] ..ハッカー(125,041ポイント)
Date: 2006/12/12(火) 23:22
No:2688
|
|
Title: Re:2点間の距離を求める
|
|
☆さん、こんばんは。
遅れてしまって申し訳ないです。
余談ですが、
typedef struct {
・・・
と
struct POINT{
・・・
は、前者だと、宣言時に毎回structって書く手間が省るものだと覚えておくといいと思います。
前者は「int型」みたいに、構造体バージョンの「POINT型」っていう型を作ってくれるんですね。
91ポイント を手に入れた。
|
|
|
|
|
Name: ☆ ..入門者(2,823ポイント)
Date: 2006/12/12(火) 23:26
No:2689
|
|
Title: Re:2点間の距離を求める
|
|
管理人さん、こんばんは。
大丈夫ですよ。
なるほど!!
たしかに、
struct の場合は、なんかいも後で、structって書きますよね☆
そーゆー意味だったんですね。
さらに勉強になりました。
ありがとうございます。
105ポイント を手に入れた。
|
|
|
|
|
Name: ☆ ..入門者(2,910ポイント)
Date: 2006/12/12(火) 23:33
No:2693
|
|
Title: Re:2点間の距離を求める
|
|
いえいえ^^
こっちこそ、丁寧な説明ありがとうざいます☆
これからも、がんばりますよー!!!^^
今回もありがとうございました☆
ではでは、おやすみなさぁーい♪(笑)
87ポイント を手に入れた。
|
|
|
|
Name: たく ..ぴよぴよ(58ポイント)
Date: 2006/12/12(火) 01:40
No:2633
|
|
Title: インストールの仕方
|
|
初めまして。
学校でC言語を習うようになって、自宅でもやりたいとおもったのですが、どうすれば自宅のPCでCが使えるようになるのかわかりません。
友達に聞いても「普通にインストールすればいいじゃん」と言われてしまい、それ以上聞けなくて困ってます。
ものすごく根本的な質問で申し訳ないのですが、どこのサイトでどういうことをすれば使えるようになるのか、誰か教えていただけませんか?
58ポイント を手に入れた。
|
|
|
|
Name: たく ..ぴよぴよ(81ポイント)
Date: 2006/12/12(火) 20:22
No:2679
| 解決!
|
Title: Re:インストールの仕方
|
|
ありがとうございます。
早速やってみます。
(既出だったみたいで、すみません。)
23ポイント を手に入れた。
|
|
|
|
Name: ME ..初心者(5,234ポイント)
Date: 2006/12/12(火) 11:59
No:2645
|
|
Title: 数字か改行のみの入力
|
|
前回レスくださったお二方ありがとうございました。
今度は修正の関数を作っていたのですが、
文字列以外の修正がうまくいきません。
作りたい機能は
・何番目かのデータを選択して一つずつ表示、
変更なしの場合はエンター、変更する場合は入力
・数字のところは半角数字以外が入力されるとエラー、再入力
というものです。どちらか片方なら実現できたのですが・・・
ソースを載せるので訂正すべき点を指摘いただけると助かります。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define BUF 128
typedef struct list {
char name[30];
int num;
struct list *next; /* 次のデータへのポインタ */
struct list *prev; /* 次のデータへのポインタ */
}List;
List *add( char *str,int num, List *head )
{
List *p;
if ( ( p = ( List * )malloc( sizeof( List ) ) ) == NULL ) {
printf( "malloc error\n" );
exit( 1 );
}
strcpy( p->name, str );
p->num = num;
p->next = NULL;
if(head){
List *q = head;
while(q->next)
q = q->next;
q->next = p;
}else{
p->next = NULL;
head = p;
}
return head;
}
List *write(int code, List *head, List *tail)
{
List *p;
char name[30];
int num=1;
if (head != NULL){
for ( p = head; p->next != NULL; p = p->next ) num++;
num++;
}
code = 1;
while(code==1){
if(code == 4) break;
printf( "名前:" ); scanf( "%s", name );getchar();
printf("No.%d\n",num);
printf("%s No.%d\n",name, num);
head = add( name, num, head );
if( head == NULL ) head = tail;
num++;
printf("追記:1 終了:4 →");
while(1){
scanf("%d",&code);getchar();
if (code==1 || code==4 ) break;
else rewind(stdin);
}
}
return(head);
}
/*** データ修正 ここの数字入力のところです。***/
List *edit(List *head)
{
List *p = head;
char buf[BUF];
int i, cnt = 0;
puts("何番を修正しますか?");
scanf("%d", &i); gets(buf);
while (p != NULL) {
if (++cnt == i) {
printf("変更しない場合は単に[return]を押下\n");
printf("名前: %s -> ", p->name);
gets(buf);
if (strlen(buf)) strcpy(p->name, buf);
printf("番号: %d -> ", p->num);
gets(buf);
if (strlen(buf)) p->num=atoi(buf);//ここの条件設定です。
return head;
} else p = p->next;
}
puts("番号がありません");
return head;
}
void dispall( List *p )
{
while ( p != NULL) {
printf( "%s No.%d\n",p->name,p->num );
p = p->next; }
}
int main( void )
{
List *head= NULL;
List *tail= NULL;
List *p;
int code;
while( 1 ) {
printf( "入力:1 表示:3 修正:4 終了:5 →");
scanf( "%d", &code );getchar();
if ( code == 5 ) break;
else if ( code == 1 ){ head = write(code, head, tail);
}else if ( code == 3 ){ dispall(head);
}else if ( code == 4 ){ edit(head);
}else rewind(stdin);
}
while ( head != NULL ) {
p = head->next;
free( head );
head = p;
}
return 0;
}
2倍のポイントを手に入れた! 2,228ポイント を手に入れた。
|
|
|
|
Name: Justy ..熟練のプログラマー(42,193ポイント)
Date: 2006/12/12(火) 12:44
No:2647
|
|
Title: Re:数字か改行のみの入力
|
|
>数字のところは半角数字以外が入力されるとエラー、再入力
こんな感じ?
do
{
printf("番号: %d -> ", p->num);
gets(buf);
if(!strlen(buf) || sscanf(buf, "%d", &p->num)) // 無入力か数値に変換できれば終了
return head;
rewind(stdin);
}while(1);
225ポイント を手に入れた。
|
|
|
|
|
Name: box ..上級者(16,211ポイント)
Date: 2006/12/12(火) 13:28
No:2650
|
|
Title: Re:数字か改行のみの入力
|
|
> struct list *prev; /* 次のデータへのポインタ */
本題とは無関係ですが、構造体のメンバーprevを使っていません。
・prevを残すなら、きちんと双方向リストにする
・単一方向リストでよいのであれば、prevの定義を削除する
のいずれかにすべきでありましょう。
88ポイント を手に入れた。
|
|
|
|
|
Name: ME ..初心者(5,273ポイント)
Date: 2006/12/12(火) 17:23
No:2668
| 解決!
|
Title: Re:数字か改行のみの入力
|
|
boxさんソース読ませていただきました。
sscanfはファイルの読み込み以外にも使えたんですね。
prevは削除機能を追加する時のために用意してあったのですが、
関数が出来上がるまでは定義から消しておくことにします。
ありがとうございました。
39ポイント を手に入れた。
|
|
|
|
Name: satoshi ..ぴよぴよ(43ポイント)
Date: 2006/12/09(土) 11:04
No:2527
|
|
Title: スレッド間のデータのやりとりについて
|
|
はじめまして。
今、スレッドについて勉強しています。そこでスレッド間のメッセージのやりとりの方法がいまいちよくわかりません…
PostThreadMessage()でメッセージの送信、GetMessage()でメッセージの受信でよろしいのでしょうか?
また、PostThreadMessage()の引数が何をいれたらいぃのかわかりません。
ちなみに送信したい内容はchar型のstrというデータで送信先のスレッド名はanswer_threadです。
詳しい人がいたらご教授をお願いします。また、他の方法でデータのやりとりをしている人がいたら教えてください。
43ポイント を手に入れた。
|
|
|
|
Name: Justy ..プログラマー(34,734ポイント)
Date: 2006/12/09(土) 17:02
No:2529
|
|
Title: Re:スレッド間のデータのやりとりについて
|
|
ポスト先のスレッドに予めメッセージキューを作成してあるなら、それでも。
普通はスレッド間のデータ共有にはクリティカルセクションとか、ミューテックスとか、セマフォなど同期オブジェクトを状況に合わせて使います。
>また、PostThreadMessage()の引数が何をいれたらいぃのかわかりません
送る型は char型の変数 strなら、1バイトなのでさくっと
PostThreadMessage(ポスト先スレッドID,メッセージID, (WPARAM)str, 0)
なかんじで良いんじゃないでしょうか。
あとは MSDNとかは Googleで調べればいろいろもっと詳しいことがわかるかと思います。
173ポイント を手に入れた。
|
|
|
|
|
Name: satoshi ..ぴよぴよ(209ポイント)
Date: 2006/12/10(日) 11:11
No:2562
|
|
Title: Re:スレッド間のデータのやりとりについて
|
|
Justyさん、ご回答いただきありがとうございました。
PostThreadMessage()の引数はそんな内容だったんですね。
ありがとうございました。
ところで、PostThreadMessage()が送信したメッセージが、スレッドで受け取るにはGetMessage()でもよいと仰っていましたが、以下のような使い方でよろしいのでしょうか。
MSG msg;
GetMessage(&msg, NULL, 0, 0);
この場合、GetMessage()の引数であるmsgにstrの内容が格納されるのでしょうか?
147ポイント を手に入れた。
|
|
|
|
|
Name: Justy ..プログラマー(35,504ポイント)
Date: 2006/12/10(日) 15:25
No:2564
|
|
Title: Re:スレッド間のデータのやりとりについて
|
|
>GetMessage()でもよいと仰っていましたが、以下のような使い方でよろしいのでしょうか。
それでいいと思います。
>この場合、GetMessage()の引数であるmsgにstrの内容が格納されるのでしょうか?
MSDNか何かのリファレンスは読みましたか?
PostThreadMessage()側でどう設定したかにもよりますが、msg構造体の中のメンバ変数に格納されます。
以下はサンプルです(エラー処理とか何もしてないので注意)。
#include <windows.h>
#include <stdio.h>
DWORD MainThreadID;
DWORD WINAPI DoThread(LPVOID x)
{
char c = 'A';
do
{
PostThreadMessage(MainThreadID, WM_APP, (WPARAM)c, 0);
Sleep(100);
} while(isgraph(++c));
PostThreadMessage(MainThreadID, WM_QUIT, 0, 0);
return 0;
}
int main(void)
{
int count = 0;
MSG msg;
MainThreadID = GetCurrentThreadId();
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)DoThread, NULL, 0, NULL);
while(GetMessage(&msg, NULL, 0, 0) > 0)
{
if(msg.message == WM_APP)
printf("[%d] Receive %c\n", ++count, (char)msg.wParam);
}
return 0;
}
641ポイント を手に入れた。
|
|
|
|
|
Name: satoshi ..ぴよぴよ(296ポイント)
Date: 2006/12/10(日) 23:14
No:2588
| 解決!
|
Title: Re:スレッド間のデータのやりとりについて
|
|
Justyさん、回答ありがとうございます。
MSDNとかのリファレンスはいろいろ読んでるんですが、いまいち理解出来ないところが多くて‥
今回はサンプルプログラムまで載せてくれて、本当にありがとうございました。
あとは、なんとか理解してやってみます。
ご回答ほんとうにありがとうございました。
87ポイント を手に入れた。
|
|
|
|
|
Name: satoshi ..ぴよぴよ(650ポイント)
Date: 2006/12/11(月) 17:49
No:2617
|
|
Title: Re:スレッド間のデータのやりとりについて
|
|
わからないことが出てきたので、また質問させていただきます。
今、main()のスレッドで、char regstrに格納されたデータをans_thread()スレッドに送りたいんですが、
ポストの書式は、PostThreadMessage(at_id,WM_APP,(WPARAM)regstr,0);でよろしいのでしょうか?
また、受け取る側のスレッド(ans_thread())は、MSG msg;を宣言してGetMessage(&msg,NULL,0,0);でよろしいのでしょうか?
ちなみに、受け取ったデータをsend()で送りたいんですが、send(sock,msg.wParam,strlen(msg.wParam), 0);なかたちでよろしいのでしょうか…?このようにすると、「2 番目の引数を 'WPARAM' から 'const char *' に変換できません。」というエラーが発生します。
MSDNのリファレンスを見たのですがやはり理解に苦しみまして…
わかる人がいたらお願いします。
354ポイント を手に入れた。
|
|
|
|
|
Name: mas ..入門者(3,242ポイント)
Date: 2006/12/11(月) 19:07
No:2618
|
|
Title: Re:スレッド間のデータのやりとりについて
|
|
> strlen(msg.wParam)
とありますが、msg.wParamがWPARAM型であるのに対して、strlenの引数はchar*です。
従ってキャストする必要あります。
が、この場合msg.wParamはchar型のregstrですよね?
それなら文字列ではなくsizeof(char)=1byte固定なので、
send(sock,msg.wParam,1, 0);
でいいと思います。
# 上のほうを見ていて気になったのですが、
# 実はcharじゃなくてchar*(文字列)のやり取りをするつもりでということはないですよね?
26ポイント を手に入れた。
|
|
|
|
|
Name: Justy ..熟練のプログラマー(41,103ポイント)
Date: 2006/12/11(月) 19:55
No:2619
|
|
Title: Re:スレッド間のデータのやりとりについて
|
|
@masさん
>実はcharじゃなくてchar*(文字列)のやり取りをするつもり〜
strlenを見て私もそんな気がしてきました。
@satoshiさん
>ポストの書式は、PostThreadMessage(at_id,WM_APP,(WPARAM)regstr,0);でよろしいのでしょうか?
regstrの型が char(1バイト)ならOK。
ただ WM_APPのIDに関しては 0x8000〜0xBFFFの間で自由にIDを設定できるので、WM_APPのまま使わないで、自前で別定義を用意した方がいいでしょう(参考ページ)。
>受け取る側のスレッド(ans_thread())は〜でよろしいのでしょうか?
多分それでいいと思いますが、実際のところはその周辺をどう書いているのかにも依存します。
# もし万が一、送りたい型が charではなく char*ないしは char[]であるなら。
PostThreadMessage()では WPARAMと LPARAMの2つのパラメータしか送れません。
つまり合わせて最大8バイトまでです。
文字列を送りたいのであれば、ちょっと工夫が必要になります。
582ポイント を手に入れた。
|
|
|
|
|
Name: satoshi ..ぴよぴよ(760ポイント)
Date: 2006/12/11(月) 20:19
No:2620
|
|
Title: Re:スレッド間のデータのやりとりについて
|
|
masさん、Justyさん回答していただきありがとうございます。
>masさん
>実はcharじゃなくてchar*(文字列)のやり取りをするつもりでということはないですよね?
申し訳ありません。実はchar*でのやり取りでした。
>Justyさん
>もし万が一、送りたい型が charではなく char*ないしは char[]であるなら。
PostThreadMessage()では WPARAMと LPARAMの2つのパラメータしか送れません。
つまり合わせて最大8バイトまでです。
最大8バイトまでなんですか!?送るのは結構長い文字列なんですよね…
その場合は8バイトづつに分けて送るという感じなるんですか?
無知で申し訳ありません。
110ポイント を手に入れた。
|
|
|
|
|
Name: Justy ..熟練のプログラマー(41,629ポイント)
Date: 2006/12/11(月) 20:29
No:2621
|
|
Title: Re:スレッド間のデータのやりとりについて
|
|
>>最大8バイトまでなんですか!?送るのは結構長い文字列なんですよね…
ぱっと思いついたのを少しサンプルを改造して作ってみました。
動作を追ってみてください。
#include <windows.h>
#include <stdio.h>
#include <time.h>
static DWORD MainThreadID;
#define WM_APP_STRING (WM_APP + 10)
DWORD WINAPI DoThread(LPVOID x)
{
static const char * const str_tbl[]
= { "ABCDEFG", "abcdefg", "12345", "67890", "3.1415926535" };
unsigned counter = 50;
do
{
unsigned index = rand() % 5;
char *buff = (char*)malloc(5 + strlen(str_tbl[index]) + 1);
sprintf(buff, "%2d : %s", counter, str_tbl[index]);
PostThreadMessage(MainThreadID, WM_APP_STRING, 0, (LPARAM)buff);
Sleep(100);
} while(--counter);
PostThreadMessage(MainThreadID, WM_QUIT, 0, 0);
return 0;
}
int main(void)
{
int count = 0;
MSG msg;
MainThreadID = GetCurrentThreadId();
srand((unsigned)time(NULL));
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)DoThread, NULL, 0, NULL);
while(GetMessage(&msg, NULL, 0, 0) > 0)
{
if(msg.message == WM_APP_STRING)
{
char *receive_str = (char*)msg.lParam;
printf("[%d] Receive %s\n", ++count, receive_str);
free(receive_str);
}
}
return 0;
}
Post側で mallocしたバッファに文字列を入れ、Post先で使い終わったら解放しています。
この方法なら mallocできる限り多少文字列が長くても問題はないですが、決してメッセージの取りこぼしがあってはいけません。
あった場合、メモリリークになります。
この程度の文字列なら無理にメッセージで送らなくてもクリティカルセクション・セマフォとかの同期オブジェクトを使った方がいいかと思います。
526ポイント を手に入れた。
|
|
|
|
|
Name: satoshi ..ぴよぴよ(820ポイント)
Date: 2006/12/12(火) 12:35
No:2646
| 解決!
|
Title: Re:スレッド間のデータのやりとりについて
|
|
Justyさん、ありがとうございます。
サンプルまで載せていただきありがとうございます。
クリティカルセクションやセフォマとかでも出来るんですね。
勉強になります。そこらへんも調べてまた頑張ってみます。
ご回答ありがとうございました。
60ポイント を手に入れた。
|
|
|
|
Name: ぴよ ..ぴよぴよ(97ポイント)
Date: 2006/12/12(火) 10:39
No:2642
|
|
Title: 日本語入力
|
|
こんにちわ。
今C言語の入力について勉強しています。
scanf("%d",&a)
の変形で、英文字(列)・数字はできたのですが、
scanfのような関数を使って日本語入力で、
例えば「日本語」という文字を入力することは可能でしょうか?
97ポイント を手に入れた。
|
|
|
|
Name: box ..上級者(16,155ポイント)
Date: 2006/12/12(火) 11:11
No:2643
|
|
Title: Re:日本語入力
|
|
こんなコードを書きます。
#include <stdio.h>
int main(void)
{
char str[80];
puts("何か文字列を入力してください(日本語可)");
scanf("%s", str);
printf("入力した文字列は'%s'です。\n", str);
return 0;
}
仮にWindowsのコマンド・プロンプトで実行する場合、
入力を求められた時点で、Alt+漢字 を使って日本語入力モードにします。
すると、任意の2バイト文字列が入力できます。
136ポイント を手に入れた。
|
|
|
|
|
Name: ぴよ ..ぴよぴよ(120ポイント)
Date: 2006/12/12(火) 11:40
No:2644
| 解決!
|
Title: Re:日本語入力
|
|
Altキーを一緒に押すのは知らなかったです。
ありがとうございました!!
23ポイント を手に入れた。
|
|
|
|
Name: けいすけ ..ぴよぴよ(727ポイント)
Date: 2006/12/10(日) 18:23
No:2569
|
|
Title: 三角形
|
|
200×200画素の画像の中心に指定した底辺と高さの三角形を配置したプログラムを作成し
画像は1次元配列でmalloc関数を用いて動的にメモリを確保。
という課題が出たので自分で作ってみたのですが、出来ません( ノД`)シクシク
もしよろしければアドバイスよろしくお願いします。
#include <stdio.h>
#include <stdlib.h>
#define MS 200
main()
{
char fi[50];
int i,j,x0,x1,y,w,h;
FILE *fp;
unsigned short header[13]={0x4d42,54490,1,0,0,26,0,12,0,200,200,1,24};
unsigned char *bmp;
bmp=(unsigned char*)malloc(MS*MS*3);
for(i=0;i<=MS*MS-1;i++)
{
bmp[i*3+0]=255;
bmp[i*3+1]=0;
bmp[i*3+2]=0;
}
printf("Input width : ");
scanf("%s",fi);
w=atoi(fi);
printf("Input height : ");
scanf("%s",fi);
h=atoi(fi);
for(i=100-h/2;i<=100+h/2;i++)
{y=i-MS/2;
for(j=100-w/2;j<=100;j++)
{x0=j-MS/2;
bmp[(i*MS+j)*3+0]>=2*h*x0/w+h/2;
bmp[(i*MS+j)*3+1]<=2*h*x0/w+h/2;
bmp[(i*MS+j)*3+2]=0;
}
}
for(i=100-h/2;i<=100+h/2;i++)
{y=i-MS/2;
for(j=100;j<=100+w/2;j++)
{x1=j-MS/2;
bmp[(i*MS+j)*3+0]>=-2*h*x1/w+h/2;
bmp[(i*MS+j)*3+1]<=-2*h*x1/w+h/2;
bmp[(i*MS+j)*3+2]=0;
}
}
printf("Input file name : ");
scanf("%s",fi);
if((fp=fopen(fi,"wb"))==NULL)
{
fprintf(stderr,"Error : file open[%s].\n",fi);
exit(1);
}
fwrite(header,2,13,fp);
fwrite(bmp,1,200*200*3,fp);
fclose(fp);
}
570ポイント を手に入れた。
|
|
|
|
Name: Justy ..プログラマー(37,147ポイント)
Date: 2006/12/10(日) 21:17
No:2578
|
|
Title: Re:三角形
|
|
以前から bmpへの描画を行う課題に取り組まれていますよね。
main関数1つで書くのもそろそろ限界でしょうし、bmpへの描画を扱うライブラリ的なものを作られてはどうでしょうか。
こんなかんじで。
#include <stdio.h>
#include <stdlib.h>
// カラー構造体
typedef struct color
{
unsigned char b;
unsigned char g;
unsigned char r;
} color;
// キャンパス構造体
typedef struct campus_info
{
int width;
int height;
color * pixels;
} campus_info;
// キャンパス作成
static void create_campus(campus_info *info, int width, int height)
{
info->width = width;
info->height = height;
info->pixels = malloc(width * height * 3);
}
// キャンパスを塗りつぶす
static void fill_campus(const campus_info *info, const color *col)
{
int x, y;
if(!info || !col) return;
for(y=0; y<info->height; ++y)
{
int w = y * info->width;
for(x=0; x<info->width; ++x)
info->pixels[w + x] = *col;
}
}
// キャンパスに点を置く
static void put_pixel_campus(const campus_info *info, int x, int y, const color *col)
{
if(!info || !col
|| x < 0 || x >= info->width
|| y < 0 || y >= info->height) return;
info->pixels[(info->height-y-1)*info->width+x] = *col;
}
// キャンパスにラインを引く
static void put_line_campus(const campus_info *info, int sx, int sy, int ex, int ey, const color *col)
{
int x, y, step_x, step_y, fraction, deltaX, deltaY;
deltaX = ex - sx; if(deltaX < 0) deltaX = -deltaX;
deltaY = ey - sy; if(deltaY < 0) deltaY = -deltaY;
step_x = (sx <= ex)? 1: -1;
step_y = (sy <= ey)? 1: -1;
x = sx, y = sy;
if(deltaY >= deltaX)
{
fraction = deltaX * 2 - deltaY;
do
{
put_pixel_campus(info, x, y, col);
if(y == ey)
break;
if(fraction >= 0)
{
x += step_x;
fraction = fraction - deltaY;
}
y += step_y;
fraction = fraction + deltaX;
}while(1);
}
else
{
fraction = deltaY * 2 - deltaX;
do
{
put_pixel_campus(info, x, y, col);
if(x == ex)
break;
if(fraction >= 0)
{
y += step_y;
fraction = fraction - deltaX;
}
x += step_x;
fraction = fraction + deltaY;
}while(1);
}
}
// キャンパスの色を取得
static const color* get_pixel_campus(const campus_info *info, int x, int y)
{
if(!info
|| x < 0 || x >= info->width
|| y < 0 || y >= info->height) return NULL;
return &info->pixels[(info->height-y-1)*info->width+x];
}
// キャンパスを bmp形式で保存する
static void save_bmp_campus(const campus_info *info, const char *filename)
{
unsigned short header[13]
={ 0x4d42,54490,1,0,0,26,0,12,0,info->width,info->height,1,24};
FILE *fp;
if((fp=fopen(filename,"wb"))==NULL)
{
fprintf(stderr,"Error : file open[%s].\n",filename);
exit(1);
}
fwrite(header, 2, 13, fp);
fwrite(info->pixels, 1, info->height * info->width * 3, fp);
fclose(fp);
}
// キャンパスを破棄
static void destroy_campus(campus_info *campus)
{
if(!campus) return;
free(campus->pixels);
}
1,006ポイント を手に入れた。
|
|
|
|
|
Name: Justy ..プログラマー(37,702ポイント)
Date: 2006/12/10(日) 21:19
No:2579
|
|
Title: Re:三角形
|
|
続きです。
int main(void)
{
campus_info campus;
const color fill_col = { 255, 0, 0 }, // 色
p1_col = { 0, 0, 255 },
p2_col = { 0, 255, 255 },
p3_col = { 255, 0, 255 };
create_campus(&campus, 160, 200); // キャンパスを生成
{
fill_campus(&campus, &fill_col); // 塗りつぶして
put_pixel_campus(&campus, 0, 0, &p1_col); // 点を打って
put_pixel_campus(&campus, 100, 10, &p1_col);
put_line_campus(&campus, 50, 50, 100, 160, &p2_col); // ラインを引く
put_line_campus(&campus, 100, 160, 150, 20, &p3_col);
save_bmp_campus(&campus, "test.bmp"); // 保存
}
destroy_campus(&campus); // キャンパスを破棄
return 0;
}
上のはサンプルで、点とラインを描画して、bmpで保存しています。
このようにキャンパスという抽象的な概念を入れて、上のメイン関数みたいに、キャンパスを生成してからいろな操作を行えるようにしておくと、後々便利です。
これなら好きなところに好きな色で点やラインを描画し更には保存もできるので、三角形の頂点さえわかればなんとかなるでしょう。
塗りつぶしが必要なら、ちょっと工夫が必要ですが・・・。
555ポイント を手に入れた。
|
|
|
|
|
Name: Justy ..プログラマー(38,105ポイント)
Date: 2006/12/11(月) 00:25
No:2591
|
|
Title: Re:三角形
|
|
塗りつぶしもやってみました。
指定した座標にある色と同じ色の周辺エリアを指定した色で塗っていきます。
static void fill_area_campus_(const campus_info *info, int x, int y, const color *r_col, const color *col)
{
const color *pixel_col = get_pixel_campus(info, x, y);
if(!pixel_col
|| pixel_col->r != r_col->r || pixel_col->g != r_col->g || pixel_col->b != r_col->b)
return;
put_pixel_campus(info, x, y, col);
fill_area_campus_(info, x + 0, y + 1, r_col, col);
fill_area_campus_(info, x + 0, y - 1, r_col, col);
fill_area_campus_(info, x + 1, y + 0, r_col, col);
fill_area_campus_(info, x - 1, y + 0, r_col, col);
}
static void fill_area_campus(const campus_info *info, int x, int y, const color *col)
{
color pixel_col;
const color *ptr_pixel_col = get_pixel_campus(info, x, y);
if(!ptr_pixel_col) return;
pixel_col = *ptr_pixel_col;
fill_area_campus_(info, x, y, &pixel_col, col);
}
で、main関数の方を
put_line_campus(&campus, 50, 50, 100, 160, &p2_col);
put_line_campus(&campus, 100, 160, 150, 20, &p2_col);
put_line_campus(&campus, 150, 20, 50, 50, &p2_col);
fill_area_campus(&campus, 100, 100, &p3_col); // 中を塗りつぶす
とすると三角形の中が塗りつぶされます。
681ポイント を手に入れた。
|
|
|
|
|
Name: けいすけ ..ぴよぴよ(889ポイント)
Date: 2006/12/11(月) 04:20
No:2600
|
|
Title: Re:三角形
|
|
大変長いレスありがとうございました。
でも僕は初心者なので習ってないわからないところがいっぱいありました。
これから独学でレスにいただいた部分も理解できるようになりたいです。
一応これが課題のヒントとして出されたフローチャートなのですが・・・・
真ん中の列の下のほうの肝要な部分がわからないのです。
もしよろしければ、これに添った形でのアドバイス、よろしくお願いします。
162ポイント を手に入れた。
|
|
|
|
|
Name: Justy ..プログラマー(38,361ポイント)
Date: 2006/12/11(月) 11:51
No:2608
|
|
Title: Re:三角形
|
|
なるほど
えーと、このヒント1は三角形を描く課題のヒントですか?
一見このヒントは□(四角形)を書くためのヒントに見えますが。
なので、このフロートの2重ループ部分は当てにはならない気がします。
60ポイント を手に入れた。
|
|
|
|
|
Name: Justy ..プログラマー(39,952ポイント)
Date: 2006/12/11(月) 12:02
No:2609
|
|
Title: Re:三角形
|
|
#include <stdio.h>
#include <stdlib.h>
#define MS 200
int main(void)
{
char fi[256];
int i, j, x, y, w, h, index;
FILE *fp;
static const unsigned short header[13]={0x4d42,54490,1,0,0,26,0,12,0,MS,MS,1,24};
unsigned char *bmp = (unsigned char*)malloc(MS * MS * 3);
// 背景を塗りつぶす
for(i=0;i<=MS*MS;i++)
bmp[i*3+0] = bmp[i*3+1] = bmp[i*3+2]=0;
printf("Input width : ");
scanf("%s",fi);
sscanf(fi, "%d", &w);
printf("Input height : ");
scanf("%s",fi);
sscanf(fi, "%d", &h);
// 底辺のライン
y = - h / 2;
j = y + MS / 2; // ヒント2の座標変換
for(x=-w/2; x<=w/2; ++x)
{
i = x + MS / 2; // ヒント2の座標変換
index = (j * MS + i) * 3;
bmp[index+0] = 255; bmp[index+1] = 0; bmp[index+2] = 0;
}
#if 1 // ヒント2の式をそのまま
// 左辺
for(x=-w/2; x<=0; ++x)
{
y = (2 * h) / w * x + h / 2;
i = x + MS / 2; j = y + MS / 2; // ヒント2の座標変換
index = (j * MS + i) * 3;
bmp[index+0] = 255; bmp[index+1] = 0; bmp[index+2] = 0;
}
// 右辺
for(x=0; x<=w/2; ++x)
{
y = - (2 * h) / w * x + h / 2;
i = x + MS / 2; j = y + MS / 2; // ヒント2の座標変換
index = (j * MS + i) * 3;
bmp[index+0] = 255; bmp[index+1] = 0; bmp[index+2] = 0;
}
#else // ヒント2の式を変換
// 左辺
for(y=-h/2; y<=h/2; ++y)
{
x = (y - h / 2) / ((2 * h) / w);
i = x + MS / 2; j = y + MS / 2; // ヒント2の座標変換
index = (j * MS + i) * 3;
bmp[index+0] = 255; bmp[index+1] = 0; bmp[index+2] = 0;
}
for(y=-h/2; y<=h/2; ++y)
{
x = (y - h / 2) / (- (2 * h) / w);
i = x + MS / 2; j = y + MS / 2; // ヒント2の座標変換
index = (j * MS + i) * 3;
bmp[index+0] = 255; bmp[index+1] = 0; bmp[index+2] = 0;
}
#endif
printf("Input file name : ");
scanf("%s", fi);
if((fp=fopen(fi,"wb"))==NULL)
{
fprintf(stderr,"Error : file open[%s].\n",fi);
exit(1);
}
fwrite(header, 2, 13, fp);
fwrite(bmp, 1, MS*MS*3, fp);
fclose(fp);
return 0;
}
これでほぼあっているかと思います。
考え方としては3回の個別のループで処理しています。
底辺の線を書くループ、左側の辺を書くループ、右側の辺を書くループ。
この問題の場合、y = .... の公式が提供されているので、二重ループの必要はなく、xの値が決まれば自動的に yの値も決まるので1重ループで処理しています。
尚、このコードをテストする時、 "#if 1"と書かれているところを "#if 0"に書き換えたバージョンもテストしてみてください。
"#if 1"の方はヒント2の通りの式を使っていますが、 "#if 0"の方はヒント2の y = ...の式を x = ....に直しています。
1,591ポイント を手に入れた。
|
|
|
|
|
Name: けいすけ ..ぴよぴよ(938ポイント)
Date: 2006/12/12(火) 02:24
No:2638
|
|
Title: Re:三角形
|
|
ありがとうございます。
一行ずつ理解しながら自分でも書いています。
内側を塗りつぶすのが出来るか心配ですが・・・・・^^;
49ポイント を手に入れた。
|
|
|
|
|
Name: けいすけ ..かけだし(1,396ポイント)
Date: 2006/12/12(火) 04:26
No:2640
|
|
Title: Re:三角形
|
|
一応習ったことをフル回転させ、解答を参考にさせていただきこのような形に落ち着きました。
分かりやすい解説ありがとうございました!またよろしくお願いします!゜+。:.゜ヽ(*´∀`)ノ゜.:。+゜アリガト
#include <stdio.h>
#include <stdlib.h>
#define MS 200
main()
{
char fi[256];
int i,j,x,y,w,h;
FILE *fp;
unsigned short header[13]={0x4d42,54490,1,0,0,26,0,12,0,MS,MS,1,24};
unsigned char *bmp;
bmp=(unsigned char*)malloc(MS*MS*3);
for(i=0;i<=MS*MS;i++)
{
bmp[i*3+0]=0;
bmp[i*3+1]=0;
bmp[i*3+2]=0;
}
printf("Input width : ");
scanf("%s",fi);
w=atoi(fi);
printf("Input height : ");
scanf("%s",fi);
h=atoi(fi);
for(x=-w/2;x<=0;++x)
{
for(y=-h/2;y<=h/2;++y)
{
if(y<=(2*h)/w*x+h/2)
{
i=x+MS/2;
j=y+MS/2;
bmp[(j*MS+i)*3+0]=0;
bmp[(j*MS+i)*3+1]=0;
bmp[(j*MS+i)*3+2]=255;
}
}
}
for(x=0;x<=w/2;++x)
{
for(y=-h/2;y<h/2;++y)
{
if(y<=-(2*h)/w*x+h/2)
{
i=x+MS/2;
j=y+MS/2;
bmp[(j*MS+i)*3+0]=0;
bmp[(j*MS+i)*3+1]=0;
bmp[(j*MS+i)*3+2]=255;
}
}
}
printf("Input file name : ");
scanf("%s",fi);
if((fp=fopen(fi,"wb"))==NULL)
{
printf(stderr,"Error : file open[%s].\n",fi);
exit(1);
}
fwrite(header,2,13,fp);
fwrite(bmp,1,200*200*3,fp);
fclose(fp);
}
458ポイント を手に入れた。
|
|
|
|
Name: ten ..ぴよぴよ(917ポイント)
Date: 2006/12/11(月) 21:37
No:2623
|
|
Title: 課題を教えて下さい。
|
|
行継続の処理をするプログラムを作れ。一行を文字列として読み込み、その一行を画面に表示するプログラムを作る。ただし、改行の直前の文字が '\' であったときには、次の行も読み込んで先の一行に続けるようにすること。という課題をやっています。printfで\nの有無利用すれば上手くいくと思いました。でも上手くいきません。ループ抜ける条件も上手く作れません。ソースです。
#include <stdio.h>
#include <string.h>
#define MAX 51
void main ()
{
char x[MAX];
int n;
start:
gets(x);
n = strlen(x)-1;
if (x[n] = \){
printf("%s", x );
}else{
printf("%s\n", x );
}
goto start;
}
299ポイント を手に入れた。
|
|
|
|
Name: フリオ(元通りすがり) ..ぴよぴよ(281ポイント)
Date: 2006/12/11(月) 22:37
No:2627
|
|
Title: Re:課題を教えて下さい。
|
|
これで、どうでしょう。
#include <stdio.h>
#include <string.h>
int main(void)
{
FILE *fp;
char data[51];
int len;
if((fp = fopen("test001.txt", "r")) == NULL){
puts("File Open Error");
return 1;
}
while(fgets(data, 51, fp) != NULL){
len = strlen(data);
if(data[len - 1] == '\n' && data[len - 2] == '\\'){
data[len - 2] = '\0';
}
printf("%s", data);
}
return 0;
}
281ポイント を手に入れた。
|
|
|
|
Name: ME ..ぴよぴよ(454ポイント)
Date: 2006/12/10(日) 21:14
No:2577
|
|
Title: 登録される順番が・・・
|
|
ファイルに1行ずつデータを書き出して
1 名前1
2 名前2
という風に後に追加することはできるようになったのですが、
そのファイルを読み出して、
キーボード入力でデータを追加すると
4 名前4
3 名前3
1 名前1
2 名前2
という風に前にデータが追加されてしまいます。
tail = add( str, num, tail);
で読み出したファイルのデータの登録に使っている関数は↓
List *add( char *str, int num, List *tail )
{
List *p;
if ((p = (List *) malloc(sizeof(List))) == NULL) {
printf("malloc error\n");
exit(1);
}
strcpy(p->name, str);
p->num = num;
p->next = NULL;
if (tail != NULL) tail->next = p;
return p;
}
同じ関数が使えなかったので、キーボードから入力するデータは↓で登録しています。
head = add_sort( name, num, head );
struct list *add_sort( char *str,int num, struct list *head )
{
struct list *p;
/* 新規リストにデータを登録 */
if ( ( p = ( struct list * )malloc( sizeof( struct list ) ) ) == NULL ) {
printf( "malloc error\n" );
exit( 1 );
}
strcpy( p->name, str );
p->num = num;
if ( head == NULL || num > head->num ) {
p->next = head;
return p;
}
return head;
}
head(先頭)指定をtail(末尾)に変更しても、上手くいきません。
初歩的な質問かもしれませんが、どこを変更したらいいか教えてください。m(_ _)m
454ポイント を手に入れた。
|
|
|
|
Name: box ..上級者(15,486ポイント)
Date: 2006/12/10(日) 21:30
No:2580
|
|
Title: Re:登録される順番が・・・
|
|
main関数などを含めて、今のソースコードを全部見せてください。
貼り付ける際、インデントを有効にするために
コードの前後を<pre>タグと</pre>タグではさんでください。
53ポイント を手に入れた。
|
|
|
|
|
Name: ME ..かけだし(1,406ポイント)
Date: 2006/12/10(日) 22:22
No:2583
|
|
Title: Re:登録される順番が・・・
|
|
ソースコードを貼り付けました。これで大丈夫でしょうか?
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "head.h"
List *write(int code, List *head, List *tail)
{
List *p;
char name[30];
int num=1;
if (head != NULL){
for ( p = head; p->next != NULL; p = p->next ) num++;
num++;
}
code = 1;
while(code==1){
if(code == 4) break;
printf( "名前:" ); scanf( "%s", name );getchar();
printf("No.%d\n",num);
printf("%s,No.%d\n",name, num);
head = add_sort( name, num, head );
if( head == NULL ) head = tail;
num++;
printf("追記:1 終了:4 →",);
while(1){
scanf("%d",&code);getchar();
if (code==1 || code==4 ) break;
}else{ fflush(stdin);
}
}
}
return(head);
}
List *read( List *head, List *tail )
{
FILE *fw;
char fname[21], line[100];
char str[30];
int num;
head = NULL;
tail = NULL;
printf( "ファイル名:" ); scanf("%s",fname);getchar();
while( ( fw=fopen( fname, "r" ) ) == NULL) {
printf( "ファイルがありません。\nファイル:" );
scanf("%s",fname);
}
while( fgets( line, 100, fw ) != NULL ) {
line[strlen(line)-1] = '\0';
sscanf(line, "%s,No.%d", str, &num);
tail = add( str,num,tail);
if( head == NULL ) head = tail;
}
fclose( fw );
return(head);
}
void dispall( List *p )
{
int code;
while ( p != NULL) {
printf( "%s,No.%d\n",p->name,p->num );
p = p->next;
}
}
int main( void )
{
List *head= NULL;
List *tail= NULL;
List *p2;
int code;
while( 1 ) {
printf( "入力:1 読込:2 表示:3 終了:4\n");
scanf( "%d", &code );getchar();
if ( code == 4 ) break;
else if ( code == 1 ){ head = write(code, head, tail);
}else if ( code == 2 ){ head = read(head,tail);
}else if ( code == 3 ){ dispall(head);
}else{fflush(stdin);
}
}
while ( p != NULL ) {
p2 = p->next;
free( p );
p = p2;
}
return 0;
}
952ポイント を手に入れた。
|
|
|
|
|
Name: ME ..かけだし(1,522ポイント)
Date: 2006/12/10(日) 22:58
No:2587
|
|
Title: Re:登録される順番が・・・
|
|
たびたびすみません・・・
#define BUF 128
typedef struct list {
char name[30];
int num;
struct list *next; /* 次のデータへのポインタ */
struct list *prev; /* 次のデータへのポインタ */
}List;
です。
116ポイント を手に入れた。
|
|
|
|
|
Name: box ..上級者(16,084ポイント)
Date: 2006/12/10(日) 23:22
No:2589
|
|
Title: Re:登録される順番が・・・
|
|
貼り付けられたソースコードをそのまま私のところで
コピー&ペーストしてBorland C++ Compilerでコンパイルしました。
すると、下記のエラーが出ました。
さしあたり、これらのエラーや警告をなくしていただけますか?
警告 W8065 D:\My Programs\C\temp1\temp1.c 23: プロトタイプ宣言のない関数 'add_sort' の呼び出し(関数 write )
警告 W8069 D:\My Programs\C\temp1\temp1.c 23: 移植性のないポインタ変換(関数 write )
エラー E2188 D:\My Programs\C\temp1\temp1.c 26: 式の構文エラー(関数 write )
エラー E2054 D:\My Programs\C\temp1\temp1.c 30: else の位置が誤っている(関数 write )
警告 W8070 D:\My Programs\C\temp1\temp1.c 33: 関数は値を返すべき(関数 write )
エラー E2040 D:\My Programs\C\temp1\temp1.c 34: 宣言が正しく終了していない
エラー E2190 D:\My Programs\C\temp1\temp1.c 35: 不要な }
警告 W8065 D:\My Programs\C\temp1\temp1.c 55: プロトタイプ宣言のない関数 'add' の呼び出し(関数 read )
警告 W8069 D:\My Programs\C\temp1\temp1.c 55: 移植性のないポインタ変換(関数 read )
警告 W8080 D:\My Programs\C\temp1\temp1.c 69: 宣言された 'code' は使われていない(関数 dispall )
エラー E2451 D:\My Programs\C\temp1\temp1.c 89: 未定義のシンボル p(関数 main )
警告 W8080 D:\My Programs\C\temp1\temp1.c 95: 宣言された 'p2' は使われていない(関数 main )
*** 5 errors in Compile ***
515ポイント を手に入れた。
|
|
|
|
|
Name: Justy ..プログラマー(37,424ポイント)
Date: 2006/12/10(日) 23:50
No:2590
|
|
Title: Re:登録される順番が・・・
|
|
動かないからテストしていませんが、add_sort()の "p->num = num"以下を
p->num = num;
p->next = NULL;
if(head)
{
struct list *q = head;
while(q->next)
q = q->next;
q->next = p;
}
else
{
p->next = NULL;
head = p;
}
return head;
な感じにすれば、それっぽい動きになるかなぁ、と。
あと
fflush(stdin);
は動作を保証されていません。
rewind(stdin);
としてください。
278ポイント を落としてしまった。
|
|
|
|
|
Name: ME ..入門者(3,006ポイント)
Date: 2006/12/11(月) 21:46
No:2624
| 解決!
|
Title: Re:登録される順番が・・・
|
|
boxさんJustyさんありがとうございます。
boxさん指摘のエラーを全部訂正して、
Justyさんの助言通りにプログラムを変更したら、
データが後ろに追加されるプログラムにすることができました。
ありがとうございました!!
一応出来上がったソースを載せておきます。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define BUF 128
typedef struct list {
char name[30];
int num;
struct list *next; /* 次のデータへのポインタ */
struct list *prev; /* 次のデータへのポインタ */
}List;
List *add( char *str, int num, List *tail )
{
List *p;
if ((p = (List *) malloc(sizeof(List))) == NULL) {
printf("malloc error\n");
exit(1);
}
strcpy(p->name, str);
p->num = num;
p->next = NULL;
if (tail != NULL) tail->next = p;
return p;
}
List *add_sort( char *str,int num, List *head )
{
List *p;
/* 新規リストにデータを登録 */
if ( ( p = ( List * )malloc( sizeof( List ) ) ) == NULL ) {
printf( "malloc error\n" );
exit( 1 );
}
strcpy( p->name, str );
p->num = num;
p->next = NULL;
if(head){
List *q = head;
while(q->next)
q = q->next;
q->next = p;
}else{
p->next = NULL;
head = p;
}
return head;
}
List *write(int code, List *head, List *tail)
{
List *p;
char name[30];
int num=1;
if (head != NULL){
for ( p = head; p->next != NULL; p = p->next ) num++;
num++;
}
code = 1;
while(code==1){
if(code == 4) break;
printf( "名前:" ); scanf( "%s", name );getchar();
printf("No.%d\n",num);
printf("%s No.%d\n",name, num);
head = add_sort( name, num, head );
if( head == NULL ) head = tail;
num++;
printf("追記:1 終了:4 →");
while(1){
scanf("%d",&code);getchar();
if (code==1 || code==4 ) break;
else fflush(stdin);
}
}
return(head);
}
List *read( List *head, List *tail )
{
FILE *fw;
char fname[21], line[100];
char str[30];
int num;
head = NULL;
tail = NULL;
printf( "ファイル名:" ); scanf("%s",fname);getchar();
while( ( fw=fopen( fname, "r" ) ) == NULL) {
printf( "ファイルがありません。\nファイル:" );
scanf("%s",fname);
}
while( fgets( line, 100, fw ) != NULL ) {
line[strlen(line)-1] = '\0';
sscanf(line, "%s No.%d", str, &num);
tail = add( str,num,tail);
if( head == NULL ) head = tail;
}
fclose( fw );
return(head);
}
void dispall( List *p )
{
while ( p != NULL) {
printf( "%s No.%d\n",p->name,p->num );
p = p->next;
}
}
int main( void )
{
List *head= NULL;
List *tail= NULL;
List *p;
int code;
while( 1 ) {
printf( "入力:1 読込:2 表示:3 終了:4 →");
scanf( "%d", &code );getchar();
if ( code == 4 ) break;
else if ( code == 1 ){ head = write(code, head, tail);
}else if ( code == 2 ){ head = read(head,tail);
}else if ( code == 3 ){ dispall(head);
}else rewind(stdin);
}
while ( head != NULL ) {
p = head->next;
free( head );
head = p;
}
return 0;
}
1,484ポイント を手に入れた。
|
|
|
|
Name: たくま ..ぴよぴよ(361ポイント)
Date: 2006/12/11(月) 12:25
No:2610
|
|
Title: データの受け渡しについて
|
|
はじめまして。
今、レジストリからデータを参照するプログラムを書いています。
そこで、main()とreg()間のデータがうまくやりとりできません…
ポインタとかの使い方がいまいちよくわからないせいなんですが…
プログラムも下記に載せておくので、もし間違いやおかしい点があればご教授をお願いします。
よろしくお願いします。
・プログラム
#include<windows.h>
#include<iostream>
char* reg(char path){
HKEY rKey;
LONG bRet;
char ValueName[256];
BYTE Data[256];
DWORD cbData;
DWORD dwType;
char d[256];
// レジストリキーハンドルを作成;
bRet = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
&path,
0, // 予約済み;
KEY_ALL_ACCESS, //キーに対す全ての操作を許可する。;
&rKey); // ここにキーハンドルが格納される。;
if( bRet != ERROR_SUCCESS ){
// 失敗
printf("RegOpenKeyEx");
exit(0);
}
// 値の読み込み;
cbData = sizeof(Data);
memset(Data, 0, cbData);
bRet = RegQueryValueEx( rKey, // オープンしているキーのハンドル;
"ProductName", // 読み取りたい値の名前を指定。;
NULL, //予約済み。NULLをいれること;
&dwType, // 値のデータの種類が入る。今回は不要なので, NULLにする。;
Data, // 情報が格納される。;
&cbData); // 情報のデータサイズ(Byte)を格納する。;
// 渡すときには情報を格納するバッファの大きさを入れておく。
if( bRet != ERROR_SUCCESS ){
// 失敗した。;
printf("RegQueryValueEx\n");
exit(0);
}
RegCloseKey(rKey);
return (char *)Data;
}
int main(){
char path[200]="SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion";
char *regstr;
regstr = reg((char)path);
printf("%s",regstr);
return 0;
}
361ポイント を手に入れた。
|
|
|
|
Name: Yuki ..ぴよぴよ(45ポイント)
Date: 2006/12/11(月) 13:07
No:2611
|
|
Title: Re:データの受け渡しについて
|
|
変数pathはファイルパスの文字列が格納されているので、
以下のようにすれば、動くと思います。
>char* reg(char path){
char* reg(char *path){
>regstr = reg((char)path);
regstr = reg(path);
45ポイント を手に入れた。
|
|
|
|
|
Name: たくま ..ぴよぴよ(519ポイント)
Date: 2006/12/11(月) 14:21
No:2612
|
|
Title: Re:データの受け渡しについて
|
|
Yukiさん、ご回答ありがとうございます。
そのように変えて実行したら、出力が文字化けしてしまいます…
この場合は変数を定義する際にpathもポインタを使うんですよね?
char *path[200]="SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion";のように。
こうすれば実行できるんですが、ここでポインタを使いたくないんです。
そんなことって出来ますか?
158ポイント を手に入れた。
|
|
|
|
|
Name: Justy ..熟練のプログラマー(40,079ポイント)
Date: 2006/12/11(月) 14:40
No:2613
|
|
Title: Re:データの受け渡しについて
|
|
reg()はローカル変数へのポインタを戻しています。
reg()内の Data変数は関数を抜けた瞬間に無効になるので、main()が受け取った regstrポインタは無効です。
main()で用意した文字列バッファのポインタに結果を入れるようにすれば解決すると思います。
127ポイント を手に入れた。
|
|
|
|
|
Name: たくま ..ぴよぴよ(578ポイント)
Date: 2006/12/11(月) 14:56
No:2614
|
|
Title: Re:データの受け渡しについて
|
|
Justyさん、回答ありがとうございます。
>main()で用意した文字列バッファのポインタに結果を入れるようにすれば解決すると思います。
理解度が低くて申し訳ないんですが、regstrではなんでダメかがよくわかりません…
59ポイント を手に入れた。
|
|
|
|
|
Name: Justy ..熟練のプログラマー(40,521ポイント)
Date: 2006/12/11(月) 15:45
No:2615
|
|
Title: Re:データの受け渡しについて
|
|
まず原則として「関数内で宣言した変数は関数を抜けた瞬間に無効になる」ということです。
つまり、reg()内で宣言した BYTE Data[256]という 256バイトのデータは returnで戻った後は消失します。
残っているように見えても、ただの残骸でしかありません。
main()の regstr = reg(path);で受け取った regstrポインタが指している先は reg()内の Data変数のアドレスです。
ですが、受け取った時にはその領域はゴミなのです。
なので、1つの解決方法としては reg()を
void reg(char *path, char *Data) のような形にして、戻り値を無くし、結果の出力先のポインタ Dataを追加します。
その上で、ローカル変数として宣言していた Data変数を削除します。
あとは main()の方を
char regstr[256];
reg(path, regstr);
とすれば、regstrに結果が入ります。
442ポイント を手に入れた。
|
|
|
|
|
Name: たくま ..ぴよぴよ(628ポイント)
Date: 2006/12/11(月) 16:28
No:2616
| 解決!
|
Title: Re:データの受け渡しについて
|
|
なるほど…
詳しくてわかり易い説明をしていただきありがとうございます。
しかも、なんとかできました。
Yukiさん、Justyさん、ご教授いただきありがとうございました。
50ポイント を手に入れた。
|
|
|
|
Name: GPGA ..中級者(13,857ポイント)
Date: 2006/12/08(金) 18:02
No:2509
|
|
Title: JIS X3010 C規格書について
|
|
実は「JIS X3010」を見たことが一度も無いのでお聞きしたいのですが
現在Cの企画書の内容は、C99の内容になってしまっているのでしょうか?
51ポイント を手に入れた。
|
|
|
|
Name: keichan ..初心者(7,484ポイント)
Date: 2006/12/08(金) 18:07
No:2510
|
|
Title: Re:JIS X3010 C規格書について
|
|
規格書のまえがきに
| 本工業規格を基礎にした国際規格原案の提案を容易にするために, ISO/IEC 9899:1999, Programming
| languages -- C及びISO/IEC 9899 Technical Corrigendum 1 : 2001 を基礎として用いた。
とあります。
>現在Cの企画書の内容は、C99の内容になってしまっているのでしょうか?
Yes.
141ポイント を手に入れた。
|
|
|
|
|
Name: keichan ..初心者(7,559ポイント)
Date: 2006/12/08(金) 18:11
No:2511
|
|
Title: Re:JIS X3010 C規格書について
|
|
以前どこかの掲示板で日本語版はあくまで直訳で訳しているので逆に分かりづらい表現をしている
箇所があるみたいです。
原書も同時に購入した方がよい。とのことです。
ご参考までに
75ポイント を手に入れた。
|
|
|
|
|
Name: GPGA ..中級者(14,120ポイント)
Date: 2006/12/08(金) 18:20
No:2512
|
|
Title: Re:JIS X3010 C規格書について
|
|
>以前どこかの掲示板で日本語版はあくまで直訳で訳しているので逆に分かりづらい表現をしている
> 箇所があるみたいです。
なるほど。
翻訳本や、MSDNの翻訳などでもこういったことはよくありますね。
>原書も同時に購入した方がよい。とのことです。
>ご参考までに
参考にさせさせていただきます。
購入して確認してしまえば済んでしまう問題なのですが
ふと気になりましたので、もう一つ質問させてください。
例えばローカル変数宣言を行う場合
C89ですと、{〜}の最初に書かなければエラーになり
C99ですと、C++と同じようにどこでも自由に宣言することができますが
そのようなC89時代にはこうであり、C99ではこう改変された
というような内容もきちんと書かれているものなのでしょうか?
263ポイント を手に入れた。
|
|
|
|
|
Name: Justy ..プログラマー(34,318ポイント)
Date: 2006/12/08(金) 18:41
No:2513
|
|
Title: Re:JIS X3010 C規格書について
|
|
>C89時代にはこうであり、C99ではこう改変された
原書とか有料版は見たことないのでわかりませんが、日本語の JIS規格のフリーで閲覧できるドキュメントには載ってないようです。
単純な言語の違いなら Webを探せばありますが、規格書レベルの差異は JIS X3010-1993のドキュメントをどこからか探してきて今の JIS X3010-1999と比較するしかないかと。
JIS X3014の C++の方にはCとの違いが事細かに載ってるんですけどねぇ。
215ポイント を手に入れた。
|
|
|
|
|
Name: GPGA ..中級者(14,479ポイント)
Date: 2006/12/10(日) 11:22
No:2563
|
|
Title: Re:JIS X3010 C規格書について
|
|
返事が遅くなりまして、すいません。
JISのフリーの規格書を閲覧することができました。
Sleipnirの設定が悪かったようなので、IEを使用して中身を確認しました。
この規格書のpdfなんですが、ワード検索でワードが引っかからないのですけど
中身は画像だったりするのですか?
>規格書レベルの差異は JIS X3010-1993のドキュメントをどこからか探してきて今の JIS X3010-1999と比較するしかないかと。
わかりました。
少しだけJIS X3010-1999の規格書を探してみましたが、見つかりませんでした。
後で時間があるときに、深く探してみようと思います。
> JIS X3014の C++の方にはCとの違いが事細かに載ってるんですけどねぇ。
C++の方の規格書もいずれ見たいと思います。
むしろ、最近のことを考えるとこちらのC++版や
JIS X3015のC#版を先に読んだほうが、実用性があるかもしれませんね。
更なる質問で申し訳ないのですけど、有料版の規格書でワード検索が可能かどうか分かる方がいたら
教えていただけますでしょうか?
ワード検索可能でしたら購入するのはpdf版にしようと思いますが
もし、ワード検索が不可能であれば、どこでも読めるという点で
書籍版の方を購入しようと考えております。
359ポイント を手に入れた。
|
|
|
|
|
Name: Justy ..プログラマー(35,808ポイント)
Date: 2006/12/10(日) 15:58
No:2565
|
|
Title: Re:JIS X3010 C規格書について
|
|
>中身は画像だったりするのですか?
冊子をスキャンしただけの画像です。
だから目grepしないといけません(w
慣れてくると大体どのあたりに何があるかわかってきますが、でもやっぱり大変ですよね。
>有料版の規格書
JSAで販売されている JISの規格書は 2002年 4月移行のはキャラクタベースで、それより前は400dpiのイメージベースだと聞いたことがあります。
ISO/ANSIはわかりません。
ちなみに JISの方は購入すると解説がついていて、改正理由、主な改正点などが記載されているらしいです。
どちらにしても、(ANSIを除いて)高価な買い物ですし事前に購入先に問い合わせた方がいいと思います。
304ポイント を手に入れた。
|
|
|
|
|
Name: GPGA ..中級者(14,647ポイント)
Date: 2006/12/11(月) 11:51
No:2607
| 解決!
|
Title: Re:JIS X3010 C規格書について
|
|
> 冊子をスキャンしただけの画像です。
> だから目grepしないといけません(w
や、やはりそうでしたか。
> 慣れてくると大体どのあたりに何があるかわかってきますが、でもやっぱり大変ですよね。
デジタルデータのpdfである以上、検索可能であったほしいですね。
> ちなみに JISの方は購入すると解説がついていて、改正理由、主な改正点などが記載されているらしいです。
おお、改正理由まで付いてくるのですか!
一プログラマとしては、興味をそそられます。
> どちらにしても、(ANSIを除いて)高価な買い物ですし事前に購入先に問い合わせた方がいいと思います。
わかりました。
確かにこのようなことは、購入先に聞くのが正しいですね。
年末は忙しいため、購入するのは来年になるかもしれませんが
購入したしましたら、この辺りの情報を書き込もうと思います。
質問にお答えくださったkeichanさん、Justyさん、誠にありがとうございました。
168ポイント を手に入れた。
|
|
|
|
Name: mikoko ..ぴよぴよ(58ポイント)
Date: 2006/12/11(月) 07:57
No:2601
|
|
Title: 円と円の交点を求めるには?
|
|
中心座標が異なる2 つの円の中心座標と半径を入力し,その交点の座標を求めるプログラムができません。
中心座標と半径は,struct CIRCLE {int x, y, r;};と、 2 つの円(struct CIRCLE)を引数とし,交点の数(0〜2)を返す関数 int Kouten(struct CIRCLE c1, struct CIRCLE c2)を使って作りたいのですが。
私はまず片方の円を原点に移動させ、次にもう片方の円を原点を軸に回転させて、両方の円の中心をx軸上にもっていき、交点を出してそれを同様に回転、移動させて交点を得ようとしたのですが・・・・。
どうかお願いします。一応作りかけを載せときます。
#include<stdio.h>
#include<math.h>
struct CIRCLE {
int x, y, r;
};
int main(void)
{
int a,b;
double x,y,y1,a2,p;
struct CIRCLE c1,c2;
printf("Input Circle 1:\nX = ");
scanf("%d",&c1.x);
printf("Y = ");
scanf("%d",&c1.y);
printf("R = ");
scanf("%d",&c1.r);
printf("Input Circle 2:\nX = ");
scanf("%d",&c2.x);
printf("Y = ");
scanf("%d",&c2.y);
printf("R = ");
scanf("%d",&c2.r);
a = c2.x -c1.x;
b = c2.y -c1.y;
printf("a = %d,b = %d\n",a,b);
p = atan2(b,a);
a = a*cos(-p) - b*sin(-p);
b = a*sin(-p) + b*cos(-p);
printf("a = %d b = %d\n",a,b);
a2 = sqrt((c2.x-c1.x)*(c2.x-c1.x) + (c2.y-c1.y)*(c2.y-c1.y));
printf("a2 = %lf\n",a2);
x = (c1.r*c1.r - c2.r*c2.r + a*a)/(2*a);
y = sqrt(c1.r*c1.r - x*x);
printf("(x,y) = (%3.1lf,%3.1lf)\n",x,y);
y1 = -1*y;
x = x*cos(p) - y*sin(p);
y = x*sin(p) + y*cos(p);
printf("x = %lf\ny = %lf\np = %lf\n",x,y,p);
if(a2 > c1.r + c2.r){
printf("Kouten:%d\n",0);
}
else if(a2 < c1.r + c2.r){
printf("Kouten:%d\n",2);
printf("(%lf,%lf),(%lf,%lf)\n",x+c1.x,y+c1.y,x+c1.x,y1+c1.y);
}else {
printf("Kouten:%d\n",1);
printf("(%lf,%lf)\n",x+c1.x,y+c1.y);
}
return 0;
}
58ポイント を手に入れた。
|
|
|
|
Name: box ..上級者(16,127ポイント)
Date: 2006/12/11(月) 09:57
No:2605
|
|
Title: Re:円と円の交点を求めるには?
|
|
2つの円の中心間の距離と半径の和には、以下の関係があります。
1)中心間の距離>半径の和のとき、2つの円の交点は0個
2)中心間の距離=半径の和のとき、2つの円の交点(接点)は1個
3)中心間の距離<半径の和のとき、2つの円の交点は2個
これらの関係を求めるための関数が、投稿でふれられているKouten関数ですね。
1)の場合は、そこで終了です。
2)の場合は、2つの円の中心を通る直線の方程式
y1-y2
y-y1 = -----(x-x1)
x1-x2
と円の方程式(2円のうちどちらでもいいですが、
例えば(x-x1)*(x-x1)+(y-y1)*(y-y1)=r1*r1)とを連立させれば
求まります。
3)の場合は、2個の交点を通る直線の方程式
x1-x2
y = − -----x + b
y1-y2
のy切片bの値を求めた後、円の方程式と連立させれば求まります。
なお、2)3)いずれの場合も、直線の方程式で傾きの分母が
ゼロになる場合を意識しておく必要があります。
ゼロで割ることはできませんので。
43ポイント を手に入れた。
|
|
|
|
|
Name: mikoko ..ぴよぴよ(331ポイント)
Date: 2006/12/11(月) 10:25
No:2606
|
|
Title: Re:円と円の交点を求めるには?
|
|
boxさん、わざわざ丁寧にありがとうございます。
関数の部分はわかりました。
if(a2 > c1.r + c2.r){
printf("Kouten:%d\n",0);
}
else if(a2 < c1.r + c2.r){
printf("Kouten:%d\n",2);
printf("(%lf,%lf),(%lf,%lf)\n",x+c1.x,y+c1.y,x+c1.x,y1+c1.y);
}else {
printf("Kouten:%d\n",1);
printf("(%lf,%lf)\n",x+c1.x,y+c1.y);
}
の部分を関数になおしてあげればいいみたいですね。
問題は座標回転なんですよ。ただ a = atan2(y,x) にすると不具合がおこってしまって。
p = atan2(b,a);
a = a*cos(-p) - b*sin(-p);
b = a*sin(-p) + b*cos(-p);
のところです。
(たとえば a = 0,90 や a<-90,90<a だとatan が使えなくて)
そのあたりが難しいです。
時間がある方、お願いします。
273ポイント を手に入れた。
|
|
|
|
Name: ペコちゃん ..ぴよぴよ(73ポイント)
Date: 2006/12/10(日) 03:17
No:2547
|
|
Title: 初心者です・・・・・
|
|
(時刻と日付を格納する構造体を設計してください。2つの時刻の違いを分の単位で表す関数を記述しなさい。)←←←←←←←←←←←←誰かこれの解答例をおしえてください(><)
73ポイント を手に入れた。
|
|
|
|
Name: 管理人 [URL] ..ハッカー(124,115ポイント)
Date: 2006/12/10(日) 03:22
No:2550
|
|
Title: Re:初心者です・・・・・
|
|
ぺこちゃんさんこんにちは。
管理人です。
構造体の作り方はわかりますか?
後、
・2つの時刻の違いを分の単位で表す関数
という意味がよくわかりません。
関数を呼んだ違う時間に分の単位で表示するのか
違う国の時間を表示するのか・・。
「2つの時刻」とはなんですか?
103ポイント を手に入れた。
|
|
|
|
|
Name: Justy ..プログラマー(34,863ポイント)
Date: 2006/12/10(日) 03:33
No:2553
|
|
Title: Re:初心者です・・・・・
|
|
>2つの時刻の違いを分の単位で表す関数
単純に2つの時間構造体を比較して、ってことではないでしょうか。
struct time_info { /*何か*/ };
typedef int diff_minutes;
diff_minutes get_diff_minutes(const struct time_info* time1, const struct time_info* time2);
93ポイント を手に入れた。
|
|
|
|
|
Name: Justy ..プログラマー(36,141ポイント)
Date: 2006/12/10(日) 19:48
No:2572
|
|
Title: Re:初心者です・・・・・
|
|
time.h内の標準関数を使えば簡単にできます。
以下がその解答例です。
あくまで例なので、このまま出しても通用するかどうかはわかりませんが。
typedef struct date_time
{
unsigned int year: 8; // 1900年を 0とする
unsigned int month: 4; // 1月を 1とする
unsigned int date: 5; // 1日を 1とする
unsigned int hour: 5;
unsigned int minute: 6;
} date_time;
int diff_date_time(const date_time *time1, const date_time *time2)
{
struct tm tm1 = { 0, time1->minute, time1->hour, time1->date, time1->month-1, time1->year, 0, 0,-1 },
tm2 = { 0, time2->minute, time2->hour, time2->date, time2->month-1, time2->year, 0, 0,-1 };
return (int)(difftime(mktime(&tm2), mktime(&tm1)) / 60);
}
333ポイント を手に入れた。
|
|
|
|
|
Name: ぺこ ..ぴよぴよ(17ポイント)
Date: 2006/12/10(日) 22:25
No:2584
| 解決!
|
Title: Re:初心者です・・・・・
|
|
JUSTYさんありがとうございました><
14ポイント を手に入れた。
|
|
|
|
Name: たろう ..ぴよぴよ(254ポイント)
Date: 2006/12/10(日) 00:44
No:2540
|
|
Title: 教えてください!!
|
|
16進数を入力しその2進数表現で0の最大連続数と連続開始ビット及び1の最大連続数と連続開始ビットを表示するプログラムを作成せよ。(最小桁を0ビットとする)
例.01110000011111111000000111110001の場合
0の最大連続数は9ビット目から始まる6ビット、1の最大連続数は15ビット目から始まる8ビットと表示されるようにする
という問題が出ました。16進数から2進数に変換することはできたのですが、そこからが何をしていいかわかりません。
お願いします。
#include<stdio.h>
int main(void){
int i;
unsigned int x;
printf("x = ");
scanf("%u",&x);
printf("%uの2進数表示 = \n",x);
for(i=32; i--;){
printf("%d",(x>>i)%2);
}
return 0;
}
254ポイント を手に入れた。
|
|
|
|
Name: box ..上級者(15,143ポイント)
Date: 2006/12/10(日) 00:56
No:2541
|
|
Title: Re:教えてください!!
|
|
> scanf("%u",&x);
「16進数を入力する」という仕様に合致していません。
今は、符号なし10進数を入力するようになっています。
16進数の入力に対応するには、書式文字列を"%x"にする
必要があるはずです。
もっと厳密にするには、fgets関数あたりでいったん
文字列として受け取り、sscanf関数で有効な16進数かどうかを
判断する必要があります。
ところで、今回は最大何桁の16進数に対応する必要がありますか?
100ポイント を手に入れた。
|
|
|
|
|
Name: たろう ..ぴよぴよ(271ポイント)
Date: 2006/12/10(日) 01:11
No:2542
|
|
Title: Re:教えてください!!
|
|
unsigned long型(32ビット)キー入力となっていました。
17ポイント を手に入れた。
|
|
|
|
|
Name: box ..上級者(15,336ポイント)
Date: 2006/12/10(日) 01:16
No:2543
|
|
Title: Re:教えてください!!
|
|
この問題では、数値であることを意識しなくてよさそうです。
文字列の世界だけで解けると思います。
今回はunsigned long型の範囲で考えるので、最大8文字(文字列終端の'\0'を除く)の
16進数に対応すればよいことになります。
入力した16進数の各々の桁について
0→0000
1→0001
2→0010
... (中略)
E→1110
F→1111
の変換を行ないます。
すると、0と1だけからなる最大32文字(文字列終端の'\0'を除く)の文字列ができます。
この文字列をいちばん右の第0ビットから調べていくロジックを考えるのが肝ですね。
193ポイント を手に入れた。
|
|
|
|
|
Name: たろう ..ぴよぴよ(364ポイント)
Date: 2006/12/10(日) 01:31
No:2544
|
|
Title: Re:教えてください!!
|
|
ありがとうございます。文字列として考えればいいということは理解することができました。
>この文字列をいちばん右の第0ビットから調べていくロジックを考えるのが肝ですね。
右の0ビット順目から順番に調べていくにはどうしたらよいのでしょうか?
初心者なもので何回もすいません。
93ポイント を手に入れた。
|
|
|
|
|
Name: 通りすがり ..かけだし(2,397ポイント)
Date: 2006/12/10(日) 07:45
No:2561
|
|
Title: Re:教えてください!!
|
|
一旦数値で受けて、右シフトしながら文字列に変換するほうが簡単じゃないですか。
並びも逆転するので、文字列として左から"strtok"と"strlen"で処理していけばいいし。
2倍のポイントを手に入れた! 106ポイント を手に入れた。
|
|
|
|
|
Name: たろう ..ぴよぴよ(419ポイント)
Date: 2006/12/10(日) 18:32
No:2570
|
|
Title: Re:教えてください!!
|
|
右にシフトしていき0と1を判断しそれぞれ格納し最大連続数を探す方法、
最大連続数の開始ビットを表示する方法がわかりません。
55ポイント を手に入れた。
|
|
|
|
|
Name: 通りすがり ..入門者(3,268ポイント)
Date: 2006/12/10(日) 19:57
No:2573
|
|
Title: Re:教えてください!!
|
|
最大連続ビットが複数ある場合は、最下位のみ表示。
#include <stdio.h>
#include <string.h>
int Input(char *bin)
{
char buff[16];
int n, i;
fgets(buff, 16, stdin);
if(sscanf(buff, "%x", &n) != 1) return 0;
for(i = 0; i < 32; i ++){
bin[i] = '0' + (n >> i & 1);
}
bin[i] = '\0';
return 1;
}
void Search(char *bin, int *max, int *maxp, char *token)
{
char bintemp[33];
char *work;
int len;
memcpy(bintemp, bin, 33);
*max = *maxp = len = 0;
work = strtok(bintemp, token);
if(work == NULL){
*max = *maxp = 0;
return;
}
if((len = strlen(work)) > *max){
*max = len;
*maxp = work - bintemp;
}
while((work = strtok(NULL, token)) != NULL){
if((len = strlen(work)) > *max){
*max = len;
*maxp = work - bintemp;
}
}
return;
}
void Print(char *bin, int n)
{
if(!n) return;
Print(bin + 1, n - 1);
putchar(*bin);
if(!(n % 4)) putchar(' ');
if(n == 32) putchar('\n');
return;
}
void Mark(int maxp0, int maxp1)
{
int i;
maxp0 = ((31 - maxp0) / 4) * 5 + (31 - maxp0) % 4;
maxp1 = ((31 - maxp1) / 4) * 5 + (31 - maxp1) % 4;
for(i = 0; i < 39; i ++){
if(i == maxp0 || i == maxp1) putchar('^');
else putchar(' ');
}
putchar('\n');
return;
}
int main(void)
{
int max0, maxp0, max1, maxp1;
char bin[33];
if(!Input(bin)){
puts("Input Error");
return 1;
}
Search(bin, &max0, &maxp0, "1");
Search(bin, &max1, &maxp1, "0");
Print(bin, 32);
Mark(maxp0, maxp1);
printf("\'0\':%d~%d, \'1\':%d~%d\n", maxp0, max0, maxp1, max1);
return 0;
}
871ポイント を手に入れた。
|
|
|
|
|
Name: たろう ..ぴよぴよ(389ポイント)
Date: 2006/12/10(日) 20:44
No:2576
| 解決!
|
Title: Re:教えてください!!
|
|
ありがとうございます。
これから理解してみたいと思います。
30ポイント を落としてしまった。
|
|
|
|
Name: ウリ ..ぴよぴよ(35ポイント)
Date: 2006/12/10(日) 18:48
No:2571
|
|
Title: グラフについて
|
|
はじめまして。
初心者なんです。 F(x)=x [0,1/2]
2x-1 [1/2,1]
といった感じでxの場合分けのグラフをつくりたいのですがどのようにすればいいかわかりません。
どうすればいいのでしょうか?
35ポイント を手に入れた。
|
|
|
|
Name: バグ ..上級者(15,501ポイント)
Date: 2006/12/10(日) 20:05
No:2574
|
|
Title: Re:グラフについて
|
|
あなたがどこまでC言語を理解していて、どこまで自分でプログラムを書いていて、その結果どこが分からないのかを書かないと誰も答えようがないのではないでしょうか?
77ポイント を手に入れた。
|
|
|
|
|
Name: ウリ ..ぴよぴよ(0ポイント)
Date: 2006/12/10(日) 20:25
No:2575
|
|
Title: Re:グラフについて
|
|
そうですね。すみませんでした。
一つのグラフを単体で描くことはできたのですが、次にどのようにすれば範囲によって違うグラフを同じ画面に表示できるのか?
と言うことなのですが。
63ポイント を落としてしまった。
|
|
|
|
Name: 初心者 ..入門者(3,920ポイント)
Date: 2006/12/10(日) 03:02
No:2546
|
|
Title: ファイル処理
|
|
卒業研究のために実験データのファイルを解析するプログラムをC言語で作ることになりました。
ファイルの形式は〜.datで中身は縦に二列、タブ区切りで保存されています。
そのファイルの二列の右側?の値のみから最大の四つの値の平均、最小の四つの値の平均を求めたいのですが、ファイルに保存されている数値が自然対数(たとえば1.3e-4)になっていて、どう扱えばいいかわかりません。
一応調べたのですが、自然対数の計算方法等しか出てこなかったのでこちらで質問させていただきました。
みなさんご教授よろしくおねがいいたします。
179ポイント を手に入れた。
|
|
|
|
Name: 管理人 [URL] ..ハッカー(124,012ポイント)
Date: 2006/12/10(日) 03:18
No:2548
|
|
Title: Re:ファイル処理
|
|
実験データはこのようにはいっているわけですね。
a b
c d
e f
g h
実際はもっと多いわけでしょうけど、
で、たとえば右側のb,d,f,hの中から最大の4つ、最小の4つを取り出して平均を求めると。
対数で書かれていても普通にdouble型に格納してもよいのですよね?
でしたら
log (x)
で計算して平均を求めてはいけないのでしょうか。
159ポイント を落としてしまった。
|
|
|
|
|
Name: Justy ..プログラマー(34,770ポイント)
Date: 2006/12/10(日) 03:26
No:2551
|
|
Title: Re:ファイル処理
|
|
>数値が自然対数(たとえば1.3e-4)になっていて、どう扱えばいいかわかりません
自然対数であっても atofとか sscanfで読みとればそのまま double型で読めます。
double value;
static const char value_str[] = "1.3e-4"; // ファイルから読みとってきた文字列としましょう
// 1
printf("value = %f\n", atof(value_str));
// 2
sscanf(value_str, "%lf", &value);
printf("value = %f\n", value);
return 0;
7ポイント を手に入れた。
|
|
|
|
|
Name: 初心者 ..入門者(4,044ポイント)
Date: 2006/12/10(日) 03:39
No:2555
|
|
Title: Re:ファイル処理
|
|
ご回答ありがとうございます。
doubleでも格納はできるのですね。あとは読み込み方しだいということで、教えていただいたものを参考にしたいと思います。
あと、右側から最大、最小をさがすにはやはりソートを使うのがよいのでしょうか?
もしほかに簡単に使えるプログラムがあればぜひ教えていただきたいです。
124ポイント を手に入れた。
|
|
|
|
|
Name: keichan ..初心者(7,970ポイント)
Date: 2006/12/10(日) 03:50
No:2558
|
|
Title: Re:ファイル処理
|
|
>ファイルに保存されている数値が自然対数(たとえば1.3e-4)になっていて、どう扱えばいいかわかりません。
テキストの保存されている入力形式が一定であるならば下記のようにすれば簡単に取得できます。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_LINE_COUNT (256)
int main()
{
FILE* fp = NULL;
char* tab_pos = NULL;
double tmp_value;
char file_buf[MAX_LINE_COUNT] = {0};
if( (fp = fopen("test.dat", "r")) == NULL ) {
printf("can't open file.\n");
return 1;
}
/* 1行ずつ file_buf へ読みこむ */
while( fgets(file_buf, MAX_LINE_COUNT, fp) != NULL ) {
/* '\t'(タブ)の位置を検索.なかったらNULLが返ってくる */
if( (tab_pos = strchr(file_buf, '\t')) == NULL ) {
continue;
}
/* 1.2e-4 4.2e-5 */
/* だったらば tmp_value へは 4.2e-5 が入る */
tmp_value = atof(tab_pos+1); /* タブ文字の直後から浮動少数が必ず始まると仮定 */
/* ここで最小・最大判定等ごにょごにょ */
}
fclose(fp);
return 0;
}
411ポイント を手に入れた。
|
|
|
|
|
Name: 初心者 ..入門者(4,173ポイント)
Date: 2006/12/10(日) 15:59
No:2566
|
|
Title: Re:ファイル処理
|
|
アドバイスありがとうございます。
ソートを使ってみたいと思います。
最後にもうひとつだけ質問させてもらいたいのですが。
データファイルの右側のデータ(タブ区切り)のみを読み込むのはどうすればいいのでしょうか?
質問ばかりですいません。。
129ポイント を手に入れた。
|
|
|
|
|
Name: box ..上級者(15,433ポイント)
Date: 2006/12/10(日) 16:28
No:2567
|
|
Title: Re:ファイル処理
|
|
> データファイルの右側のデータ(タブ区切り)のみを読み込むのはどうすればいいのでしょうか?
サンプルです。
#include <stdio.h>
int main(void)
{
char str[] = "1.2e-4\t4.2e-5"; /* ファイルに、こう書いてあるつもり */
double d;
printf("str='%s'\n", str);
sscanf(str, "%*s%lf", &d); /* 1個目のフィールドを読み飛ばす */
printf("d=%f\n", d);
return 0;
}
97ポイント を手に入れた。
|
|
|
|
Name: 宿題で困ってます。 ..入門者(3,885ポイント)
Date: 2006/12/05(火) 13:15
No:2342
|
|
Title: URLからページをとってくるには?
|
|
いつもお世話になっています。
なんとなく枠の色が変わったような気がしますが、気のせいかな?
質問は「URLをうつとインターネットのページがみれるようなプログラムを
C言語で作る」というものです。
ひょっとしてC言語だけではできないことですか?
自分はUNIXを使っているので、UNIXと連動させてやることなのでしょうか。
よろしくお願いします。
169ポイント を手に入れた。
|
|
|
|
Name: 管理人 [URL] ..ハッカー(111,157ポイント)
Date: 2006/12/05(火) 14:39
No:2358
|
|
Title: Re:URLからページをとってくるには?
|
|
何かのブラウザを使用する必要がありそうですね。
LinuxでIPアドレス使った通信プログラムは書いたことがありますが、
ブラウザを使わずに見るにはC単体では無理だと思います。
何かライブラリを使用するとか・・。
すみません、よくわかりません。
他の方が何かよい回答をしてくれるかもしれません(_ _||)
121ポイント を手に入れた。
|
|
|
|
|
Name: Justy ..プログラマー(32,007ポイント)
Date: 2006/12/05(火) 14:44
No:2360
|
|
Title: Re:URLからページをとってくるには?
|
|
実際の問題、出来なくはないです。
ただ、C言語で作ったアプリ「単体で」HPを見られるようなプログラム(フルブラウザ)を書くことは非常に困難です。
ですがテキストと gif/jpegだけとか機能を限定するなら一人且つ短時間で出来るとは思います。
※ ちょっとずるいですが、一番簡単なのは Firebirdのようなブラウザと連携して、CのプログラムがURLを受け取り、そのままブラウザに垂れ流す、という方法があります。
やったことはないですが、w3mのようなテキストブラウザなら表示を乗っ取って、あたかも自アプリが取得・表示しているようにみせかけることができる・・・かも。
2倍のポイントを手に入れた! 318ポイント を手に入れた。
|
|
|
|
|
Name: box ..中級者(12,515ポイント)
Date: 2006/12/05(火) 14:46
No:2362
|
|
Title: Re:URLからページをとってくるには?
|
|
以下のコードは単なる冗談です。決して真に受けないでください。
実行時の引数にどこかのURLを指定すると…。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char **argv)
{
char str[1024];
if (argc >= 2) {
if (strncmp(argv[1], "http://", 7) == 0) {
sprintf(str, "start %s", argv[1]);
system(str);
}
}
return 0;
}
181ポイント を手に入れた。
|
|
|
|
Name: かな ..ぴよぴよ(29ポイント)
Date: 2006/12/09(土) 22:10
No:2531
|
|
Title: 最大値を返す関数作成について
|
|
学校で「数値配列の最大値を返す関数を作成しなさい」というものがでました。
誰かおしえてください。
29ポイント を手に入れた。
|
|
|
|
Name: 管理人 [URL] ..ハッカー(121,687ポイント)
Date: 2006/12/09(土) 22:45
No:2532
|
|
Title: Re:助けて><
|
|
こんにちは。管理人です。
では、どの辺まで理解していらっしゃいますか?
この関数を作成するには
・関数への値渡し
・最大値計算
・返り値渡し
が理解できていれば出来るものと思います。
main関数のみで最大値を求めなさいと言われたら作成できますか?
今どの辺までできていらっしゃるでしょうか。
2倍のポイントを手に入れた! 302ポイント を手に入れた。
|
|
|
|
|
Name: かな ..ぴよぴよ(73ポイント)
Date: 2006/12/09(土) 22:54
No:2534
|
|
Title: Re:助けて><
|
|
最大値計算はできると思うのですが・・・・数値配列の意味と「返す」というところがわからないです。
44ポイント を手に入れた。
|
|
|
|
|
Name: 管理人 [URL] ..ハッカー(122,281ポイント)
Date: 2006/12/09(土) 23:01
No:2535
|
|
Title: Re:助けて><
|
|
なるほど、では念のため、最大値についてもご説明しますね。
・最大値計算
これは簡単です。大きい順、小さい順に並び替えるのなら少し考えてプログラムを組む必要がありますが、
大きいものだけ取り出せばいいのなら簡単です。
for文で配列要素数だけループさせ、
int max;
で用意した最大値を格納するmaxという変数に初め、配列の最初の要素を代入します。
配列がxという名前なら
max=x[0];
を最初に書きます。
後はループ文の中で、今の配列要素とmaxの値を比較し、maxより今の配列要素の方が大きければその時maxにその配列要素を代入する操作を繰り返せばいいのです。配列要素の番号を1ずつ進めていきましょう。
これで最大値計算処理が出来ます。
以下ご覧ください。
#include <stdio.h>
int main(){
int i,x[5]={1,8,3,6,7},max;
max=x[0];
for(i=0;i<5;i++)
if(max<x[i])
max=x[i];
printf("%d",max);
return 0;
}
これを実行してみてください。8が出力されるはずです。
アルゴリズムは上記を参考にしてください。
次は関数についてご説明します。
520ポイント を手に入れた。
|
|
|
|
|
Name: 管理人 [URL] ..ハッカー(123,039ポイント)
Date: 2006/12/09(土) 23:13
No:2536
|
|
Title: Re:助けて><
|
|
最大値を求める関数を作るときは
・ポインタを使う
・最大値を返り値として返す
という2種類の作り方がありますが、問題の回答として後者がふさわしいと思うので、
こちらをご説明します。
まず、最大値とかはおいといて、関数化について考えてみましょう。
メイン関数の中でmax_returnという名前の関数に処理を渡して戻ることを考えます。
#include <stdio.h>
int max_return(){
return 0;
}
int main(){
max_return();
return 0;
}
これが最小限の処理になりますが、ここまで大丈夫ですか?
どの関数にも「return」と書いてありますね。
これが返り値を示すもので、returnの次に書いてある数字が関数を呼び出したところへ返ります。
つまりこの場合両者とも0が返ってくるわけですね。
では、これならどうでしょう。
#include <stdio.h>
int max_return(){
return 1;
}
int main(){
int i;
i=max_return();//★
printf("%d \n",i);
return 0;
}
return で書いた数字はその関数をよんだところに返るといいましたね。
つまりmax_return関数をmain関数で呼んだ//★の所に1が返ってきますね。
ということは、iには何が入っているでしょうか?
printfで出力される結果を予想しましょう。
実際に上記プログラムをコンパイルして、その予想とあっているか確かめてください。
仕上げにこちら。
#include <stdio.h>
int max_return(int a){
a = a+5;
return a;
}
int main(){
int max;
max=max_return(6);
printf("max = %d\n",max);
return 0;
}
出力されるprintf文には何が出力されるか考え、実際にコンパイルして実行し、確認してください。
(現時点で考える範囲ではmain関数のreturn 0;はあってもなくても変わらないです。)
ここまで解れば後は簡単です。ここまでで、わからないところがあれば聞いてください。
758ポイント を手に入れた。
|
|
|
|
|
Name: かな ..ぴよぴよ(99ポイント)
Date: 2006/12/09(土) 23:36
No:2537
| 解決!
|
Title: Re:助けて><
|
|
たいへんよくわかりました☆
本当にありがとうございました≧ー≦。
26ポイント を手に入れた。
|
|
|
|
|
Name: 管理人 [URL] ..ハッカー(123,977ポイント)
Date: 2006/12/09(土) 23:54
No:2538
|
|
Title: Re:助けて><
|
|
あ、サンプルプログラムを用意していましたが、もう全部出来ました?
一番いいのはサンプルを見ずに全部自分で完成させてしまう事ですが、それが出来たのでしたら
よかったです☆
せっかく作ったのでよければ、サンプル見てください。
これは要素数に影響されず、どんな配列のサイズでも、対応します。
☆アルゴリズム解説☆
最大値を計算する過程で「何回ループするか」を直接先ほど「5」としましたが
渡される要素数は何個かわからないので、いつも「5」とするわけにはいきません。
ですから、配列の大きさを事前にチェックし、その値も渡してやるとよいでしょう。
len = sizeof(x) / sizeof(x[0]);
ここの部分ですが、sizeof関数は、そのデータのある領域サイズを返す関数です。
int型という変数は1つで4バイトという領域の大きさを取ります。
int i;
と宣言すれば、i用の4バイトの領域が確保されます。
int i[3];
と宣言すれば、i用の12バイトの領域が確保されます。
i[3]
の「3」が今わからないとして、この3を調べるにはどうしたらいいでしょうか?
それは「全体の領域サイズ÷1つの領域サイズ」を調べてやればいいですね。
よって
len = sizeof(x) / sizeof(x[0]);
このように書くことで、lenには配列の要素数が入り、この数だけループすればいいことがわかります。
ですから、max_return関数には、xだけでなく、このlenも渡し、lenだけループさせてみてください。
今回はxの要素数を7としました。
要素数を変更しましたが、きちんと最大値が求まっています。
max_return関数内で、きちんと7回ループが行われているからです。
#include <stdio.h>
int max_return(int x[],int len){
int max,i;
max=x[0];
for(i=0;i<len;i++)
if(max<x[i])
max=x[i];
return max;
}
int main(){
int m,x[7]={4,5,1,8,3,6,9},len;
len = sizeof(x) / sizeof(x[0]);
m=max_return(x,len);
printf("最大値は[%d]\n",m);
return 0;
}
実際にコンパイルしてみてください。
さっきとは違う「9」が出力されるはずです。
このプログラムがしっかり理解できると
len = sizeof(x) / sizeof(x[0]);
「この処理はmax_return関数内に書いたほうがいいんじゃないの?
そうすれば値を渡す数も1つで済むし」
と思うかもしれませんけど、これは理由があって、
そのまま考えたんじゃ出来ないんです。
max_return関数内でsizeof(x)を行うと「4」になってしまいます。
データ1個分しか無い事になってしまいます。
その辺の奥深い話は興味があったら調べてみてください。
938ポイント を手に入れた。
|
|
|
|
|