2010-10-13 6 views
4

Я начал изучать C++ около 3 недель назад после 2 лет Java. Кажется, это так отличается, но я туда попал. мой лектор - прекрасный парень, но в любое время я задаю вопрос, почему что-то так или иначе. он просто отвечает «потому что это».У меня много вопросов о C++, которые меня действительно путают

Theres много комментариев в коде ниже с несколькими случайными вопросами, но главная проблема заключается в том, что im получает две ошибки сборки, говорят, что массив не инициализирован (хотя я нашел для него значение), а другой говорит внешняя ссылка в основном.

может ли кто-нибудь уметь читать код и отвечать на несколько комментариев внутри, и, может быть, общая проблема с им?

#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

этот код скомпилирован? он не появляется. возможно, было бы хорошо получить компилируемый фрагмент кода, чтобы лучше понять. –

+0

Пожалуйста, проверьте ваше сообщение еще раз. Я думаю, вам нужно отформатировать текст. Я вижу #include #include #include. Имена файлов заголовков отсутствуют. –

+0

эта часть проблемы. Я не знаю, почему это не будет. – OVERTONE

ответ

0

Мои быстрые ответы без двойной проверки (его было некоторое время, так как я разработал в C++), являются:

  1. arraytotal не был инициализирован

    Я подозреваю, что ваши флаги компилятора это как ошибку чтобы убедиться, что вы это сделаете. Если вы этого не сделаете, вы не можете быть уверены в его инициализации. Традиционно для отладочных сборников инициализированная память C/C++ используется для некоторого значения отладки, чтобы помочь идентифицировать неинициализированные переменные. Установите arrayTotal = 0, когда он инициализирован, и это должно исчезнуть. (Передовая практика)

    например. double arrayTotal = 0;

  2. внешняя ссылка в главном

    Я подозреваю, что это потому, что ваш прототип для averageN не соответствует определенному методу позже. Прототип должен включать типы параметров, а также тип возврата. Измените прототип от double averageN(); до двойной среднийN (двойной []);, и я верю, что это исправит эту проблему.

  3. действительно ли массив должен быть const всегда? это значит, что он не будет создан после создания массива?

    Поскольку вы используете его для определения размера массива, переданного в среднее значениеN, да. Для установки такого размера массива требуется постоянное значение.

  4. Этот массив создается в функции averageN(), но почему? Не могу я просто создать его вверх и ссылаться на него?

    Не создается в среднемN. Это формальный параметр для среднегоN.Вызывающий из среднего N должен предоставить соответствующую переменную и передать ее. Затем изнутри метода вы получаете доступ к нему через десятичные числа.

  5. Почему вы должны написать имя функции здесь, прежде чем вы ее даже создадите?

    Это прототип функции. Это необходимо, если функция указана в коде до того, как функция определена. Это может быть разрешено и другими способами, такими как перемещение определения averageN перед всеми его использованием.

2
  • Const дает компилятору подсказку о том, что элемент не должен быть изменен, и если код пытается это то компилятор может флаг ошибки.

  • имя функции указано перед фактическим объявлением, что функция main() должна ссылаться на нее до того, как компилятор действительно пришел, чтобы скомпилировать ее (как позже в файле кода). Вы можете переместить всю функцию перед main(), чтобы избежать этого.

  • double averageN (double decimals [массивSize]) говорит, что эта функция принимает массив. Он не говорит, что он создает массив. Если вы посмотрите в функции, он принимает массив и добавляет в него вычисленные значения (decimals[i] = (0+(rand()%10))). Эта функция также вычисляет среднее значение по массиву и возвращает это как double.

Так, чтобы ответить на ваш большой вопрос, что случилось - читать последнюю точку и посмотреть на вызов вы делаете - averageN(); - вы можете увидеть, как это не правильный вызов?

6
  1. // Требуется, чтобы массив был всегда const? это значит, что он не будет создан после создания массива? Да, он должен быть const, более того, он должен быть постоянным выражением, что означает, что его размер должен быть известен во время компиляции (а не во время выполнения). Если вы хотите изменить размер массивов, лучше всего использовать стандартный контейнер std :: vector. Или используйте динамически распределенные массивы, если вам нужен массив фиксированного размера, но размер неизвестен до времени выполнения

  2. /* Этот массив создается в функции averageN(), но почему? Не могу я просто создать его вверх и ссылаться на него? */ Если вы говорите о десятичных знаках, то нет, это глобальная переменная, вы можете использовать ее из любого места.

  3. // почему вы должны написать имя функции здесь, прежде чем вы ее даже создадите? Вы должны объявить любое имя на C++ до его использования. Поскольку вы вызываете эту функцию в основном, ее нужно как минимум объявить заранее. Вы также можете предоставить определение (тело) перед основным.

  4. // почему массив должен быть создан здесь?

Ой, похоже, что у вас большой компромисс. На самом деле, у вас есть 2 функции с именем averageN, один - среднийN, который не принимает параметров, другой - AveraeN, беря массив из double.Вы никогда не определяли первый, просто объявленный.

Ошибки:

  1. doubleTotal не инициализированы. Ну это не double arrayTotal; изменить на

    double arrayTotal = 0.0;

  2. неразрешенный extenal в основном - это функция AverageN в основном, которую вы качаете. Вы никогда не писали тело для этого. Вы создали функцию, которая принимает массив, который не был полезен, так как ваш массив является глобальным. Просто удалите параметр массива из определения AverageN.

НТН

P.S. Прочтите документ С. Липпмана «C++ Primer». Это лучшая книга для начинающих, для C++. IMO :)

+0

Да Я согласен C++ Primer - действительно хорошая книга для новичков – Vinzenz

1

ОК, вот ваше единственное назначение в 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

Я не могу это сделать. если я это сделаю, тогда, когда я перехожу к заполнению массива случайными величинами, у него нет доступа к нему, потому что массив определен внутри него. – OVERTONE

+0

@OVERTONE: Я не понимаю вашего комментария: Да, массив определен в main(). Вы также передаете его как параметр, также функцию averageN(), чтобы он был доступен и там. –

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; 

Оба average и arrayTotal не отформатирована. Это означает, что они начнутся с неизвестного значения.
Для 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

+1

@OVERTONE: Нет, было бы лучше сказать 'arrayTotal = 0.0'. NULL следует использовать только для указателей. –

0

В дополнении к техническим деталям других ответов, вместо того, чтобы ответить на жалобу в вашем первом пункте: один из способов получить качественные ответы на «почему» C++ вопросов, это спросить в одном из Usenet групп, потому что , как и в случае с StackOverflow, там присутствуют настоящие эксперты, но в отличие от StackOverflow даже вопрос новичка , вероятно,, чтобы получить ответ от члена комитета по стандартизации, и если вам повезет даже с теми, кто написал стандарт (как Эндрю Кениг или в настоящее время Пит Беккер). Раньше там был Бьярн. Но в последние годы он не опубликовал много.

Основные новички «почему» вопросы: alt.comp.lang.learn.c-c++. Фрэнсис Стеклоборов висит там. Он является членом комитета и автором нескольких успешных вводных книг на C++. Он также знает немного математики, и поскольку частота проводки там низкая (что с StackOverflow!), Вы почти уверены, что на любой интересующий вопрос на полпути будет дан почти сразу - и правильно - Фрэнсисом. :-)

Общие вопросы о языке C++: comp.lang.c++ и/или comp.lang.c++.moderated. Последняя группа модерируется и имеет устав. Модерация уменьшает шум - например, нет спама, но добавляет задержку. Некоторые члены комитета предпочитают публиковать в основном немодерированную группу (например, Джеймс Канзе), некоторые, такие как Пит Беккер и Говард Хиннант, должность в обеих группах и некоторые известные эксперты, например, Андрей Александреску, теперь, видимо, только пост в модерируемой группе.

Вопросы о том, что означает стандарт, сообщает об ошибках в стандарте и т. Д. (Ранее в этом случае вы официально сообщали о дефектах в стандарте): [comp.std.C++]. Это также умеренная группа, и, к сожалению, модальная задержка теперь почти невыносимо длинная.Но, как новичок, вы, вероятно, менее заинтересованы в формальных деталях и больше заинтересованы в рассуждениях и объяснениях, для которых [comp.lang.C++] и [comp.lang.C++. Moderated] - отличные группы (я думаю, что StackOverflow Преимущество заключается в том, когда вы задаетесь вопросом: «Какая ошибка в этом коде», или вопросы, которые в принципе могут быть решены, просто прочитав соответствующую документацию).

Наконец, я связался с группами Google, которые предоставляют веб-интерфейс, но вы можете напрямую обращаться к этим группам с помощью клиента Usenet, такого как Thunderbird (или, например, браузера Opera, который имеет встроенный клиент). Все, что вам нужно сделать для доступа к Usenet через локальный клиент, - это настройка клиента, рассказывающая об этом сервере, как бесплатный EternalSeptember. Или AIOE. .

Приветствия & НТН,

- Альф

+0

спасибо. Я решил разместить здесь, потому что код не компилировал swell как все другие проблемы, но il определенно дал этим группам вид – OVERTONE

0

Одна вещь кажется, никто не прокомментировали: вашего возвращения заявления в конце averageN неправильно. Вы говорите, что возвращаете среднее значение, тогда вы вычисляете радиус, а затем return 0.0;. Попробуйте return average; или return arrayTotal/arraySize;.

+0

Thronley я планировал распечатать среднее значение в заявлении cout. мой лектор непреклонен, мы все время возвращаем 0, чтобы показать, что он выполнен правильно. вероятно, облегчает выяснение, работает ли он для него. я уверен, что он изменит его в конечном итоге – OVERTONE

+0

@OVERTONE: Ах, одна из этих проблем. Ваш лектор ошибается, и это не очень хорошая практика. Старайтесь не привыкать. Функция, которая вычисляет что-то, должна возвращать то, что она вычисляет, а не произвольное значение успеха. По крайней мере, подумайте о правильной практике, пока вы включаете то, о чем просит ваш лектор. –

Смежные вопросы