4

在学习了 2 年的 java 之后,我大约在 3 周前开始学习 c++。看起来很不一样,但我到了那里。我的讲师是一个可爱的人,但任何时候我问一个问题,为什么事情会这样或那样。他只是回答“因为它是”。

下面的代码中有很多注释,带有一些随机问题,但主要问题是我遇到了两个构建错误,一个说 arraytotal 尚未初始化(即使我找到了它的值),另一个说外部引用主要。

有人会介意阅读代码并回答其中的一些评论,也许是我遇到的整体问题?

#include<string>
#include<fstream>
#include<ostream>

using namespace std;

//double decimals[5] ={2,4,6,8,10};

const int arraySize = 5;
// does an arraySize have to be const always? is it so it doesnt channge after the array has been created?

//double decimals[arraySize];

/*
   this array is being created in the function averageN() but why?
   cant i just create it up top and reference it in?
 */

// why do you have to write the name of the function up here before you even create it?
double averageN();

int main()
{
    averageN();
    return 0;
}

// why does the array have to be created here?
double averageN(double decimals[arraySize])
{

    double average;
    double arrayTotal;
    for (int i = 0; i<5;i++)
    {
        // fills with random numbers from 0 - 10
        decimals[i] = (0+(rand()%10));
    }

    // find the total of all the elements in the array
    for (int i = 0; i < arraySize;i++)
    {
        double currentElement = decimals[i];
        arrayTotal = (currentElement+arrayTotal);
        //arrayTotal +=decimals[i]) ;
    }
    // return the average
    average = (arrayTotal/arraySize);
    return 0.0;
}
4

8 回答 8

6
  1. // arraySize 必须始终为 const 吗?是不是在创建数组后它不会改变?是的,它必须是 const,此外,它必须是一个常量表达式,这意味着它的大小必须在编译时(而不是在运行时)已知。如果要调整数组大小,那么最好使用标准容器 std::vector。或者如果您想要一个固定大小的数组,则使用动态分配的数组,但直到运行时才知道大小

  2. /* 这个数组是在函数 averageN() 中创建的,但为什么呢?我不能在上面创建它并引用它吗?*/ 如果您谈论小数,那么不,它是一个全局变量,您可以在任何地方使用它。

  3. // 为什么你必须在创建函数之前在这里写下函数的名称?在使用之前,您必须在 C++ 中声明任何名称。由于您在 main 中调用此函数,因此至少必须事先声明它。您还可以在 main 之前提供定义(正文)。

  4. // 为什么一定要在这里创建数组?

糟糕,您的代码中似乎存在很大的混淆。事实上,您有 2 个名为 averageN 的函数,一个是不带参数的 averageN,另一个是带有 double 数组的 AveraeN。您从未定义过第一个,只是声明了。

错误:

  1. doubleTotal 未初始化。好吧,这不是 double arrayTotal; 改变

    双数组总计 = 0.0;

  2. main 中未解决的 extenal - 这是您正在校准的 main 中的 AverageN 函数。你从来没有为它写过正文。您创建了一个接受数组的函数,因为您的数组是全局的,所以这没有用。只需从 AverageN 定义中删除数组参数。

高温高压

PS 阅读 S. Lippmann 的 C++ Primer。对于初学者来说,这是最好的书,对于 C++ 来说也是如此。海事组织:)

于 2010-10-13T13:38:31.687 回答
2
  • const 为编译器提供不应更改项目的线索,如果代码尝试更改,则编译器可以标记错误。

  • 函数名在实际声明之前提到,main() 函数需要在编译器实际编译它之前引用它(稍后在代码文件中)。您可以将整个函数移到 main() 之前以避免这种情况。

  • double averageN(double decimals[arraySize]) 是说这个函数需要一个数组。它并没有说它创建了数组。如果您查看函数,它会获取数组,并将计算值添加到其中(decimals[i] = (0+(rand()%10)))。此函数还计算数组的平均值并将其作为双精度值返回。

因此,要回答您的大问题出了什么问题-阅读最后一点并查看您正在拨打的电话averageN();-您能看出这不是正确的电话吗?

于 2010-10-13T13:32:34.553 回答
1

好的,这是您对 arrayTotal 的唯一分配:

 arrayTotal = (currentElement+arrayTotal);

现在,arrayTotal这个分配之后的价值是什么?好吧,这取决于它在分配之前的价值。在第一次分配之前它的价值是什么?你不知道。它可以是任何东西,因为你从来没有给它一个初始值。

于 2010-10-13T13:45:08.720 回答
1
  const int arraySize = 5;
// does an arraySize have to be const always? is it so it doesnt channge after the array has been created?

C++ 基本上支持两种数组:固定大小的数组,声明为type name[size],动态数组,分配为new[].
对于固定大小的数组,您必须向编译器提供它们的大小,以便它可以为数组留出足够的内存。由于编译器必须知道大小,因此您只能使用const变量或文字来指定它。
虽然可以自己创建动态分配的数组,但通过调用new[],这会让您在正确管理内存时有些头疼。最好使用为您执行此操作的现有类,例如std::vector.

 //double decimals[arraySize];

/*
 this array is being created in the function averageN() but why?
 cant i just create it up top and reference it in?
 */

您可以在此处创建它,但这将使任何人都可以访问该阵列。对于像这样的小程序,这不是什么大问题,但考虑到还有十几个其他文件也可以访问数组并在意外时刻更改它。

关于为什么不在 Java 中公开所有类和成员的问题基本上是同一个问题:限制谁可以访问。

// why do you have to write the name of the function up here before you even create it?
double averageN();

您必须先声明该函数,然后才能使用它。C++ 要求您使用的所有名称必须在首次使用之前向编译器声明,并且编译器将从上到下按顺序读取文件。

请注意,此声明与您在下面给出的函数定义不匹配。由于 C++ 支持函数重载,因此两者被认为是不同的函数,因为它们接受不同的参数(无参数与指针)

 int main()
 {
    averageN();
    return 0;
 }

 // why does the array have to be created here?
 double averageN(double decimals[arraySize])
     {

这不会创建数组。相反,它指定希望使用指针参数调用函数(arraySize完全忽略,并且您不能将数组传递给 C++ 中的函数,因此将参数调整为 read double *decimals)。

要获得一个工作程序,您需要将上面的两行更改为

 double averageN()
     {
    double decimals[arraySize];

double average;
double arrayTotal;

两者averagearrayTotal都没有初始化。这意味着它们将从一些未知值开始。
对于average,这不是问题,因为您对它做的第一件事就是分配一个新值。但是对于arrayTotal,您正在向它添加值,因此您必须让它以已知值开始。

for (int i = 0; i<5;i++)
{
    // fills with random numbers from 0 - 10
    decimals[i] = (0+(rand()%10));
}

// find the total of all the elements in the array
for (int i = 0; i < arraySize;i++)
{
    double currentElement = decimals[i];
    arrayTotal = (currentElement+arrayTotal);
    //arrayTotal +=decimals[i]) ;
}
// return the average
average = (arrayTotal/arraySize);
return 0.0;
 }
于 2010-10-13T14:00:14.490 回答
0

我没有仔细检查的快速答案(自从我用 C++ 开发以来已经有一段时间了)是:

  1. arraytotal 尚未初始化

    我怀疑您的编译器将此标记为错误以确保您这样做。如果不这样做,您将无法确定它将被初始化为什么。传统上,对于调试版本,C/C++ 将内存初始化为某个调试值,以帮助识别未初始化的变量。初始化时设置 arrayTotal = 0 并且应该消失。(最佳实践)

    例如 double arrayTotal = 0;

  2. 主要外部参考

    我怀疑这是因为您的 averageN 原型与稍后定义的方法不匹配。原型需要包括参数的类型以及返回类型。将原型从double averageN(); 平均加倍N(double []); 我相信这会解决这个问题。

  3. arraySize 必须始终为 const 吗?是不是在创建数组后它不会改变?

    由于您使用它来定义传递给averageN的数组的大小,是的。像这样设置数组的大小需要一个常量值。

  4. 这个数组是在函数 averageN() 中创建的,但为什么呢?我不能在上面创建它并引用它吗?

    它不是在平均 N 中创建的。它是平均 N 的形式参数。averageN 的调用者需要提供适当的变量并将其传入。然后从方法内部,您可以通过小数访问它。

  5. 为什么你必须在创建函数之前在这里写下函数的名称?

    这是函数原型。如果在定义函数之前在代码中引用了该函数,则必须这样做。这也可以通过其他方式解决,例如在所有使用之前移动平均 N 的定义。

于 2010-10-13T13:49:41.910 回答
0

几个问题:

  • 您对 averageN 的前向声明不正确

代码:

double averageN();

下面提供的版本带有一个参数。

  • 您对 averageN 的声明不太有效
    声明数组类型的参数并不直观。
    通常人们让数组降级为指向数组的指针并传递一个长度作为第二个参数。

代码:

double averageN(double *decimals, int arraySize)

如果您只想传递特定大小的数组,则需要通过引用进行:

double averageN(double (&decimals)[arraySize])
  • 您在 main 中调用 averageN()。
    您传递的参数为零。现在这与前向声明匹配,但与实际定义不匹配。

结果我会像这样更改代码:

extern double averageN(double (&decimals)[arraySize]);

int main()
{
    double data[arraySize];
    averageN(data);
    return 0;
}

// why does the array have to be created here?
double averageN(double (&decimals)[arraySize])
{
于 2010-10-13T13:50:17.757 回答
0

除了其他答案的技术细节之外,而是在第一段中回答投诉:获得“为什么”C++ 问题的高质量答案的一种方法是在 Usenet 组中提问,因为与 StackOverflow 一样,有 Real专家们在那里闲逛,但与 StackOverflow 不同,即使是初学者的问题也可能会从标准化委员会的成员那里得到答案,如果你幸运的话,即使是那些编写标准的人(如 Andrew Koenig 或目前的 Pete Becker)。在早期,Bjarne 也在那里。但最近几年他的帖子不多。

基本的新手“为什么”问题:alt.comp.lang.learn.c-c++。弗朗西斯·格拉斯伯罗在外面闲逛。他是几本成功的 C++ 入门书籍的委员会成员和作者。他还懂一点数学,而且由于那里的发帖频率很低(StackOverflow 怎么样!),你几乎可以肯定,任何半途而废的有趣问题都会很快得到 Francis 的回答——而且是正确的。:-)

关于 C++ 语言的一般问题:comp.lang.c++和/或comp.lang.c++.moderated。后一组是有节制的并有章程。节制减少了噪音——例如没有垃圾邮件——但增加了延迟。一些委员会成员更喜欢在不受监管的小组中发帖(例如 James Kanze),有些人,例如 Pete Becker 和 Howard Hinnant,在两个小组中都发帖,而一些知名专家,例如 Andrei Alexandrescu,现在显然只在有审核的小组中发帖。

关于标准含义的问题,关于标准中的错误的报告等等(在早期这也是您正式报告标准中的缺陷的地方):[comp.std.c++]。这也是一个有节制的小组,不幸的是,模组延迟现在几乎无法忍受。但是作为一个新手,你可能对正式的细节不太感兴趣,而对基本原理和解释更感兴趣,[comp.lang.c++] 和 [comp.lang.c++.moderated] 是很好的群体(我认为 StackOverflow 的主要优势是当您想知道“此代码中的错误是什么”或原则上可以通过阅读相关文档来解决的问题时)。

最后,我已链接到提供基于 Web 界面的 Google Groups,但您可以更直接地从诸如 Thunderbird 之类的 Usenet 客户端(或例如具有内置客户端的 Opera 浏览器)访问这些组。为了通过本地客户端访问 Usenet,您所要做的就是配置客户端,告诉它有关服务器的信息,例如免费的 EternalSeptember。或者AIOE。

干杯&hth.,

– 阿尔夫

于 2010-10-13T15:04:16.140 回答
0

似乎没有人评论过的一件事:您最后的退货声明averageN是错误的。你说你要返回平均值,然后计算半径,然后return 0.0;。尝试return average;return arrayTotal/arraySize;

于 2010-10-13T19:14:51.237 回答