简体   繁体   English

C ++从数组中分离正负值

[英]C++ Separate Positive and Negative Values From An Array

Beginner in C++ here and learning arrays. 这里的C ++初学者和学习数组。 The program below is supposed to separate positive and negative numbers in an array. 下面的程序应该在数组中分隔正数和负数。 However, it is returning random numbers in both the splitPos and splitNeg functions. 但是,它在splitPos和splitNeg函数中都返回随机数。

Could someone ever so kindly advice and show me what is incorrect in the functions and what can be done to omit these random digits so that only positive and negative digits are returned respectively by the program for each function/loop? 有人能这么仁慈地建议我,让我看看函数中什么是错误的,以及可以做些什么来省略这些随机数,以便程序对于每个函数/循环仅分别返回正数和负数吗? I am obviously not seeing and/or understanding what is incorrect. 我显然没有看到和/或理解不正确的地方。

Thank you so very much for your help and time in advance!!! 非常感谢您的帮助和提前的时间!!!

#include <iostream>

using namespace std;

//function prototypes
int splitNeg(int[], int[], int);
int splitPos(int[], int[], int);
void displayArr(int[], int);

int main()
{
    const int SIZE = 20;
    int usedPos, usedNeg;
    int origArr[SIZE] = { 4, -7, 12, 6, 8, -3, 30, 7, -20, -13, 17, 6, 31, -4, 3, 19, 15, -9, 12, -18 };
    int posArray[SIZE];
    int negArray[SIZE];


    usedPos = splitPos(origArr, posArray, SIZE);
    usedNeg = splitNeg(origArr, negArray, SIZE);


    cout << "Positive Values: " << endl;
    displayArr(posArray, usedPos);
    cout << endl;
    cout << "Negative Values: " << endl;
    displayArr(negArray, usedNeg);

    return 0;
}

int splitPos(int origArr[], int posArray[], int SIZE)
{
    int j = 0;

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

            if (origArr[i] >= 0)
                posArray[j] = origArr[i];

        }


            return j;

}

int splitNeg(int origArr[], int negArray[], int SIZE)
{
    int k = 0;

    for (int i = 0; i < SIZE; i++ && k++)
    {
        if (origArr[i] < 0)
            negArray[k] = origArr[i];

    }

    return k;
}

void displayArr(int newArray[], int used)
{
    for (int i = 0; i < used; i++)
        cout << newArray[i] << endl;
    return;

}

If you change your for-loops a bit: 如果您稍微更改for循环:

int splitPos(int origArr[], int posArray[], int SIZE)
{
    int j = 0;

        for (int i = 0; i < SIZE; i++)
        {

            if (origArr[i] >= 0)
                posArray[j++] = origArr[i];

        }


            return j;

}

int splitNeg(int origArr[], int negArray[], int SIZE)
{
    int k = 0;

    for (int i = 0; i < SIZE; i++)
    {
        if (origArr[i] < 0)
            negArray[k++] = origArr[i];

    }

    return k;
}

you will get the result you desire. 您将获得想要的结果。

The counter variables of your target arrays only get increased if you find a value that matches the criterion of being less (or greater) than 0. 仅当找到与小于(或大于)0的条件匹配的值时,目标数组的计数器变量才会增加。

I honestly do not understand what you tried to achieve with a ... hmmm.. "combined" increase like i++ && j++ , this goes into short circuit evaluation. 老实说,我不明白您试图通过... hmmm ..“组合”增加来实现什么,例如i++ && j++ ,这涉及短路评估。

j and k must be incremented only when the correct value is copied to posArray and negArray , by definition. 根据定义, 当将正确的值复制到posArraynegArrayjk必须递增。

If the value is the wrong sign, j and k , obviously, should remain unchanged, since the number of values with the right sign, in the corresponding output array, does not change on this iteration. 如果值是错误的符号,则jk显然应该保持不变,因为在相应的输出数组中具有正确符号的值的数量在此迭代中不会改变。

This is not what the code is doing. 这不是代码在做什么。 It is incrementing them on every iteration of the loop, except for the one where i is 0. 除了i为0的循环外,它在循环的每次迭代中都将它们递增。

All the answers in this post are good, but I'm disappointed that none of them talk about the STL algorithms! 这篇文章中的所有答案都不错,但是令我失望的是,他们都没有谈论STL算法!

A good c++ programmer must know the language but he have to know also the C++ library. 一个好的c ++程序员必须知道这种语言,但他还必须知道c ++库。

look the following code: 看下面的代码:

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

using namespace std;

template<typename T>
void print(const string& desc, T first, T last)
{
    cout << desc;
    for_each(first, last,
      [](const auto& i ) { cout << i << ' ';});
    cout << endl;
}

int main()
{
    array<int, 20> originalArray = { 4, -7, 12, 6, 8, -3, 30, 7, -20, -13, 17, 6, 31, -4, 3, 19, 15, -9, 12, -18 };

    print("original array is ", begin(originalArray), end(originalArray)); 

    auto it = partition(begin(originalArray), end(originalArray),
    [](int n) { return n >= 0; });

    print("now original array is ", begin(originalArray), end(originalArray));
    print("positives are: ", begin(originalArray), it);    
    print("negatives are: ", it, end(originalArray));

    return 0;
}

More generally you want partition your set with a predicate. 通常,您希望用谓词对集合进行分区。

Look to my code do you find any if or for ? 查看我的代码,您是否找到了iffor It's impossible make mistakes this way! 这样不可能犯错误!

The only thing that does matter in the whole code is auto it = partition(begin(originalArray), end(originalArray), [](int n) { return n >= 0; }); 整个代码中唯一重要的事情是auto it = partition(begin(originalArray), end(originalArray), [](int n) { return n >= 0; }); that can be read as: partition from start to finish of originalArray elements that are positive . 可以理解为: partition from start to finish of originalArray elements that are positive

There is a standard algorithm made just for that. 为此专门设计了一种标准算法。 It is named std::partition . 它被命名为std::partition

Your code with that algorithm will look like this: 使用该算法的代码将如下所示:

struct SplitPosAndNegResult {
    std::vector<int> negatives;
    std::vector<int> positives;
};

auto splitPosAndNeg(std::array<int, SIZE> orig) {
    // Here `it` is the first element of the second partition (positives)
    auto it = std::partition(orig.begin(), orig.end(), [](int i){ return i < 0; });

    return SplitPosAndNegResult{
        std::vector<int>(orig.begin(), it), // negative numbers
        std::vector<int>(it, orig.end()) // positive numbers
    };
}

Then, use it like that: 然后,像这样使用它:

int main () {
    auto result = splitPosAndNeg({ 4, -7, 12,  6, 8, -3, 30,  7, -20, -13,
                                   17,  6, 31, -4, 3, 19, 15, -9,  12, -18});

    for (int n : result.positives) {
        std::cout << n << ' ';
    }
    std::cout << std::endl;

    for (int n : result.negatives) {
        std::cout << n << ' ';
    }
    std::cout << std::endl;
}

This program will output this: 该程序将输出以下内容:

7 30 8 17 6 31 6 3 19 15 12 12 4 7 30 8 17 6 31 6 3 19 15 12 12 4

-18 -7 -9 -4 -13 -3 -20 -18 -7 -9 -4 -13 -3 -20

Here's a live example at Coliru . 这是Coliru的一个实时示例。

The answers given in this post have correctly identified your problem, so you can have a look at them to learn more about the mistakes you did. 这篇文章中给出的答案可以正确识别您的问题,因此您可以查看一下它们,以了解更多有关您所犯错误的信息。 However, the aim of this answer is to give you a modern approach for writing the same code using the std::vector and the range-based for loop (since you are in the beginning of your learning process, try as much as you can to avoid C-style arrays and learn more about the STL containers) 但是,此答案的目的是为您提供一种现代的方法,以使用std :: vector和基于范围的for循环来编写相同的代码(因为您正处于学习过程的开始,请尽您所能以避免使用C样式的数组,并了解有关STL容器的更多信息)

#include <iostream>
#include <vector>

using namespace std;

void splitArr(const vector<int>& origArr, vector<int>& posArr, vector<int>& negArr);
void displayArr(const vector<int>& Arr);

int main()
{
vector<int> origArr = { 4, -7, 12,  6, 8, -3, 30,  7, -20, -13,
                       17,  6, 31, -4, 3, 19, 15, -9,  12, -18};
vector<int> posArr, negArr;

splitArr(origArr,posArr,negArr);

cout << "Positive Values: \n" ;
displayArr(posArr);

cout << "\nNegative Values: \n";
displayArr(negArr);

return 0;
}

/*________________________________________________________________________________ 
| splitArr function
|
| This function adds the postive elements of the origArr vector into the posArr vector, 
| and the negative ones into the negArr vector
|________________________________________________________________________________ 
*/
void splitArr(const vector<int>& origArr, vector<int>& posArr, vector<int>& negArr)
{
                               // Using range-based for loop
for (auto& number : origArr)
   {
   if (number >=0)
                               // if the number is positive, then add it to
                               // the posArr vector
      posArr.emplace_back(number);
   else
                               // otherwise (the number is negative), then
                               // add it to the negArr vector
      negArr.emplace_back(number);
   }
}

/*________________________________________________________________________________ 
| displayArr function
|
| This function prints to the standard output (cout), all the elements of the 
| vector given as argument using the range-based for loop
|________________________________________________________________________________ 
*/
void displayArr(const vector<int>& Arr)
{
for (auto& number: Arr)
   {
   cout << number << "\n";
   }
}

Let me know if you need more clarification :) 让我知道是否需要进一步说明:)

#include<iostream>
using namespace std;
int main(){
    int a[10]={9,4,-3,-2,1,-1,5,7,-9,-5};
    int low=0;
    int high=10-1;
    while(low<high){
        while(a[low]>=0){
            low++;
        }
        while(a[high]<=0){
            high--;
        }
        if(low<high){
            int temp=a[low];
        a[low]=a[high];
        a[high]=temp;   
        }

    }
    for(int i=0;i<10;i++){
        cout<<a[i]<<" ";
    }
}

Time Complexity: O(n) 时间复杂度:O(n)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM