【问题标题】:Boolean statements c++布尔语句 C++
【发布时间】:2021-12-19 04:25:38
【问题描述】:

我正在创建一个程序,它比较数组的所有值并读取哪些值加起来等于所需的总和。如果没有任何值加起来达到所需的总和,它应该输出一条语句说没有找到匹配的总和,这是我遇到问题的部分。我应该指定它输出的内容。目前每次没有匹配时它都会打印“没有找到匹配的总和”,所以它会产生相当混乱的输出

using namespace std;

const int SIZE = 15;
int intArray[SIZE];

void readData(istream& inFile) {
    for (int i = 0; i < SIZE; i++){
        inFile >> intArray[i];
        cout << intArray[i] << " ";
    }
}

int main() {
    int sum;
    ifstream inFile;
    string inFileName = "inFile.txt";
    inFile.open(inFileName.c_str());

    readData(inFile);
    
    cout << "Please enter the number for which a matching sum is needed: ";
    cin >> sum;
    bool error = true;
    for(int i = 0; i <= SIZE; i++){
        for(int j = 1; j <= SIZE; j++){
            if((intArray[i] + intArray[j]) == sum){
                cout << "Item " << i << " (With value " << intArray[i] << ") " << "and item " << j << " (With value " << intArray[j] << ") add up to " << sum << endl;
                error = false;
            }
        }
    }
    if(error == true){
        cout << "No matching sum was found" << endl;
    }
    return 0;
}

【问题讨论】:

  • 请使用valgrind 运行它并修复所有错误。您可以明显地访问数组末尾 (&lt;= SIZE)。 (旁注:int j = i + 1int j = 1 更合理:它仍然是二次方,但它会是一种改进。)如果您不想输出错误消息,那么就不要输出它 -你的问题到底是什么?
  • 奇怪,我认为我的编译器可能存在一些问题,因为我完全删除了错误消息,但我仍然在输出中得到它。我将尝试将程序转移到另一个软件,看看它是否可以在那里工作。

标签: c++ boolean


【解决方案1】:

您的问题的快速解决方法如下。

for(int i = 0; i < SIZE; i++){
    for(int j = i+1; j < SIZE; j++){
        if((intArray[i] + intArray[j]) == sum){
            cout << "Item " << i << " (With value " << intArray[i] << ") " << "and item " << j << " (With value " << intArray[j] << ") add up to " << sum << endl;
            error = false;
        }
    }
}

请注意:

  1. 您正在读取一个“SIZE”数组,但循环了 SIZE+1 次,从 0 到 SIZE
  2. 您从 1 开始 j 循环,这是一种低效的方式。您可以使用 i+1 开始循环,因为匹配对不可能逃脱此循环的注意。

【讨论】:

  • 感谢您的回复,这对如何使程序更有效率很有意义。但是,每次没有匹配时,它仍然输出“没有找到匹配的总和”。
【解决方案2】:

您的函数中有一个小问题,您在其中迭代数组的边界。在 C++ 中,数组从索引 0 开始。因此,最后一个元素索引是数组大小减 1。

示例:包含五个元素的数组

int array[5] = {10,20,30,40,50};
  • 索引 0 处的数组 (array[0]) = 10
  • 索引 1 处的数组 (array[1]) = 20
  • 索引 2 处的数组 (array[2]) = 30
  • 索引 3 处的数组 (array[3]) = 40
  • 索引 4 处的数组 (array[4]) = 50

而且,如果你想循环遍历数组,那么大小为 5,你需要写:

for (int i = 0; i < 5; ++i)

因此,对于这种情况,总是,而不是

如果你运行你的程序,你会注意到你得到了双倍的结果,所以,你可能会得到索引 3 和 5,以及索引 5 和 3。如果总和由user 是数组中某个值的两倍。示例:如果您的数组中有值 4,并且正在寻找总和 8,那么您的程序将为您提供具有相同索引的值 4。

所以,你需要了解你对结果的要求

  • 如果你想得到有序对,那么: 对于和 10,对 3,7 和 7,3 是不同的。在这种情况下,您需要从 0 开始两个循环索引
  • 如果你想避免一个元素是双倍的,比如 sum 8 和一个元素 4,然后得到 pair 4,4.,你需要添加一个额外的if-statement,比如if (i != j)
  • 如果需要无序对,也就是说,我们不想看到 3,7 和 7,3,那么您需要在索引 i+1 处开始您的第二个循环。

然后,接下来进行一些优化。您可能会注意到术语intArray[i] 是不变的。它永远不会改变。因此,您可以将其从内循环中取出并将其移至外循环。此外,您始终执行相同的加法。这基本上没有必要。你可以重写:

intArray[i] + intArray[j] == sum      to
intArray[j]) == sum - intArray[i]

如果我们用delta 替换术语sum- intArray[i],那么我们可以优化我们的循环:

    bool error = true;
    for (int i = 0; i < SIZE; i++) {
        const int delta = sum - intArray[i];

        for (int j = i+1; j < SIZE; j++) {

            if (intArray[j] == delta) {
                cout << "Item " << i << " (With value " << intArray[i] << ") " << "and item " << j << " (With value " << intArray[j] << ") add up to " << sum << endl;
                error = false;
            }
        }
    }

我们现在只有一个减法(而不是多次加法),只访问一次 intArray[i],并且只在内循环中进行比较。

然后我们通常可以改进代码并使用更现代的 C++ 元素。我们需要为用户输入添加错误检查并在需要时而不是之前定义变量。

#include <iostream>
#include <fstream>
#include <vector>

int main() {

    // First open source file and check, if it could be opened
    // If we cannot open it then no need to do something else
    if (std::ifstream inFileStream{"r:\\inFile.txt"}; inFileStream) {

        // Instructions for the user
        std::cout << "\nPlease enter the number for which a matching sum is needed: ";

        // Get the required sum and check for a correct input
        if (int requiredSum{}; std::cin >> requiredSum) {

            // Now, the indicator that shows, if we could find a pair or not
            bool matchingPairFound{};
            // Container for data
            std::vector<int> data{};

            // Read next value from source file until end of file and store it
            for (int i{}, value{}; inFileStream >> value; i++) {

                data.push_back(value);

                // Delta value to find
                const int delta = requiredSum - value;

                for (int j = i - 1; j >= 0; --j) {
                    if (delta == data[j]) {

                        // We found a match
                        matchingPairFound = true;
                        // Show somedebug output
                        std::cout << "Item " << i << " (With value " << data[i] << ") " << "and item " << j << " (With value " << data[j] << ") add up to " << requiredSum << '\n';
                    }
                }
            }
            std::cout << "\nMatching sum was " << (matchingPairFound ? "found" : "not found") << '\n';
        }
        else std::cerr << "\n\n***Error: Could not read sum value\n\n";
    }
    else std::cerr << "\n\n***Error: Could not open input file\n\n";

    return 0;
}

这还没有结束。如果要求是我们只想知道是否有一对加起来是和,我们不需要读取所有值。我们将逐个读取值,然后在得到结果后立即停止。然后循环将向后运行

#include <iostream>
#include <fstream>
#include <vector>

int main() {

    // First open source file and check, if it could be opened
    // If we cannot open it then no need to do something else
    if (std::ifstream inFileStream{"r:\\inFile.txt"}; inFileStream) {

        // Instructions for the user
        std::cout << "\nPlease enter the number for which a matching sum is needed: ";

        // Get the required sum and check for a correct input
        if (int requiredSum{}; std::cin >> requiredSum) {

            // Now, the indicator that shows, if we could find a pair or not
            bool matchingPairFound{};
            // Container for data
            std::vector<int> data{};

            // Read next value from source file until end of file and store it
            for (int i{}, value{}; (inFileStream >> value) and not matchingPairFound; i++) {

                data.push_back(value);

                // Delta value to find
                const int delta = requiredSum - value;

                for (int j = i - 1; (j >= 0) and not matchingPairFound; --j) {
                    if (delta == data[j]) {

                        // We found a match
                        matchingPairFound = true;
                        // Show somedebug output
                        std::cout << "Item " << i << " (With value " << data[i] << ") " << "and item " << j << " (With value " << data[j] << ") add up to " << requiredSum << '\n';
                    }
                }
            }
            std::cout << "\nMatching sum was " << (matchingPairFound ? "found" : "not found") << '\n';
        }
        else std::cerr << "\n\n***Error: Could not read sum value\n\n";
    }
    else std::cerr << "\n\n***Error: Could not open input file\n\n";

    return 0;
}

而且,如果我们不想看到该对的内容而不是索引,那么程序将更加紧凑。我们假设结果是无序对。而且我们不关心源输入文件中的重复项。他们不会增加任何价值。有一个很好的容器可用于此目的。 std::unordered_set 只会存储唯一值并使用快速哈希算法来访问数据。

以下代码

  • 从输入文件中读取任意数量的数据
  • 只有在无法做出决定时才读取
  • 在做出决定之前只存储不同的值
  • 已针对该大小和速度进行了优化
  • 而且结构紧凑。函数main中只有10行代码
#include <iostream>
#include <fstream>
#include <vector>
#include <unordered_set>

int main() {

    // First open source file and check, if it could be opened
    // If we cannot open it then no need to do something else
    if (std::ifstream inFileStream{"r:\\inFile.txt"}; inFileStream) {

        // Instructions for the user
        std::cout << "\nPlease enter the number for which a matching sum is needed: ";

        // Get the required sum and check for a correct input
        if (int requiredSum{}; std::cin >> requiredSum) {

            // Now, the indicator that shows, if we could find a pair or not
            bool matchingPairFound{};

            // Container for data
            std::unordered_set<int> alreadySeenData{};

            // Read values from input file until End-Of-File or until a matching pair was found
            for (int value{}; (inFileStream >> value) and not matchingPairFound; alreadySeenData.insert(value)) {

                // Check, if matching pair was found
                matchingPairFound = (alreadySeenData.count(requiredSum - value));
            }
            // Show result
            std::cout << "\nMatching sum was " << (matchingPairFound ? "found" : "not found") << '\n';
        }
        else std::cerr << "\n\n***Error: Could not read sum value\n\n";
    }
    else std::cerr << "\n\n***Error: Could not open input file\n\n";
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-26
    • 1970-01-01
    • 1970-01-01
    • 2016-05-17
    • 2015-05-03
    • 2016-04-28
    相关资源
    最近更新 更多