这两个功能能合二为一吗?

Can these two functions be combined into one?

本文关键字:合二为一 功能 两个      更新时间:2023-10-16

我刚刚完成了下面代码中注释块中描述的一个迷你任务,但是我一直试图通过将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;
}

这两个函数既大又笨重。有时候这是很难避免的,但是把它们合二为一并不是一个好主意。

相反,尝试找出它们的共同逻辑,并将其放入您可以从get…和display…函数中使用的单个函数中。

你还应该看看continuebreak来跳出循环。尽管人们普遍认为goto是跳出多个循环级别的可行选择,并且可以用来简化代码,使其更短,更容易理解。

这两个函数有一些共同之处,也有一些很大的不同。这意味着让一个函数同时做这两件事肯定是不对的。

拆分COMMON功能,并保留函数中的整体逻辑。例如,编写一个识别整数中的稀有数字的函数将有助于您的代码,因为您在两个不同的地方需要该信息,并且您有循环在两个地方计算该信息。

这不是一个真正的答案,因为您不应该将这些函数组合在一起。
相反,您应该对程序进行不同的分解。

这是我的建议:

三个的地方,你把一个数字分解成单独的数字,所以这显然是一个单独的函数。
使用字符串更容易做到这一点,因为我们不关心数字是什么,只关心它们是否唯一。

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