Hey everyone, I have a question that it seems like I shouldn't have. I am recreating a hangman game that I made in my c++ class last semester, just for practice, for comparison, and fun. I'm trying to generate a random number to help choose which word from my words list to use and I've done it a billion times before just like this. So, here's my code:
#include <iostream>
#include <cstdlib> //standard library.
#include <ctime> //for random.
#include <fstream> //for reading and writing to a file.
#include <string>
usingnamespace std;
int main()
{
int num_words;
string word[num_words];
ifstream infile;
ofstream outfile;
// read in words for the word list
infile.open("words.txt");
infile >> num_words;
for(int i = 0; i < num_words; i++)
{
infile >> word[i];
}
infile.close();
// Generate a random number to get a word from the word list.
long seed = time(NULL); // gets current time
srand(seed);
int random_num = rand(); // Computer's random selection
cout << random_num % 5<< endl;
// Debug
for(int i = 0; i < num_words; i++)
{
cout << word[i] << endl;
}
}
I have the text file "words.txt" info below.
5
dog
cat
horse
pig
bird
If I run the program as it is, I get a segmentation fault core dumped error, however, if I take all the stuff that reads in the words from the words.txt file, like so:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
#include <iostream> //every program has this.
#include <cstdlib> //standard library.
#include <ctime> //for random.
#include <fstream> //for reading and writing to a file.
#include <string>
usingnamespace std;
int main()
{
long seed = time(NULL); // gets current time
srand(seed);
int random_num = rand(); // Computer's random selection
cout << random_num << endl;
}
it works correctly and generates a random number. I have no idea what's going on and would greatly appreciate any help.
(Also, just a side note, I'm using Linux Mint. I believe I wrote the last version of this on Windows. I can't really remember.)
This is not standard C++, it belongs to a non-standard dialect that the GCC crowd calls gnucxx.
Even if it were syntactically correct (it would be in C++14), it results in undefined behaviour - num_words has not been initialized before it is used.
Tip: compile with -std=c++11 -pedantic-errors -Wall -Wextra
Why not just call your string array string word[5], since you know there are 5 words. Or otherwise, if you want its size to be somewhat dynamic, then read in the number of lines in the file and assign that value to num_words, before the declaration string word[num_words].
Also, #include <iostream> //every program has this. This is not true. ;)
Is legal in all compilers and also in all versions of C/C++..... the important thing is that the int variable must be initialized before being used as value for array dimension.
mhaggard: I would suggest to use std::vector<std::string> instead of an array of std::string
int main() {
std::vector <std::string> word;
ifstream infile;
// read in words for the word list
infile.open("words.txt"); //now "words.txt" does not require to start with "5" (number of words)
while (!infile) { //continue until end of file
std::string tstr;
infile >> tstr;
word.append(tstr);
}
// Generate a random number to get a word from the word list.
long seed = time(NULL); // gets current time
srand(seed);
int random_num = rand(); // Computer's random selection
cout << random_num % 5<< endl;
// Debug
for(int i = 0; i < word.size(); i++)
{
cout << word[i] << endl;
}
return 0;
}
if you really want to mantain array approach (and bind dimension of the first value).
In this case you must, instead, specify in first line of word.txt the size of the array (in this case "5")
int main() {
int num_words=0; //it is a good thing to initialize the value even if it is not the desired one
ifstream infile;
//NOTE: we already don't know size of array becouse we don't know num_words
// so we cannot declare here string world[num_worls] becouse the array would be invalid
infile.open("words.txt");
infile >> num_words;
//now num_words is truely initialized. It will be "5" as the first line of wolrds.txt
//so AT THIS POINT we can declare the array "word"
std::string word[num_words]; //now we can declare it... and not before this moment
for(int i = 0; i < num_words; i++)
{
infile >> word[i];
}
infile.close();
// Generate a random number to get a word from the word list.
long seed = time(NULL); // gets current time
srand(seed);
int random_num = rand(); // Computer's random selection
cout << random_num % 5<< endl;
// Debug
for(int i = 0; i < num_words; i++)
{
cout << word[i] << endl;
}
#include <string>
#include <iostream>
#include <random>
#include <ctime>
// invariant: first line of stm contains the number of words in it
std::string random_word( std::istream& stm )
{
std::string word ;
int n ;
if( stm >> n && n > 0 )
{
static std::mt19937 rng( std::time(nullptr) ) ;
constint r = std::uniform_int_distribution<int>( 1, n )(rng) ;
for( int i = 0 ; i < r ; ++i ) stm >> word ;
}
return word ;
}
@Mats: Also, #include <iostream> //every program has this. This is not true. ;)
^^ Ha yea I know. I just copied my "#includes" and that was there from the first time I wrote the program when I started the class. Thanks for pointing that out though.
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <fstream>
#include <string>
#include <vector>
usingnamespace std;
int main()
{
ifstream infile;
vector<string> word; // Use a vector instead of an array.
// read in words for the word list
infile.open("words.txt");
while(!infile)
{
string tstr;
infile >> tstr;
word.push_back(tstr);
}
for(int i = 0; i < num_words; i++)
{
infile >> word[i];
}
infile.close();
// Generate a random number to get a word from the word list.
long seed = time(NULL); // gets current time
srand(seed);
int random_num = rand(); // Computer's random selection
cout << random_num % 5<< endl;
// Debug
for(int i = 0; i < word.size(); i++)
{
cout << word[i] << endl;
}
}
@Nobun: I really like the vector approach, but when I compile I get this error:
class std::vector<std::basic_string<char> >’ has no member named ‘append’
so, I changed append to push_back (Sorry if that's dumb I'm not too familiar with vectors. it's kind of a learn as I go thing with them) and now it compiles fine, but the program stalls when running.
Thank all of you so much for your help so far. Sorry for all the dumb questions.
int main() {
std::vector <std::string> word;
ifstream infile;
// read in words for the word list
infile.open("words.txt"); //now "words.txt" does not require to start with "5" (number of words)
while (!infile) { //continue until end of file
std::string tstr;
infile >> tstr;
word.push_back(tstr);
}
// Generate a random number to get a word from the word list.
long seed = time(NULL); // gets current time
srand(seed);
int random_num = rand(); // Computer's random selection
cout << random_num % 5<< endl;
// Debug
for(int i = 0; i < word.size(); i++)
{
cout << word[i] << endl;
}
return 0;