这两个功能可以组合成一个吗?

时间:2015-10-15 06:25:39

标签: c++ arrays sorting

我刚刚完成了下面代码中注释块中描述的迷你任务,但我一直试图通过将getRareDigitsdisplayRareDigits合并为一个来改善代码功能。无论我做什么,逻辑总是最终打破。任何人都可以向我解释这两个功能是否可以合并?谢谢^ _ ^

/*
    Written by: Stephanie Yumiko

* This program will ask the user
for a series of integers, defined by
the user.

* The program will display back to the
user the number of rare digits, digits
that only occur once in a single integer,
but not the rest. 

* The program will then sort the integers
based on the number of occurrences of
rare digits it contains, from greatest
to least.
*/

#include <iostream>
using namespace std;

bool num_contains(int, int);
void showRareDigits(int*, int);
void sortRareDigits(int*, int* , int);

bool num_contains(int digit, int n) {
    while (n) {
        if (digit == n % 10) return true;
        n /= 10;
    }
    return false;
}

void getRareDigits(int *arr, int *ordered, int len) {
    for (int index = 0; index < len; ++index) {
        int n = arr[index];
        if (n < 0)
            n *= -1;
        int d = 0;
        while (n) {
            d = n % 10;
            int i;      // keep track of loop counter outside the loop
            int stop = 0; // to break out loop
            for (i = 0; i < len; ++i) {
                if (i != index && num_contains(d, arr[i]))
                    stop = 1;
            }
            // only increment the array if the loop exited before
            // completing (implying the goto would have happened)
            if (!stop) {
                ++ordered[index];
            }
            // always execute 
            n /= 10;
        }
    }

    for (int i = 0; i<len; i++) {
        for (int j = 0; j<len - i - 1; j++) {
            if (ordered[j]<ordered[j + 1]) {
                int temp = ordered[j];
                ordered[j] = ordered[j + 1];
                ordered[j + 1] = temp;

                int temp2 = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp2;
            }
        }
    }

    cout << "\nArray after sort:\n";
    for (int i = 0; i < len; i++) {
        cout << arr[i] << endl;
    }
}

void showRareDigits(int* iAry, int size) {
    const int size2 = 10;
    int* tmpAry = new int[size];
    int totalCount[size2] = { 0 };
    int currentCount[size2] = { 0 };
    int totalUncommon = 0;
    int i, j;
    int* ordered;
    ordered = new int[size];

    for (i = 0; i < size; i++) {
        ordered[i] = 0;
        tmpAry[i] = iAry[i];
        if (tmpAry[i] < 0)
            tmpAry[i] *= -1;

        for (j = 0; j < size2; j++)
            currentCount[j] = 0;

        if (tmpAry[i] == 0) {
            currentCount[0] = 1;
        }

        while (tmpAry[i] / 10 != 0 || tmpAry[i] % 10 != 0){
            currentCount[tmpAry[i] % 10] = 1;
            tmpAry[i] /= 10;
        }

        for (j = 0; j < size2; j++) {
            totalCount[j] += currentCount[j];
        }
    }

    for (i = 0; i < size2; i++) {
        if (totalCount[i] == 1) {
            totalUncommon++;
        }
    }

    cout << "\nTotal rare digits: " << totalUncommon << endl
        << "\nThe rare digits:\n";
    if (totalUncommon == 0) {
        cout << "\nNo rare digits found.";
    }
    else {
        for (i = 0; i < size2; i++) {
            if (totalCount[i] == 1) {
                cout << i << endl;
            }
        }
    }

    getRareDigits(iAry, ordered, size);

    delete[] tmpAry;
    delete[] ordered;

    return;
}


int main() {    
    int size;
    int* arr;

    cout << "Enter # of integers: ";
    cin >> size;
    arr = new int[size];

    for (int i = 0; i < size; i++) {
        cout << "Enter the value for #" << i << " : ";
        cin >> arr[i];
    }

    cout << "Array before sorting:\n";
    for (int i = 0; i < size; i++) {
        cout << arr[i] << endl;
    }

    showRareDigits(arr, size);  

    delete[] arr;

    return 0;
}

3 个答案:

答案 0 :(得分:1)

你的两个功能很大很笨重。有时难以避免,但将它们合并为一个并不是一个好主意。

而是试图弄清楚哪些逻辑对他们来说是常见的,并将其放入可以从get ...和display ...函数中使用的各个函数中。

此外,您应该看一下 continue break 以打破循环。尽管普遍认为 goto 是打破多个循环级别的可行选项,可用于简化代码并使其更简单易懂。

答案 1 :(得分:1)

这两个功能之间存在一些共性和一些重大差异。这意味着制作一个功能来做这两件事绝对不是正确的事情。

打破COMMON功能,并将整个逻辑保留在函数中。例如,编写一个标识整数中稀有数字的函数将有助于您的代码,因为您需要在两个不同的位置使用该信息,并且您有两个循环来计算这两个位置。

答案 2 :(得分:0)

这不是一个真正的答案,因为你不应该将这些功能结合起来 相反,你应该以不同的方式考虑程序。

这是我的建议:

三个位置可以将数字分成不同的数字,所以这显然是一个单独功能的工作。
使用字符串更容易,因为我们对数字 不感兴趣,只知道它们是否是唯一的。

// Return the number of "rare" digits in 'i'; digits which occur only once.
int rare_digits(int i)
{
    std::map<char, int> frequency;
    std::string s = std::to_string(i);
    // Count the characters
    for (auto c : s)
    {
        frequency[c]++;
    }
    // Count how many were unique
    int rare = 0;
    for (auto f: frequency)
    {
        if (f.second == 1)
        {
            rare++;
        }
    }
    return rare;
}

如果我们将数据存储在结构中,我们可以携带稀有数字和数字本身 这样,我们只需要计算一次数。

struct Rarity
{
    Rarity(int n, int r)
        : number(n),
          rarity(r) {}
    int number;
    int rarity;
};

对于排序,自定义比较运算符很有用:

bool operator< (const Rarity& lhs, const Rarity& rhs)
{
    return lhs.rarity > rhs.rarity;
}

我们需要的其他一切都由标准库提供:

int main()
{
    std::vector<Rarity> numbers;
    int input = 0;
    while (std::cin >> input)
    {
        int rarity = rare_digits(input);
        // Filter out the "non-rare" numbers early, since they're not interesting
        if (rarity > 0)
        {
            numbers.emplace_back(input, rarity);
        }
    }

    std::sort(numbers.begin(), numbers.end());
    std::cout << numbers.size() << " numbers contained rare digits." << std::endl;
    std::cout << "These numbers were:" << std::endl;
    for (const auto& r: numbers)
    {
        std::cout << r.number << " (" << r.rarity << " rare digits)" << std::endl;
    }
}