2010-10-13 181 views
4

大约3周前,我在2年的java开始学习C++。它看起来很不同,但即时到达那里。我的讲师是一个可爱的家伙,但任何时候我都会问一个问题,为什么这样或者那样。他只是回应“因为它”。我有很多关于C++的问题,让我很困惑

Theres在下面的代码中有很多注释,有一些随机问题,但主要问题是即时获取两个构建错误,一个说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; 
} 
+1

是否会编译代码?它似乎没有。先编写一段可编译的代码以更好地理解 – 2010-10-13 13:31:15

+0

请检查一下您的文章。我认为你需要格式化文本。我可以看到#include #include #include。头文件名称丢失。 – 2010-10-13 13:33:58

+0

这就是问题的一部分。我不知道为什么它不会建立。 – OVERTONE 2010-10-13 13:34:19

回答

0

我快速解答没有双重检查(其已一段时间,因为我用C已经开发++)是:

  1. arraytotal尚未初始化

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

    例如double arrayTotal = 0;在主

  2. 外部参考我怀疑这是因为你的原型averageN不符后来定义的方法。原型需要包括参数的类型以及返回类型。将原型从改为double averageN();double averageN(double []);,我相信会解决这个问题。

  3. 做一个arraySize必须是常量const?是这样,它没有channge阵列创建后?

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

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

    它并没有被创建在averageN。它是averageN的一个形式参数。averageN的调用者需要提供相应的变量并将其传入。然后从该方法内部,通过小数点访问它。

  5. 为什么在创建它之前你必须写出函数的名字?

    这是函数原型。在函数定义之前,如果函数在代码中被引用,这是必要的。这也可以通过其他方式解决,比如在所有使用它之前移动averageN的定义。

2
  • 常量使编译器的线索,该项目不应该被改变,如果代码尝试它,然后编译器可以标记一个错误。

  • 函数名称在实际声明之前被提及过,main()函数在编译器实际编译它之前需要引用它(就像它在代码文件中那样)。你可以在main()之前移动整个函数来避免这种情况。

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

因此,要回答你的大问题什么是错的 - 阅读的最后一个点,看看你正在进行的呼叫 - averageN(); - 你可以看到这是不是正确的电话吗?

6
  1. //做一个arraySize必须是const常量吗?是这样,它没有channge阵列创建后? 是的,它必须是const,而且它必须是一个常量表达式,这意味着它的大小在编译时(而不是在运行时)必须已知。 如果你想调整数组大小,那么最好是使用标准容器std :: vector。或使用动态分配的数组,如果你想有一个固定大小的数组,但大小不知道,直到运行时

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

  3. //为什么在创建它之前你必须写出函数的名字? 您必须在使用C++之前声明任何名称。既然你在main中调用了这个函数,它至少必须事先声明。你也可以在main之前提供定义(body)。

  4. //为什么数组必须在这里创建?

糟糕,看起来你的代码有很大的混淆。事实上,你有2个函数名为averageN,一个是averageN,不带参数,另一个是AveraeN,取一个double数组。你从来没有定义第一个,只是宣布。

错误:

  1. doubleTotal未初始化。那么它不是 double arrayTotal;更改为

    double arrayTotal = 0.0;

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

HTH

附:阅读S. Lippmann的C++入门。对于初学者来说,它是C++最好的书。 IMO :)

+0

是的,我同意C++入门是一本非常好的初学者书籍 – Vinzenz 2010-10-13 15:17:56

1

OK,这里是你的唯一分配到arrayTotal:

arrayTotal = (currentElement+arrayTotal); 

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

0

两个问题:

  • 你averageN的向前声明是不正确的

代码:

double averageN(); 

下提供的版本需要的参数。

  • 你averageN的声明完全不是那么回事
    声明数组类型的参数是不直观明显。
    通常,人们让数组退化为一个指向数组的指针并传递一个长度作为第二个参数。

代码:

double averageN(double *decimals, int arraySize) 

如果你只想通过你需要参考这么做特定大小的数组:

double averageN(double (&decimals)[arraySize]) 
  • 您对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]) 
{ 
+0

我不能这样做。如果我这样做,那么当我去用随机变量填充数组时,它无法访问它,因为数组是definied int他主。 – OVERTONE 2010-10-14 14:23:55

+0

@OVERTONE:我不明白你的意见:是的,数组是在main()中定义的。您还将它作为参数传递给函数averageN(),因此它在那里也可以访问。 – 2010-10-14 15:27:58

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++中的函数,因此参数被调整为读取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; 
} 
+0

它足以说arrayTotal = NULL? – OVERTONE 2010-10-14 12:55:51

+1

@OVERTONE:不,最好说'arrayTotal = 0.0'。 NULL应该只用于指针。 – 2010-10-14 13:27:14

0

除了其他的答案的技术细节,而不是回答你的第一个段落投诉:一种途径获得高质量的回答“为什么”的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,都在这两个团体中发帖,还有一些知名的专家,例如,现在,安德烈亚历山德雷斯库显然只在缓和组中发帖。

关于标准意味着什么的问题,关于标准错误的报告等等(在早些时候,这也是您正式报告标准缺陷的地方):[comp.std.C++]。这也是一个慢节奏的小组,不幸的是mod延迟现在几乎无法忍受。但作为一个新手,你可能对形式细节不太感兴趣,并且对[comp.lang.C++]和[comp.lang.C++。moderated]都是很棒的组合(我认为StackOverflow的main好处是当你想知道“这段代码中的错误是什么”或原则上可以通过阅读相关文档来解决的问题时)。

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

干杯&心连心,

阿尔夫

+0

谢谢。我选择在这里发布,因为代码没有编译膨胀作为所有其他问题,但我肯定给这些组看一看 – OVERTONE 2010-10-14 12:52:43

0

有一件事似乎没有人上都评论:您的return语句在averageN到底是错的。你说你正在返回平均值,然后你计算半径,然后return 0.0;。试试return average;return arrayTotal/arraySize;

+0

Thronley我打算在cout声明中打印出平均值。我的讲师坚持我们一直返回0来表明它的正确执行。可能会让人更容易判断它是否适合他。我确定他会最终改变它 – OVERTONE 2010-10-14 12:50:47

+0

@OVERTONE:啊,其中的一个问题。你的讲师是错误的,这不是一个好习惯。尽量不要养成习惯。计算某个东西的函数应该返回它计算的值,而不是任意的成功值。至少在你接受讲师要求的时候,考虑正确的做法。 – 2010-10-14 13:56:47