RNG in loop and printing word from string array - c++

Ok, I have this working perfectly now, and I've edited this post and code below to reflect the updated correctly working code.
Read 50 words from a text file into an array of strings
The program will use random numbers for:
a.- It will generate a random number between 2 and 7 for the selection of the words to be used in the sentence
b.- It will generate a random number for the selection of the words. The number will be between 0 and 49, because those are the positions of the words in the array
It will display the sentence on the screen.
Thank you ahead of time for any suggestions
#include <string>
#include <iostream>
#include <fstream>
#include <time.h>
#include <stdlib.h>
#include <array>
using namespace std;
int main() {
ofstream outFile;
ifstream inFile;
const int size = 50; //initiate constant size for array
string word[size]; //initialize array of string
srand(time(0)); //sets timing factor for random variables
int Random2 = rand() % 6 + 2; //determines random value beteen 2 and 7
inFile.open("words.txt"); //opens input text file
if (!inFile.is_open()) { //tests to see if file opened corrected
exit(EXIT_FAILURE);
}
while (!inFile.eof()) { //Puts file info into string
for (int i = 0; i < size; ++i)
inFile >> word[i];
}
for (int i = 0; i < Random2; i++) { //loops through array and generates second random variable each loop to determine word to print
int Random1 = rand() % size;
cout << word[Random1] << " ";
}
cin.get();
}

int generateRandom()
{
default_random_engine generator;
uniform_int_distribution<int> distribution(0, 49);
int random = distribution(generator); // generates number in the range 0..49
return random;
}
The problem is that each time you call the getRandom() function you create a new PRNG instance. Therefore, each instance is called only once and the first result is always the same.
Instead you want to create the instance once and call the same instance multiple times.
default_random_engine generator;
uniform_int_distribution<int> distribution(0, 49);
for (int i = 0; i < 5; ++i)
{
std::cout << distribution(generator) << std::endl;
}
cout << words[generateRandom()]
words is declared to be type std::string. Using [] accesses a single character within the string. What are you expecting here? Did you intend to have an array of strings (i.e., one for each line in the text file)? If so, you want something like std::vector<std::string> words. Now using words[0] accesses an element in the array and each element is of type std::string (as opposed to a single character like before).

As for printing single characters, you're only printing the character because that's how the [] operator works for strings. You'll need to tokenize the string. See strtok.

Related

Random Number Generator Without Any Repeating Numbers

So basically I have to make an array that allows the user to randomly generate the amount of numbers of their choice, and none of the numbers can be the same. My code generates them normally but still gets repeated numbers and I'm not sure why as I think I prevented it. I'm still fairly new to arrays so this may look really dumb, any help would be appreciated! I've left a lot of side notes to try and break down each section, and at the bottom I'll include what it looks like when it runs.
#include <iostream>
#include <ctime>
#include <windows.h>
using namespace std;
int main()
{
int numberlist[20]; //the array
int count=0,amount=0,value=0;
bool found=false;
srand(time(NULL)); //makes randomizer not the same
cout << "How many numbers to generate?" << endl;
cin>>amount; //gets user input
for(int count=0; count<amount; count++){
value = rand() % 40 + 1; //generates random number from 1-40 until amount is reached
found=false;
if(value==numberlist[count])found=true; //if value is in the array, change found from false to true
if(value!=numberlist[count] && found==false){ //if number is unique and new
numberlist[count]=value; //add number to array
cout << value << endl; //show the value to the screen
}
else if (found==true) {count--;} //if value is in array erase 1 from count
}
return 0;
}
//What it looks like altogether
//How many numbers to generate?
// 9 (<the users input)
//37
//5
//30
//13
//7
//18
//1
//25
//25 (The 25 is the repeating number in this case)
you have mistake in your logic
if(value==numberlist[count])found=true; //if value is in the array, change found from false to true
That's only check if there is no duplicates on in position equals count, You have to iterate over all array position!
Full code below:
#include <iostream>
#include <ctime>
using namespace std;
int main()
{
int numberlist[20]; //the array
int count=0,amount=0,value=0;
bool found=false;
srand(time(NULL)); //makes randomizer not the same
cout << "How many numbers to generate?" << endl;
cin>>amount; //gets user input
for(int count=0; count<amount; count++){
value = rand() % 40 + 1; //generates random number from 1-40 until amount is reached
found=false;
for(int i = 0 ; i < count; i++) // iterate over all position in array
if(value==numberlist[i])found=true; //if value is in the array, change found from false to true
if(found==false){ //if number is unique and new <--- I have also fix this condition
numberlist[count]=value; //add number to array
cout << value << endl; //show the value to the screen
}
else if (found==true) {count--;} //if value is in array erase 1 from count
}
return 0;
}

Return value from string function

i have a string array that contains 20 words. I made a function that take 1 random word from the array. But i want to know how can i return that word from array. Right now i am using void function, i had used char type but it wont work. Little help here ? Need to make word guessing game.
CODE:
#include <iostream>
#include <time.h>
#include <cstdlib>
#include <stdlib.h>
#include <algorithm>///lai izmantotu random shuffle funckiju
#include <string>
using namespace std;
void random(string names[]);
int main() {
char a;
string names[] = {"vergs", "rokas", "metrs", "zebra", "uguns", "tiesa", "bumba",
"kakls", "kalns", "skola", "siers", "svari", "lelle", "cimdi",
"saule", "parks", "svece", "diegs", "migla", "virve"};
random(names);
cout<<"VARDU MINESANAS SPELE"<<endl;
cin>>a;
return 0;
}
void random(string names[]){
int randNum;
for (int i = 0; i < 20; i++) { /// makes this program iterate 20 times; giving you 20 random names.
srand( time(NULL) ); /// seed for the random number generator.
randNum = rand() % 20 + 1; /// gets a random number between 1, and 20.
names[i] = names[randNum];
}
//for (int i = 0; i < 1; i++) {
//cout << names[i] << endl; /// outputs one name.
//}
}
Make random return string. You also only need to seed the number generator once. Since you only want to get 1 random word from the array, you don't need a for loop.
string random(string names[]){
int randNum = 0;
randNum = rand() % 20 + 1;
return names[randNum];
}
Then, in the main function, assign a string variable to the return value of the random function.
int main() {
srand( time(NULL) ); // seed number generator once
char a;
string names[] = {"vergs", "rokas", "metrs", "zebra", "uguns", "tiesa", "bumba",
"kakls", "kalns", "skola", "siers", "svari", "lelle", "cimdi",
"saule", "parks", "svece", "diegs", "migla", "virve"};
string randomWord = random(names);
cout<<"VARDU MINESANAS SPELE"<<endl;
cin>>a;
return 0;
}
In your question as well as in the previous answer, you are running out of bounds accessing the names array:
int randNum = rand() % 20 + 1;
return names[randNum];
You are never accessing names[0] but instead reach behind the array when addressing names[20].
Additionally srand(time(NULL)) should be called only one time, on the beginning of main() function.
I'm not super familiar with strings, but you should be able to just declare random() as a string function.
Ex:
string random (string names[]);

Reading digits on separate lines in a txt.-file to an array in C++

In order to solve Euler Project 8 without resorting to a "Big Number" library, I would like to read the separate digits in an txt.-file to separate spots in an array. The digits in the txt.-file are arranged as follows:
094239874......29837429837 [50 of them],
192319274......12837129873 [50 of them]
such that there are in total 20 lines with 50 digits, all separated by enters. So I am trying to write a program which writes the first digits to the first spot in the array and continues this process (paying attention to the spaces) until the 1000th digit. I have tried finding solutions to this problem in tutorials and elsewhere online, but I cannot make it work for this specific example. Up to now I have something like
int main() {
int array[999];
string trial[999];
ofstream myfile;
myfile.open ("example.txt");
for(i=1 ; i<=1000 ; i++) {
myfile >> trial;
// Somehow convert string to int as well in this loop?
}
You can try to do it this way (first read the file contents into a string, then convert each char to an int, btw you should use a vector<int> instead of a raw array):
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
using namespace std;
int main()
{
string str;
string total;
ifstream a_file("data.txt");
while (getline(a_file, str))
total += str;
vector<int> vec;
for (int i = 0; i < total.size(); i++)
{
char c = total[i];
int a = c - '0';
vec.push_back(a);
}
}
You can read your file line by line, then add your digits to an array like this way:
// out of your loop
std::vector<int> digits;
// in your loop
std::string buffer = /*reading a line here*/;
for (auto c : buffer) {
digits.push_back(c - '0');
}
Furthermore, STL containers are better than C-style arrays (std::vector / std::array).
I suppose this is what you're looking for
int main(void)
{
unsigned char numbers[20][50];
FILE *pf = fopen("example.txt", "r");
for(int i = 0; i < 20; i++)
{
// read 50 characters (digits)
fread(&numbers[i], 1, 50, pf);
// skip line feed character);
fseek(pf, 1, SEEK_SET);
}
fclose(pf);
// conversion from ascii to real digits by moving the digit offset (subtracting by the first digit char in ascii table)
for(i = 0; i < 20*50; i++)
((unsigned char*)numbers)[i] -= (unsigned char) '0';
// the digits are now stored in a 2-dimensional array (50x20 matrix)
return 0;
}
This approach will not work. According to this question, any built-in integral type is likely to be too small to represent the value of a number with 50 decimal digits.

How to ignore non-letters from std::cin

So, I am trying to read a string from cin, then loop through the string to count which characters in that string are actually letters in the English alphabet. I have wrote a program that works just fine, but I want to know if there is a more efficient way of doing this, without looping through the entire English alphabet.
#include <iostream>
#include <string>
using namespace std;
int main() {
string my_str; //will use to store user input
getline(cin, my_str); //read in user input to my_str
int countOfLetters = 0; //begine count at 0
string alphabet = "abcdefghijklmnopqrstuwxyz"; //the entire english alphabet
for(int i = 0; i < my_str.length(); i++){
for(int j = 0; j < alphabet.length(); j++){
if (tolower(my_str.at(i)) == alphabet.at(j)){ //tolower() function used to convert all characters from user inputted string to lower case
countOfLetters += 1;
}
}
}
cout << countOfLetters;
return 0;
}
EDIT: Here is my new and improved code:
#include <iostream>
#include <string>
using namespace std;
int main() {
string my_str; //will use to store user input
getline(cin, my_str); //read in user input to my_str
int countOfLetters = 0; //begine count at 0
string alphabet = "abcdefghijklmnopqrstuwxyz"; //the entire english alphabet
for(unsigned int i = 0; i < my_str.length(); i++){
if (isalpha(my_str.at(i))){ //tolower() function used to convert all characters from user inputted string to lower case
countOfLetters += 1;
}
}
cout << countOfLetters;
return 0;
}
enter code here
Use isalpha() to see which characters are letters and exclude them.
So, you could modify your code like this:
#include <iostream>
#include <string>
using namespace std;
int main() {
string my_str;
getline(cin, my_str);
int countOfLetters = 0;
for (size_t i = 0; i < my_str.length(); i++) { // int i produced a warning
if (isalpha(my_str.at(i))) { // if current character is letter
++countOfLetters; // increase counter by one
}
}
cout << countOfLetters;
return 0;
}
You could perhaps use isalpha:
for(int i = 0; i < my_str.length(); i++)
if (isalpha(my_str.at(i))
countOfLetters++;
You can use the std::count_if() algorithm along with the iterator interface to count characters for which some predicate returns true. The predicate can use std::isalpha() to check for alphabetical characters. For example:
auto count = std::count_if(std::begin(str), std::end(str),
[&] (unsigned char c) { return std::isalpha(c); });
You could also check if the int cast is between 65-90 or 97-122
at example
(int)'a'
Should give 97
This will be the most performant method without any doubt.
Its better than using isalpha().
Check http://www.asciitable.com/ for ASCI Numbers
isalpha works well for this particular problem, but there's a more general solution if the list of characters to accept wasn't so simple. For example if you wanted to add some punctuation.
std::set<char> good_chars;
good_chars.insert('a'); good_chars.insert('A');
good_chars.insert('b'); good_chars.insert('B');
// ...
good_chars.insert('z'); good_chars.insert('Z');
good_chars.insert('_');
// the above could be simplified by looping through a string of course
for(int i = 0; i < my_str.length(); i++){
countOfLetters += good_chars.count(my_str[i]);
}

Checking for spaces in C++?

I'm writing an encryption program for class. I need to be able to track the position of spaces in a string, as well as adding 13 to the ASCII value of each character of the string. I keep getting an error in line 46, and I don't see what I'm doing wrong.
/*
program 4
use an array to store the string
convert decimal values to ASCII, add 13 to the ASCII values,
convert back to decimal
the character for the space shoud be determined by the character
that came before it.
The character before it should have 4 added to it and
placed after itself to act as the space.
*/
#include <iostream>
#include <fstream>
#include <string>
#include <conio.h>
using namespace std;
int valueChange(string array), length(string array);
int spacePosition[0];
string message[0], encrypt[0];
int main()
{
cout << "Please enter your message."; //start with this
cin >> message[0];
int value = length(message[0]);
int count=0;
/*
store message as an array
loop through array, adding 13 to each value, use tolower() on each value
if value is
*/
for (int i=0; i < value; i++)
{
valueChange(message[i]);
if (message[i] == ' ') //checks for spaces in the string
{
spacePosition[count] = i + 1; //records the placement of spaces
//in the string
//have the array cast the i value to a new int value
//store space positions in an array
count++;
}
}
cout << "&";
cout << "Message encrypted and transmitted."; //final message
getch();
return 0;
}
int valueChange(int array[])
{
array[0] += 13;
if (array[0] > 122)
{
array[0] - 122;
}
return (array[0]);
}
int length(string array)
{
return (array.length() - 1);
}
If you need to search for spaces you can use string::find_first_of(string). You just need to write
`
std::string yourstring;
yourstring.find_first_of(" ");
`
then you need to iterate through the whole string using iterator.
And why are you declearing array if zero length? You can simply use simple std::string class. If you are not allowed to then simply use find_first_of(....) function available in standerd library. It basically returns the iterator to the first matching element.
int spacePosition[0];
string message[0], encrypt[0];
Probably want those to be 1's... or not use an array at all. But you are declaring arrays with 0 length, so yeah, you're going to segfault when you try writing to them.