[C++] KWIC program

Will

Senior Administrator
Staff member
Joined
Mar 4, 2012
Posts
8,196
Location
%tmp%
Hi all,

I've been programming in C++ for a couple of days now. I'm having problems with a Keyword in Context program. The program is meant to display user input:

"The quick brown fox"

and display the following output:

" __________________The quick brown fox
____________The___quick brown fox
_______The quick___brown fox
The quick brown____fox"

Currently getting two error messages I can't wrap my head around. I'll display the code first, and the error messages after.

Main.cpp:
C++:
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <iterator>
#include <cctype>
#include <iostream>
#include "index.h"

using namespace std;

// Structure - Rot_String objects.



// Find the max width from a vector of strings.
string::size_type width(const vector<string>& v)
{
    string::size_type maxlen = 0;
    for(vector<string>::size_type i = 0; i != v.size(); ++i)
        maxlen = max(maxlen, v[i].size());

    return maxlen;
}

int main()
{
    //User input
    cout << "Please enter a short sentence." << endl;
    string s;
    getline(cin, s);


    // Rotate function called. Return stored in rotated.
    vector<Rot_String> rotated = rotate(s);

    vector<string> left;
    vector<string> right;
    vector<string> print; //Final string to be printed.

    string::size_type len = rotated.size(); //Find length of rotated.


    // Form Left and Right vectors.
    // We have processed i lines.
    for (string::size_type i = 0; i != len; ++i)
    {
        string::size_type split = rotated[i].split;
        string rot = rotated[i].str;
        string::size_type end = rot.size();

        right.push_back(rot.substr(0, split));
        left.push_back(rot.substr(split, end));
    }

    // Find max characters in Left
    string::size_type maxlen = width(left);

    // Create final vector.
    for (vector<string>::size_type i = 0; i != left.size(); ++ i)
    {
        print.push_back(string(maxlen - left[i].size(), ' ') + "\t" + right[i]);
    }

    // Print final vector
    ostream_iterator<string>ofile(cout, "\n");
	copy(print.begin(), print.end(), ofile);
	cout << endl;

    return 0;
}

This code compiled fine - not sure if there are any more errors in it.

Index.h:

C++:
#ifndef GUARD_pics_h
#define GUARD_pics_h

#include <string>
#include <vector>

using std::string;
using std::vector;

struct Rot_String {

    string str; // Stores rotated sentence.
    string::size_type split; // Stores split character point.

    };

bool compare(const Rot_String& x, const Rot_String& y);

std::vector<string> seperate(const string& s);
std::vector<Rot_String> rotate(const string& s);

#endif

Also seems to be fine. Currently having trouble with index.cpp below.

Index.cpp:

C++:
#include <algorithm>
#include <iterator>
#include <string>
#include <vector>
#include <cctype>
#include <iostream>
#include "index.h"

using namespace std;

// File contains functions for the index.


bool compare(const Rot_String& x, const Rot_String& y)
{
    return x.str < y.str;
}

// seperate function. Splits string into seperated words stored in a vector.

vector<string> seperate(const string& s)
{
    vector<string> ret;
    typedef string::size_type string_size;
    string_size i = 0;

    // invariant: we have processed characters [original value of i, i)
    while (i != s.size()){
        // ignore leading blanks
        // invariant: characters in range [original i, current i) are all spaces
        while (i != s.size() && isspace(s[i]))
            ++i;

        //find end of next word
        string_size j = i;
        // invariant: none of the characters in range [original j, current j) is a space
        while (j != s.size() && !isspace(s[j]))
            ++j;

        // if we found some nonwhitespace characters
        if (i != j){
            // copy from s starting at i and taking j-i chars
            ret.push_back(s.substr(i, j - i));
            i = j;
        }
    }
    return ret;
}

// Rotate function. Returns a vector of Rot_String types.

vector<Rot_String> rotate(const string& s)
{
    vector<Rot_String> ret;
    vector<string> split = seperate(s);

    // we have rotated i lines so far
    for (int i = 0; i != split.size(); ++i)
    {
        // Create a Rot_String object
        Rot_String rote;

        // String is split into a vector
        vector<string> temp;
        vector<string> splitcopy = split;

        // Words 0 - i are removed and stored in a temp vector
        copy(splitcopy[0], splitcopy[i], temp[0]);
        splitcopy.erase(0, i);

        // Remaining words reformed into string.
        string::size_type len = splitcopy.size();
        for (int x = 0; x != len; ++x)
            {
            rote.str += splitcopy[x] + " ";
            }
        rote.split = rote.str.size(); // Split character is counted and added to object.

        // Removed words are added to end of string.
        len = temp.size();
        for (int y = 0; y != len; ++y){
            rote.str += temp[y] + " ";
            }

        // Rot_String object is added to vector ret.
        ret.push_back(rote);

    }

    //sort ret alphabetically
    sort(ret.begin(), ret.end(), compare);

    return ret; //return sorted vector.

}

The first error message I'm getting is on this line in index.cpp:

splitcopy.erase(0, i);

The error message is below.

Code:
C:\Users\Will\Documents\Documents - Main\TSF\C++\Permuted Index\index.cpp|69|error: no matching function for call to 'std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::erase(int, int&)'|

Is this just because I'm using an index position and 0 rather than iterators? Does this function only take iterators? I can't quite work this error message out, but I can start to guess where the problem is. It says no matching function - so either I've left out the reference somewhere and it doesn't know what erase means, or I'm using the function incorrectly and it will only accept iterators as the range.

This next error message, threw me a bit more... I commented out the above code, fixed a couple of forgotten ";" errors and tried to compile again. There are no remaining error messages in the files themselves, instead I get directed to some new files that are part of the C++ implimentation: stl_iterator_base_types.h and stl_algobase.h

The error message is:

Code:
C:\Users\Will\Documents\Documents - Main\TSF\C++\Permuted Index\index.cpp||In function 'std::vector<Rot_String, std::allocator<Rot_String> > rotate(const std::string&)':|
C:\Users\Will\Documents\Documents - Main\TSF\C++\Permuted Index\index.cpp|58|warning: comparison between signed and unsigned integer expressions|
C:\Users\Will\Documents\Documents - Main\TSF\C++\Permuted Index\index.cpp|73|warning: comparison between signed and unsigned integer expressions|
C:\Users\Will\Documents\Documents - Main\TSF\C++\Permuted Index\index.cpp|81|warning: comparison between signed and unsigned integer expressions|
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.4.1\include\c++\bits\stl_algobase.h|388|instantiated from '_OI std::__copy_move_a(_II, _II, _OI) [with bool _IsMove = false, _II = std::basic_string<char, std::char_traits<char>, std::allocator<char> >, _OI = std::basic_string<char, std::char_traits<char>, std::allocator<char> >]'|
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.4.1\include\c++\bits\stl_algobase.h|436|instantiated from '_OI std::__copy_move_a2(_II, _II, _OI) [with bool _IsMove = false, _II = std::basic_string<char, std::char_traits<char>, std::allocator<char> >, _OI = std::basic_string<char, std::char_traits<char>, std::allocator<char> >]'|
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.4.1\include\c++\bits\stl_algobase.h|468|instantiated from '_OI std::copy(_II, _II, _OI) [with _II = std::basic_string<char, std::char_traits<char>, std::allocator<char> >, _OI = std::basic_string<char, std::char_traits<char>, std::allocator<char> >]'|
C:\Users\Will\Documents\Documents - Main\TSF\C++\Permuted Index\index.cpp|68|instantiated from here|
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.4.1\include\c++\bits\stl_iterator_base_types.h|127|error: no type named 'iterator_category' in 'struct std::basic_string<char, std::char_traits<char>, std::allocator<char> >'|
||=== Build finished: 1 errors, 3 warnings ===|

I'm ignoring the warnings from my program for now - I'll deal with them if I need to after I've sorted out the main errors. Obviously there is nothing wrong with the standard library iterator header, or algorithm header - usually the iterator head error pops up, the last time I tried the stl_algobase.h error popped up. I don't remember changing anything.

In the stl_iterator_base_types.h file, the error message is on this line:

127 typedef typename _Iterator::iterator_category iterator_category;

...and in algobase:

388 typedef typename iterator_traits<_II>::value_type _ValueTypeI;

I suspect it has something to do with this section in my main.cpp:

C++:
ostream_iterator<string>ofile(cout, "\n");
	copy(print.begin(), print.end(), ofile);
	cout << endl;

I'm all for trying to debug my own programs and learn, but what the hell does that mean. At my stage, it's the equivalent of shouting "You've done something wrong, but I'm not telling you what." :lol:
 
Last edited by a moderator:
I think I've worked out why I'm getting an error on this line:

Code:
splitcopy.erase(0, i);

If I'm correct, the erase() member function only accepts iterators - not an index or any other type. The error message is telling me it can't find the overloaded erase function that accepts the arguments I've been trying. I'll have to think of a way round it.

I've also worked out the line causing the second error message:

Code:
copy(splitcopy[0], splitcopy[i], temp[0]);

Another iterator problem - those two lines are causing me issues, but the fix should apply to both. Just got to fix it now..
 
Last edited:
My rotate function is broken. Many other errors fixed so far though. :grin1:

This is my current Rotate function:

Code:
vector<Rot_String> rotate(const string& s)
{
    vector<Rot_String> ret;
    vector<string> split = seperate(s);

    // we have rotated i lines so far
    for (int i = 0; i != split.size(); ++i)
    {
        // Create a Rot_String object
        Rot_String rote;

        // String is split into a vector
        vector<string> temp;
        vector<string> splitcopy = split;

        // Words 0 - i are removed and stored in a temp vector
        vector<string>::iterator it = splitcopy.begin();
        vector<string>::iterator out = temp.begin();

        //Creates iterators for use in copy function.
        for (int ab = 0; ab != i; ++ab);
        {
            ++it;
        }

        --it; // Program crashes without. Why is this needed? Fix.


        vector<string>::iterator start = splitcopy.begin();

        copy(start, it, out);
        splitcopy.erase(start, it);

        // Remaining words reformed into string.
        string::size_type len = splitcopy.size();
        for (int x = 0; x != len; ++x)
            {
            rote.str += splitcopy[x] + " ";
            }
        rote.split = rote.str.size(); // Split character is counted and added to object.

        // Removed words are added to end of string.
        len = temp.size();
        for (int y = 0; y != len; ++y){
            rote.str += temp[y] + " ";
            }

        // Rot_String object is added to vector ret.
        ret.push_back(rote);

    }

    //sort ret alphabetically
    sort(ret.begin(), ret.end(), compare);

    return ret; //return sorted vector.

}

The current output of the program is not quite what was intended.

Input: "The brown cow jumped."

Output:
"The brown cow jumped
The brown cow jumped
The brown cow jumped"

Very interesting learning experience doing this project, I've learnt a lot from it. Hopefully I'll be able to fix this function, and display the output correctly next time.
 
Last edited:
The --it is needed because you are incrementing each time you go through the initial while loops. The for loop you created is not actually running:
Code:
for (int ab = 0; ab != i; ++ab)[COLOR=#ff0000][B];[/B][/COLOR]        {
            ++it;
        }
That segment increments it each time it gets to the it block without considering the for loop. I believe your intent was:
Code:
for (int ab = 0; ab != i; ++ab)
        {
            ++it;
        }
Clearly, there is more wrong than just the above. If I get rid of the semicolon, I am given a number of other exceptions related to the iterator. The --it is one exception due to trying to decrement it prior to incrementing it, but removing that causes another exception for the copy(start, it, out) line causing the iterator offset to go out of range. It is the out iterator that is going out of range due to temp never being defined or having a vector pushed back onto. If you create temp outside the loop, you get closer to the functionality you want, i.e.:
Code:
vector<Rot_String> rotate(const string& s){
    vector<Rot_String> ret;
    vector<string> split = seperate(s);
    // to give an iterator for copy and removed words for end of the string
    vector<string> temp;  


    // we have rotated i lines so far
    for (int i = 0; i != split.size(); ++i)
    {
        // Create a Rot_String object
        Rot_String rote;


        // String is split into a vector
        temp.push_back("");
        vector<string> splitcopy = split;


        // Words 0 - i are removed and stored in a temp vector
        vector<string>::iterator it = splitcopy.begin();
        vector<string>::iterator out = temp.begin();


        //Creates iterators for use in copy function.
        for (int ab = 0; ab != i; ++ab)
        {
            ++it;
        }


        //--it; // Program crashes without. Why is this needed? Fix.




        vector<string>::iterator start = splitcopy.begin();


        copy(start, it + 1, out);
        splitcopy.erase(start, it + 1);


        // Remaining words reformed into string.
        string::size_type len = splitcopy.size();
        for (int x = 0; x != len; ++x)
            {
            rote.str += splitcopy[x] + " ";
            }
        rote.split = rote.str.size(); // Split character is counted and added to object.


        // Removed words are added to end of string.
        len = temp.size();
        for (int y = 0; y != len; ++y){
            rote.str += temp[y] + " ";
            }


        // Rot_String object is added to vector ret.
        ret.push_back(rote);


    }


    //sort ret alphabetically
    sort(ret.begin(), ret.end(), compare);


    return ret; //return sorted vector.
}

You may also want to note that the intput for the copy and erase functions needed a
Code:
 it + 1
instead of just an
Code:
it
Essentially, you were telling the program that you wanted to copy from iterator 0 to iterator 0 and into an empty iterator before. Then you told it to copy from iterator 0 to iterator 1 into an empty iterator. The iterator 0 to iterator 0 is empty since there is no span of iterators there, i.e. 0 - 0 = empty. That was okay to copy an empty iterator into another empty iterator. As soon as you spanned 0 to 1, it threw an exception for trying to write a 0 to 1 iterator span into an empty iterator span. Iterator 0 to 1 will include the word "The" from your example. Iterator 0 to 2 will include "The brown" etc. You can then erase those spans the same way, i.e erase(start,it + 1) will erase the set that spans 0 to 1 or the string included in array index [0], which is "The" when start and it are both 0, your first case.

The above does not quite get you what you want, but I think you will be able to determine where things are going wrong with that slight push in the right direction. Best wishes!

-Mike
 
Last edited:
Hi Mike, thanks for the reply.

The code you posted works correctly - once the it + 1 is changed back to it for copy and erase. There is still a formatting issue in the main() function, but that can be ignored for now.

A couple of questions:

Using your rotate() code, the output (ignoring incorrect formatting) displays:

3lineversion.JPG

The version of the code that is the "original" - aka "the brown cow jumps" is still missing. If I changed the code back to:

Code:
copy(start, it, out);
splitcopy.erase(start, it);

The rotate function returns the correct vector with all intended items - consequently it displays as:

4lineversion.JPG

If it + 1 is added - for every line processed, we'll miss the first iterator. I think I understand that on the first try through the loop - it attempts to copy 0 - 0, but on subsequent tries copy(start, it, out) is correct - on the second run through, it will be 1.

Am I correct that this is happening? How can I re-design the program so that it won't unnecessarily run through the program the first time to copy 0-0, but without affecting subsequent lines?

It is the out iterator that is going out of range due to temp never being defined or having a vector pushed back onto. If you create temp outside the loop, you get closer to the functionality you want

The default vector<string> initialization is a blank vector - I thought objects can be pushed back onto a blank vector, it'll just lengthen the vector? Am I confused with back_inserter iterators? Can I use the back_inserter here instead of temp.push_back(""); and initializing the vector outside of the loop. I wanted temp to be created inside the loop each time - as it's just a temporary vector to hold 0-i whilst the vector is reordered.

I can see that it works your way - I'm just don't fully understand it, I haven't so far had to push an empty character into a vector before using it.
 
The way you currently have it set up, the first time through the loop, you are doing a copy command that is not needed, and the erased words will be missing the first iteration due to out being empty. The variable rote ends up missing some words; I thought the intent of rote was to store the words that were erased, or am I misunderstanding the code?

Starting with i = 0 is not a problem. Also, the copy function still does work with that case with it = start since the span is empty; better though would be to have ab include i = 0 so the storage all works as intended for rote. I end up with the same output as you, but it looks a bit cleaner:

// Rotate function. Returns a vector of Rot_String types.
vector<Rot_String> rotate(const string& s){
vector<Rot_String> ret;
vector<string> split = seperate(s);
// to give an iterator for copy and removed words for end of the string

// we have rotated i lines so far
for (int i = 0; i != split.size(); ++i){
// Create a Rot_String object
Rot_String rote;

// String is split into a vector
vector<string> temp;
vector<string> splitcopy = split;

vector<string>::iterator it = splitcopy.begin();

//Creates iterators for use in copy function.
/* I added ab <= i instead of ab != i to allow ++it to occur when i = 0
This way, it will be greater than start for the copy command and erase will remove the first word. temp will store the removed word
as I believe was intended*/

for (int ab = 0; ab <= i; ++ab)
{++it;
/* If you want to have temp inside the i for loop, it needs to grow
with i. Before, it was empty at all times, which caused the out iterator to go out of bounds during the copy command.*/

temp.push_back("");
}
// Words 0 - i are removed and stored in a temp vector
vector<string>::iterator out = temp.begin();

//--it; // Program crashes without. Why is this needed? Fix.

vector<string>::iterator start = splitcopy.begin();
copy(start, it, out);
splitcopy.erase(start, it);

// Remaining words reformed into string. string::size_type len = splitcopy.size();
for (int x = 0; x != len; ++x)

{

rote.str += splitcopy[x] + " ";
}

rote.split = rote.str.size(); // Split character is counted and added to object.

// Removed words are added to end of string. len = temp.size();
for (int y = 0; y != len; ++y)

{

rote.str += temp[y] + " ";
}

// Rot_String object is added to vector ret. ret.push_back(rote);
}

//sort ret alphabetically
sort(ret.begin(), ret.end(), compare);

return ret; //return sorted vector.
}







I've added my comments in /* */ format so you can see what changes were made and why.

In response to your temp confusion: Yes, you can put temp inside the i for loop as you did before. The problem with your previous declaration of temp, though, is it was never initialized. Not initializing the vector caused problems with the copy command. There were no indices within temp to store the erased words since temp was empty, so if iterator it was greater than iterator start, you were trying to pass 1-4 indices into 0 indices, and the program faulted due to not having anywhere to store those indices because the memory had not been allocated. If you want to use temp inside the i for loop, you must add indices to the temp vector through the push_back command, or you may be able to use the back_inserter function instead:
Code:
// Rotate function. Returns a vector of Rot_String types.


vector<Rot_String> rotate(const string& s)
{
    vector<Rot_String> ret;
    vector<string> split = seperate(s);
    // to give an iterator for copy and removed words for end of the string


    // we have rotated i lines so far
    for (int i = 0; i != split.size(); ++i)
    {
        // Create a Rot_String object
        Rot_String rote; 


        // String is split into a vector
        vector<string> temp; 
        vector<string> splitcopy = split;


        vector<string>::iterator it = splitcopy.begin();


        //Creates iterators for use in copy function.
        /* I added ab <= i instead of ab != i to allow ++it to occur when i = 0
              This way, it will be greater than start for the copy command and 
              erase will remove the first word. temp will store the removed word
              as I believe was intended*/
        for (int ab = 0; ab <= i; ++ab)
        {
            ++it;
        }


        //--it; // Program crashes without. Why is this needed? Fix.




        vector<string>::iterator start = splitcopy.begin();
        /* If you want to have temp inside the i for loop, back_inserter also works. 
              Before, temp was empty at all times, which caused the out
              iterator to go out of bounds during the copy command.
        Note: that with the back_inserter method, the iterator
              out is unnecessary and has been removed.*/
        // Words 0 - i are removed and stored in a temp vector
        copy(start, it, back_inserter(temp));
        splitcopy.erase(start, it);


        // Remaining words reformed into string.
        string::size_type len = splitcopy.size();
        for (int x = 0; x != len; ++x)
            {
            rote.str += splitcopy[x] + " ";
            }
        rote.split = rote.str.size(); // Split character is counted and added to object.


        // Removed words are added to end of string.
        len = temp.size();
        for (int y = 0; y != len; ++y){
            rote.str += temp[y] + " ";
            }


        // Rot_String object is added to vector ret.
        ret.push_back(rote);


    }


    //sort ret alphabetically
    sort(ret.begin(), ret.end(), compare);


    return ret; //return sorted vector.
}

Output of both:

brownCow1.PNG
 
Last edited:
Thanks again for your reply - it's starting to make more sense to me now.

The variable rote ends up missing some words; I thought the intent of rote was to store the words that were erased, or am I misunderstanding the code?

rotate() is meant to take a line of input "The brown cow jumps", and create several rotated versions stored in a Rot_String object - the Rot_String is just a vector<string> forming the sentence, and a marker indicating where the sentence begins. The rotate() function is actually working correctly now - the display errors are coming later in the program.

I wrote some test code to print the return from rotate():

test.JPG

This is the correct return - it displays split.size() lines, rotated in every position. The display error was actually caused by me failing to add the left vector to the output. The program is now working correctly (ish, one remaining error but it doesn't matter for this).

final.JPG

Here is the final version of main.cpp:

Code:
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <iterator>
#include <cctype>
#include <iostream>
#include "index.h"

using namespace std;

// Find the max width from a vector of strings.
string::size_type width(const vector<string>& v)
{
    string::size_type maxlen = 0;
    for(vector<string>::size_type i = 0; i != v.size(); ++i)
        maxlen = max(maxlen, v[i].size());

    return maxlen;
}

int main()
{
    //User input
    cout << "Please enter a short sentence." << endl;
    string s;
    getline(cin, s);


    // Rotate function called. Return stored in rotated.
    vector<Rot_String> rotated = rotate(s);

    vector<string> left;
    vector<string> right;
    vector<string> print; //Final string to be printed.

    string::size_type len = rotated.size(); //Find length of rotated.

//*/Output code.
    // Form Left and Right vectors.
    // We have processed i lines.
    for (string::size_type i = 0; i != len; ++i)
    {
        string::size_type split = rotated[i].split;
        string rot = rotated[i].str;
        string::size_type end = rot.size();

        right.push_back(rot.substr(0, split));
        left.push_back(rot.substr(split, end));
    }

    // Find max characters in Left
    string::size_type maxlen = width(left);

    // Create final vector.
    for (vector<string>::size_type i = 0; i != left.size(); ++ i)
    {
        print.push_back(string(maxlen - left[i].size(), ' ') + left[i] + "\t" + right[i]);
    }

    // Print final vector
    ostream_iterator<string>ofile(cout, "\n");
	copy(print.begin(), print.end(), ofile); //Correct function
	cout << endl;

    //*/

/*
//TESTING CODE - Tests return from rotate();

    vector<Rot_String>::size_type testsize = rotated.size();
    vector<string> testprint;

    for(vector<Rot_String>::size_type testi = 0; testi != testsize; ++testi)
    {
        string testrot = rotated[testi].str;
        testprint.push_back(testrot);
    }

    cout << "\nOutput: " << endl;
    ostream_iterator<string>ofile(cout, "\n");
    copy(testprint.begin(), testprint.end(), ofile);
	cout << endl;

//END TESTCODE
*/

    return 0;
}

Thanks a lot for your help - it's also nice to know I wasn't completely off with the program logic. Only one final question, is there anything I could have done better in this program? Obviously I'm not expecting a huge analysis, but feedback is good :grin1:.
 

Attachments

  • test.JPG
    test.JPG
    35.9 KB · Views: 4
Last edited:
The program takes 0.018 seconds to run from the time the user inputs the sentence, so I would say it is pretty efficient. :smile9:

It looks good to me.
 
Last edited:
Glad I could help. Nicely done!


Just out of curiosity, is there a reason you used iterators to accomplish the task? I myself would have used stringstream variables. You probably learned a lot more with the method you used, but I was curious as to the reason behind it.

There is no wrong way to solve a problem with code, and there are probably ten or more different ways to do what you did. Wanted you to know that so you understand I am not questioning the method, just curious about the reason.
 
Using iterators was the only feasible method I knew when I started the program - I'm using Accelerated C++ to learn at the moment, I don't think stringsteam is covered in it. The program itself was a challenge quite a few chapters back, I moved past it in the book as although the program still had errors - I felt I'd learnt enough from it to justify moving on. I'm glad I got it fixed though, it's helped me understand iterators and vectors in more depth, which is good as iterators seem pretty fundamental.
 
Yeah, I haven't used iterators in c++ before helping out with this thread. I did use them in Java when I tutored my sister's boyfriend, so I understand some aspects of the method. I had to learn a lot more going through your code, so it was a learning experience for both of us.

My proficiency using the string and stringstream classes are a lot stronger than my knowledge of vectors and iterators, which is why I would have gone the stringstream route. I think the BSOD Apps were the first place I ever really used vectors regularly, and nearly all were string vectors. I should probably read up on iterators at some point in my C++ Object Oriented Programming manual.

I owe you some thanks for helping me learn a bit more, too. :smile9:
 
How did you learn C++?

I'm having another issue on a Naughts and Crosses/Tic-Tac-Toe game I've just written. It's not quite finished, but I've tested some of the code and one of the errors is confusing me.

Function:

Code:
void play_turn(bool player_turn&)
{
    //Play a turn
    if(player_turn = true)
    {
        player_go();
    }
    else
        computer();


}

The function is being called with:

Code:
play_turn(player_turn);

player_turn is defined as a bool and is passed through several functions. The intention is that the play_turn function can change the player_turn bool, depending on whether or not the player has just had it's turn.

I'm getting this error:

Code:
game.cpp|36|error: expected ',' or '...' before '&' token|

It doesn't seem to like me using & - I thought this was used to tell the function not to copy the variable, but to read/write to it directly. Does this only work for vectors then?
 
Simple problem to solve. Your ampersand is in the wrong place to pass player_turn as a reference. Also, your if statement is assigning a value of true to player_turn instead of checking the condition that player_turn==true.

void play_turn(bool &player_turn&){
//Play a turn
/* you may also choose
if(player_turn)
instead. The result is the same*/
if(player_turn==true)
{
player_go();
}
else
computer();
}
 
Last edited:
Ah, thanks for that. I thought it would be something simple. I've got the program to compile now.
 
Just seen this, and decided to write my own code to achieve a similar layout:
9Sw7SMA.png
 

Has Sysnative Forums helped you? Please consider donating to help us support the site!

Back
Top