ページ 11

C言語プログラムで行き詰っています

Posted: 2015年2月12日(木) 06:25
by りゅき
こんにちは。プログラミング初心者です。
私は今、C言語でベクトルの電卓をつくっています。
「ベクトル名(アルファベット1文字) 演算子(「=」 など) ベクトル成分(a1, a2, a3)」のように入力すると構造体にベクトル名とベクトル成分が保存できるといった形にしようとしています。
入力されてた式をif文で判断ができておらず、式を正しく判断してくれません。
このプログラムをif文、または別の方法で判断するにはどうしたら良いのでしょうか。

コード:

 
#include <stdio.h>
#include <string.h>
#include <math.h>


struct date {       /* ベクトルの要素 */
    float e1;       /* 要素1 */
    float e2;       /* 要素2 */
    float e3;       /* 要素3 */
};

struct vector {    /* 名前付きベクトル */
    char  name[2];  /* ベクトル名 */
    struct date element;
};

/* 和 */
float sum1(float a1, float b1)
{
      return (a1 + b1);
}
float sum2(float a2, float b2)
{
      return (a2 + b2);
}
float sum3(float a3, float b3)
{
      return (a3 + b3);
}

/* 差 */
float diff1(float a1, float b1)
{
      return (a1 - b1);
}
float diff2(float a2, float b2)
{
      return (a2 - b2);
}
float diff3(float a3, float b3)
{
      return (a3 - b3);
}

/* 定数倍 */
float teisu1(float k, float a1)
{
     return (k * a1);
}
float teisu2(float k, float a2)
{
     return (k * a2);
}
float teisu3(float k, float a3)
{
     return (k * a3);
}

/* 内積 */
float sprod(float a1, float a2, float a3, float b1, float b2, float b3)
{
      return (a1 * b1 + a2 * b2 + a3 * b3);
}

/* なす角 */
float cs(float a1, float a2, float a3, float b1, float b2, float b3)
{
      return ((a1 * b1 + a2 * b2 + a3 * b3) / (sqrt((a1 * a1) + (a2 * a2) + (a3 * a3)) * (sqrt((b1 * b1) + (b2 * b2) + (b3 * b3)))));

}

/* 極座標に変換 */
/* r */
float polarr(float a1, float a2, float a3)
{
      float r = 0.0;     
      r += ((a1 * a1) + (a2 * a2) + (a3 * a3));

      return sqrt(r);
}
/* θ */
float polarshita(float a1, float a2)
{
      return atan(a2 / a1);
}
/* φ */
float polarfai(float a1, float a2, float a3)
{
      float f = 0.0;
      f += sqrt((a1 * a1) + (a2 * a2)) / a3;
	  
      return atan(f);
}

int main(void)
{
	struct vector v = {"", 0.0, 0.0, 0.0};
	struct vector rireki[10];
	float  a1, a2, a3;
	float  b1, b2, b3;
    int    s , i = 0;
	char   name[1];
    char   op, op1;

        printf("開始します\n");
        printf("> ");
/* [ベクトル名] */
	  	if(scanf("%s", name)){ 
        /* ベクトル名が重複されているか */
		for ( s = 0; s < i; ++s ) {
			if ( strcmp( name, rireki[s].name ) == 0 ) {
                break;
			}
		}
		if(s == i) {
		/* 登録可能 */
		   strcpy(rireki[s].name, name);
		   ++i;
           printf("登録可能です\n");
	    }
		else {
		   printf("登録済み\n");
		   printf("ベクトル名:%s 要素:%.2f, %.2f, %.2f\n",
		          rireki[s].name, rireki[s].element.e1, rireki[s].element.e2, rireki[s].element.e3);
		   }
		  } 
/* [ベクトル名] = [ベクトルa1, a2, a3] */
else if (scanf("%s %c %f %f %f", v.name, &op, &a1, &a2, &a3)){
      switch ( op ) {
            case ('=') : printf("ただの代入\n");
                         v.element.e1 = a1;
                         v.element.e2 = a2;
                         v.element.e3 = a3; 
                         printf("ベクトル名:%s 要素:%.2f, %.2f, %.2f\n",v.name, v.element.e1, v.element.e2, v.element.e3); break;
            case ('>') : printf("極座標に変換\n");
                         v.element.e1 = polarr(a1, a2, a3);
                         v.element.e2 = polarshita(a1, a2);
                         v.element.e3 = polarfai(a1, a2, a3);
                         printf("ベクトル名:%s 極座標(r,θ,φ):%.2f, %.2f, %.2f\n",v.name, v.element.e1, v.element.e2, v.element.e3); break;
      }
}}
/* [ベクトル名] = [ベクトルa1, a2, a3] [演算子op1(+,-,&)] [ベクトルb1, b2, b3] */
else if(scanf("%s %c %f %f %f %c %f %f %f", v.name, &op, &a1, &a2, &a3, &op1, &b1, &b2, &b3)){
      switch ( op ) {
         case ('=') : switch( op1 ) {
                       case '+' : printf("和\n");
                                  v.element.e1 = sum1(a1, b1);
                                  v.element.e2 = sum2(a2, b2);
                                  v.element.e3 = sum3(a3, b3);

                                  printf("ベクトル名:%s 要素:%.2f, %.2f, %.2f\n", v.name, 
			                              v.element.e1, v.element.e2, v.element.e3); break;
					
                       case '-' : printf("差\n");
                                  v.element.e1 = diff1(a1, b1);
                                  v.element.e2 = diff2(a2, b2);
                                  v.element.e3 = diff3(a3, b3);

                                  printf("ベクトル名:%s 要素:%.2f, %.2f, %.2f\n",v.name,
								          v.element.e1, v.element.e2, v.element.e3); break;
					
                       case '&' : printf("内積\n");
                                  v.element.e1 = sprod(a1, a2, a3, b1, b2, b3);

                                  printf("ベクトル名:%s 内積:%.2f\n", v.name, v.element.e1); break;
                       case '@' : printf("なす角\n");
                                  v.element.e1 = cs(a1, a2, a3, b1, b2, b3);
                                  printf("ベクトル名:%s なす角(ラジアン):%.2f\n",
                                         v.name, v.element.e1); break;
                      } break;
      	  }
}
/* [ベクトル名] = [定数] * [ベクトルa] */
else if(scanf("%s %c %f %c %f %f %f", v.name, &op, &k, &op1, &a1, &a2, &a3)){
      switch ( op ) {
            case ('=') : switch( op1 ) {
				           case ('*') : printf("積\n");
                                        v.element.e1 = teisu1(k, a1);
                                        v.element.e2 = teisu2(k, a2);
                                        v.element.e3 = teisu3(k, a3); 
                                        printf("ベクトル名:%s 要素:%.2f, %.2f, %.2f\n",v.name, v.element.e1, v.element.e2, v.element.e3); break;
      }break;
   } 
}
else {
	printf("エラー");
	}
	
    return(0);
}

Re: C言語プログラムで行き詰っています

Posted: 2015年2月12日(木) 08:10
by みけCAT
scanf関数は読み込んだ文字列を入力バッファから削除するので、
一旦fgets関数で入力を読み込んだあと、sscanf関数でパースするようにしてみてください。
判定の順番も、読み込むデータ数の多いものから少ないものという順番にするべきです。
さらに、条件式もsscanf関数の戻り値を直接渡す(すなわち0でないかを判定する)のではなく、
sscanfの戻り値が読み込もうとしたデータの数と一致したかを判定してください。

Re: C言語プログラムで行き詰っています

Posted: 2015年2月12日(木) 08:15
by みけCAT
オフトピック
ベクトルの要素をそれぞれ計算する関数を作るのではなく、
ベクトル2個(もしくはベクトルとスカラー)を受け取って、計算結果のベクトルを返す関数を作り、利用してみてはいかがでしょうか?
中身が全く同じsum1, sum2, sum3関数があるのが不自然に感じました。

Re: C言語プログラムで行き詰っています

Posted: 2015年2月12日(木) 14:21
by non
103行 char name[1];
最低2文字は必要ですが、入力ミスをする場合もあるので、もっと大きくした方が安全です。

Re: C言語プログラムで行き詰っています

Posted: 2015年2月13日(金) 01:42
by りゅき
fgets関数とsscanfを使い、解決しました。
ありがとうございます!