I'm writing a C++ application that has a user enter a 0 (zero) or a one (1) as input, then stores the numbers as an array and sorts them so that the zeros come first and the ones come last.
However, I think I'm getting a memory address in my array that's messing up the sorting operation.
The function that accepts input looks like this:
cout << "Please enter number " << i+1 << ":\n";
cin >> ar[i];
Then there's a function that's called that sorts the input and displays the sorted list:
sort_elements(ar, number);
... and that function looks like this:
void sort_elements(int ar[], long int num_elements) {
int temp_num;
num_elements -= 1; //since the array starts at 0
cout << "num_elements is " << num_elements << "\n";
for (int i=0; i < (num_elements/2); i++ ) {
if (ar[i] > ar[num_elements-i]) {
temp_num = ar[i];
ar[i] = ar[num_elements-i];
ar[num_elements-i] = temp_num;
}
}
cout << "Here's your neatly sorted list of numbers: \n";
for (int j=0; j <= num_elements; j++) {
cout << ar[j] << ", ";
}
cout << "\n";
}
For a five number input, starting with three "1"s, and ending with two "0"s, this results in an output that looks like this:
1, 0, 1, 1, 1892218304,
I'm assuming the 1892218304 is a memory address, that's messing up the input. Though I don't really know.
Can anyone figure out why my sort operation is getting messed up?
Thanks in advance.
Suggestion
Use vector and sort in standard library
#include <algorithm>
#include <vector>
#include <iostream>
#include <iterator>
int main()
{
std::vector<int> v;
for(int i=0; i < 10; i++)
{
v.push_back(i);
}
std::sort(v.begin(), v.end());
return 0;
}
The number you are seeing is not a memory address, but the value of the 4 bytes either immediately before or immediately after your array, interpreted as an int. Your code has an off-by-one error that causes an access to just outside the array. That much I suspect even though I don't have proof.
However, I can't find anything wrong with the code you posted that would cause it to access outside the array bounds.
Are you sure that num_elements has the correct value when this function is called?
Update to address the pastebin code
Things are going wrong already from the start:
int number;
int ar[number]
This is called a variable-length array and it's not legal in C90 or any flavor of C++. That your program compiles is probably "thanks to" a compiler extension... which helpfully raises a bug: the value of number is not initialized before the array is allocated.
You need to do one of the following:
declare ar as an array of constant size (a hard limit on the number of inputs you can accept)
dynamically allocate ar with new[] after number is entered from the user
(by far preferable) use an std::vector instead of an array
It looks to me like you're just getting an uninitialized value in your output.
Under the circumstances, the simplest "sorting" method is probably a counting sort -- i.e., count the number of 0's and the number of 1's the user enters, and then print out the appropriate number of 0's followed by the appropriate number of 1's.
As Tony said, your sorting algorithm is incorrect.
If we assume the following values:
ar[0] = 0
ar[1] = 1
ar[2] = 0
ar[3] = 1
ar[4] = 0
that gives us num_elements equal to 5.
Running this through your function as written, we get the following sorting behavior:
First pass, i = 0
ar[0] > ar[4] -> not true, so no switch
Secon pass, i = 1
ar[1] > ar[3] -> not true, so no switch
There is no third pass, as your for loop condition is met
i = 2
num_elements/2 = 2
2 is not less than 2
So based on your code, you didn't sort anything. This is the first issue.
Your print problem is interesting, based on what you have shown num_elements has been decremented by 1 at the top of your code snippet in your function - therefore the <= condition is correct and you should not be outside the bounds of your 'ar' array. Are you sure this is the exact code, or perhaps you did not copy it properly here and you are actually having a scoping issue?
(EDIT: Although the other answers suggesting using a built in sorting method via vectors, I'd suggest you still work your current implementation out to figure out WHY this is wrong, and what you need to do to fix it. You will not always have an available type that has built in sorting, so understanding the fundamentals is important for any young programmer.)
EDIT2: Based on the link you provided, you aren't properly defining your integer array. You are defining the array based on an uninitialized integer (int ar[number]) when number has not yet been initialized. You then read a value from the standard input to set number, and assume your array has been dynamically adjusted to be of the size read from cin. It does not work this way. Your entire loop is reading/writing outside the bounds of your array which is a big no-no. You want to read the number first, and then define your array based on the size read. - Looks like Jon beat me again.. BAH! :P
The last element being read and printed to the screen has never been written to. I think it's likely your function which accepts input has a fault, like maybe you have a line like you have here
num_elements -= 1; //since the array starts at 0
at the input function so that the first element you write to is at address 1. Then when you're reading them you read from address zero.
I kind of agree with Jim's point: Use the facilities in the C++ standard library to finish your task as much as possible.
Besides, I suggest you go through the algorithm all by yourself, manually, instead of letting the computer run it for you. Ever heard of the "Rubber Duck Debugging Method"? :-) Have a try.
Related
I'm working on a program that takes a long variable (x) and stores it into an array, then is able to read the separate values both reversed and in order. I've used a while loop in order to store the values but am a little stuck getting the program to read the values, but practices like this will help my understanding of the subject in the long run. Any advise on where I'm making a mistake would be great, thanks in advance! I'm still kind of a n00b with arrays in C++
int arr[]={};
long x;
int i=0;
int j;
cout<<"Enter value to be stored: "<<endl;
cin>>x;
while(x>0){
int lastdigit=x%10;
arr[i]=lastdigit;
x=x/10;
}
if(arr[i]>0){
for(j=i-1;j>-1;j--){
cout<<"Array values "<<arr[j];
}
}
}
This is just to read the array values in order, I'll add the reversal once I get this part down.
Your fundamental error is here
int arr[] = {};
this creates a zero size array if it was allowed but on my machine its not even valid syntax
cannot allocate an array of constant size 0 ConsoleApplication1 C:\work\ConsoleApplication1\ConsoleApplication1.cpp 12
I changed it to
int arr[12] = {};
since 10 decimal digits is enough for a 32 bit integer, plus one to be sure, and another one just in case :-)
Next mistake is you never increment i in the mod / divide loop
Then finally you test arr[i] > 0. This is not needed, take it out
Now your code works fine
PS. Make arr a std::vector<int> so it will grow rather than hard coding to 12 digits
CSES problem (https://cses.fi/problemset/task/2216/).
You are given an array that contains each number between 1…n exactly once. Your task is to collect the numbers from 1 to n in increasing order.
On each round, you go through the array from left to right and collect as many numbers as possible. What will be the total number of rounds?
Constraints: 1≤n≤2⋅10^5
This is my code on c++:
int n, res=0;
cin>>n;
int arr[n];
set <int, greater <int>> lastEl;
for(int i=0; i<n; i++) {
cin>>arr[i];
auto it=lastEl.lower_bound(arr[i]);
if(it==lastEl.end()) res++;
else lastEl.erase(*it);
lastEl.insert(arr[i]);
}
cout<<res;
I go through the array once. If the element arr[i] is smaller than all the previous ones, then I "open" a new sequence, and save the element as the last element in this sequence. I store the last elements of already opened sequences in set. If arr[i] is smaller than some of the previous elements, then I take already existing sequence with the largest last element (but less than arr[i]), and replace the last element of this sequence with arr[i].
Alas, it works only on two tests of three given, and for the third one the output is much less than it shoud be. What am I doing wrong?
Let me explain my thought process in detail so that it will be easier for you next time when you face the same type of problem.
First of all, a mistake I often made when faced with this kind of problem is the urge to simulate the process. What do I mean by "simulating the process" mentioned in the problem statement? The problem mentions that a round takes place to maximize the collection of increasing numbers in a certain order. So, you start with 1, find it and see that the next number 2 is not beyond it, i.e., 2 cannot be in the same round as 1 and form an increasing sequence. So, we need another round for 2. Now we find that, 2 and 3 both can be collected in the same round, as we're moving from left to right and taking numbers in an increasing order. But we cannot take 4 because it starts before 2. Finally, for 4 and 5 we need another round. That's makes a total of three rounds.
Now, the problem becomes very easy to solve if you simulate the process in this way. In the first round, you look for numbers that form an increasing sequence starting with 1. You remove these numbers before starting the second round. You continue this way until you've exhausted all the numbers.
But simulating this process will result in a time complexity that won't pass the constraints mentioned in the problem statement. So, we need to figure out another way that gives the same output without simulating the whole process.
Notice that the position of numbers is crucial here. Why do we need another round for 2? Because it comes before 1. We don't need another round for 3 because it comes after 2. Similarly, we need another round for 4 because it comes before 2.
So, when considering each number, we only need to be concerned with the position of the number that comes before it in the order. When considering 2, we look at the position of 1? Does 1 come before or after 2? It it comes after, we don't need another round. But if it comes before, we'll need an extra round. For each number, we look at this condition and increment the round count if necessary. This way, we can figure out the total number of rounds without simulating the whole process.
#include <iostream>
#include <vector>
using namespace std;
int main(int argc, char const *argv[])
{
int n;
cin >> n;
vector <int> v(n + 1), pos(n + 1);
for(int i = 1; i <= n; ++i){
cin >> v[i];
pos[v[i]] = i;
}
int total_rounds = 1; // we'll always need at least one round because the input sequence will never be empty
for(int i = 2; i <= n; ++i){
if(pos[i] < pos[i - 1]) total_rounds++;
}
cout << total_rounds << '\n';
return 0;
}
Next time when you're faced with this type of problem, pause for a while and try to control your urge to simulate the process in code. Almost certainly, there will be some clever observation that will allow you to achieve optimal solution.
I'm storing the results of a "Dice Roll" in an Array.
Everything seems to be working fine, except the last value of the Array is a ╠ (-858993460)?
I tried troubleshooting and its happening right in the beginning and I don't know why.
const int QDice = 3;
int Domain = 6 * QDice;
int CD[6 * QDice]{};
do
{
cout << "Array CD[" << i << "] = " << CD[i] << "\n";
i++;
} while (i <= Domain);
This yields:
Array CD[1] = 0
...
Array CD[18] = -858993460
Everything is fine accept the last element.
C++ array index starts from 0, so the array CD[] range is from 1 to 17. When the Domain becomes 18, the array is out of bounds. I suggest that you could modify the code to the following code.
do
{
cout << "Array CD[" << i << "] = " << CD[i] << "\n";
i++;
} while (i <= Domain - 1);
As mentioned in the comments and another answer, you're assuming 1-based indexing while c++ arrays use 0-based indexing. This means index 18 is out-of-bounds, i.e., it is past the end of the array. But why that does that negative number show up?
First of all, when an out-of-bounds condition exists, the program exhibits undefined behaviour. That means the program can do literally anything, whether it's what you intended or not. In practice, though, the program will often assume that arrays are large enough for the index being used. So in your case, it will look up the memory where index 18 ought to be (as if the array were large enough for that), and then try to interpret the bytes it finds there as some meaningful value.
Now, as a general rule, memory can have any value at all, unless you set it to something specific. By initializing your array, you set the memory for each array element to a definite value (0). But just past the end of the array is memory that you haven't set, so those bytes could be anything. In your case, they just happen to be set in such a way that they are interpreted as the -858993460, but that could just as well be any other value.
First time around, first time learning to code anything. Sorry for my ignorance.
So I've been asked to code a program that gets infinite amount of number from the users until he submits the number I manage to do so very well, but I also need to print the biggest sum of a following three inputs, for example, the user inputs 4,20,2,4,11,9,8,1 the program should print 11,9,8 because the sum of those 3 is greater than all other 3.
I must tell you I cannot use arrays, I know its a bummber but I know it is possible to do so without.
I was trying to build a function that tries to act like an array but I can't really call her back since its a two-variable function and one of them is the input, which I obviously don't know. was working on this question for 5 hours now and thought ill ask for your wisdom
cout << " enter numbers as long as you wish" << endl;
cout << "when you wish to stop enter the number 1" << endl;
int n;
int sum;
int i = 1;
while (n != 1) {
cin >> n;
remember(i, n);
if (n == 1) {
cout << "you choosed to stop " << endl;
break;
}
i++;
}
And the function I was trying to build is really simple but I can't call any specific value for example remember(1, n) when I want to sum them up and see who is bigger.
int remember(int i, int n){
return n;
}
*** Please note that the sums that are being tested are the sums of the numbers in the exact order that the user-submitted therefor 11,9,8 is the output and NOT 20,11,9
You need seven variables: Three which is the "window" you're currently reading, and which you check your sum with; Three which is the "biggest sum" triple; And one which is the current input.
For each input you read into the "current input" variable, you shift the window down one value and set the top variable to the just read input.
Then you take the sum of all three values in the window, and check if it's bigger than the sum of the current "biggest sum" triple. If it is, then you make the "biggest sum" triple equal to the current window values.
Iterate until there is no more input, and then print the "biggest" values.
Regarding the shifting of the three window values, lets say you have three variables named window1, window2 and window3 then you could shift like this:
window1 = window2;
window2 = window3;
window3 = current;
Checking the sum is as easy as
if ((window1 + window2 + window3) > (biggest1 + biggest2 + biggest3))
All window and biggest variables need to be initialized to the lowest possibly value for the type (for int that would be std::numeric_limits<int>::min()).
Since you initialize all values, there's no need to have special cases for the first and second input.
Iterating while there's input could be done by doing
while (std::cin >> current)
First of all, n is uninitialized, so it's undefined behavior when you do while (n != 1){. So technically, there's no guarantee that anything works past that. You should initialize it, for example by setting it to 0 (or any other value that's not 1, in this case):
int n = 0;
But the issue that you observe is because you have another int n; in your loop, which shadows the outer n (the one that is checked in the while condition). So the cin >> n; only ever modifies that inner n. The outer one will stay at the same uninitialized value. So if that value made it enter the loop, it will never exit the loop, because n != 1 is always true.
Remove the int n; inside the loop to solve the problem.
Basically, what you need is 4 variables to account the actual list and its sums (3 for the list and 1 for the sum of it)
You need 3 more variables to account the actual list.
At each interaction, you have two things to do:
Compare the sum of actual list with the stored one. If the sum the actual list is greater than that stored, actualize it
For each new number, rotate you variables that account for the actual list.
In pseudo code:
v3 = v2;
v2 = v1;
v1 = new_number;
I'm new here as well to coding. Recently I've been going through Principles and Practice Using C++ and inside his code there is always an i inserted into his examples. Some are inside "vector's subscript" function, or inside "for statements" such as int i. But he didn't even make an int called i, it's just there. Maybe I missed something while reading, I don't know, but I hope someone wouldn't mind giving me a meaning as to why it's inserted in the places it's placed in, or just the meaning of i.
Below I took one of his examples from page 148 to show you
int main()
{
vector<double> temps; //temperatures
double temp = 0;
double sum = 0;
double high_temp = 0;
double low_temp = 0;
while (cin>>temp) // read and put into temps
temps.push_back(temp) ;
for (int i = 0; i<temps.size(); ++i) // these 'i's
{
if(temps[i] > high_temp) high_temp = temps[i]; // and these
if(temps[i] < low_temp) low_temp = temps[i];
sum += temps[i]; // compute sum
}
cout << " High temperature: " << high_temp<< endl; // find high
cout << " Low temperature: " << low_temp << endl; // find low
cout << "Average temperature: " << sum/temps.size() << endl;
}
When you write a software program, each variable that you declare must have a meaning, must represent something.
This is also the case in the book fragment you just read, only that we are talking about arrays. As you know, arrays are a collection of values of the same value type. Because it's a collection, it means there are 1 or more values into that array.
This raises the question: if there are 1 ore more values, how can I acces one specific value of that array? Here is where the i you read comes in.
The variable i has the meaning of the position of the array I am working on right now, where "working on" can mean reading, writing, etc. Because i is a variable, it must have a data type, hence the int i notation.
Using i as a variable in this context is not mandatory, but it's a very common practice. If you have a matrix, for example, you will need two such variables (one for rows and one for columns) which most likely will be i and j.
This also explains why we use i inside a for loop. In English, this means that the loop works with the elements that have the coefficient number from 0 to the array size.
i was declared as an int type in the for loop, but it could also be declared before that loop. Something like:
int i=0;
...
for (i=0; i<...)
i is declared as a variable of type int, here:
for (int i = 0; .......)
{
// 'i' used here
}
// 'i' cannot be used here
That i has a scope only inside that for loop. After the loop terminates, so does the lifetime of that variable i.
i is a part of convention, where it stands for iteration number.
It has been defined in the for loop:
for (int i = 0 ....
Which basically states that you start from iteration number zero. Once you gain some experience, you will see that iterations don't always start from zero, so i may be initialized with a different value (or a different variable name may be used instead of i altogether).
Mathematically, i is often used in context of a list/array: the ith element or summation from i=0 to i=n etc.
i is an integer, used as an indexing variable. You often see it in loops.
First, let's think about a vector and what it looks like. A vector is a variable-length array.
So if we have a vector named myVector with 5 elements, then we have something that looks like
myVector: item1 item2 item3 item4 item5
Now how do we specify individual items? We'll need to index each item. Traditionally (from mathematics), indexing begins at 0. So to index the first element, we do myVector[0]. To index the second element, we do myVector[1], and so on. (The [] is known as the subscript operator. You can also use myVector.at(0), myVector.at(1), but this is less used.)
Now what if we wanted to find the minimum or maximum value in a vector? We'd need to check each item and compare them. So we'll need to iterate (loop) through the entire array.
How do we do this? How do we iterate through each and every item? To loop through each item, we'd need something to specify the items. To loop through every item, we'd need a loop.
The loop in your code does this, iterating from 0 up to the length of the array/vector.
for (int i = 0; i < temps.size(); ++i) // iterate through EVERY element of the vector
{
// access EACH element of using temps[i]
}