У меня есть много вопросов о C ++, которые действительно меня смущают - PullRequest
4 голосов
/ 13 октября 2010

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

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

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

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

Ответы [ 8 ]

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

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

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

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

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

Ошибки:

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

    double arrayTotal = 0.0;

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

HTH

PS Прочитайте праймер С. Липпмана для C ++.Это лучшая книга для начинающих, в том числе и для C ++.ИМО:)

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

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

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

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

1 голос
/ 13 октября 2010
  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;
 }
1 голос
/ 13 октября 2010

ОК, вот ваше единственное назначение в arrayTotal:

 arrayTotal = (currentElement+arrayTotal);

Теперь, каково значение arrayTotal после этого назначения?Ну, это зависит от его стоимости до назначения.Какова была его ценность до самого первого назначения?Вы не знаетеЭто может быть что угодно , потому что вы никогда не давали ему начальное значение.

0 голосов
/ 13 октября 2010

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

0 голосов
/ 13 октября 2010

В дополнение к техническим деталям других ответов вместо ответа на жалобу в первом абзаце: один из способов получить качественные ответы на вопросы «почему» на 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] являются отличными группами (я думаю, что основной преимущество заключается в том, что вы задаетесь вопросом «что за ошибка в этом коде» или какие вопросы в принципе можно решить, просто прочитав соответствующую документацию).

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

Приветствия & hth.,

- Альф

0 голосов
/ 13 октября 2010

Пара проблем:

  • Ваше предварительное объявление среднего N неверно

Код:

double averageN();

В приведенной ниже версии требуетсяпараметр.

  • Ваше объявление Среднее N не совсем работает
    Объявление параметров типа массив не является интуитивно очевидным.
    Обычно люди позволяют массиву ухудшаться до указателя на массив и передаютдлина как второй параметр.

Код:

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 голосов
/ 13 октября 2010

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

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

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

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

  2. внешняя ссылка в main

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

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

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

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

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...