【问题标题】:Unexpected array behavior in basic averaging program基本平均程序中的意外数组行为
【发布时间】:2015-09-06 01:02:05
【问题描述】:

似乎我总是来这里问愚蠢的问题,但它就是这样。截至目前,我正在参加我的第一门 compsci 课程,我们正在学习 c++。我之前对 c 有过非常基本的介绍,所以我想我会超越我目前的任务。现在我这样做只是为了炫耀,我觉得如果我不练习我以前的概念,它们最终会褪色。无论如何,解决问题!我应该编写一些代码,允许用户输入他们的姓名首字母,并进行一系列考试。现在这应该完成三件事:平均考试,打印输入的考试,并打印出他们的姓名首字母。嗯,本来很简单的任务,被你搞得一团糟。

#include <iostream>
#include <string>
#include <iomanip>

using namespace std;

int main()
{
  string uInitials;
  float avgExam = 0, tExam = 0;
  int aExams[10] = {'0'};
  int i, nExam = 0, cExam;


  cout << "Enter your three initials!";
  cin >> uInitials;


  do
      {

        cout << "Enter your exam(s) to be averaged. Enter 0 when          complete!\n";
        cin >> cExam;
        aExams[nExam] = cExam;  //I used this before nExam was incremented, in order to get nExam while it was '0' That way the first exam score would be properly saved in the first space
        nExam++;
        tExam += cExam;     //This is just to add all the exams up to later calculate the average
    }
  while(cExam != 0);

avgExam = tExam/(nExam - 1); //subtracted '1' from nExams to remove the  sentinel value from calculations.

cout << "The average for initials: " << uInitials << " is: " << avgExam <<   endl;
cout << "This average was obtained using the following scores that were entered: \n";

for(i = 0; i < (nExam+1); i++)
{
    cout << aExams[i] << endl; //Used a for loop to prevent redundancy
}

return 0;
}

前面是我的代码,问题是当我打印出输入的考试列表时,我得到了输出错误,它添加了两个“0”。此外,我觉得我让整个 do{}while() 循环变得非常笨拙,所以我也想改进它。如果有人能帮助这个可怜的、无知的初学者,我将不胜感激。感谢您的宝贵时间!

【问题讨论】:

  • 无保护以防止超出输入缓冲区的末尾
  • 您使用的是 IDE 吗?如果有,是哪一个?
  • 我正在使用 code::blocks!这是我最舒服的一个。
  • Code::blocks 是 GDB 调试器的前端。你会有一点学习曲线,但从长远来看,没有什么比弄清楚如何调试自己的代码更有用的了。如果您单步执行代码,您当前的问题很容易发现。
  • 不要使用 C 风格的数组。使用std::arraystd::vector,它们是由好的调试器检查的边界,并且会检测到许多错误。 Vector 还允许您根据需要调整大小,而不是选择任意数字,例如 10,如果需要超过 10 个元素,它将中断。 = {'0'}; 不会将 int 的数组设置为全 0(检查您的调试器)。请改用= {};。 (对于自动为 0 的向量不需要)

标签: c++ arrays codeblocks average


【解决方案1】:

我可以给出的一些建议是例如在第 5 行没有必要 将 0 放在 ' ' 之间,甚至不需要使用 assign = 运算符。 您可以像这样初始化数组: int aExams[10]{0}; 它将所有元素初始化为0,但不能用于其他值。 例如,如果您编写,您将不会拥有所有值为 1 的元素 int aExams[10]{1}; 如果您打算初始化数组中的所有元素的值不是 0,则可以使用 fill_n();功能。

fill_n(aExams, 10, 1); 第一个参数是数组的名称,第二个是您希望使用第三个参数初始化的元素,第三个是您希望所有元素具有的值。

不要将未初始化的变量(如第 6 行中的 cExam 和 i 变量)留下。像 cExam=0; 一样初始化它(复制分配初始化)或 cExam(0); (直接初始化)。后者调用 int 内置类型的构造函数。

我在你的 do-while 循环中看到的一个负面因素是你不能确保用户将输入 10 个考试,如果用户尝试在一个只能容纳 10 个的数组中输入 15 个考试,就会发生不好的事情。

只需将 while 更改为类似这样的内容: while( cExam != 0 && (nExam

您也可以在循环之外编写 do-while 循环的前两行。 只需要一次告诉用户要停止循环,他/她需要输入 0。无需在每次迭代时都告诉他们这一点,而且如果将这两行放在循环。

看这里我将如何编写代码并询问您是否有任何问题。

http://pastebin.com/3BFzrk5C

【讨论】:

  • 如果你不介意指导我的话,我确实有几个问题!请注意,我并不是在暗示我比您了解更多,但这些只是我在查看您改进的代码时的一些想法。 1.) 我注意到您更改为 while 循环,而是运行 'cin >> cExam;'在 while 循环外调用,然后在 while 循环内再次调用。在 do{}while() 期间只调用一次它在技术上不是更有效吗?使用 do()while{} 有问题吗?附言我的字符用完了,我会在其他 cmets 中问我的其他问题
  • 2.) 我怀疑有错误,但我想问一下,以防我只是无知。在代码的第 21 行中,您删除了我放在那里的 (nExam - 1) 以删除标记值,使其不包含在平均计算中。有什么特别的原因吗? 3.)我的最后一个问题,我注意到你用 '\n' 替换了很多我的 'endl' 用法,甚至在 for 循环之后做了一个 cout
  • 1) 在我的代码中,我切换到了一个 while 循环并做了一个 cin>>cExam;甚至在尝试进入循环之前,在进入while之前我已经在cExam中有一些可以评估的值,编译器将决定它是否执行while。看看你的do-while循环,如果你的第一个值为0会发生什么?由于是do循环,所以body中的代码会被执行,你不希望这样,你希望0作为控制号退出循环。
  • 1) 在任何时候,如果您输入 0,它将首先添加到数组中,然后退出循环。
  • 您不希望数组中有 0。 2)我不需要减少 nExam 因为我有确切的元素数量。看这个例子:我输入 cExam 10,然后 nExam 变成 1,我输入 cExam 5,然后 nExam 变成 2 我输入 cExam 0 和退出循环,但 nExam 不会增加,所以它不是 3 而是 2,就像我输入的元素一样多。至于 \n 和 endl。 \n 表示换行,而 endl 是换行和缓冲区刷新,您不需要在 for 循环中的每次迭代时刷新缓冲区,只需在循环之后,以确保打印出内存中的所有内容。
【解决方案2】:

它在代码末尾打印出两个 0 的问题是您编写 for 循环的方式造成的。

代替:

for(i = 0; i < (nExam+1); i++)
{
    cout << aExams[i] << endl; //Used a for loop to prevent redundancy
}

用途:

for (i = 1; i < (nExam); i++)
{
    cout << aExams[i - 1] << endl; //Used a for loop to prevent redundancy
}

【讨论】:

  • 一个致命的问题,但很可能此时 OP 已经崩溃了。建议添加解释为什么 do/while 循环是错误的。
  • 所以我想我明白你为什么建议使用这种方法。基本上,通过允许 for 循环在它小于 nExams 的值时停止,它将从输出中删除标记值“0”。问题是,当我做出这个改变时,它反而让我首先输出一个垃圾号码。为了说明这一点,我在更改后的输出(同时输入三个 100“分数”进行测试)是:268716 100 100 100
猜你喜欢
  • 2014-06-03
  • 1970-01-01
  • 1970-01-01
  • 2015-02-02
  • 1970-01-01
  • 1970-01-01
  • 2016-11-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多