I was doing a uva problem uva 10935 throwing cards away, and my code is as follows. when i ran it, it said An unhandled exception was raised: read access conflict, and it also shows "cannot seek vector iterator before begin", i don't know where is the problem in my code:
#include<vector>
#include<iostream>
using namespace std;
int n;
vector<int> out;
int main() {
freopen("data.txt", "r", stdin);
while (scanf("%d", &n) == 1 && n) {
vector<int> cards;
for (int i = 1; i <= n; i++)cards.push_back(i);
vector<int>::iterator it = cards.begin();
vector<int>::iterator end = cards.end();
while (it != (end-1)) {
out.push_back(*it);
it++;
cards.push_back(*it);
it++;
end++;
}
cout << "Discarded cards: ";
for (int j = 0; j < out.size(); j++) {
if(j!=(out.size()-1))cout << out[j] << ", ";
else cout << out[j] << endl;
}
cout << "Remaining card: " << *it << endl;
}
return 0;
}
The problem here remains in the while() loop, where you are pushing new element in the vector while holding it's old "end" address as terminal reference.
When a vector pushes a new element, it may need to reallocate it's whole array to a new location. In that case, the "end" reference that you are holding will become obsolete as you are increasing it linearly, but the whole vector after that push may have shifted somewhere else.
I added some debug lines in your code, so you can see how this happens. Just run the code with an input value of 4. And you will see the "end" value probably will not relate with the vector's reallocated address anymore (if reallocation happens, it basically depends on the system to decide).
#include<vector>
#include<iostream>
using namespace std;
int n;
vector<int> out;
void printVectorElementAddresses(vector<int> &v){
cout<<"==== Vector Element Addresses ====\n";
for(auto itr = v.begin(); itr != v.end(); itr++)
{
cout<<&(*itr);
if(itr == v.end()-1){
cout<<endl;
}
else{
cout<<" ";
}
}
cout<<endl;
}
void printIteratorAddressWithTag(char* tag, vector<int> :: iterator & it, bool printNewLine){
cout<<tag<<&*it<<"; ";
if(printNewLine){
cout<<endl;
}
}
int main() {
// freopen("data.txt", "r", stdin);
while (scanf("%d", &n) == 1 && n) {
vector<int> cards;
for (int i = 1; i <= n; i++)cards.push_back(i);
vector<int>::iterator it = cards.begin();
vector<int>::iterator end = cards.end();
//print vector addresses after initial pushes are done
printVectorElementAddresses(cards);
while (it != (end-1)) {
printIteratorAddressWithTag("it initial = ", it, false);
out.push_back(*it);
it++;
printIteratorAddressWithTag("it after first increment = ", it, false);
cards.push_back(*it);
it++;
printIteratorAddressWithTag("it after second increment = ", it, true);
printIteratorAddressWithTag("end initially in loop = ", end, false);
end++;
printIteratorAddressWithTag("end after increment = ", end, true);
cout<<"Vector Addresses after a new push"<<endl;
printVectorElementAddresses(cards);
}
cout << "Discarded cards: ";
for (int j = 0; j < out.size(); j++) {
if(j!=(out.size()-1))cout << out[j] << ", ";
else cout << out[j] << endl;
}
cout << "Remaining card: " << *it << endl;
}
return 0;
}
Just change the logic in your while loop to keep track of the old "end" reference after the push happens. And if the other logic are fine, it should work.
I think there is a problem with end++, and others iterators.
If the vector cards grows, its memory location may be changed, and end++ will be pointing to an invalide position. Similar happens with it++.
I propose you to use lists instead:
#include<bits/stdc++.h>
using namespace std;
int n;
int main() {
//freopen("a.in", "r", stdin);
while (scanf("%d", &n) == 1 && n) {
list<int> out;
list<int> cards;
for (int i = 1; i <= n; i++)
cards.push_back(i);
list<int>::iterator it = cards.begin();
list<int>::iterator end = cards.end();
end--;
while (it != (end)) {
out.push_back(*it);
it++;
cards.push_back(*it);
it++;
end++;
}
cout << "Discarded cards: ";
list<int>::iterator it2 = out.begin();
for (int j = 0; j < out.size(); j++, it2++) {
if(j !=(out.size()-1))
cout << *it2 << ", ";
else
cout << *it2 << endl;
}
cout << "Remaining card: " << *it << endl;
}
return 0;
}
NOTE: I haven't read the UVA problem.
Related
This is my code:
#include <iostream>
#include <list>
using namespace std;
template <class T>
void display(list<T> l){
list<int>::iterator i;
for (i = l.begin(); i != l.end(); i++)
{
cout << *i << " ";
}
}
void enter(list<int> l){
list<int>::iterator i;
int index = 1;
for (i = l.begin(); i != l.end(); i++, index++)
{
// cout << "check" << endl;
cout << "Enter element at index " << index << endl;
cin >> *i;
}
}
int main(){
list<int> l;
display(l);
cout << endl;
l.push_front(1);
l.push_front(2);
l.push_front(3);
l.push_front(4);
l.push_front(5);
list<int> l2(3);
enter(l2);
display(l2);
cout << "EXE";
return 0;
}
The output of the following program is:
Enter element at index 1
1
Enter element at index 2
2
Enter element at index 3
3
0 0 0 EXE
Required Output:
Enter element at index 1
1
Enter element at index 2
2
Enter element at index 3
3
1 2 3 EXE
The issue is that you pass the list by value in enter. When you update the list with cin >> *i, you are updating a copy of l2 instead of the l2 declared in main().
If you would like to update the list you will need to pass by reference instead.
void enter(list<int>& l){
list<int>::iterator i;
int index = 1;
for (i = l.begin(); i != l.end(); i++, index++)
{
// cout << "check" << endl;
cout << "Enter element at index " << index << endl;
cin >> *i;
}
}
I have a problem with this piece of code, I'm trying to print the EVEN and ODD numbers, but there is a problem when it comes to show them, the vectors don't save the numbers as I'm expecting.
#include <iostream>
using namespace std;
int main() {
int n;
cin >> n;
int vect[n], even[n], odd[n]; // CREATING VECTORS LIMIT AFTER "n"
for(int i = 1; i <= n; ++i) { // ENTERING The ELEMENS IN VECTOR
cin >> vect[i];
}
for(int i = 1; i <= n; ++i) {
if(vect[i] % 2 != 0) {
odd[i] = vect[i]; // I think that here's the problem, the vectors don't save the right numbers.
} /// VERIFYING IF THE NUMBER IS ODD OR EVEN.
else if (vect[i] % 2 == 0) {
even[i] == vect[i];
}
}
for(int i = 1; i <= n; ++i) {
cout << even[i] << " " << endl; /// PRINTING THE ODD AND EVEN numbers.
cout << odd[i] << " " << endl;
}
return 0;x
}
I have fixed the problem, thanks all for help.
Now it works perfectly.
#include <iostream>
using namespace std;
int main() {
int n;
cin >> n;
int vect[n], even[n], odd[n], z = 0, x = 0; // CREATING VECTORS LIMIT AFTER "n"
for(int i = 1; i <= n; ++i) { // ENTERING The ELEMENS IN VECTOR
cin >> vect[i];
}
for(int i = 1; i <= n; ++i) {
if(vect[i] % 2 != 0) {
odd[1+z] = vect[i];
z++;
// I think that here's the problem, the vectors don't save the right numbers.
} /// VERIFYING IF THE NUMBER IS ODD OR EVEN.
else if (vect[i] % 2 == 0) {
even[1+x] = vect[i];
x++;
}
}
for(int i = 1; i <= x; i++) {
cout << even[i] << " ";
}
cout << endl;
for(int i = 1; i <= z; i++) {
cout << odd[i] << " ";
}
return 0;
}
Considering the hints of the comments, your program shall be changed into this:
#include <iostream>
#include <vector>
using namespace std;
int main() {
int n, number;
cin >> n;
vector<int> vect, even, odd; // CREATING DYNAMIC VECTORS
for(int i = 0; i < n; ++i) { // ENTERING THE ELEMENTS IN VECTOR
cin >> number;
vect.push_back(number);
}
for(int i = 0; i < n; ++i) {
if(vect[i] % 2 != 0) { /// VERIFYING IF THE NUMBER IS ODD OR EVEN.
odd.push_back(vect[i]);
}
else {
even.push_back(vect[i]);
}
}
for (int i = 0; i < n; ++i)
cout << vect[i] << " ";
cout << endl;
/// PRINTING THE ODD AND EVEN NUMBERS.
for (auto& val : odd)
cout << val << " ";
cout << endl;
for (auto& val : even)
cout << val << " ";
cout << endl;
return 0;
}
It uses the vector container of STL for your arrays, start the indexing at 0 and prints out the resulting arrays separately, as the number of odd and of even entries might be different.
Hope it helps?
With standard, you might use std::partition (or stable version) to solve your problem:
void print_even_odd(std::vector<int> v)
{
auto limit = std::stable_partition(v.begin(), v.end(), [](int n){ return n % 2 == 0; });
std::cout << "Evens:";
// Pre-C++20 span:
// for (auto it = v.begin(); it != limit; ++it) { int n = *it;
for (int n : std::span(v.begin(), limit)) {
std::cout << " " << n;
}
std::cout << std::endl;
std::cout << "Odds:";
for (int n : std::span(limit, v.end())) {
std::cout << " " << n;
}
std::cout << std::endl;
}
Demo
Hello everybody can you help me?
the problem is that when a person enters a element from list he can insert before this element elements from another list, but I constantly knock out mistakes. Maybe someone will help?
It looks like:
3 6 7 9
user enters 6
he can create another list like 8 7 5
and output is 3 8 7 5 6 7 9
The error
#include <iostream>
#include <list>
#include <algorithm>
#include <iterator>
int main()
{
int size
int size1;
int el1;
int znach=0;
cout << "Enter size: " << endl;
cin >> size;
list<int>lis;
list<int>lis1;
list <int> ::iterator it;
int s = lis.size() / 2;
auto it1 = lis.begin();
advance(it1, s);
for (int i = 0; i <size; i++)
{
cout << "Enter " << i << " element: ";
cin >> t;
lis.push_back(t);
}
cout << "Enter element: " << endl;
cin >> el1;
for (it = lis.begin(); it != lis.end(); it++)
{
if (*it = el1)
{
znach++;
}
}
if (znach == 0)
{
cout << "There is no element;" << endl;
}
else
{
cout << "Enter size of new vector: " << endl;
cin >> size1;
for (int i = 0; i < size1; i++)
{
int t1;
cout << "Enter " << i << " element: ";
cin >> t1;
lis1.push_back(t1);
}
auto it2 = lis.begin();
while (*it2 != el1)
{
it2++;
}
--it2;
lis.splice(it2, lis1);
}
for (it = lis.begin(); it != lis.end(); it++)
{
cout << *it<<" ";
}
}
I don't know what your code is doing, and maybe there are other problems. However, the runtime error you get is caused by
auto it2 = lis.begin();
while (*it2 != el1)
{
it2++;
}
--it2;
When *lis.begin() == el1 then you never increment it2 and then decrement it, but you cannot decrement the begin iterator. Usually thats just undefined, but as you compiled a debug build you got an assertion fired up that tells you what went wrong.
I'm writing a program that should look through a graph and calculate the minimum number of edges that need to be deleted to leave a forest where each connected group has an even number of vertices. I know how to solve the problem, but when I try and iterate through a list I get a segmentation fault and can't figure out why.
#include <cmath>
#include <cstdio>
#include <list>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
int main() {
/* Enter your code here. Read input from STDIN. Print output to STDOUT */
int N;
cin >> N;
int M;
cin >> M;
// matrix of adjacency list to hold node values
vector<list<int> > adjList(N, list<int>());
// find the number of children nodes each node has
int ui, vi;
for (int i = 0; i < M; i++) {
cin >> ui;
cin >> vi;
ui--;
vi--;
//cout << ui << " " << vi << endl;
adjList[ui].push_back(vi);
adjList[vi].push_back(ui);
//cout << "list length: " << adjList[ui].size() << endl;
}
//cout << "after for loop" << endl;
// count the number of nodes with even numbers of children
for (int i = 0; i <= M; i++) {
cout << i << "-> ";
for (list<int>::iterator it = adjList[i].begin(); it != adjList[i].end(); it++) {
cout << *it << " ";
}
cout << endl;
}
int edgesRemoved = 0;
for (int i = 0; i <= M; i++) {
for (list<int>::iterator it = adjList[i].begin(); it != adjList[i].end(); ++it) {
int j = *it;
if (adjList[j].size() % 2 == 1) {
// delete vertex from current list
cout << "test" << endl;
adjList[i].erase(it);
// delete vertex on the other list
cout << "test" << endl;
cout << j << endl;
cout << *adjList[j].begin() << endl;
for (list<int>::iterator it2 = adjList[j].begin(); it2 != adjList[j].end(); ++it2) {
cout << *it2 << " ";
if (i == *it2) {
adjList[j].erase(it2);
}
}
edgesRemoved++;
}
}
}
cout << edgesRemoved << endl;
return 0;
}
After using cout statements to debug the program I figured out that the problem is here:
for (int i = 0; i <= M; i++) {
for (list<int>::iterator it = adjList[i].begin(); it != adjList[i].end(); ++it) {
int j = *it;
if (adjList[j].size() % 2 == 1) {
// delete vertex from current list
cout << "test" << endl;
adjList[i].erase(it);
// RIGHT UNDER HERE
// vvvvvvvvvv
for (list<int>::iterator it2 = adjList[j].begin(); it2 != adjList[j].end(); ++it2) {
cout << *it2 << " ";
if (i == *it2) {
adjList[j].erase(it2);
}
}
edgesRemoved++;
}
}
}
I get a segmentation fault after the program creates an iterator that is meant to go through another list in the vector. I don't understand why though, the syntax is the same as the first for loop with another iterator going through the first list.
Here is an example of what happens after I type in the input of the digits that represent a tree, the program then prints the adjacency matrix and goes on to the actual calculation (this part works fine, it's the end result during calculation):
10 9
2 1
3 1
4 3
5 2
6 1
7 2
8 6
9 8
10 8
0-> 1 2 5
1-> 0 4 6
2-> 0 3
3-> 2
4-> 1
5-> 0 7
6-> 1
7-> 5 8 9
8-> 7
9-> 7
test
test
1
0
Segmentation fault
Erasing the item under the iterator invalidates the iterator; using it further results in undefined behavior, so anything could happen. The usual idiom for this sort of thing is:
std::list<int>::iterator it = adjList[i].begin();
while ( it != adjList[i].end() ) {
if ( *it == i ) {
it = adjList[j].erase( it );
} else {
++ it;
}
}
The erase function returns an iterator to the element immediately following the one which was removed.
This is valid for all sequence types, not just std::list.
You must not delete the current item in a list (the thing the iterator is pointing to) while you are iterating over it. You could do something like this:
adjList[j].erase(it2++);
However, afaik, it is considered best practice to neither shrink nor expand a list while iterating.
I'm in desperate need of assistance.
I'm working on a population program in C++ for my Systems Software class.
This is my first foray into C++ territory, I only have some Java knowledge to help me out.
Basically, the program is supposed simulate a simple population. The guidelines are as follows:
The first elements (starting population) have random age and sex.
2 elements can pair if their lifespan falls between [0.25,0.50] (assuming they die at 1) and they are of the opposite sex.
Each element can only pair twice.
So here's my code, and take it easy guys I'm not very well versed in C++ yet...:
#include <vector>
#include <ctime>
#include <stdlib.h>
#include <iostream>
#include <iterator>
using namespace std;
class Element {
public:
int pair;
double life;
int tag;
void setValues(double, int);
int getPair() {
return pair;
}
void incrementPair() {
pair = pair++;
}
double getLife() {
return life;
}
void incrementLife() {
life = life + 0.05;
}
int getTag() {
return tag;
}
}; //Element
void Element::setValues(double b, int c) {
pair = 0;
life = b;
tag = c;
}
int main() {
double Time = 0.0;
srand(time(NULL));
vector<Element> vec;
for (int i = 0; i<50; ++i) {
Element x;
x.setValues(((double) rand() / (RAND_MAX)), rand()%2);
vec.push_back(x);
}//for
while (vec.size() != 0) {
int newPopCount = 0;
int Dead = 0;
for(int count = 0; count != vec.size(); ) {
std::vector<Element>::iterator p = vec.begin();
std::vector<Element>::iterator i = vec.begin() + 1;
if ((p->getPair() == 2) || (p->getLife() < 0.25) || (p->getLife() > 0.50)) {
count++;
p++;
}//if
else {
for(int count1 = count + 1 ; count1 != vec.size() ; ) {
if ((i->getLife() < 0.25) || (i->getLife() > 0.50) || (i->getPair() == 2) || (p->getTag() == i->getTag())) {
++i;
count1++;
}//if
else {
cout << i->getTag() << " " << p->getTag() << endl;
cout << i->getPair() << " " << p->getPair() << endl;
cout << i->getLife() << " " << p->getLife() << endl;
p->incrementPair();
i->incrementPair();
newPopCount++;
count1++;
count++;
p++;
i++;
}//else
}//for
}//else
}//for
Time += 0.05;
for ( vector<Element>::iterator m = vec.begin(); m != vec.end(); ++m ) {
m->incrementLife();
if ( m->getLife() >= 1.00 ) {
Dead++;
//vec.clear();
vec.erase(m);
//vec.shrink_to_fit();
}//if
for (int i = 0; i = newPopCount; i++) {
Element woo;
woo.setValues(0.0, rand()%2);
vec.push_back(woo);
}//for
}//for
cout << "The total number of dead is: " << Dead << endl;
cout << "The total number born is: " << newPopCount << endl;
cout << "Current population is: " << vec.size() << endl;
cout << "Population has survived for: " << Time << endl;
sleep(1);
}//while
cout<< "The populace is now extinct." << endl;
cout<< "The populace survived for: " << Time << endl;
}//main
You can see my silly debugging methods, I was getting a Segmentation Fault error before, but I believe that to be fixed. The issue now is that I'm getting stuck in the loops. The program seems to run almost erratically, and I can't pinpoint the issue any closer than inside of one of the loops.
My Dead integer is incremented and displayed properly, but the newPopCount integer is not, which makes no sense to me.
Also the program never gets out of the while loop, it will continue until it gets stuck in another of the many loops I have.
I have had several other issues, which I've been fixing slowly but surely as you can see by my patchwork code.
Any help at all will be greatly appreciated.
Two obvious issues, which your compiler will warn you about if you turn up your warnings high enough.
First:
void incrementPair() {
pair = pair++;
}
This is undefined behavior. Should be just:
void incrementPair() {
++pair;
}
Second:
for (int i = 0; i = newPopCount; i++) {
Element woo;
woo.setValues(0.0, rand()%2);
vec.push_back(woo);
}
That condition in your for loop is almost certainly wrong. It likely should be i <= newPopcount, or something like that.
As a side note, your setValues() member function looks like it's doing the job that a constructor should be doing.
EDIT: Look here:
for(int count = 0; count != vec.size(); ) {
std::vector<Element>::iterator p = vec.begin();
std::vector<Element>::iterator i = vec.begin() + 1;
Imagine you have a std::vector with only one element in it, and then think about what i is going to represent when you do i->getLife() a few lines later. Just having those definitions inside the for loop looks a bit suspicious in itself, since you increment both p and i during the loop, but you're going to reset them again on every iteration, but it's not all that easy to follow the logic, so perhaps that's what you intended.
vec.erase(m); results in an invalid m. You want to do m = vec.erase(m)