Program Aborts when using vector iterators - c++

Can somebody tell me what is the problem with this program?
The idea is to display "Yes" if the vector array satisfies all these criteria:
The array elements are not sorted in ascending order.
The array contains distinct elements.
All the array elements should have a value between 1 to n inclusive.
Otherwise "No".
The program aborts when it reaches the line at if(bSort).
Is there anything wrong with the iterator increment?
#include <iostream>
#include <string>
#include <bits/stdc++.h>
using namespace std;
std::string solve(vector <int> &a, int n) {
vector<int> visited (n);
int i=0;
for(std::vector<int>::iterator it = a.begin(); it != a.end(); ++it) {
i++;
if((it+1)!=a.end() && (*it > *(it+1)))
{
bSort = false;
}
if(std::find(visited.begin(), visited.end(), *it)!=visited.end())
{
return "No";
}
else
{
visited[i] = *it;
}
if(*it <= 0 || *it > n)
{
return "No";
}
}
if(bSort)
return "No";
else
return "Yes";
}
int main() {
int q;
cin >> q;
for(int a0 = 0; a0 < q; a0++){
int n;
cin >> n;
vector<int> a(n);
for(int a_i = 0; a_i < n; a_i++){
cin >> a[a_i];
}
std::string result = solve(a,n);
cout << result << endl;
}
return 0;
}
The issue appears to be happening only with the following input:
1
30
18 8 24 20 7 17 5 9 26 21 25 12 11 15 30 13 19 16 22 10 14 1 3 29 23 2 6 28 4 27

I'm not sure the problem has to do with iterators specifically.
At the very beginning of the loop, variable i is incremented before it's used, which means the set of numbers that i will range between is [1, vector.size()]. This means that at some point, you'll access vector[vector.size()], which is undefined behavior and can crash your program.
In your program specifically, given the input you provided, because none of the numbers in your example code are duplicated, the else branch of the std::find(...) conditional statement is always executed, which means you end up calling visited[30] at some point, which again, is out of bounds and undefined behavior, potentially causing a crash.

Related

what is wrong in this code trying to print Fibonacci series in reverse order

tried to take terms in array and printed that array but expected output is different from my output not able to find the logic behind it.
code:-
#include <iostream>
using namespace std;
int main() {
int num;
int t1=0;
int t2=1;
int next;
cin>>num;
int arr[num];
for (int i = num-1; i >= 0; i--)
{
if (i == num-t1-1)
{
arr[i] = t1;
continue;
}
if (i == num-t2-1)
{
arr[i] = t2;
continue;
}
next = t1+t2;
arr[i] = next;
t1 = t2;
t2 = next;
}
for(int j=0;j<num;j++)
{
cout<<arr[j]<<" ";
}
return 0;
}
what is wrong in this code?
output if user enter 20 is
20
2584 1597 987 610 377 233 144 89 55 34 21 8 13 8 5 3 2 1 1 0
one additional 8 is coming in between 21 and 13.
But expected output should be
20
4181 2584 1597 987 610 377 233 144 89 55 34 21 13 8 5 3 2 1 1 0
Your code is a good example of how code should not be written.:)
It is very difficult to understand your code. It's a rule that badly readable code is bound to contain bugs.
For example there are used three variables t1, t2 and next to assign values to elements of the array
arr[i] = t1;
//...
arr[i] = t2;
//...
arr[i] = next;
and it is not clear for which value of the variable i there will be used one of the assignments.
For starters variable length arrays like this
int arr[num];
are not a standard C++ feature. Instead you should use standard container std::vector.
That is if you write a C++ program you should use features provided by the C++ language.
Your code is invalid. For example when i is equal to 11 then t1 is equal tp 8. and this if statement
if (i == num-t1-1)
in this case is equivalent to
if ( 11 == 20-8-1)
or
if ( 11 == 11 )
and the value of t1 is written in the array element arr[11]. instead of writing the value 21.
Here is a demonstration program that shows how your assignment can be performed.
#include <iostream>
#include <functional>
#include <vector>
#include <iterator>
int main()
{
unsigned int n;
if (std::cin >> n && n != 0)
{
std::vector<unsigned long long> v( n );
std::pair<unsigned long long, unsigned long long> fibonacci( 0, 1 );
for (auto first = std::rbegin( v ), last = std::rend( v ); first != last; ++first)
{
*first = fibonacci.first;
fibonacci.first =
std::exchange( fibonacci.second, fibonacci.first + fibonacci.second );
}
for (const auto &item : v)
{
std::cout << item << ' ';
}
std::cout << '\n';
}
}
The program output is the same as expected.
20
4181 2584 1597 987 610 377 233 144 89 55 34 21 13 8 5 3 2 1 1 0
Pay attention that instead of using the signed type int for the variable num you should use an unsigned integer type as for example unsigned int. And to avoid an overflow the variables t1 and t2 should have at least the type unsigned long long int.
In the provided demonstration program this declaration
std::pair<unsigned long long, unsigned long long> fibonacci( 0, 1 );
makes it clear that the program deals with fibonacci numbers.
You want to place t1 and t2 at the last two indices of arr. Those indices are not num-t1-1 and num-t2-1, but num-1 and num-2.
Rather than special casing the loop, it is easier to assign them outside of the loop and start the loop at the 3rd last.
int arr[num]; is not valid C++. Use std::vector for dynamically sized arrays.
Last but not least, the logic in your loop looks too complicated. You only need to use the recurrence relation directly (well, ok reversed) arr[i] = arr[i+1] + arr[i+2], no additional variables are needed.
#include <iostream>
#include <vector>
int main() {
int num;
std::cin >> num;
if (num < 3) {
std::cout << "num is too small\n";
return 1;
}
std::vector<int> arr(num);
arr[num-1] = 0;
arr[num-2] = 1;
for (int i = num-3; i >= 0; i--) {
arr[i] = arr[i+1] + arr[i+2];
}
for(const auto& e : arr) {
std::cout << e << " ";
}
}
For further reading I refer you to https://en.cppreference.com/w/cpp/container/vector,
Why is “using namespace std;” considered bad practice?,
Why aren't variable-length arrays part of the C++ standard?,and What is a debugger and how can it help me diagnose problems?.

Bubble sort the numbers from a file in descending order for the first number

I want to sort using the "Bubble Sort" algorithm of the 2d array. My array size will be about array[100000][100000]. my input number will be n=100,000.
For now we can use a small size of the array to fix the sorting issue.
I need to sort them in descending order for the first number(first number's line).
If the first number of 2 values are the same, then I have to sort them according to their second number.
Finally I have to output the result into a txt file
Let's' understand using an example. Here, my input looks like this
41 11
34 4
69 4
78 6
62 8
5 5
81 3
5 10
above our input example and we have a couple of inputs. Now I need to sort them descending orders for the first number. But if the first number of 2 values are the same, then sort them according to their second number.
Example output below,
81 3
78 6
69 4
62 8
41 4
34 4
5 10
5 5
If anyone can please help me.
I am a beginner so I am trying to input the file manually to solve this sorting problem. I can solve the sorting problem then I will try to input and out the text.
Something I have tried but not worked. I am still trying to solve it.
#include<bits/stdc++.h>
#include <algorithm>
using namespace std;
int main ()
{
int arr[100][100];
int n,j;
cin >>n;
cout << "Please enter a number: " << endl;
for(int i=0;i<n;i++)
{ for (int j=i; j<n; j++)
{
cin>>arr[i][j];
}
}
cout << "Unsorted array:" << endl;
for (int i=0; i<n; i++)
{
for (int j=i; j<n; j++)
{
cout<<arr[i][j]<<"\t";
}
}
for (int i=0; i<=n; i++)
{
for (int j=i+1; j<=n-1; j++)
{
int temp;
if(arr[i]>arr[j])
{
temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
}
}
return 0;
}
Use a std::vector<std::array<int,2>>for your base container. The dynamic growth capabilities of std::vector solves your stack space issue, and the std::array use gives you tied cell comparison. I.e. you can do this:
std::array<int, 2> ar1{1,2}, ar2{1,3};
if (ar1 < ar2) ...
and it will do the right thing. The result then boils down to effectively this:
#include <iostream>
#include <array>
#include <vector>
#include <utility>
int main()
{
std::vector< std::array<int,2> > v;
std::size_t n;
if (std::cin >> n && n > 0)
{
std::array<int,2> row;
while (n-- && std::cin >> row[0] && std::cin >> row[1])
v.emplace_back(row);
// bubblesort the content
std::size_t len = v.size();
while (len-- > 0)
{
bool swapped = false;
for (std::size_t i=0; i<len; ++i)
{
// std::array support multi-cell comparison.
if (v[i] < v[i+1])
{
// use library swap to swap entire row.
std::swap(v[i], v[i+1]);
swapped = true;
}
}
// early exit if no swaps happened on the last pass
if (!swapped)
break;
}
// report final output.
for (auto const& row : v)
std::cout << row[0] << ' ' << row[1] << '\n';
}
}
Input
8
41 11
34 4
69 4
78 6
62 8
5 5
81 3
5 10
Output
81 3
78 6
69 4
62 8
41 11
34 4
5 10
5 5

Segmentation fault with vectors, but not sure what I did wrong

So when I run this code:
#include <iostream>
using namespace std;
#include <vector>
#include <string>
int main()
{
int current_number = 0;
vector<int>primes;
for(int i = 0; i < 100; i++)
{
current_number++;
for(int h= 0; h < primes.size(); h++)
{
if(current_number % primes[h] == 0)
{
continue;
}
else
{
primes.push_back(current_number);
}
}
}
for(int x =0; x < 100; x++)
{
cout << primes[x];
}
}
I get a segmentation fault. Im pretty sure it has something to do with vectorprimes. But, I'm not sure exactly what. The purpose of the code is to find every prime number between 1 and 100.
Among the problems in the posted code.
The inner loop body will never be entered because primes is initially empty the only code that changes it is in that loop.
Even after fixing the initial primes content with {2} and starting the counter loop with 3, the logic in the inner loop is still wrong. It appends on ever non-zero modulo. That shouldn't be done at all in the inner loop. Rather, the loop should break on any zero-modulo, and the outer loop then only appends to primes when it knows the inner loop didn't break early.
The final reporting loop assumes there are 100 primes in the first 100 numbers, which clearly isn't the case. Either it should be iterating based on container size, using iterators, or better still, just used ranged-for.
Minor: the current_number is pointless; just use i from the outer loop and start it at 3.
#include <iostream>
#include <vector>
int main()
{
std::vector<int> primes = {2};
for (int i = 3; i <= 100; i++)
{
bool isprime = true;
for (auto x : primes)
{
if (i % x == 0)
{
isprime = false;
break;
}
}
if (isprime)
primes.emplace_back(i);
}
for (auto x : primes)
std::cout << x << ' ';
std::cout << '\n';
}
Output
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97
Note
There are better ways to do this. I suggest you investigate how to build a Sieve of Eratosthenes or similar sieve. In truth, the above code is already over halfway there. It wouldn't take much more to do it.

Cannot give necessary input to C++ program in windows console

I'm trying to solve CSES Problem Set: Apartments, which have input like this in 3 lines, but I am unable to process/pass all three lines in the Windows terminal. I am using Geany editor and compilation is successful.
10 10 0
37 62 56 69 34 46 10 86 16 49
50 95 47 43 9 62 83 71 71 7
Can anyone review and tell me what is wrong? Is there fault in my logic?
#include <bits/stdc++.h>
using namespace std;
int n, m, k;
int main()
{
vector<int> v1;
vector<int> v2;
vector<bool> allotted(n, false);
cin >> n >> m >> k;
for (int i = 0; i < n; ++i) {
cin >> v1[i];
}
for (int j = 0; j < m; ++j) {
cin >> v2[j];
}
sort(v2.begin(), v2.end());
sort(v1.begin(), v1.end());
int ans = 0;
for (int req = 0; req < n; ++req) {
for (int x = -k; x <= k; ++x) {
if (find(v2.begin(), v2.end(), v1[req]+x) != v2.end() && alloted[req] == false) {
++ans;
allotted[req] = 1;
}
else {
continue;
}
}
}
cout << ans;
return 0;
}
Output:
10 10 0
37 62 56 69 34 46 10 86 16 49
------------------
(program exited with code: -1073741819)
You must allocate elements before accessing them or add elements via push_back.
To allocate elements, using resize() is one good way.
vector<int> v1;
vector<int> v2;
vector<bool> allotted(n, false); // note that n is zero here!
cin>>n>>m>>k; // after here, the size will be n (may not when the reading fails)
// allocate elements
v1.resize(n);
v2.resize(m);
allotted.resize(n);
You forgot to tell your vectors how long they should be. As a result you 're reading data into non-existing variables.
As an alternative to MikeCAT's answer, if you delay the declaration of your vectors until you know how big they need to be then you can create them at the correct size.
cin>>n>>m>>k;
vector<int> v1(n); // v1 has size n
vector<int> v2(m); // v2 has size m
vector<bool> allotted(n, false); // allotted has size n

C++: St9bad_alloc failure for small Input

I built a program for converting a multigraph into undirected graph with multiple edges and self loops removed using adjacency-list as Graph representation.
`
#include<iostream>
#include<istream>
#include<algorithm>
#include<list>
using namespace std;
int main()
{
list<int> adj[3];
list<int> auxArray[3];
list<int> adjnew[3];
cout<<adjnew[2].back()<<endl; // Gives output 0, whereas it should have some garbage
//value
for(int i = 0;i<3;i++){
int x;
while(true){ // reading a line of integers until new line is encountered , peek()
returns the next input character without extracting it.
cin>>x;
adj[i].push_back(x);
auxArray[i].push_back(x);
if(cin.peek() == '\n') break;
}
}
//flatten the adj-list
for(int i = 0;i<3;i++){
list<int>::iterator it = adj[i].begin();
while(it != adj[i].end()){
auxArray[*it].push_back(i);
it++;
}
}
for(int i = 0;i<3;i++){
list<int>::iterator it = auxArray[i].begin();
while(it != auxArray[i].end()){
//cout<<*it<<" "<<adjNew[*it].back()<<endl;
if((*it != i) && ((adjnew[*it].back()) != i)){
// cout<<*it<<" -> "<<i<<endl;
adjnew[*it].push_back(i);
}
it++;
}
}
for(int i = 0;i<3;i++){
list<int>::iterator it = adjnew[i].begin();
while(it != adjnew[i].end()){
cout<<*it<<" ";
it++;
}
cout<<endl;
}
return 0;
}
`
But it shows St9bad_alloc error whereas my list has size of just 3.
Also, adjnew[2].back() is assigned to "0" without being initialized, whereas it should have some garbage value.
'
Input:
1 2 1
0
1 1
Output of Program(Incorrect because of 0 as back element in adjnew[2]):
1 2
0 2
1
Correct Output:
1 2
0 2
0 1
'
All suggestions are welcomed!
The
cout<<adjnew[2].back()<<endl;
at begin is plain undefined behavior on an empty container.
valgrind gives
Conditional jump or move depends on uninitialised value(s)
for this line:
if ((*it != i) && ((adjnew[*it].back()) != i))
Again an undefined behavior on an empty container.
Hint: You could use container.at() instead of operator [] to have a range check.