C++: St9bad_alloc failure for small Input - c++

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.

Related

cin is not taking in the last input in a while loop

In the following code segment, the cin inside the while loop, which is nested inside the while loop in the main function, is somehow not working during the last input (i.e, when h == n-1) and reporting a segmentation fault instead.
I figured this out by using the print statements (which are commented in the code below), one at the start of the inner while loop, one after the cin statement (to find the read values of v and x decremented by 1) and one outside the while loop. The third cout statement doesn't execute, from which I concluded that the segmentation fault is inside the while loop.
Moreover, in the last iteration of the inner while loop, the cout statement after the cin statement (to print the values of v and x) also didn't execute. And so, I think that the cin inside the inner while loop isn't working in the last iteration.
I tried searching a lot and put in the cin.clear() and cin.ignore(numeric_limits<streamsize>::max(), '\n'); statements but still no use!
Why is there such an issue?
#include <bits/stdc++.h>
using namespace std;
vector <vector<int>> adj;
vector<unordered_set <int>> leaf;
int process(int node, int *pans, int k){
*pans = *pans + (leaf[node].size() / k) * k;
int temp = (leaf[node].size() / k) * k;
if(temp == 0) return 0;
for(auto it : leaf[node]){
if(temp == 0) break;
leaf[node].erase(it);
auto j = find(adj[node].begin(), adj[node].end(), it);
adj[node].erase(j);
temp --;
}
if(adj[node].size() == 1){
leaf[adj[node][0]].insert(node);
process(adj[node][0], pans, k);
}
return 0;
}
int main(){
int t, v, x, n, k;
cin>>t;
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
while(t--){
int ans = 0;
cin>>n>>k;
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
adj.resize(n);
int h = 1;
while(h < n){
// cout<<"r";
cin>>v>>x;
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
v --; x --;
cout<<v<<" "<<x<<"\n";
adj[v].push_back(x);
adj[x].push_back(v);
h++;
}
// cout<<"out";
leaf.resize(n);
for(int i = 0; i < n; i ++){
if(adj[i].size() == 1) leaf[adj[i][0]].insert(i);
}
for(int i = 0; i < n; i ++){
if(leaf[i].size() >= k) process(i, &ans, k);
}
cout<<ans<<"\n";
adj.clear();
leaf.clear();
}
}
Following is an example of the input:
1
8 3
1 2
1 5
7 6
6 8
3 1
6 4
6 1
The error is here
for(auto it : leaf[node]){
if(temp == 0) break;
leaf[node].erase(it);
auto j = find(adj[node].begin(), adj[node].end(), it);
adj[node].erase(j);
temp --;
}
By modifying the unordered_set leaf[node].erase(it); you are invalidating the implicit iterator used by the range based for loop. Rewrite your loop with an explciit iterator so you can account for the iterator invalidation. Like this
for (auto i = leaf[node].begin(); i != leaf[node].end(); ) {
if(temp == 0) break;
auto it = *i;
i = leaf[node].erase(i);
auto j = find(adj[node].begin(), adj[node].end(), it);
adj[node].erase(j);
temp --;
}
With this loop your code runs to completion (at least for me). I've no idea if the output is correct or not.

Symmetric Matrix in C++

Checking whether a 2D Matrix is symmetric or not
Task is to output YES if the matrix is symmetric else output NO.
I am not getting the expected result. Can someone please help me out and please let me know what's wrong with this code
#include<iostream>
#include<vector>
using namespace std;
bool rev(int n)
{
int n1,d,rn=0;
n1=n;
while(n>0)
{
d=n%10;
rn=(rn*10)+d;
n/=10;
}
if(n1==rn)
{return true;}
else
return false;
}
bool XAxisSymCheck(vector<int> vect)
{
// Declaring iterator to a vector
vector<int>::iterator ptr;
for (ptr = vect.begin(); ptr < vect.end(); ptr++)
{ if(!rev(*ptr)) // reversing the elements in each element of vector to check whether its symmetric or not .. similar to palindrome
{
return false;
}
}
}
int main()
{int testcase;
cin>>testcase;
for(int k=0;k<testcase;++k)
{vector<int> rows;
bool IsSymmetric=true;
int row;
cin >> row;
// read each row and append to the "rows" vector
for (int r = 0; r < row; r++)
{
int line;
cin >> line;
rows.push_back(line);
}
if(XAxisSymCheck(rows))
{int i,j;
i=0;
j=row-1;
while(i<j) // looping through the elements of vector and checking the first element with last element , second element with the second last element and so on.
{
if(rows[i]!=rows[j])
{
IsSymmetric=false;
break;
}
i++;
j--;
}
}
else
{
IsSymmetric=false;
}
cout << (IsSymmetric ? "Yes" : "No") << endl;
}
return 0;
}
Input:
First line contains T - number of test cases.
T test cases follow.
First line of each test case contains the N - size of matrix.
Next N lines contains binary strings of length N.
Output:
Print YES or NO in a new line for each test case
SAMPLE INPUT
5
2
11
11
4
0101
0110
0110
0101
4
1001
0000
0000
1001
5
01110
01010
10001
01010
01110
5
00100
01010
10001
01010
01110
SAMPLE OUTPUT
YES
NO
YES
YES
NO
Test Case #1: Symmetric about both axes, so YES.
Test Case #2: Symmetric about X-axis but not symmetric about Y-axis, so NO.
Test Case #3: Symmetric about both axes, so YES.
Test Case #4 and #5 are explained in statement.
There are three problems with your code
1) You are never returning true from XAxisSymCheck (this can easily discovered by inspecting the compiler warnings, eg g++ -Wall matrix.cpp)
bool XAxisSymCheck(vector<int> vect) {
vector<int>::iterator ptr;
for (ptr = vect.begin(); ptr < vect.end(); ptr++) {
if(!rev(*ptr, vect.size()))
return false;
}
return true;
}
2) When your XAxisSymCheck fails, you are not setting IsSymmetric to false (at least in the original post before the edit)
for(int k=0;k<testcase;++k) {
vector<int> rows;
bool IsSymmetric = true;
// ....
if (XAsxisSymCheck(rows)) {
// ...
} else {
IsSymmetric = false;
}
cout << (IsSymmetric ? "Yes" : "No") << endl;
}
3) Your reverse check fails, if a line has leading zeros, because the reverse is not multiplicated by 10 often enough.
bool rev(int n,int len) {
int n1,d,rn=0;
n1=n;
for (int i = 0; i < len; i++)
{
d=n%10;
rn=(rn*10)+d;
n/=10;
}
return n1==rn;
}

min difference between two unsorted arrays

I have to find min absolute difference between two elements of unsorted arrays.
My approach is to first sort both the array, run a loop over one array and find lower bound of each element of this array in another array.
And then check whether it is minimum or not and store it for further comparisons
Test Case:
2
8 1 3 5 7 9 7 3 1
8 2 4 6 8 10 8 6 2
8 2 3 5 10 9 3 2 1
7 1 2 6 12 13 3 2
Output :
1
0
result : passed
Explanation:
1) min will be abs(a[7]-b[7])
2) min will be abs(a[0]-b[(1)])
But when i am submitting to spoj I am getting wrong answer ,it look like I am missing some thing else .
problem https://www.spoj.com/problems/ACPC11B/
Please help where I am doing wrong?
My code:
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
vector <int> a;
vector <int> b;
int main(){
int t;
cin>>t;
while(t--){
int na;
cin>>na;
for(int i=0;i<na;i++){
int temp;
cin>>temp;
a.push_back(temp);
}
int nb;
cin>>nb;
for(int i=0;i<nb;i++){
int temp;
cin>>temp;
b.push_back(temp);
}
sort(a.begin(),a.end());
sort(b.begin(),b.end());
int ans=a[0]-b[0];
for(int i=0;i<a.size();i++){
int bval = lower_bound(b.begin(),b.end(),a[i])-b.begin();
ans = min(ans,abs(a[i]-b[bval]));
if(bval>0)
ans = min(ans,abs(a[i]-b[bval-1]));
}
cout<<ans<<endl;
a.clear();
b.clear();
}
}
Your version has several issues:
a[0]-b[0] which might be negative, invalidating remaining computation.
lower_bound which might result in b.end() leading to out of bound access.
You can do something like the following:
std::size_t min_distance(std::vector<int> v1, std::vector<int> v2)
{
std::sort(v1.begin(), v1.end());
std::sort(v2.begin(), v2.end());
auto it1 = v1.begin();
auto it2 = v2.begin();
auto min = std::abs(*it1 - *it2);
while (min != 0 && it1 != v1.end() && it2 != v2.end()) {
min = std::min(min, std::abs(*it1 - *it2));
if (*it1 < *it2) {
++it1;
} else /*if (*it2 <= *it1)*/ {
++it2;
}
}
return min;
}
Demo

Program Aborts when using vector iterators

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.

How Iterator works in C++

I am learning container in C++ and trying to insert and print element of list with the help of iterator. I am getting a different output then my expectations.
#include<iostream>
#include<list>
#include<vector>
#include<deque>
#include<string>
using namespace std;
int main()
{
list<int> ilist(10);
cout<<ilist.size()<<endl;
list<int>::iterator litr = ilist.begin();
int i =0;
for(litr = ilist.begin();litr != ilist.end();litr++,i++)
{
cout<<"i:"<<i<<" ";
//ilist.push_back(i);
*litr=i;
litr++;
}
litr = ilist.begin();
cout<<endl;
cout<<ilist.size();
while(litr != ilist.end())
{
i=*litr;
cout<<i<<endl;
litr++;
}
return 0;
}
output :
10
i:0 i:1 i:2 i:3 i:4
100
0
1
0
2
0
3
0
4
0
why size changed after Inserting element and why elements are not properly inserted ?
Thanks in advance.
In the first loop, you are incrementing the iterator twice per iteration (once in the for statement and once more at the bottom of the loop).
This causes the iterator to skip every other element.
The size of the list remains unchanged: the 100 is 10 immediately followed by 0. The 10 is the size of the list and the 0 is the first element of the list. Print a space or a newline after printing out the size and you'll see for yourself.
Size did not change. Before second loop you display size of the list and then it's contents without any separator. Since the first element in the list is equal to 0 it looks as if the list grew to the length of 100.
Also, like NPE has mentioned, in the first loop you increment the iterator twice.
In this loop
for(litr = ilist.begin();litr != ilist.end();litr++,i++)
{
cout<<"i:"<<i<<" ";
//ilist.push_back(i);
*litr=i;
litr++;
}
you are increasing iterator litr twice: in the control statement and within the body of the loop.
It could be written simpler
list<int>::iterator litr;
int i = 0;
for ( litr = ilist.begin(); litr != ilist.end(); litr++, i++ )
{
cout<<"i:"<<i<<" ";
*litr = i;
}
Or
list<int>::iterator litr;
int i = 0;
for ( litr = ilist.begin(); litr != ilist.end(); litr++ )
{
cout<<"i:"<<i<<" ";
*litr = i++;
}
As for the output then that it would be more clear you need to insert std::endl after printing the size the second time. For example
cout<<ilist.size() << endl;
// ^^^^^^^
while(litr != ilist.end())
{
i=*litr;
cout<<i<<endl;
litr++;
}
Then the output will look like
10
i:0 i:1 i:2 i:3 i:4
10
0 0 1 0 2 0 3 0 4 0
Take into account that there are several standard algorithms declared in header <algorithm> that can do the same task. For example you could use algorithm std::generate.
#include <algorithm>
//...
int i = 0;
std::generate( ilist.begin(), ilist.end(), [&] { return i++; } );