Thread: Random Poem Generator

  1. #1
    Registered User
    Join Date
    Dec 2009
    Posts
    40

    Random Poem Generator

    Ok, so as an assignment I have been asked to create a random poem generator.
    I have been provided with the format for the poem to take so thats not an issue, what I need to work out, is how to select random words or phrases from a text/data file.

    I have been considering having the lists of words/phrases in a text file, seperated by carriage returns. I then generate a random number and count this many carriage returns into the file, then take the next string after that. I would need to limit the range of the random numbers to the length of the list presumably. But yea basically I'm just posting to see what people think of this approach? Will it be efficient? Is there another approach I should consider? Will this be easily achievable in C++? I think it should be, I just need to brush up on my file handling.

    Thank you for any input.

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    That sounds like a feasible idea.

    If you need to repeatedly generate poems, then it may be better to just read the words/phrases into a std::vector<std::string> instead of doing many file accesses.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #3
    Registered User
    Join Date
    Dec 2009
    Posts
    40
    Well it will need to access 12 random words/phrases from 5 different lists. Would it be safe to have 5 different vectors (I'm assuming thats what is meant by that code, I'm very new to C++ I've just come from doing standard C) all of which could end up being quite long lists of words/phrases?

    edit: thanks for replying btw

  4. #4
    Registered User
    Join Date
    Mar 2010
    Posts
    18
    A vector will take about as much space as an array in C (well, up to 1.5 times as much if you fill it via push_back and don't reserve() before that). So if your lists of phrases are alltogether 30MB, you will need at most 45MB. And if you actually come up with 30MB of poem phrases, you should consider switching your profession.
    Code:
    std::vector<std::string> first_phrase(
    std::istream_iterator<std::string>(std::cin), std::istream_iterator<std::string>());
    ...will fill the vector via reading from cin (replace it with a std::ifstream to read from a file).

    (I do find it a pity, however, that you only copy phrases together. A formal grammar would be much nicer, and make generic-poem-phrase-writing so much more fun... <poem> ::= <cynical_statement> <random_fill_in> <even_more_cynical_statement> | <illogical_premise> ... well, I guess you get the point)

  5. #5
    Registered User
    Join Date
    Dec 2009
    Posts
    40
    Ha well when I said phrases I was actually talking about prepositions. And other things that need more than one word sometimes.

    The format I've been given is:
    A <adjective1> <noun1> <verb1> <preposition1> the <adjective 2> <noun 2>.
    <adverb 1> the <noun 1> <verb 2>.
    The <noun 2> <verb 3> <preposition 2> a <adjective 3> <noun 3>.

    Just in case you were interested lol

    And thank you for the advice, I'll go do a bit of background reading, I really need to get used to reading the format of C++ syntax still.

    EDIT: Ok so I've been looking as some examples and trying to work out some stuff.
    I'll just take the first part for now, std::vector<std::string>
    is it necessary to have the std:: part when coding? or is this just a way of writing it for a definition?
    Last edited by ineedmunchies; 03-23-2010 at 07:54 AM.

  6. #6
    Registered User
    Join Date
    Feb 2010
    Posts
    38
    EDIT: Ok so I've been looking as some examples and trying to work out some stuff.
    I'll just take the first part for now, std::vector<std::string>
    is it necessary to have the std:: part when coding? or is this just a way of writing it for a definition?
    Code:
    #include <string>
    
    int main(int argc, char* argv[]) {
        std::string mystring = "Hello, World!";
    
        return 0;
    }
    Is the same as:

    Code:
    #include <string>
    
    using namespace std;
    
    int main(int argc, char* argv[]) {
        string mystring = "Hello, World!";
    
        return 0;
    }
    Is the same as:

    Code:
    #include <string>
    
    using namespace std::string;
    
    int main(int argc, char* argv[]) {
        string mystring = "Hello, World!";
    
        return 0;
    }
    However, I believe "using namespace std" is frowned upon (globally), due to potential name clashes with _your_ function names.

  7. #7
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by nicoqwertyu
    Is the same as:
    You have a typo error there as the using declaration should be:
    Code:
    using std::string;
    Quote Originally Posted by nicoqwertyu
    However, I believe "using namespace std" is frowned upon (globally), due to potential name clashes with _your_ function names.
    Using directives can be fine if you use them in a limited scope, or at least only in source files but not before any header inclusions.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  8. #8
    Registered User
    Join Date
    Mar 2010
    Posts
    18
    Quote Originally Posted by nicoqwertyu View Post
    Code:
        std::string mystring = "Hello, World!";
    Is the same as:
    Code:
    using namespace std;
    string mystring = "Hello, World!";
    That's right. But:
    Code:
    std::vector<std::string> foo(std::istream_iterator<std::string>(std::cin),
      std::istream_iterator<std::string>());
    does what you think it does (calling the range constructor of vector with strings read from cin). Now consider
    Code:
    using namespace std;
    vector<string> foo(istream_iterator<string>(cin), istream_iterator<string>());
    This also does what you think it does - if you think that what you do is to declaration a function, that is.
    That's right, you declare a function named foo, returning a vector of strings and taking two arguments, one iterator named cin, and one unnamed iterator. It's an ambiguity in C's ugly function declaration syntax: what *can* be parsed as a declaration, *is* parsed as a declaration. The ambiguity vanishes as you explicitly declare the namespace, since parameter names cannot contain a '::'.
    To prevent the following statement from starting a flame-war, pleas note that it is my personal opinion which is not worth arguing about, so don't. This opinion is: use 'using' only to prevent name hiding in subclasses, and not for "typing convenience", especially if you didn't spot the problem in my example above.

  9. #9
    Registered User
    Join Date
    Dec 2009
    Posts
    40
    So your argument is in favour of using the scope operator?

    Does std::vector mean that vector is a component of class std, which is included in the preprocessor directives? And this would be the more proper usage in your opinion?

    Edit: just found a good bit in a book about it, it suggests using std::vector as opposed to just using std. I think I've got it now anyway cheers.
    Last edited by ineedmunchies; 03-24-2010 at 08:37 AM.

  10. #10
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by assertion
    The ambiguity vanishes as you explicitly declare the namespace
    ... as you qualify the name.

    Quote Originally Posted by assertion
    This opinion is: use 'using' only to prevent name hiding in subclasses, and not for "typing convenience"
    You appear to have left out the case where a using declaration is used to enable argument dependent lookup, most commonly when writing a swap function that will use std::swap by default, but a custom swap function if one is available.

    Quote Originally Posted by ineedmunchies
    Does std::vector mean that vector is a component of class std, which is included in the preprocessor directives?
    std is a namespace, not a class, but I think you have the rough idea.

    Quote Originally Posted by ineedmunchies
    just found a good bit in a book about it, it suggests using std::vector as opposed to just using std.
    You can still run into name ambiguity related problems with a using declaration like using std::vector, so whether you use using directives like using namespace std or using declarations, you have to be careful.
    Last edited by laserlight; 03-24-2010 at 08:47 AM.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  11. #11
    Registered User
    Join Date
    Dec 2009
    Posts
    40
    Quote Originally Posted by assertion View Post
    Code:
    std::vector<std::string> first_phrase(
    std::istream_iterator<std::string>(std::cin), std::istream_iterator<std::string>());
    ...will fill the vector via reading from cin (replace it with a std::ifstream to read from a file).
    Ok so I'm trying this, and I want to read from the file I have open, but surely std::ifstream is not enough? I need to give the filename somehow?

    Code:
        std::ifstream myfile;
        myfile.open ("D:\\School\\C\\adjectives.txt")
        std::vector<std::string> adjective1 (std::istream_iterator<std::string>(std::ifstream), std::istream_iterator<std::string>());
        std::ostream_iterator<std::string> out_it (std::cout, ", ");
        std::copy (adjective1.begin(), adjective1.end(), out_it);
    This is what I have so far, all I want to do is open the file and read from it into a vector.

  12. #12
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    That's right, you declare a function named foo, returning a vector of strings and taking two arguments, one iterator named cin, and one unnamed iterator.
    O_o

    That second parameter is an unnamed pointer to a function with no parameters that returns a `std::istream_iterator<std::string>' object.

    But [...] does what you think it does (calling the range constructor of vector with strings read from cin).
    It doesn't do what you think it does. It does not call the range constructor. It doesn't do anything. It is an illegal line of C++ code. (If it wasn't illegal, it would still be a function declaration.)

    For the future, before laying out advice regarding the interpretation of the standard, you will want to try a compiler that isn't "G++" or Sun CC. (Or at least turn G++ up to its most pedantic.) You need to try at least two; no one compiler sets the benchmark for standard behavior.

    The ambiguity vanishes as you explicitly declare the namespace, since parameter names cannot contain a '::'.
    That is not an ambiguity. An ambiguous statement is a legal statement with several potential, all valid, interpretations.

    You've changed a legal, unambiguous statement to an illegal statement.

    This opinion is: use 'using' only to prevent name hiding in subclasses, and not for "typing convenience", especially if you didn't spot the problem in my example above.
    O_o

    The above referenced line is illegal. You would still need to use another method "on top" of fully qualifying the name. The problem persists even if you use a `typedef'. (I'm talking about the valid line of C++ source. The illegal line of code would remain illegal.)

    Fully qualifying every name at every use is no better than decoration; you've lost all of their utility. You may as well use "__" instead of "::".

    Soma

  13. #13
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    Code:
        std::ifstream myfile;
        myfile.open ("D:\\School\\C\\adjectives.txt")
        std::vector<std::string> adjective1 (std::istream_iterator<std::string>(std::ifstream), std::istream_iterator<std::string>());
        std::ostream_iterator<std::string> out_it (std::cout, ", ");
        std::copy (adjective1.begin(), adjective1.end(), out_it);
    You are going in the right direction, but you have misunderstood the parameters to the iterator constructor. The parameter is the name of the `istream' object. (The token `std::cin' is the name of an `istream' object.)

    Soma

    Code:
    #include <fstream>
    #include <iostream>
    #include <iterator>
    #include <string>
    #include <vector>
    
    int main()
    {
    	using namespace std;
    	ifstream fin("test.cxx");
    	istream_iterator<string> fin_begin(fin); // these three
    	istream_iterator<string> fin_end; // lines will
    	vector<string> data(fin_begin, fin_end); // work
    	//vector<string> data((istream_iterator<string>(fin)), (istream_iterator<string>())); // or this
    	copy(data.begin(), data.end(), ostream_iterator<string>(cout, " "));
    	return(0);
    }

  14. #14
    Registered User
    Join Date
    Mar 2010
    Posts
    18
    One question, if I may: why is it be illegal?

  15. #15
    Registered User
    Join Date
    Dec 2009
    Posts
    40
    Ok so I tried working with istream iterator, and I just don't get it, so I've gone back to using loops that I understand instead.

    Code:
    #include <iostream>
    #include <vector>
    #include <string>
    #include <iterator>
    #include <fstream>
    
    using namespace std;
    
    int main()
    {
        ifstream myfile;
        myfile.open ("H:\\Programming\\Poem\\adjectives.txt");
    
        int i=0;
        vector<string> strVector;
    
        while (!myfile.eof())
            {
                getline(myfile, strVector[i]);
                i++;
            }
    
        cout << strVector[2];
    }
    I'm using this as code, it compiles ok, but it crashes when it opens the file. Any thoughts? Do I need to add another argument to the open function maybe? just thought of that there.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Quantum Random Bit Generator
    By shawnt in forum C++ Programming
    Replies: 62
    Last Post: 06-18-2008, 10:17 AM
  2. How exactly does the random number generator work?
    By Finchie_88 in forum C++ Programming
    Replies: 6
    Last Post: 08-24-2007, 12:46 AM
  3. NAQ: Everything you never wanted to know about CPP
    By evildave in forum C Programming
    Replies: 21
    Last Post: 12-12-2005, 10:56 AM
  4. Testing Random Number Generator
    By Roaring_Tiger in forum C Programming
    Replies: 7
    Last Post: 08-12-2005, 12:48 AM
  5. Random number generator
    By Caze in forum C++ Programming
    Replies: 6
    Last Post: 12-03-2002, 08:10 AM