三角表生成器的输入问题

时间:2018-10-28 05:44:45

标签: c++

  1. 选择的三角函数(正弦,余弦,正切)。
  2. 角度单位(A.度或B.弧度)
  3. 角度的起始值和终止值
  4. 从一个角度值到下一个角度值的增量

这些是我目前的任务。当前,例如,如果我选择正弦-A,那么我想选择度-A,那么如何防止这2个碰撞?我还是C ++的新手,所以我仍然对如何执行此操作感到困惑。任何帮助,将不胜感激。这是我的第一篇文章,因此,如果我做错了任何事情,请原谅我。

#include <iostream>
#include <iomanip>
#include <cmath>

const double PI = 3.14159265;
using namespace std;


int main()
{
    double v1, v2 , i;
    cout << "Trigonometric Table Generator" << endl;
    cout << " Choose the trignometric function(s): A-Sine, B-Cosine, C-Tangent" << endl;
    cout << " (e.g Enter A for Sine or AC for both Sine and Tangent): ";
    char input1;
    cin >> input1;


    cout << " Choose the unit of angle : A - degree or B - radian(e.g Enter A for degree) ";
    char input2;
    cin >> input2;

    if (input2 = 'A') {

        double degrees,i;
        degrees = (PI / 180)* i;
    }

    else if (input2 == 'B') {

        double radians, i;
        radians = ( 180 / PI)* i;

    }

    cout << "Enter the starting value and ending values for the angle, separated with a space: ";
    cin >> v1 >> v2;

    cout << "Enter the increment from one angle value to the next: ";
    cin >> i;



    switch (input1) {

    case 'A':

        double sine;

        for (i = 0; i <= v2; i = i + v1) {

            //degrees
            sine = (PI / 180)* i;

            cout << i << setw(10) << setprecision(3) << sine << endl;
        }
    }
    system("pause");
    return 0;
}

2 个答案:

答案 0 :(得分:0)

以下是一些使您在正确的轨道上的想法:

首先,在C ++中(与大多数其他编程语言一样),必须先使用 变量,然后再使用它的值。例如:

counter / 200

由于在给表达式赋值之前在表达式中使用了double radians, i; radians = ( 180 / PI)* i; ,这将导致未定义的行为。而是尝试将表达式i移动到已分配radians = ( 180 / PI)* i;的for循环内。

第二,在C ++中,变量的作用域通常由定义在其内的括号i决定。因此,当您编写类似的内容时:

{}

然后,变量if (input2 = 'A') { double degrees,i; degrees = (PI / 180)* i; } degrees仅存在于if语句中。即使您定义了另一个具有相同名称的变量,但如果它在不同的范围内,它实际上也不是相同的变量。

最后,您需要仔细考虑您在此处执行的数学运算。例如,似乎您实际上并未在任何地方调用i函数。在C ++中,通过使用名称以及括号中的参数来调用函数。例如,sin返回3的正弦。

当您不熟悉C ++时,这些东西可能会非常棘手,因此不要气disc!您可能想向老师或朋友寻求帮助,他们将能够提供更多个性化帮助,以指导您完成整个过程。

答案 1 :(得分:0)

让我们以旧的方式进行操作,让编译器为我们提供帮助。让我们从代码不变开始。让我们在启用了警告的情况下进行编译,以便查看编译器是否会为我们指出任何潜在的问题。我们通过至少包含-Wall -Wextra来为gcc / clang提供警告(对于新的C程序员,我们也应该也包括-pedantic -Wshadow),而在VS中,请使用/W3。因此,让我们尝试编译代码:

g++ -Wall -Wextra -pedantic -Wshadow -std=gnu++11 -Ofast -o trigtable trigtable.cpp

VS开发人员命令提示符的窗口中,创建可执行文件trigtable.exe

cl /nologo /W3 /Ox /Fetrigtable /Tp trigtable.cpp

哦,不。编译器说:

trigtable.cpp: In function ‘int main()’:
trigtable.cpp:23:21: warning: suggest parentheses around assignment used as truth value [-Wparentheses]
     if (input2 = 'A') {
                     ^
trigtable.cpp:25:24: warning: declaration of ‘i’ shadows a previous local [-Wshadow]
         double degrees,i;
                        ^
trigtable.cpp:11:21: warning: shadowed declaration is here [-Wshadow]
     double v1, v2 , i;
                     ^
trigtable.cpp:25:16: warning: variable ‘degrees’ set but not used [-Wunused-but-set-variable]
         double degrees,i;
                ^
trigtable.cpp:31:25: warning: declaration of ‘i’ shadows a previous local [-Wshadow]
         double radians, i;
                         ^
trigtable.cpp:11:21: warning: shadowed declaration is here [-Wshadow]
     double v1, v2 , i;
                     ^
trigtable.cpp:31:16: warning: variable ‘radians’ set but not used [-Wunused-but-set-variable]
         double radians, i;

因此在行23上,我们忘记了=是分配,而==是比较。固定。

25行的下一个-Wshadow警告中发现,我们在i行中使用的变量25 阴影了i行中11的数量。通过更改行11的声明以使用描述性名称increment代替i来解决此问题。

接下来在行25上设置变量degrees(与行radians上的31相同),但是在您的程序中都没有使用,是吗?哦,因为我们在degrees block-scope 中声明了if (input2 == 'A') {...},所以它仅在该块中可用,并且在 out-of-scope 该方块结束后。 (同样适用于radiansif (input2 == 'B'))。

在这两种情况下,由于我们还没有初始化i进行任何输入来设置它,因此degrees = (PI / 180)* i;会调用 Undefined Behavior 尝试使用i而其中包含不确定的值。

i到底是什么?哦,它是increment的起始值。但是我们也没有设置。让我们来制作iincrement,并将对increment的读取移到该代码块上方...实际上,让我们将所有输入移到计算上方。如果我们输入的任何内容无效,无论如何将使计算毫无意义。让我们还将radiansdegrees的声明移到main()的顶部,以便它们在程序的整个过程中都有效。

仅进行这些更改并添加快速编译器检查,以仅在Windows上运行时引起system ("pause");(否则不需要),您的代码可能如下所示:

#include <iostream>
#include <iomanip>
#include <cmath>

const double PI = 3.14159265;
using namespace std;

int main()
{
    double v1, v2 , increment, degrees, radians;
    char input1, input2;

    v1 = v2 = increment = degrees = radians = 0.0;  /* initialize values */

    cout <<  "Trigonometric Table Generator" << endl
         << " Select function(s): A-Sine, B-Cosine, C-Tangent" << endl
         << " (e.g Enter A for Sine or AC for both Sine and Tangent): ";

    if (!(cin >> input1)) { /* validate EVERY user input */
        cerr << "error: invalid input for 'input1'\n";
        return 1;
    }

    cout << " Unit of angle : (A - degree, B - radian): ";

    if (!(cin >> input2)) { /* validate EVERY user input */
        cerr << "error: invalid input for 'input2'\n";
        return 1;
    }

    cout << "Starting and ending angle values ("
         << ((input2 == 'A') ? "degrees" : "radians") << "): ";
    if (!(cin >> v1 >> v2)) { /* validate EVERY user input */
        cerr << "error: invalid input for 'v1 or v2'\n";
        return 1;
    }

    cout << "Enter the angle increment("
         << ((input2 == 'A') ? "degrees" : "radians") << "): ";
    if (!(cin >> increment)) {  /* validate EVERY user input */
        cerr << "error: invalid input for 'increment'\n";
        return 1;
    }

    if (input2 == 'A')
        degrees = (PI / 180.0) * increment;
    else if (input2 == 'B')
        radians = (180.0 / PI) * increment;

    switch (input1) {

        case 'A':
            double sine;

            for (double i = v1; i <= v2; i += increment) {

                //degrees
                sine = (PI / 180.0) * i;

                cout << i << setw(10) << setprecision(3) << sine << endl;
            }
            break;
        case 'B':
            cerr << "case 'B' not implemented\n";
            return 1;
            break;      /* technically not required, but good form */
        default : 
            cerr << "error: invalid function selection\n";
            return 1;
            break; 
    }
#if defined (_WIN32) || defined (_WIN64)
    system("pause");
#endif
    return 0;
}

即使启用了完整警告也可以再次编译-现在为警告,没有错误。现在我们有信心,至少该代码应能在没有基本错误的情况下运行。

使用/输出示例

$ ./bin/trigtable
Trigonometric Table Generator
 Select function(s): A-Sine, B-Cosine, C-Tangent
 (e.g Enter A for Sine or AC for both Sine and Tangent): A
 Unit of angle : (A - degree, B - radian): A
Starting and ending angle values (degrees): 30 45
Enter the angle increment(degrees): 1
30     0.524
31     0.541
32     0.559
33     0.576
34     0.593
35     0.611
36     0.628
37     0.646
38     0.663
39     0.681
40     0.698
41     0.716
42     0.733
43      0.75
44     0.768
45     0.785

嗯,等待"30 0.524"错误sin(30 degrees)0.5而不是0.524。让我们检查一下计算... sine = (PI / 180.0) * i;-这是不对的,那只是从度到弧度的转换。如果我们将该行更改为:

                sine = sin((PI / 180.0) * i);

正确的使用/输出

$ ./bin/trigtable
Trigonometric Table Generator
 Select function(s): A-Sine, B-Cosine, C-Tangent
 (e.g Enter A for Sine or AC for both Sine and Tangent): A
 Unit of angle : (A - degree, B - radian): A
Starting and ending angle values (degrees): 30 45
Enter the angle increment(degrees): 1
30       0.5
31     0.515
32      0.53
33     0.545
34     0.559
35     0.574
36     0.588
37     0.602
38     0.616
39     0.629
40     0.643
41     0.656
42     0.669
43     0.682
44     0.695
45     0.707

那更好。

您需要做许多进一步的改进。从 使用描述性变量名称 开始。 input1input2v1v2是什么意思?为什么不使用trigfuncs的{​​{1}}和input1的{​​{1}}和unitangle的{​​{1}}和input2的{​​{1}}。 (当您在代码中再排100行时,这会更有意义)。

我在上面内联了一些附加评论。阅读它们。还要注意,这些只是为了使代码正确编译和正确计算anglestart值而需要的最小,较小的更改,应该做很多额外的工作。您将输入v1用作度数,将angleend用作弧度,然后使用单独的v2sin变量的方式有点奇怪。只需准备代码以使用弧度和弧度增量来计算所有内容,然后选择度数即可进行转换。您实际上并不需要'A'来处理单独的情况,从逻辑上讲,流一点更容易的是在'B'中的字符上循环,并在其功能所在的字符上使用degrees计算,然后在其中检查radiansswitch是弧度还是度。这些只是一些想法,其余的实现留给您。

如果您有任何疑问,请告诉我。