My variables are mixing values with each other ???? C++ - c++

I have two string variables that are mixing each others letters after a certain point and I have no idea why.
string dna1 and dna2 is read in from a .txt file like this:
string opfile1(string& dnafile, string& dnaseq1); // function dec
string opfile2(string& dnafile, string& dnaseq2);
int main()
{
string dna1;
string dna2;
string seq1;
string seq2;
order1 = openSecondFile(dna1, seq1);
order2 = openThirdFile(dna2, seq2);
//function calls ^
string opfile1(string& dnafile, string& dnaseq1); // function dec
{
string PName;
string frag;
ifstream in_s;
in_s.open(dnafile.c_str());
if(in_s.fail()) //if file does not exist a fail message will appear
{
cout << "Unable to open input file " << song1File << endl;
exit(EXIT_FAILURE);
}
getline(in_s, frag, '|');
Name = frag.substr(1);
in_s >> dnaseq1;
in_s.clear();
return Name;
}
//func def.
The function opfile2 is the exact same except wherever you see a '1', I replaced it with a '2' to match its variables.
Now when I print these out in my main function they appear like this:
cout << dnaseq1 << endl;
cout << dnaseq2 << endl;
Output:
FDFDAFDAF
DFDAFDATZY
Which is correct! Now, when I try to print them using a for loop this happens:
int columns = dnaseq1Size + 1;
for(int i = 0; i < columns; ++i)
{
if(i == 0)
{
cout << setw(3) << "-" << " ";
}
else
{
cout << setw(3) << dnaseq2.at(i) << " ";
}
}
Output:
terminate called after throwing an instance of 'std::out_of_range'
what(): basic_string::at: __n (which is 9) >= this->size() (which is 9)
- D F D A F D A F Aborted (core dumped)
(it starts printing the other notes)
I have no idea what's happening, can anyone help?
EDIT: I figured out the issue and fixed it. I think the issue had something to do with the fact I was using arrays and a "size" so I switched to a 2D vector and used .size instead and the issue fixed it self.

It's clear enough. Your string has size 9, (FDFDAFDAF for example) but you try and print musicalnotes2.at(9). If your string has size 9 then only 0 to 8 are legal indexes
As said in the comments the suspicious part is when you write
int columns = song2Size + 1;
for(int i = 0; i < columns; ++i)
...
Why do you add one there? That seems to be the problem.

It sounds like looks like your're trying to print out each char from the musicalnotes variables
one way to be able to do it is to wrap it in a function (easier to reuse)
void printNotes(const string &musicalNotes) {
cout << setw(3) << "-" << " ";
for(int i = 0; i < musicalNotes.length(); ++i)
{
cout << setw(3) << musicalNotes.at(i) << " ";
}
cout << endl;
}
int main()
{
//... code up until you wish to print it
printNotes(musicalnotes1);
printNotes(musicalnotes2);
//... if you want something afterward
return 0;
}
Here we replace the int columns = song2Size + 1; with the length of the string, and prior to writing anything from there we write out the -
Example output would be:
- F D F D A F D A F
- D F D A F D A T Z Y
I assume that song2Size would be equal to the musicalnotes2.length(), if that's the case you do write over the strings length and therefor you get your out of bounds error. If it contains 9 chars then it would be at index 0,1...7,8 not to 9

Related

C++ isdigit() Query for converting a char array to an int array

I am trying to convert an input character array, to an int array in c++.
Inputs would be in a format like: 'M 911843 6', where the first value of the char array is a uppercase letter, which I convert to an ASCII value and -55.
Edit: I should also mention I just want to use the iostream library
The last value of the char array can be a letter or number also.
I want to retain the exact number value of any input in the char array, which is why I convert to an ASCII value and -48, which retains the same number, but stored as an int value:
I use the checkdigit() function to check if the char input is a number or not.
The difficulty I am facing is that the input will always have a blank space at i[1] and i[8] (if we count i[0] as the first value) - so I try to give them an int value of 0 (int of a " " is 0)
Upon several debugging attempts, I found that it is after the blank space is given a 0 value, the output in my for loop keeps outputting the wrong values, I suspect it has something to do with the isdigit() function in my for loop.
If the spaces from M 911843 6 were removed, the int output is usually fine, e.g. a char input of
M9118436 will return an int array of [22][9][1][1][8][4][3][6].
The output with spaces: [22][0][-183][-120][37][-118][-59][72][0][-55]
Ideal output: [22][0][9][1][1][8][4][3][0][6]
The code is listed below, any help or advice would be greatly appreciated, thanks!!
#include <iostream>
using namespace std;
int main() {
char a[10];
int z[10];
int i = 0;
int r; //result of the isdigit check (0 or 1)
cout << "in ";
cin >> a;
for (int i = 0; i < 10; i++) {
r = isdigit(a[i]);
if (r == 0) {
if (i==1 || i==8)
z[i] = 0;
else z[i] = int(a[i]) - 55;
}
else {
z[i] = int(a[i]) - 48;
}
}
cout << z[0] << "\n" << z[1] << "\n"<< z[2]<< "\n" << z[3] << "\n"<< z[4] << "\n"<< z[5] << "\n"<< z[6] << "\n"<< z[7]<< "\n" << z[8] << "\n"<< z[9];
return 0;
}
The problem is that cin >> a; does not read sizeof(a) characters, but up to the first space character and will terminate that with a null.
That means that you array will containt 'M', '\0' and 8 uninitialized characters. You must read the characters one at a time with unformatted reads:
for (auto& c : a) {
cin.get(c);
if (!cin) {
cerr << "Incorrect input\n";
return EXIT_FAILURE;
}
}
Just a follow on from Serge's answer which gave me a good understanding of how strings are read - I solved my problem using cin.getline() function.

How to count how many times a specific letter appears in a string? (C++)

I've been struggling with a homework assignment that counts the amount of instances a uppercase letters, lowercase letters, and numbers in a string. appears in a string.
I'm using a one-dimensional array with a constant size of 132 to store the entered string, and I need to use two functions. One needs to count the amount of letter occurrences in the string and the other function will execute the output something similar to above. I'm struggling most with the letter counting aspect of the program itself.
Currently, this is what my current homework resembles for the most part. It's a work in progress (of course) so errors in the code are very likely.
void LetterCount(char c_input[], int l_count)
{
// code to count letters
}
void CountOut(//not sure what should go here yet until counting gets figured out)
{
// code that handles output
}
int main()
{
const int SIZE = 132;
char CharInput[SIZE];
int LetterCount = 0;
cout << "Enter a string of up to 132 characters in size: ";
cin.getline(CharInput, SIZE);
cout << "You entered: " << CharInput << endl;
Count(CharInput);
CountOut(//not sure what goes here yet);
return 0;
}
The output would look something like:
a - 2
b - 1
c - 1
d - 0
e - 1
etc...
I've tried some experimentation with for loops to count the letters and have seen some examples of the function gcount(), but I haven't gotten anything to work. Does anyone have a suggestion as to how I would count the letters in an inputted string?
map is a very efficient data structure here
#include <iostream>
#include <map>
using namespace std;
int main(){
string str = "a boy caught 2 fireflies";
map<char, int> str_map;
for(auto x : str) ++str_map[x];
for(auto x : str_map) cout << x.first << ' ' << x.second << '\n';
}
What you want is to build a simple histogram, and it's pretty easy to do. Since what you're looking at is chars, and there can be 256 possible values of an 8-bit char (in practice your input string probably uses less, but we'll be conservative here because memory is cheap), you'll want to start with an array of 256 ints, all of them initialized to zero. Then iterate over the chars your string, and for each char in your string, use that char-value as an offset into the array(*), and simply increment that item in the array.
When you're done, all that remains is to iterate over the ints in the array and print out the ones that are non-zero, and you're done.
(*) you may want to cast the char to unsigned char before using it as an offset into the array, just to avoid any chance of it being interpreted as a negative array-index, which would result in undefined behavior (this is only an issue if your input string contains ASCII characters 128 and higher, so it may not matter in your case, but it's always good form to make code that does the right thing in all cases if you can)
As Jeremy frisner said you're building a histogram, but I disagree with the types used.
You'll want to declare your histogram like so:
size_t histogram[sizeof(char)*CHAR_BIT] = {0};
The size_t because you might overflow without it, and you need enough space if it's a nonstandard byte size.
As for printing it out. You should take a look at an ASCII table and examine which values you need to print out.
You could do it by comparing c-strings with other c-strings. But with chars and strings you can get errors like: "const *char cant be compared with strings". So you'll have to compare each c string(array) index with other c string indexes. In this program I use if statements to look for certain vowels. The way it works is that each "string alphabet_letter" is equal to it's respective lowercase and capital letters (for comparison). this is a very redundant way to do it and, if you want to count all total letters, perhaps you should try a different way, but this method doesn't use very complicated methods that require deeper understanding.
using namespace std;
int main(){
int vowel;
string A = "aA";
string E = "eE";
string I = "iI";
string O = "oO";
string U = "uU";
string str;
string str1;
bool userLength = true;
int restart = 0;
do{
cout << "Enter a string." <<endl;
getline(cin, str);
int VowelA = 0;
int VowelE = 0;
int VowelI = 0;
int VowelO = 0;
int VowelU = 0;
for(int x = 0; x < 100; x++){
if(restart == 1){
restart = 0;
x = 0;
}
if(A[0] == str[x]){
VowelA = VowelA + 1;
}
if(E[0] == str[x]){
VowelE = VowelE + 1;
}
if(I[0] == str[x]){
VowelI = VowelI + 1;
}
if(O[0] == str[x]){
VowelO = VowelO + 1;
}
if(U[0] == str[x]){
VowelU = VowelU + 1;
}
if(A[1] == str[x]){
VowelA = VowelA + 1;
}
if(E[1] == str[x]){
VowelE = VowelE + 1;
}
if(I[1] == str[x]){
VowelI = VowelI + 1;
}
if(O[1] == str[x]){
VowelO = VowelO + 1;
}
if(U[1] == str[x]){
VowelU = VowelU + 1;
}
int strL = str.length();
if(x == strL){
cout << "The original string is: " << str << endl;
cout << "Vowel A: "<< VowelA << endl;
cout << "Vowel E: "<< VowelE << endl;
cout << "Vowel I: "<< VowelI << endl;
cout << "Vowel O: "<< VowelO << endl;
cout << "Vowel U: "<< VowelU << endl;
cout << " " << endl;
}
}
char choice;
cout << "Again? " << endl;
cin >> choice;
if(choice == 'n' || choice == 'N'){userLength = false;}
if(choice == 'y' || choice =='Y')
{
restart = 1; userLength = true;
cin.clear();
cin.ignore();
}
//cout << "What string?";
//cin.get(str, sizeof(str),'\n');
}while(userLength == true);
}
/*
Sources:
printf help
http://www.cplusplus.com/reference/cstdio/printf/
This helped me with the idea of what's a vowel and whats not.
http://www.cplusplus.com/forum/general/71805/
understanding gets()
https://www.programiz.com/cpp-programming/library-function/cstdio/gets
Very important functional part of my program...Logic behind my if statements, fixed my issues with string comparison
What i needed to do was compare each part of one cstring with another c string
strstr compares two strings to see if they are alike to one another this source includes that idea-> https://www.youtube.com/watch?v=hGrKX0edRFg
so I got the idea: What is one c string was all e's, I could then compare each index for similarities with a c string whos definition was all e's.
At this point, why not just go back to standard comparison with strings? But you cant compare const chars to regular chars, so I needed to compare const chars to const chars
hence the idea sparked about the c strings that contained both e and E.
https://stackoverflow.com/questions/18794793/c-comparing-the-index-of-a-string-to-another-string
https://stackoverflow.com/questions/18794793/c-comparing-the-index-of-a-string-to-another-string
Fixed Error with using incremented numbers outside of involved forloop.
https://stackoverflow.com/questions/24117264/error-name-lookup-of-i-changed-for-iso-for-scoping-fpermissive
understanding the use of getline(cin, str_name)
https://stackoverflow.com/questions/5882872/reading-a-full-line-of-input
http://www.cplusplus.com/reference/istream/istream/getline/
http://www.cplusplus.com/forum/beginner/45169/
cin.clear - cin.ignore --fixing issue with cin buffer not accepting new input.
https://stackoverflow.com/questions/46204672/getlinecin-string-not-giving-expected-output
*/

Variables seem to be changing value on their own

Ok so my project is a program that analyses a .txt file that has a bunch of DNA strands of varying lengths. I got it all to work in 3 functions but my teacher wants us to us oo programming. So i put my code in a class and broke it up into different functions. Now, however my variables seem to randomly change their value and I don't know why.
I ran a bunch of tests with my "sum" variable (but it is not the only one doing this) and it calculates the correct value in the function but if I cout the value of "sum" back in my main, the value is changed to a ridiculous number.
Here is the code: it is not my whole program just where the problem variable is and how it is used.
If this isnt enough code to show the problem i can add more i just didnt want to make it cluttered.
DNAProcessing.cpp
void DNAProcessing::CalcSumAndMean()
{
int lineLength = 0;
int lineCounter = 0;
int wholeFileStringLen = 0;
double sum = 0;
double mean = 0;
string wholeFileString = "";
string line;
bool filefail = false;
ifstream DNAFile;
DNAFile.open(nameoffile.c_str());
if(DNAFile.fail())
{
filefail = true;
return;
}
else
{
cout << "\nYour data was processed\n" << endl;
}
while(DNAFile >> line)
{
//cout << line << endl;
lineCounter += 1;
lineLength = line.length();
sum += lineLength;
wholeFileString += line;
}
cout << "sum: " << sum << endl; // with my test .txt file this outputs 736
mean = (sum / lineCounter);
wholeFileStringLen = wholeFileString.length();
cout << "sum: " << sum << endl; // with my test .txt file this outputs 736
}
main.cpp
int main()
{
srand(time(0));
bool noexit = true;
string yesorno;
string filename;
while(noexit == true)
{
cout << "Would you like to process a list of DNA strings? (y/n)" << endl;
cin >> yesorno;
if((yesorno == "y") || (yesorno == "Y" ))
{
cout << "please input the name of the file you wish to process." << endl;
cin >> filename;
DNAProcessing DNAStrandFile(filename);
DNAStrandFile.CalcSumAndMean();
cout << "sum: " << DNAStrandFile.sum << endl; //for some reason sum turns into 3.18337e-314 and i have no clue why
if (DNAStrandFile.filefail == false)
{
cout << "sum: " << DNAStrandFile.sum << endl; // same here
DNAStrandFile.CalcNucleobaseRelProb();
DNAStrandFile.CalcBigramRelProb();
DNAStrandFile.CalcVarianceAndStndDev();
DNAStrandFile.CalcNormRand();
DNAStrandFile.PrintData();
DNAStrandFile.PrintNewList();
}
else
{
cerr << "No file found" << endl;
}
}
else if((yesorno == "n") || (yesorno == "N"))
{
noexit = false;
}
else{}
}
}
output while passing my test .txt file into this program.
sum: 736
sum: 736
sum: 3.18337e-314
sum: 3.18337e-314
Since sum is declared as double, it's value of 0 may not be stored exactly as zero, for all practical purposes, value of 3.18337e-314 can be considered as zero. You may define a threshold value
double epsilon = 0.00001 ; // depending on precision
and if sum < epsilon, sum = 0.0 (not needed though)
In your example, you have used sum as a local variable as well, either don't declare local variable, just use the member variable or declare the local variable as different name to avoid confusions
The value of a local variable is valid within the scope of the function,thats why you are getting correct answer inside method.
But no value is returned back,therefore garbage value is printed in the main.
Try sending the variable in the method by reference, then their exact value will be available in main also. Try it.

Remembering a variable for next use

I am having a problem with remembering a variable for next use and printing it out. I explain it more so understand what am I trying to do in my program.
I have a person walking on a rectangle of size a b. I input starting location x y together with persons starting direction (North = y+1, South = y-1, East = x+1, West = x-1 // in my code it is S,J,V,Z). So my input looks like this:
5 6 // a b
3 3 S // x y s(this stands for starting direction - north)
Now, I input number of moves d to generate for the person where it should move.
I enter number 4, and it can generate from 3 letters: D, L, P (Forward, turn left 90 degrees, turn right 90 degrees).
4 // d
PLDL // moves
Now, the person should be walking by those moves. So if the person location and starting direction is 3 3 S, it should just turn right (my direction is east but same location), then left (direction is north again, same location), then forward (now I move y+1, my direction is still north) and last move is turn left(direction west). So mi final location and direction (output) is:
3 4 Z
Hope you understand it. If is something unclear, just ask in comment.
I am getting weird output now, unreal numbers. I cant figure out how to put together variables and if conditions to solve it. My code takes first, starting direction and location, but later on when I generate moves, it should change to final output based on the generated string. Sadly, it doesnt work as I expect. Do you have any suggestions? My question is kind of wide but I hope we can solve it together.
#include <iostream>
#include <string>
#include <stdlib.h>
#include <string.h>
#include <vector>
using namespace std;
int n; // pocet uloh
int a; // rozmer obdlznika a
int b; // rozmer obdlznika b
int i;
static const char alpha[] = {'D', 'L', 'P'};
char genRandom()
{
return alpha[rand() % strlen(alpha)];
}
// end of generator
// funkcia na pohyb
void pohyb (){
int x[i];
int y[i];
string sD = ""; // starting direction
string mD = ""; // middle direction (stored one for next use)
string eD = ""; // ending direction to print out in output
string d = ""; // number of generated directions eg. d=6 ==> PDDLPPD
for (int i=0; i < d.size(); i++){
if (sD[i] == 'S'){
if(d[i] == 'D'){
y[i] = (y[i]+1);
}else if(d[i] == 'L'){
mD[i] == 'Z';
}else if(d[i] == 'P'){
mD[i] == 'V';
}
}else if (sD[i] == 'J'){
if(d[i] == 'D'){
y[i] = (y[i]-1);
}else if(d[i] == 'L'){
mD[i] == 'V';
}else if(d[i] == 'P'){
mD[i] == 'Z';
}
}else if (sD[i] == 'V'){
if(d[i] == 'D'){
x[i] = (x[i]+1);
}else if(d[i] == 'L'){
mD[i] == 'S';
}else if(d[i] == 'P'){
mD[i] == 'J';
}
}else if (sD[i] == 'Z'){
if(d[i] == 'D'){
x[i] = (x[i]-1);
}else if(d[i] == 'L'){
mD[i] == 'J';
}else if(d[i] == 'P'){
mD[i] == 'S';
}
} // koniec if podmienky
eD = mD[i];
} // koniec for loopu
// vystup
for ( i = 0 ; i < n ; i++ )
{
if(!((x[i]>=0)&&(x[i]<=a) & (y[i]>=0)&&(y[i]<=b))){
cout << x[i] << ' ' << y[i] << ' ' << eD[i] << ' ' << "SPADOL" << endl;
}else{
cout << x[i] << ' ' << y[i] << ' ' << eD[i] << endl;
}
}
} // koniec funkcie pohyb
int main() {
cin >> n;
vector<int> x(n); // x position
vector<int> y(n); // y position
vector<int> d(n); // zombie directions generation ex. DPLDDP
vector<string> sD(n); // starting direction
vector<string> eD(n); // ending direction
while(!((n >= 1)&&(n <=15000)))
{
cout << "max 15000" << flush;
cin >> n;
}
cin >> a >> b;
while(!((a >= 1)&&(a <=100) & (b >= 1)&&(b <= 100)&&(a!=b)))
{
cout << "chyba max 100 alebo a!=b" << endl;
cin >> a >> b;
}
for (i = 0; i < n; i++)
{
cout << "Uloha " << i+1 << ":" << endl;
cin >> x[i];
cin >> y[i];
cin >> sD[i];
while(!((x[i]>=0)&&(x[i]<=a))) {
cout << "Try Again x: " << flush;
cin >> x[i];}
while(!((y[i]>=0)&&(y[i]<=b))) {
cout << "Try Again y: " << flush;
cin >> y[i];}
cin >> d[i];
while(!((d[i]>=1)&& (d[i]<=200))) {
cout << "Try Again d: " << flush;
cin >> d[i];}
for (int counter=0; counter<d[i]; counter++)
{
cout << genRandom();
}
cout << endl;
} // koniec for
pohyb();
system("pause");
}
Sample input:
3
3 5
2 2 S
8
DPLDLPDD
2 4 Z
7
PDDPDPD
2 1 J
8
PPDLDDDD
and output
2 5 S SPADOL // spadol means his location is out of the rectangle
3 4 J
0 2 Z SPADOL
Rather than fix your code, I'm going to give you a number of explanations that should help you understand and fix it yourself.
Firstly, let me adjust your understanding of what a variable is. In a programming language, there are values that need to be stored. Once we store a value, we will need to be able to retrieve it again and so we will need a way to describe where it was stored.
int i = 5;
This tells the compiler to create an instance of the int value type, to assign it the value of 5, and to call it i.
However, C++ is a scoped language. That means that there is a limitation on how visible any given name is.
int x() {
int i;
}
int y() {
i = 5; // ERROR: I not declared in this scope.
}
In the above code, we declared i in one scope - the function body of x - but then tried to use it in another.
C++ scopes are generally distinguished by '{ ... }', for example the following is valid:
#include <iostream>
int i = 0; // globally visible 'i'.
void f() { std::cout << "from f i = " << i << '\n'; }
int main() { // <-- function body scope
int i = 1;
{ // inner scope
int i = 2; // new variable, called 'i', but only inside this scope.
{ // <-- another inner scope
i = 3;
f();
}
} // scope ended, the second 'i' has no gone away.
std::cout << "from end of main i = " << i << '\n';
return 0;
}
The above program prints "0" and then "1".
C++ allows us to do something call "shadowing" - we can use the same name for different variables in different scopes.
Scope also affects the "lifetime" of variables (see http://ideone.com/fXPlB7), but I'm not going to cover that.
Let me demonstrate more clearly the implications - that the variables have a similar name but are NOT the same variable:
int i = 5;
void f(float i)
{
std::cout << "in f, i is " << i << '\n';
}
int main()
{
char i[] = "Hello";
f(3.141);
std::cout << "in main, i is " << i << '\n';
return 0;
}
What does this program print?
Make sure you understand this: i is not changing, but rather which variable i refers to in a given scope.
In your function pohyb, you have the following two lines of code:
string d = ""; // number of generated directions eg. d=6 ==> PDDLPPD
for (int i=0; i < d.size(); i++){
This declares a new variable and within this scope causes the name d to refer to it. d is an empty string.
The next line iterates over all the values in d. How many values are in the empty string? 0. So, the for loop line says this:
int i = 0;
is i < 0?
0 is not < 0, so the loop is never executed.
Your next problem is the difference in C++ between a character-string (C-string) and a character-array.
C++ is based on C, which did not have a 1st-class definition of a "string". Instead, C has a convention that says: "a string is an array of 0 or more chars followed by a zero-value char".
char empty[1] = { 0 }; // valid, empty string. it has 1 element, the 'nul'.
char a[] = { 'a', 0 }; // represents "a", size is 2 chars, 'a' and '\0'
char hello[] = { 'h', 'e', 'l', 'l', 'o', 0 }; // size 6, 5 letters and a nul
char Hello[] = "hello"; // short-cut for writing the above
char ten[] = { '1', '0', 0 }; // '0' and 0 are not the same
char hundred[] = { '1', '0', '\0' }; // '\0' == 0
char ouch[4] = "ouch"; // ERROR: the string is actually 5 chars.
All of the C functions that deal with "strings" (not to be confused with std::strings), operate on this principle -- the only way to tell the length is to count characters until you reach a value of zero.
For your purposes, you actually want an array of characters, but that does not automatically make them a string.
Your code uses strlen to find the number of elements in a char array - this is incorrect, and potentially dangerous for your application. The bytes immediately following the 3 valid elements of alpha could be anything, so strlen might return 3 or it might return very large values.
What you actually want is the C keyword sizeof.
sizeof(X) is a compile-time determination of the size of a thing. When X is a fully qualified array, it returns the size in bytes of X. Be aware that this means you can only use it on an array in the global or local scope: when you pass arrays to functions they are passed by pointer.
#include <iostream>
char hello[] = "hello"; // has size 6: 'h', 'e', 'l', 'l', 'o', 0
void f(char x[])
{
std::cout << "f(x), sizeof x = " << sizeof(x) << '\n';
}
void g()
{
char x[] = "world";
std::cout << "g() sizeof x = " << sizeof(x) << '\n';
}
void h()
{
int x[] = { 1, 2, 3, 4, 5, 6, 7 };
std::cout << "h() sizeof x = " << sizeof(x) << ", but sizeof(x[0]) = " << sizeof(x[0]) << '\n';
}
int main()
{
std::cout << "main() sizeof hello = " << sizeof(hello) << '\n';
f();
g();
h();
return 0;
}
What do you expect the output to be? Paste to ideone if you want to find out.
For your code, the use of a char array looks correct, so you want to use sizeof to determine how many chars are in the array. Remember that sizeof returns the size in bytes, the formally correct way to write this would be:
size_t index = size_t(rand()) % (sizeof(alpha) / sizeof(*alpha))];
return alpha[index];
This will take the total size of alpha and divide it by the size of what type alpha points to/contains (a char). These values are known at compile time so the compiler will do this calculation and emit code equivalent to:
return alpha[rand() % (3 / 1)];
or just
return alpha[rand() % 3];
There are 3 elements in alpha, but C/C++ arrays are 0 indexed, so the modulo will provide us a value [0,3) i.e. 0, 1 or 2.
Lastly, you were concerned about working with if statements. For complex logic, sometimes the best thing to do is to write them out and run thru them by hand. You may want to familiarize yourself with the switch keyword which takes a variable and matches it against potential values:
#include <iostream>
#include <string>
int main()
{
std::string input;
while (std::cin.good()) {
std::cout << "Direction? (n/s/e/w/q): ";
std::getline(std::cin, input);
// if input is empty, input[0] would be undefined behavior.
if (input.empty())
continue;
switch (input[0]) // check the first character only
{
// input[0] is of type char, so we can express our values
// a character literals. we could also write the ascii values,
// e.g. for 'n' we could put "case 110:"
case 'n':
std::cout << "You have entered a dark room.\n";
break; // escape the switch, not the loop.
case 'e':
case 's': // no break, 'e' falls thru
case 'w': // still no break, 'e' and 's' fall thru
std::cout << "You can't go that way.\n";
break;
case 'q':
std::cout << "bye!\n";
return 0;
break;
default:
std::cout << "I asked you to type n, s, e, w or q, but you typed " << input << ".\n";
break;
}
}
return 0;
}
http://ideone.com/s4xana
---- EDIT ----
On "remembering" values between scopes. Within a function body and nested scopes, this happens automatically:
int main() {
int i = 1;
{ // inner scope
std::cout << "inner scope\n";
{ // another inner scope
if (i == 1) {
// this is a scope
std::cout << "i = " << i << '\n'; // prints 1
}
}
}
}
But between functions and modules, you need to make them function arguments.
#include <iostream>
int f(int i, int j, int k) {
std::cout << "f() i = " << i << ", j = " << j << ", k = " << k << '\n';
i = 10;
j = 100;
k = 300;
}
int main() {
int j = 42;
f(j, j, j);
std::cout << "in main: j = " << j << '\n';
return 0;
}
What does this print? Remember: variables are locally scoped. Just because they have the same name as another variable in a different scope does not make them connected.
Think of the following code like this, WARNING: PSUEDO CODE:
define f - takes int as f::i, int as f::j, int as f::k
"f() i = ", f::i, ", j = ", f::j, ", k = ", f::k, '\n';
f::i = 10;
f::j = 100;
f::k = 300;
end f
define main
declare main::j as int
let main::j be 42
call f with f::i = 42, f::j = 42 f::k = 42
"in main: j = " << main::j << '\n';
end main
Now it perhaps makes more sense - even tho we changed j in f it was not the same j as we are seeing in main.
How to overcome this:
C++ provides two methods. The old, 'c' method is to pass the address of a variable, called passing it by pointer. Pointers can get hairy and often confuse new programmers, so instead I'm going to show you the C++ mechanism: reference.
As you just saw above, when you call a function with an argument, C++ creates a new locally-scoped variable and copies the value of the input variable into it:
void f(int n)
{
n += 2;
}
f(5);
Here we see that '5' is not a variable, but a hard coded value. There is no way that 'f' could work otherwise - throughout the program '5' would have become 7.
When we want to say "call f and operate on my LOCAL variable" we use a reference.
void f(int& n)
{
n += 2;
}
int main()
{
int x = 23;
f(x);
// x is now 25
}
It's tempting to think that a reference is somehow just an alias, but that's not how they are implemented. A reference is a clever way of passing the location in memory of an existing variable, but not clever enough to be aware of that variable going away or being relocated in memory.
std::vector<int> v;
v.push_back(5);
int& first = v[0]; // reference to the first element of v at the moment,.
std::cout << "first = " << first << '\n'; // prints 5.
v.reserve(2000); // causes 'v' to relocate in memory
v[0] = 25;
std::cout << "first = " << first << '\n'; // may crash or print 5, but not 25.
The other thing to remember about references is that once they are connected to something, you cannot change the connection:
int a = 5, b = 6;
int& r = a;
std::cout << r;
r = b;
std::cout << r;
std::cout << a;
This prints: 566, not 565 because int& r = a made r a reference to a. When we said r = b, because r is now a reference to a we effectively said a = b.
---- EDIT 2 ----
C and C++ have a modifier keyword, const which is a contract that says you promise not to modify a thing. If you want to write a function that accepts a complex object by reference (to avoid copying strings, etc, which is expensive), but you don't want to change it, you can use the const modifier:
#include <iostream>
#include <string>
void writeln(const std::string& str)
{
std::cout << str << '\n';
}
int main()
{
std::string greeting = "hello";
writeln(greeting);
}
Also, a note on '&'. It doesn't matter to the compiler whether you write string& str or string &str, they mean the same thing. Whether & means 'reference' or 'address of' (for pointers) or 'and' (for logic) depends on the context.
Note: these are written before you post your sample input and output.
When you define alpha as
static const char alpha[] = {'D', 'L', 'P'};
it's really a char array of three elements. However strlen() is a function to count the number of characters before the 1st \0 (NUL) character encountered. So strlen() in your genRandom() will not work as you expect (I guess it returns a random large number.) You should define alpha as
static const char alpha[] = "DLP";
to add an implicit 4th element \0 to alpha.
In your pohyb() you define string varibales sD, mD and d with empty initial values. They have no relationship with vector<int> d and vector<string> sD, mD in your main(). So all your i < d.size(), sD[i] == 'S', d[i] == 'D'... will not work as you expect. You should pass sD, mD and d in your main() to pohyb() as arguments.
Update: OK I'll be more specific. Because string d in pohyb() is unrelated to vector<int> d in main() and remains empty throughout pohyb(), for (int i=0; i < d.size(); i++) will not run even once. Because int x[i], y[i] in pohyb() are unrelated to vector<int> x, y in main() and contain uninitialized (= random) i elements (here i happens to be equal to n when pohyb() is invoked) you see weird ("SPADOL") outputs. Please learn how to pass parameters to a function in C++ first. You will get nowhere until you learn it.
I haven't checked if these two are all you need. They are just obvious mistakes I found so far. You might need a fundamental rework on your program structure.

Having a SegFault where there should be none

Program keeps throwing a seg fault under conditions where it should not. I have arrays and vectors, and have tried both options. Seems to always throw the seg fault on the third value of the array/vector of 3. There is another functions after this that when commented out lets it go a few more times. But the results is the same, it still seg faults.
char bits[3];//vector<char> bits(3,'0');
vector<string> inputs;
string temp;
for(int x = 0;!i.eof();x++)
{
getline(i, temp);
inputs.push_back(temp);
}
for(int x = 0; x < inputs.size();x++)
{
cout << endl << inputs[x];
}
for(int x = 0; x < 3;x++)
{
cout << endl << bits[x];
}
for(int cursor = 0;cursor< inputs.size();cursor++)
{
cout << endl << "bitstogoin " << cursor;
cout << endl << inputs.size();
bits[0]=inputs[cursor][0];
cout << endl << "got1 " << bits[0];
bits[1]=inputs[cursor][1];
cout << endl << "got2 " << bits[1];
bits[2]=inputs[cursor][2]; //seg faults on this line.
cout << endl << "bitsin";
for(int t = 0; t < 3;t++)
{
cout << bits[t];
}
The commands that are being given via the input file look like:
100 10110101
101 11001011
111
110
000
111
110 etc...
Note: this probably has nothing to do with your segfault but should still be addressed.
The following input loop has two problems. First, the x is pointless because you never do anything with the value of x. Second, looping on eof() is rarely correct (see: Testing stream.good() or !stream.eof() reads last line twice).
for(int x = 0;!i.eof();x++)
{
getline(i, temp);
inputs.push_back(temp);
}
Try the following instead:
while (getline(i, temp))
{
inputs.push_back(temp);
}
In your code here:
vector<string> inputs;
string temp;
for(int x = 0;!i.eof();x++)
{
getline(i, temp);
inputs.push_back(temp);
}
You read in strings and place them into a vector.
Ask yourself this? What is the length of each of these strings?
When you call
bits[2]=inputs[cursor][2];
You are accessing the 3rd character of a string in that vector. Before this statement try this:
if (inputs[cursor].size() < 3)
cout << "String is less than 3!" << endl;
If your program prints that debug line, then you know you're in trouble.
Indeed, you're not really doing anything to check the lengths of your strings before you try to access characters in them.