Лучший способ использовать указатель? - PullRequest
0 голосов
/ 13 сентября 2011

Я пытаюсь создать программу, которая будет отображать гистограммы с * максимальным числом *, которое может быть 40. У меня все работает, но у меня возник вопрос с кодом.Как вы можете видеть, есть ли лучший способ, чтобы я дважды возвращался к исходному адресу, используя:

    p_bar_length = p_bar_length - size;

Есть ли лучший способ сделать это?

#include <iostream>

using namespace std;

const int MAX_SPLATS = 40;

void bar_chart(double values[], int size)
{
    double largest = values[0]; //assign first element to be the largest

    //Find the largest value
    for (int i = 1; i < size; i++)
    {
        if (largest < values[i]) // check to see if there is something larger
        {
            largest = values[i];
        }
    }

    // Find the number of spalts to use
    // with the precent based on the largest value
    int* p_bar_length = new (nothrow) int[size];
    for (int i = 0; i < size; i++)
    {
        *p_bar_length = (values[i] / largest) * MAX_SPLATS;
        p_bar_length++; // Go to next memory address
    }

    // Go back to the orignal memory address
    p_bar_length = p_bar_length - size;

    // Pritnt the correct number of splats
    for (int i = 0; i < size; i++)
    {
        for (int j = 0; j < *p_bar_length; j++)
        {
            cout << "*";
        }
        p_bar_length++;
        cout << endl;
    }

    // Go back to the orignal memory address
    p_bar_length = p_bar_length - size;

    delete[] p_bar_length;
}

int main()
{
    double values[6] = { 22, 40, 28, 26, 14, 46};
    int val_size = 6;

    bar_chart(values, val_size);

    system("pause");

    return 0;
}

Ответы [ 8 ]

8 голосов
/ 13 сентября 2011

Поскольку это C ++, лучше всего использовать , а не для использования указателей;вместо этого используйте std::vector.

Тем не менее, вы также можете всегда обращаться с указателем как с массивом и просто обращаться к p_bar_length[i] для заданной позиции 0 <= i < length вместо увеличенияуказатель.

6 голосов
/ 13 сентября 2011

Вместо увеличения указателя используйте индекс массива:

p_bar_length[i] = (values[i] / largest) * MAX_SPLATS;

или используйте арифметику указателя:

*(p_bar_length + i) = (values[i] / largest) * MAX_SPLATS;
4 голосов
/ 13 сентября 2011

Вам не нужен первый цикл for, если вы используете std :: max_element из <algorithm>.

Вам не нужен второй цикл for, если вы рассчитываете длину бара в третьем цикле for.

Примерно так:

void bar_chart(double values[], int size)
{
    //Find the largest value
    double largest = *std::max_element(values, values + size);

    // Print the correct number of splats
    for (int i = 0; i < size; i++)
    {
        int p_bar_length = (values[i] / largest) * MAX_SPLATS;
        cout << string(p_bar_length, '*') << endl;
    }
}

Таким образом, вам вообще не нужен массив p_bar_length. Это просто int.

Редактировать: И вы даже можете заменить внутренний цикл for (пример изменен)

4 голосов
/ 13 сентября 2011

Поскольку вы пометили это как C ++, я бы рекомендовал использовать стандартную библиотеку.

Ваша программа на C больше, чем C ++, но если с c все в порядке, улучшать нечего.
С другой стороны, при использовании vector и algorithm вам не нужновозиться с указателями.А с помощью C ++ 11 он удаляет неровности, ранее связанные с шаблонами и итераторами.

Быстрый выстрел:

#include <iostream>
#include <vector>
#include <algorithm>

const int MAX_SPLATS = 40;

template <typename C>
    void bar_chart(const C& values)
{
    if (std::distance(values.begin(), values.end())<1)
        return; // do some error handling

    auto largest = *std::max_element(values.begin(), values.end());

    // Find the number of splats to use with the percent based on
    // the largest value
    std::vector<int> bars(values.size());
    std::transform(values.begin(), values.end(), bars.begin(),
        [=] (double d) { return (d/largest)*MAX_SPLATS; });

    // Print the correct number of splats
    std::for_each(bars.begin(), bars.end(), 
        [](int val){ std::cout << std::string(val, '*') << std::endl; });
}

int main()
{
    std::vector<double> values = { 22, 40, 28, 26, 14, 46 };

    bar_chart(values);

    std::cin.get();
    return 0;
}
2 голосов
/ 13 сентября 2011

Вы можете рассматривать p_bar_length как массив и просто использовать непротиворечивую запись

int* p_bar_length = new (nothrow) int[size];
for (int i = 0; i < size; i++)
{
    p_bar_length[i] = (values[i] / largest) * MAX_SPLATS;
}
2 голосов
/ 13 сентября 2011

Сделайте еще одну копию указателя для использования в вашем цикле.Гораздо меньше ошибок.

int* p_bar_length = new (nothrow) int[size];
int* p = p_bar_length;
for (int i = 0; i < size; i++)
{
    *p = (values[i] / largest) * MAX_SPLATS;
    p++; // Go to next memory address
}

PS Почему вы используете nothrow?Поскольку вы не проверяете значение, которое вы возвращаете из new, исключение будет намного приятнее, чем беспорядок, который вы получите, когда вернете указатель NULL.

0 голосов
/ 14 сентября 2011

Это довольно похоже на сообщение от @mkaes, но идет еще дальше. Вместо использования std::transform для создания вектора правильной длины, затем std::for_each для создания строки правильной длины из каждого из них, это создает строку непосредственно из входных данных и записывает строки непосредственно из std::transform:

#include <iostream>
#include <array>
#include <algorithm>
#include <string>
#include <iterator>

const int MAX_SPLATS = 40;

template <typename C>
void bar_chart(const C& values)
{
    if (std::distance(values.begin(), values.end())<1)
        return; // do some error handling

    auto largest = *std::max_element(values.begin(), values.end());

    std::transform(values.begin(), values.end(), 
        std::ostream_iterator<std::string>(std::cout, "\n"), 
        [=](double d) { return std::string((d/largest)*MAX_SPLATS, '*');} );
}

int main() {
    std::array<double, 6> values = {22, 40, 28, 26, 14, 46};

    bar_chart(values);

    return 0;
}

Так как он все равно использует C ++ 11, я решил также использовать std::array, так как он, кажется, хорошо подходит для текущей работы.

0 голосов
/ 13 сентября 2011

Как насчет двух в одном?

int* p_bar_length = new (nothrow) int[size];
for (int i = 0; i < size; i++)
{
    *p_bar_length = (values[i] / largest) * MAX_SPLATS;
     for (int j = 0; j < *p_bar_length; j++) cout << "*";
     cout << endl;
     p_bar_length++; // Go to next memory address
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...