Jump to content
  • Advertisement
Sign in to follow this  
Noobis

Why is this crashing?

This topic is 4133 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

#include <iostream> #include <string> #include <vector> using namespace std; int main(){ string word; vector<string> text; while (cin >> word){ if(word == "break"){ cout << "breaking loop" << endl; break;} else {text.push_back(word);} } for(vector<string>::size_type ix = 0; ix <= text.size(); ++ix){ cout << text[ix] << endl;} char a; cin >> a; return 0; } Ok thats the full code. Im doing some practice and experiments with vectors because I have come farther in my book. It crashes after the for loop. To me it doesn't make sense why it would crash... I use the Bloodshed dev-c++ compiler.

Share this post


Link to post
Share on other sites
Advertisement
Quote:
Original post by Noobis
#include <iostream>
#include <string>
#include <vector>

using namespace std;

int main(){
string word;
vector<string> text;
while (cin >> word){
if(word == "break"){ cout << "breaking loop" << endl; break;}
else {text.push_back(word);}
}

for(vector<string>::size_type ix = 0; ix <= text.size(); ++ix){
cout << text[ix] << endl;}

char a;
cin >> a;
return 0;
}






Ok thats the full code. Im doing some practice and experiments with vectors because I have come farther in my book. It crashes after the for loop.

To me it doesn't make sense why it would crash...

I use the Bloodshed dev-c++ compiler.


shouldn't it be:
for(vector<string>::size_type ix = 0; ix < text.size(); ++ix){
cout << text[ix] << endl;}

with say 5 strings in the vector the last string would be stored in text[4] thus you want < text.size() instead of <= text.size()

unless im missing something... (its late (or early) so i probably shouldn't be posting

Share this post


Link to post
Share on other sites
No I start at 0 so it should only go to 4 even if it has 5 strings right?

If it only went to < size then it wouldn't get the last string right?

I did it with a string and it only goes to the last character so why doesn't it work with a vector?

It might just be my computer but I don't know I get a "Just-in-Time debugger" error if I run it. Or if I run it through the debugger stopping just after char a; I get a Access violation (segmentation fault) raised.

Edit: well it worked.. I just don't understand why... does it have something to do with break maybe?

Share this post


Link to post
Share on other sites
Quote:
Original post by Noobis
No I start at 0 so it should only go to 4 even if it has 5 strings right?

If it only went to < size then it wouldn't get the last string right?

I did it with a string and it only goes to the last character so why doesn't it work with a vector?

It might just be my computer but I don't know I get a "Just-in-Time debugger" error if I run it. Or if I run it through the debugger stopping just after char a; I get a Access violation (segmentation fault) raised.

Edit: well it worked.. I just don't understand why... does it have something to do with break maybe?


your loop ran like this:


ix=0;
start:
if (ix<=5) goto end;
cout <<text[ix]<<endl;
++i;
goto start;
end:


thus it will run cout << text[5] at the end.

strings contain one character more than their length (the last character in a C string is always 0)

Share this post


Link to post
Share on other sites
Quote:
Original post by Noobis
No I start at 0 so it should only go to 4 even if it has 5 strings right?

If it only went to < size then it wouldn't get the last string right?


if 'text' contains 5 strings text.size() will be 5, and 0-4 are valid indecies.

with a for loop like: "ix = 0; ix <= text.size(); ++ix" then ix will count 0-5 (thats 6 numbers).

with a for loop like: "ix = 0; ix < text.size(); ++ix" then ix will count 0-4 correctly.

Share this post


Link to post
Share on other sites
Well its a vector not a string? Do vectors contain an extra space?

I know that a string would be "S,T,R,I,N,G,/0" but don't vector only go, "Object, Object, Object" with no null positions?

Because I can use:

for(string::size_type ix=0; ix <= s.size(); ix++){
cout << s[ix] << endl;}

but not the same loop for vectors without a crash? Thats why I am not sure what is going on. In the book it says nothing about vectors containing a null position and I never even heard of a vector having a null position.

OHHHH holy crap.. I get why it should only be < size

There isn't a null position.

x=0
size =5

it will loop 0,1,2,3,4,5

while x <= 5

Vector size is 5 but lists only to 4... ok. Thank you for the help now I understand. 0,1,2,3,4 = 5 total positions

Edit: Yah, it didn't click at first I had to write it out, Thank you guys.

Share this post


Link to post
Share on other sites
you could use an iterator to traverse a vector. This built and ran fine.

#include <iostream>
#include <string>
#include <vector>

using namespace std;

int main(){
string word;
vector<string> text;
while (cin >> word){
if(word == "break"){ cout << "breaking loop" << endl; break;}
else {text.push_back(word);}
}

for(vector<string>::iterator ix = text.begin(); ix != text.end(); ++ix){
cout << (*ix) << endl;
}

char a;
cin >> a;
return 0;
}

Share this post


Link to post
Share on other sites
I just got to that part in my book.

Introducing Iterators

lol.

I will have to take a look at that code after i read this. Thanks


This is off topic but: Anyone know where I can get source to a fully built tetris clone using c++ and opengl?

Share this post


Link to post
Share on other sites
ALWAYS use != when comparing with the end() iterator in a for loop!
Do not use < or <= (lesson learn't I'm sure)
Even better, use std::for_each[grin]

Also, use a const_iterator if you don't modify the elements.[cool]

Share this post


Link to post
Share on other sites
A few assorted notes.

Writing for loops "manually" is kind of unintuitive in C and C++. This is one of the reasons these languages aren't really suited for beginners. These loops are low level constructs, thin wrappers around what you'd have to do with while-loops to get the same effect. The construct is much more powerful than is normally "useful" (because you could do anything instead of just incrementing, and you don't have to use the same variable in each "clause", and you could work with more than one counter variable, and...), and because of that, it becomes easy to make mistakes.

To get around that, we can use standard library algorithms, such as the std::for_each that iMalc mentioned. Unfortunately, the C++ language design makes this a little tricky to use, because you have to wrap up the loop body into some kind of function (or function object) - but the idea is that the algorithm accepts the range of elements and "something to do to" an element, and does the something-to-do to each element in the range. This also makes sure that the .end() (or .size(), for the version of a loop using indices) function is evaluated only once for the loop.

It would look something like:


#include <algorithm>

void output(const std::string& s) {
cout << s << endl;
}

// ...
std::for_each(text.begin(), text.end(), output);


But in our particular situation, we can use a more specific tool ;)


#include <algorithm>
#include <iterator>

// ...
std::copy(text.begin(), text.end(), std::ostream_iterator<std::string>(cout, "\n");


The std::ostream_iterator is a tool that lets use treat an output stream as if it were a container: it is an object that behaves like an iterator, but writes "elements" to an ostream. (Because the ostream is a stream and not a container, the ostream_iterator is a very restricted form of iterator: it can only be advanced forwards, and has no random access.) The std::copy algorithm copies stuff from one range to another (the destination range is implied: you specify just the beginning point, and the endpoint is assumed to be whereever it needs to be in order to hold everything from the source range).

These tools are very powerful. We avoid having to mess around with loop counters, and we also don't have to worry about figuring out the types of a bunch of temporary variables. (You'll notice there are no variable declarations in the above use of std::copy; that means I don't have to worry about what type 'text.begin()' returns, for example.)

Also as iMalc said, you should use != rather than < for testing iterators. The reason is that while it works for a vector's iterators (and for pointers, which are "iterators" for an array), it doesn't necessarily work for all kinds of iterators - the concept of an "iterator" doesn't require that they are "ordered" (i.e. that you can consistently say that one is less than another, and that this property is transitive), only that they are "comparable" (i.e. that you can consistenly say whether two iterators are equal, i.e. referring to the same element). Requesting a const_iterator is useful too, so that if you don't intend to change elements, you can tell the compiler "I don't intend to change elements", and then it will warn you if the code might actually do so (const correctness). Note that a "const iterator" is an iterator which cannot change (i.e. be set to refer to a different element), which is different from a "const_iterator", which is an iterator to a const element (i.e. you promise not to change the element accessed via that iterator).

Of course, the original code doesn't use the container's iterators at all, but just plain old indices. This is restrictive in a similar fashion. For example, if we later wanted to change the container to be a std::list, the code would break, because there is no operator[] for a std::list - it's not a random access container, so treating it that way doesn't make sense. With iterators, however (as in MrRage's code), it would work. (And with std::copy or std::for_each it will certainly work, because those will be implemented in terms of iterators behind the scenes.)

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!