【问题标题】:I have lots of questions about c++ that are really confusing me我有很多关于 c++ 的问题让我很困惑
【发布时间】:2011-04-24 20:38:16
【问题描述】:

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

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

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

#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;
}

【问题讨论】:

  • 该代码能编译吗?它似乎没有。最好先获得一段可编译的代码以更好地理解
  • 请再次检查您的帖子。我认为您需要格式化文本。我可以看到#include #include #include。缺少头文件名。
  • 这是问题的一部分。我不知道为什么它不会构建。
  • @SB,代码无法编译,OP 正是在寻求帮助以使其首先编译。
  • 抱歉没听清楚。

标签: c++ arrays initialization unresolved-external


【解决方案1】:

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

【讨论】:

  • Thronley 我打算在 cout 声明中打印出平均值。我的讲师坚持我们一直返回 0 以表明其执行正确。可能更容易判断它是否适合他。我相信他最终会改变它
  • @OVERTONE:啊,其中一个问题。你的讲师错了,这不是一个好的做法。尽量不要养成这个习惯。计算某些东西的函数应该返回它计算的结果,而不是任意的成功值。至少在提交讲师要求的内容时思考正确的做法。
【解决方案2】:

除了其他答案的技术细节之外,而是在第一段中回答投诉:获得“为什么”C++ 问题的高质量答案的一种方法是在 Usenet 组中提问,因为就像 StackOverflow那里有真正的专家,但与 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。

干杯,

--阿尔夫

【讨论】:

  • 谢谢。我选择在这里发帖是因为代码没有像所有其他问题一样编译膨胀,但我肯定会让这些组看看
【解决方案3】:
  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++ 中的函数,因此将参数调整为读取 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;
 }

【讨论】:

  • 说arrayTotal = NULL就够了吗?
  • @OVERTONE:不,最好说arrayTotal = 0.0。 NULL 只能用于指针。
【解决方案4】:
  1. // arraySize 必须始终为 const 吗?是不是在创建数组后它不会改变? 是的,它必须是 const,而且,它必须是一个常量表达式,这意味着它的大小必须在编译时(而不是在运行时)已知。 如果要调整数组大小,那么最好使用标准容器 std::vector。或者如果你想要一个固定大小的数组,则使用动态分配的数组,但直到运行时才知道大小

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

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

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

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

错误:

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

    双数组总计 = 0.0;

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

HTH

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

【讨论】:

    【解决方案5】:

    几个问题:

    • 您对 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])
    {
    

    【讨论】:

    • 我不能这样做。如果我这样做了,那么当我用随机变量填充数组时,它无法访问它,因为数组是在 main 中定义的。
    • @OVERTONE:我不明白你的评论:是的,数组是在 main() 中定义的。您还可以将它作为参数传递给函数 averageN(),因此它也可以在那里访问。
    【解决方案6】:

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

    1. arraytotal 尚未初始化

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

      例如双数组总计 = 0;

    2. main 中的外部引用

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

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

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

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

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

    5. 为什么要在创建函数之前将其名称写在这里?

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

    【讨论】:

      【解决方案7】:

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

       arrayTotal = (currentElement+arrayTotal);
      

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

      【讨论】:

        【解决方案8】:
        • const 为编译器提供了一个提示,即不应更改项目,如果代码尝试这样做,则编译器可以标记错误。

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

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

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-04-11
          • 2014-09-28
          相关资源
          最近更新 更多