C言語の問題を授業で出されたのですがさっぱり分かりません。教えて下さい。

1.キーボードから整数nを入力して、1+2+…+nを求めるプログラムを作れ。
2.キーボードから整数nを入力して、1*2*…*nを求めるプログラムを作れ。
3.キーボードから10個の実数を入力し、それらの平均を求めるプログラムを作   れ。
4.円錐の体積を求めるプログラムを作れ。 注:円錐体積V=π*r*r*h/3
5.キーボードから文字列を入力し、それを逆さまにするプログラムを作れ。例えば、”dog”を逆さまにすると”god”になる。
6.キーボードから一つの整数を入力し、それは奇数か偶数かを判断するプログラムを作れ。

ちなみに6番は
/* iftst.c */
#include <stdio.h>

void main(void)
{
int n;

printf("n=");
scanf("%d",&n);
if(n%2 == 0){
printf("偶数です\n");
}
else{
printf("奇数です\n");
}
}

で合っているのでしょうか?

このQ&Aに関連する最新のQ&A

A 回答 (5件)

/* iftst.c */


#include <stdio.h>

void main(void)
{
int n; /* 入力値 */
int loop_cnt; /* カウンタ */
int gokei; /* 加算合計 */

printf("n=");
scanf("%d",&n);

gokei = 0; /* 加算合計初期化 */
for( loop_cnt = 1; loop_cnt <= n; loop_cnt++ ){
gokei = gokei + loop_cnt;
}
printf("1,nの合計%d\n",gokei);
}
    • good
    • 0
この回答へのお礼

これは何番なのでしょう?ホントに初心者なのでプログラムを見てもさっぱり分からないのです…。

お礼日時:2001/07/10 11:11

naturalです。


コメント読みました。

取り敢えず最も初歩の段階から説明することにします。
以下のソースは何の処理もしませんがコンパイル出来る完全なプログラムです。

void main(void)
{
}

このような形でC言語の最小のプログラムは書けるわけです。
後は{と}の間に処理を書き連ねていけばプログラムとして色々な仕事をする様にできます。

voidと言う部分が2カ所ありますが、ちょっと解説しておきたいと思います。
最初の方は関数型と呼ばれる部分で、どんな型の値を返してくるかを指定します。
つまり人間に例えると、その関数が仕事を終えた後でどういった形で報告をおこなうかを指定する部分です。
後者の方は引数と呼ばれる部分でその関数がどんな型の値を引き受けて仕事をするかを指定します。
こちらも人間に例えると、どんな資料を与えて仕事をさせるかを指定するわけです。
このプログラムではどちらもvoid型となっていますがvoidは「特に無い」ことを示します。
つまり使用する際には返却値も引数も無いと言うことになります。

さて前述の様に{と}の間にいよいよ処理を加えたいと思います。
但し関数を使用する場合その関数を宣言しているヘッダーファイルと呼ばれるものを読み込んでやるように指定しなければなりませんのでご注意下さい。
例えばこうです。

#include <stdio.h>
void main(void)
{
  printf("Hello,world!\n");
}

上記の例で言うところの#includeで始まる行がヘッダーファイルの読み込み指定部分です。(厳密に言うと読み込みでは無いのですが便宜的にそう述べておきます)
お解りでしょうか?
printfと言う関数がどういった形で使われるべきかと言った情報がstdio.hにはあり、このファイルの情報を読み込ませることによってコンパイラーにも情報がわたり、翻訳の際に参照されるわけです。
因みに使う関数によってどんなヘッダーファイルを指定すればよいかについてですが、テキストをお持ちならば関数の仕様がどこかに解説してあるはずですのでそちらをご覧頂ければ記載されているはずです。

ここまででC言語の第一歩となるはずですが、既に理解されていたでしょうか?
もしまだならばもう一度テキストの冒頭部分を読み返してみることをお奨めします。
単位をあきらめるのはまだ早いですよ!頑張って!!p(^^)q
    • good
    • 0
この回答へのお礼

5回ほど繰り返し読んでみましたがやっぱり理解不能です。せっかく丁寧に書いていただいたのに…。ありがとうございます。

お礼日時:2001/07/10 14:57

出題者の観点から、重要と思われる点については●をつけてあります。



■1,2について
 合計はsum、階乗はfacなどとして、計算途中の値を覚えておく変数を用意する必要があります。全ての計算を終えた時、この変数が答えになります。
 1~nの範囲で計算を行うので、カウント用変数 i の値が1~nになるようforループを作り、ループ内で「sum += i;」「fac *= i;」のようにします。
●このとき重要なのは sum、facの初期値で、ループに入る前に正しく設定しなければなりません。nを4くらいに仮定して、机上でループを展開してみれば分かるハズです。

■3について
 平均は「合計÷個数」なので、合計に関しては1を参考にしましょう。n=10としてループし、中で値を入力→sumへの足しこみを行います。
●気を付けなければならないのは「÷個数」の計算式の書き方です。
 10で割った結果が必ず整数になる保証は無いので、結果は小数として処理しなければなりません。つまり、平均用の変数は「double ave;」のように宣言します。
 更に、整数÷整数の結果は整数となってしまうため、単純に「ave = sum / 10;」としても、aveには正しい結果は入りません。小数の結果を得るためには、「ave = sum / 10.0」として整数÷小数とするか、「ave = (double)sum / 10;」のようにsumを小数型へキャストするようにしましょう。もちろん両者を同時に行っても構いません。
 結果の表示も、%fで小数表示するようにしましょう。

■4について
 必要なのはrとhだけですから、それぞれを%fでdouble型(またはfloat型)変数に入力させ、計算します。
●おそらく求められているのは、処理の関数化でしょうね。
  double calc_volume_cone(double r, double h);
のようなプロトタイプで処理するようにすると良いでしょう。

■5について
 文字列を逆さまにする関数はないので、入力された文字列の終端を調べ、1文字ずつ処理を行います。
 ただ、とにかく逆さに表示すればよいのか、文字列を格納した文字配列の中身自体を反転するのか分かりません。naturalさんは表示のみ、brogieさんは別配列への格納を解説されているので、文字配列内部の反転について書きます。

  char *strrev(char *str) {
    int n1, n2;
    char ch;

    n1 = 0;
    n2 = strlen(str) - 1;
    while (n1 < n2) {
      ch=str[n1]; str[n1]=str[n2]; str[n2]=ch;
      n1++; n2--;
    }
    return str;
  }

 引数として渡された文字列strの、n1番目とn2番目を交換していくことで反転を行います。よってn1の初期値は0、n2の初期値は文字列終端に合わせます。(strlenで求めた「文字数」は1から数えたものであり、0から数える配列添字に直すため1を引いています。)
 n1は0から後ろに、n2は終端から前に調べていくため、ループの条件を「n1 < n2」とし、文字の交換後、「n1++;(後ろへ)」「n2--;(前へ)」を行います。
 戻値で文字列strの先頭アドレスをそのまま返しているのは、「puts(strrev(s));」のような使い方ができるようにするためで、文字列処理では一般的な方法です。

■6について
 ikuchanさんの回答でOKです。
 欲を言えば、if文の条件を直接「n % 2 == 0」とせず、マクロで
  #define iseven(n) ((n) % 2 == 0)
のように定義し、
  if (iseven(n)) {
のようにすると良いでしょう。まぁ関数にしても良いですが。
    • good
    • 0
この回答へのお礼

用語についても分からないのでとっても難しいです。まだはじめたばかりだし苦手なので、この文を読んでも分かっていないのですが、とりあえずがんばってみます。ありがとうございます。

お礼日時:2001/07/10 11:19

ヒントです。

これ以上は書けません。ご自分で考えてください。
6.の解答が出来ているではありませんか?
宣言やmain関数も省略しています。

1.について
for(i = 1;i<=n;i++){
   s+=i;
}

2.について
ans=1;/*これ必要です*/
for(i=1;i<=n;i++){
   ans*=i;
}

3.について
for(i=1;i<=10;i++){
   scanf("%d",&n);
   asn +=n;
}

4.略(簡単)

5.について
#include <string.h>  /*strlen()のプロトタイプ宣言*/
char str1[256],str2[256];
scanf("%s",str1);
len1=strlen(str1);
for(i=len1;i>0;i--){
   str2[len1-i] =str1[i];
}
以上です。参考まで(^^)
    • good
    • 0
この回答へのお礼

これをどこにどういう風に入れていいかさえも分かりません。やっぱり私にはC言語は理解不能です。この授業の単位はないと思われます(ToT)ありがとうございました。

お礼日時:2001/07/10 11:23

1番及び2番に関しては関数分割しなくて良いのなら、単純に入力された数を元にfor文でカウンタをインクリメント、または元の数からデクリメントしていけば出来ます。


ループ内部の処理は単純計算ですから判りますよね。
3番では問題に書かれている通り「実数」を使用するのがポイントです。
用意する変数、入力時、出力時それぞれ実数を意識してやればOKです。
10回分の入力は勿論ベタで書いてはいけません。
構文を使えば簡単ですよね。
4番も3番と同じく実数を使用することで簡単に出来るはずです。
5番は入力された文字列を逆順で出力するだけですから、入力された文字列の末尾を見つけます。(つまりヌル文字の前の文字を見つけるわけです)
文字列の長さを測る関数の使用が許されているならばそれを使えば良いのですが、そうでない場合は構文を使ってヌル文字を検索しその場所が何番目か判れば良いわけです。
そこから一文字ずつ先頭文字まで改行しないで出力していけばOKです。
6番は、上記のやり方で大丈夫でしょう。(^_^)
    • good
    • 0
この回答へのお礼

う~ん…。読んでも分からないです。初心者だし苦手だし将来必要なものでもないのでホントにさっぱり分かりません。でもありがとうございます。

お礼日時:2001/07/10 11:15

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

Qvoid main(void){...}だとDosWindowが開くので

わざわざWindowsアプリにして以下のようにするしかないのでしょうか?

LONG WINAPI WinProcedure(HWND hW,UINT wM,UINT wP,LONG lP)
{
//ここに宣言を置く
switch(wM)
{
case WM_CREATE:
//ここに処理を置く
return 0;
default:
return(DefWindowProc(hW,wM,wP,lP));
}
}
WINAPI WinMain(HINSTANCE hI,HINSTANCE,LPSTR,int nCS)
{
WNDCLASSwc;
HWNDhW,hPW;
MSGms;

wc.lpszClassName="goo";
wc.lpfnWndProc=(WNDPROC)WinProcedure;
wc.hInstance=hI;
wc.style=CS_HREDRAW|CS_VREDRAW;
wc.cbClsExtra=NULL;
wc.cbWndExtra=NULL;
wc.hIcon=LoadIcon(NULL,IDI_EXCLAMATION);
wc.hCursor=LoadCursor(NULL,IDC_ARROW);
wc.hbrBackground=(HBRUSH)(COLOR_WINDOW+1);
wc.lpszMenuName=NULL;
RegisterClass(&wc);
hW=CreateWindow
(
"goo",
"教えて!goo",
WS_OVERLAPPED,
0,
0,
640,
456,
NULL,
NULL,
hI,
NULL
);
ShowWindow(hW,nCS);
UpdateWindow(hW);
while(GetMessage(&ms,NULL,NULL,NULL))
{
TranslateMessage(&ms);
DispatchMessage(&ms);
}
return (ms.wParam);
}

もっと簡単にDosWindowが開かないようにする方法はないのでしょうか?
もしないとすると上記記述でもっと簡単にできないでしょうか?

わざわざWindowsアプリにして以下のようにするしかないのでしょうか?

LONG WINAPI WinProcedure(HWND hW,UINT wM,UINT wP,LONG lP)
{
//ここに宣言を置く
switch(wM)
{
case WM_CREATE:
//ここに処理を置く
return 0;
default:
return(DefWindowProc(hW,wM,wP,lP));
}
}
WINAPI WinMain(HINSTANCE hI,HINSTANCE,LPSTR,int nCS)
{
WNDCLASSwc;
HWNDhW,hPW;
MSGms;

wc.lpszClassName="goo";
wc.lpfnWndProc=(WNDPROC)WinProcedure;
wc.hInstance=hI;
wc.style=CS_HREDRAW|CS_VREDRAW;
wc...続きを読む

Aベストアンサー

ウィンドウを開く必要がないなら、mainをWinMainに変更するだけで良いのでは? ウィンドウクラス登録、ウィンドウ作成、メッセージループ、ウィンドウプロシージャは全て不要な気がしますが。

WINAPI WinMain(HINSTANCE hI,HINSTANCE,LPSTR,int nCS)
{
  //処理内容

  return 0;
}

Qvoid (*signal(int signum, void (*handler)(int)))(int);

の解釈を教えてください
最後の「(int)」については詳しくお願いします

Aベストアンサー

signalが

(1)1つ目の引数の型:int
(2)2つ目の引数の型:引数がintで戻り値がvoidである関数へのポインタ
(3)戻り値の型:引数がintで戻り値がvoidである関数へのポインタ(2と同じ)

を満たす関数である事を宣言しています。最後の(int)はsignalの戻り値の
関数ポインタがint型の引数を持つ事を示しています。

「引数がintで戻り値がvoidである関数へのポインタ」の型をHANDLERと表すと

HANDLER signal(int signum, HANDLER handler);

となります。

Qtry{}catch(){}とデストラクタの関係を教えてください。

try-catchでメモリ確保を含むクラスをスローした場合、デストラクタはどの時点で働くのか、教えてください。たとえば、↓の使いかたは大丈夫でしょうか?

【1】
try{
 throw(CError(100, "エラー情報"));
}catch(CError& err){
 //ここでerrを参照しても問題ないのでしょうか?
}

【2】
try{
 CError err(100, "エラー情報");
 throw(err); // (1)
}catch(CError& err){
 //ここでerrを参照しても問題ないのでしょうか?
 //まだデストラクタはちゃんと動作するのでしょうか?
 //catchが呼び出し元のメンバであったりしても大丈夫なのでしょうか?
}

宜しくお願いします。

Aベストアンサー

【1】【2】どちらの場合も問題がありません。
コンパイラが必要に応じてerrオブジェクトのコピーを作成します。
デストラクタが呼び出されるタイミングはコンパイラに依存するところもあると思いますが、
例えばVC7.1では【2】は以下のように動作します。
(1) errオブジェクトのコンストラクタが呼び出される
(2) CErrorクラスのテンポラリオブジェクト(以下a)のコピーコンストラクタが呼び出される。
(3) errオブジェクトのデストラクタが呼び出される
(4) catch文まで到達
(5) aオブジェクトのデストラクタが呼び出される。

VC7.1では、【1】は以下のように動作します。
(1) errオブジェクトのコンストラクタが呼び出される
(2) catch文まで到達
(3) errオブジェクトのデストラクタが呼び出される。

コンパイラがオブジェクトのコピーを省略しているようです。

Q{x = x>y ? x:y; return x;}

#include <iostream>
using namespace std;

inline int max(int x, int y){x = x>y ? x:y; return x;}

int main()
{
int num1, num2, ans;

cout << "2つの整数を入力して。\n";
cin >> num1 >> num2;

ans = max(num1, num2);

cout << "最大値は" << ans << "です。\n";

return 0;
}
の{x = x>y ? x:y; return x;}の部分の意味が解りません。

Aベストアンサー

inline int max(int x, int y){x = x>y ? x:y; return x;}
これを普通に関数で書くと

int max(int x, int y)
{
x = x>y ? x:y;
return x;
}

です。

x = 部分は右辺の結果が代入されます。これはわかりますよね。
x>y?x:y;
と書くと?より左にある条件式を判定し、その結果が真である場合は:で区切られた左側の値を、偽である場合は右の値を帰します。
x>yが真であればxを、偽であればyを返します。
それが、左辺値xに代入され、関数の戻り値として帰ります。

従って、2つの値をこの関数に入れると、大きいほうの値が帰ることになります。

Qint main()、void main()、void main(void)、int main(void)

今日、大学でC言語の講義の時間、先生が、

#include <stdio.h>

void main(void){

}

と宣言してプログラムを書くと教えていました。
main関数には、
main()
void main()
void main( void )
int main()
int main( void )

と、人によりいくつかの描き方があったりします。
どれが本当は正しいのでしょうか?
void mainはすべきではないとなんかの本で読んだのですが・・。

Aベストアンサー

通称C89という以前の言語規格(現行コンパイラの多くが準拠)では、下記のいずれかが正しい。
int main(int argc, char *argv[])
int main(void)

但し、最新のC言語規格(通称C99)では、
<ISO/IEC9899:1999>
or in some other implementation-defined manner.
</ISO/IEC9899:1999>
となっているので、処理系が戻り値のvoidを認めていればvoidも可。
# 組込み系などで戻り値を使わない環境もあるためでしょうか。

なので、コンパイラのマニュアルで戻り値のvoidにしていい/しろと書いてない限り、
voidは言語仕様的には正しくない。(でも動くものもある)


人気Q&Aランキング

おすすめ情報