Remembering a variable for next use - c++

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.

Related

I can't figure out why my while loop is not giving the expected result ):

I can't figure out what I'm doing wrong. I am new to c++ and am practicing. I found code that writes two letter combinations with nested while loops and adds .com at the end. That code worked fine. In order to practice I wanted it to output a third combination but for some reason everytime I add the a third while loop the one in the middle only outputs {. Any help is greatly appreciated! Thank you!!!
#include <iostream>
using namespace std;
int main() {
char letter1;
char letter2;
char letter3;
cout << "Three-letter domain names:" << endl;
letter1 = 'a';
while (letter1 <= 'z') {
letter2 = 'a';
while (letter2 <= 'z') {
letter3 = 'a';
++letter2;
}
while (letter3 <= 'z') {
cout << letter1 << letter2 << letter3 << ".com" << endl;
++letter3;
}
++letter1;
}
return 0;
}
Your third loop needs to be nested inside your second loop.
But there is an easier way which has the added bonus that it's also portable C++ (your assumption that the lower case letters are contiguous is the issue). Essentially this is a single integral counter converted to a base 26 radix:
#include <iostream>
int main() {
constexpr char alphabet[] = "abcedfghijklmnopqrstuvwxyz";
constexpr std::size_t radix = sizeof(alphabet) - 1;
for (std::size_t i = 0; i < radix * radix * radix; ++i){
std::cout
<< alphabet[i / radix / radix]
<< alphabet[(i / radix) % radix]
<< alphabet[i % radix]
<< ".com\n"
;
}
}
The third loop shall be a nested loop of the second while loop. That is there should be three nested loops.
Also as the variables letter1, letter2, and letter3 are not used outside the loops it is better to make them local variables of the loops. That is it is better to substitute the while loops for for loops.
Here is a demonstrative program.
#include <iostream>
int main()
{
std::cout << "Three-letter domain names:" << '\n';
for ( char letter1 = 'a'; letter1 <= 'z'; ++letter1 )
{
for ( char letter2 = 'a'; letter2 <= 'z'; ++letter2 )
{
for ( char letter3 = 'a'; letter3 <= 'z'; ++letter3 )
{
std::cout << letter1 << letter2 << letter3 << ".com" << '\n';
}
}
}
}
Its output is
Three-letter domain names:
aaa.com
aab.com
aac.com
aad.com
aae.com
...
and so on.
Pay attention to that in general it is not necessary that letters follow each other without gaps in the used coding system.

C6001: using unititialized memory "str[i]"

The program works fine, although the fist printed number is always "3452816845". I have tried initializing "str[i]" by adding curly brackets when defining the array, or by giving it NULL value, but then the first printed number is always "zero", and only then it prints what I entered. Please take a look below:
#include <iostream>
using namespace std;
int main() {
unsigned* str = new unsigned[1000];
int cnt = 0;
char ch;
int a;
cout << "Please enter text: ";
do {
cin.get(ch);
if (ch <=57 && ch >=48) {
int a = ch - '0';
cnt++;
str[cnt] = a;
}
} while (ch != '\n');
cout << "The entered numbers are: ";
for (int i = 0; i <= cnt; i++) {
cout << str[i] << " "; // here is where the error appears
}
delete[] str;
return 0;
}
Do not using namespace std;. Especially not in headers, but try to not use it in plain .cpp files either. It's more convenient to debug code that unambiguously tells you which namespace an identifier came from right where that identifier is being used.
unsigned* str = new unsigned[1000];
Since the advent of C++11, "naked" memory allocation like that is frowned upon, and is definitely not necessary here.
You could just use a static array (unsigned str[1000];).
You could use smart pointers (auto str = std::make_unique<char[]>(1000);).
Best choice, use C++ containers, like <vector>, <string>, or (if overhead really bothers you) <array>.
if (ch <=57 && ch >=48) {
int a = ch - '0';
Do not use "magic numbers" in your code. If you want to know if the character entered is a digit, use isdigit, which is more expressive and works even for non-ASCII encodings that might have their digits at a different location in the code table.
int a = ch - '0';
This isn't wrong, as the standard guarantees this to work for digits. Note that similar arithmetic on characters (the infamous ... - 'a') is frowned upon though, and will break as soon as you leave the realm of strict ASCII-7 encoding.
cnt++;
str[cnt] = a;
C/C++ start counting at zero. You just left the first item in the array uninitialized. The beauty of the post-increment is that you can do it right there where you use the index, i.e. str[cnt++] = a;.
for (int i = 0; i <= cnt; i++)
cout << str[i] << " "; // here is where the error appears
}
Very C, and also wrong. You didn't initialize str[0], so the first round through that loop accesses uninitialized memory. If you had initialized str[0] (by incrementing cnt only after using it as an index), i <= cnt would go one item beyond what you wrote into str[], again accessing uninitialized memory. A loop should run from 0 to < cnt (not <=).
If you took my earlier advice to use <vector> or <string>, there's a much better way to loop through the items stored in it, the range-for.
#include <iostream>
#include <vector>
int main()
{
char ch;
std::vector< int > digits;
std::cout << "Please enter text: ";
do
{
std::cin.get( ch );
if ( std::isdigit( ch ) )
{
digits.push_back( ch - '0' );
}
} while (ch != '\n');
std::cout << "The entered numbers are: ";
for ( auto & i : digits )
{
std::cout << i << " ";
}
std::cout << std::endl;
return 0;
}
You never initialize str[0], but you output it.
The problem is here:
...
if (ch <=57 && ch >=48) {
int a = ch - '0';
cnt++;
str[cnt] = a;
}
...
You are incrementing cnt too early, leaving str[0] uninitialized. You should do:
if (ch <=57 && ch >=48) {
int a = ch - '0';
str[cnt++] = a;
}
Also you do have a problem in your for loop; You should start from 0 till the last initialized element in the string which is at index cnt - 1. It should be like this:
for (int i = 0; i < cnt; i++) {
cout << str[i] << " ";
}
or
for (int i = 0; i <= cnt - 1; i++) {
cout << str[i] << " ";
}

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
*/

wraparound c++ for ASCII

I'm Matt, first time posting. I'm in school and learning c++ at the moment and I'm stuck on this problem. I can't seem to find the solution so I'm looking for help.
#include <iostream>
using namespace std;
int main()
{
char ch;
cin >> ch;
if(ch <= 122){
cout << ++ch;
cout << ++ch;
}else if (ch > 122){
cout << static_cast<char>(97)++ch;
cout << static_cast<char>(97)++ch;
}
}
The program is very basic. All it needs to do is be fed a lowercase letter and the program just needs to spit out the next two characters. My problem is that after 'z' I don't know how to wrap back around to 'a'. I've tried to static_cast but it says I can'. I've tried reassigning the variable and it says I can't. I've tried several other basic things but none seem to work.
Thank you in advance for the help!
First, don't use magic numbers like 122 and 97. Use the actual character value.
Second, just declare a string abcdefghijklmnopqrstuvwxyz, and index into that string. This eliminates the need for 122, 97, or any other number. Not only that, you can probably see how to do the problem much easier when dealing with indices such as 0, 1, 25, etc. instead of 122, 97, etc.
Once you do that, a little bit of insight shows that the next two characters will be at position (if positions start at 0), (index + 1) % 26 and (index + 2) % 26. The % is the modulus operator, and it returns the remainder after a division is done.
For example, if the current character is y, the yis located at position 24 of the string. So
(24 + 1) % 26 = 25 % 26 = 25
and
(24 + 2) % 26 = 26 % 26 = 0
So the next two characters are situated at position 25 and position 0, which are z and a.
Take another example: z:
(25 + 1) % 26 = 26 % 26 = 0
and
(25 + 2) % 26 = 27 % 26 = 1
So the next characters after z are a and b.
Basically, when you get an assignment where the data "wraps around" to 0, then the word "remainder" or "modulo arithmetic" should immediately come to mind.
So the final program would look like this:
#include <iostream>
int main()
{
char ch;
const char * alphabet = "abcdefghijklmnopqrstuvwxyz";
std::cin >> ch;
int position1 = ch - 'a'; // get position of input character
int position2 = (position1 + 1) % 26; // get position of next character
int position3 = (position1 + 2) % 26; // get position of next next character
// output results
std::cout << ch << alphabet[position2] << alphabet[position3];
}
Live Example
(assuming that the input is: 'a' - 'z')
Keep It Simple
Solution 1:
#include <iostream>
int main()
{
char ch = 0;
std::cin >> ch; // "fed a lowercase letter"
// "spit out the next two characters"
if (ch < 'y')
std::cout << ++ch << ++ch;
else if (ch == 'y')
std::cout << "za";
else // (ch=='z')
std::cout << "ab";
}
Solution 2:
#include <iostream>
int main()
{
const char * lut = "abcdefghijklmnopqrstuvwxyzab";
char ch = 0;
std::cin >> ch; // "fed a lowercase letter"
ch -= 'a'; // lowercase letter to index
// "spit out the next two characters"
std::cout << lut[++ch] << lut[++ch];
}
Try to use the following code for your problem.
#include <iostream>
using namespace std;
int main()
{
char ch = '\0';
cin >> ch; // "fed a lowercase letter"
char c_next;
c_next = (ch-'a'+1)%26+'a';
cout <<c_next;
c_next = (ch-'a'+2)%26+'a';
cout << c_next;
return 0;
}
Here is one way at going about tackling your problem that is clean and elegant. It is very readable that uses a look up table, converts caps to lowercase using a bit of modulo arithmetic; it also leverages some of the newer features of modern C++ such as range loops.
#include <iostream>
#include <ccytpe> // needed for ::tolower
int main() {
// ascii a-z [97,122]
char alphabet[26] = {}; // 0 initizlize this will be a look up table
int i = 97;
for( auto & c : alphabet ) {
c = static_cast<char>( i );
i++;
}
// check to see if our table is correct
for( auto & c : alphabet ) {
std::cout << c << " ";
std::cout << '\n';
}
std::cout << '\n';
// Alphabet Seems to be fine.
char c = {};
std::cout << "Please enter a lower case character: ";
std::cin >> c;
if( c >= 'A' && c <= 'Z' ) {
::tolower( c ); // make sure that it's not in caps
} else if( c >= 'a' && c <= 'z' ) {
// nothing to do
} else {
std::cout << "Error: input value\n";
return -1;
}
// Now that we have the correct inputs we can show your next two characters.
// Since we know that the ascii table has a range of [97,122] for
// lower case letters and that our array index starts at 0; what we can do
// is a little bit of arithmetic to take the input character and set that
// to the index value of the array above. Then use the array indexing to
// output the next 2 characters. To do this we simply just need to subtract 97 or 'a'
c = c - 'a';
// Now we can print the two lines using the adjusted c value with
// a little bit of modulo arithmetic using the stride, size, or
// length of the alphabet.
int stride = 26;
std::cout << alphabet[++c % stride] << '\n';
std::cout << alphabet[++c % stride] << '\n';
// And we are done!
return 0;
}
This is what the code would look like without the comments and the code to print the whole alphabet:
#include <iostream>
#include <cctype>
int main() {
char alphabet[26] = {};
int i = 97;
for( auto & c : alphabet ) {
c = static_cast<char>( i );
i++;
}
char c = {};
std::cout << "Please enter a lower case character: ";
std::cin >> c;
if( c >= 'A' && c <= 'Z' ) {
::tolower( c );
} else if( c >= 'a' && c <= 'z' ) {
// nothing to do
} else {
std::cout << "Error: input value\n";
return -1;
}
c = c - 'a';
int stride = 26;
std::cout << alphabet[++c % stride] << '\n';
std::cout << alphabet[++c % stride] << '\n';
return 0;
}

While loop terminates after one iteration

I am trying to write a function in C++ to evaluate a postfix notation equation. My general strategy is to scan a string (in the proper format, e.g. "10 20 + 30 -").
I am doing this by incrementing an index variable i. At each increment, I check to see if the character is a digit, operator, or neither. If it's a digit, I use the getNextNum() function to get all following digits, convert that to a float, then push it to a stack. I also increment i by the length of the number captured.
If the character is an operator, I get the top two elements of the stack, do the operation, then push the result back to the stack.
The trouble is, my while loop only seems to go through once. The function only returns the first number in the string. I can't figure out what's wrong, I would appreciate any help! I inserted cout statements in the while loop, and i is only incrementing to the index after the first number.
EDIT: Ok, I added the getNextNum() function. Also, I updated the evalPostfix() with a cout of strLength, as well as i after each iteration of the while loop. When running the given code, I get this:
Running…
Please enter an expression in postfix notation: 555 666+
3
555
3
Your expression evaluates to: 555
It seems like strLength is being set to less than it should. Why could this be?
#include <iostream>
#include <string>
#include <vector>
#include <deque>
#include <stack>
using namespace std;
string getNextNum(string equation, int i);
float evalPostfix(string postfix);
float doOperation(float x, float y, char op);
float doOperation(float x, float y, char op)
{
switch (op) {
case '+':
return x + y;
case '-':
return x - y;
case '*':
return x * y;
case '/':
return x / y;
default:
return 0.0;
}
}
string getNextNum(string equation, int i)
{
string num = "";
const string DELIM = "+-*/%^ ";
while (i<equation.length()) {
// Iterate through equation until you hit a delimiter.
if (DELIM.find(equation[i]) != -1) {
break;
}
num += equation[i];
i++;
}
return num;
}
float evalPostfix(string postfix)
{
const string OPS = "+-*/%^";
const string NUMS = "0123456789";
int strLength = postfix.length();
stack<float> numStack;
int i = 0;
cout << strLength << endl;
while (i<strLength) {
if (NUMS.find(postfix[i]) != -1) {
// If a character is a digit, then you should get the
// value and push it to the stack (could be multiple characters long).
string sNextNum = getNextNum(postfix, i);
float fNextNum = atof(sNextNum.c_str());
numStack.push(fNextNum);
cout << sNextNum << endl;
i += (sNextNum.length() - 1);
}
else if (OPS.find(postfix[i] != -1)) {
// Otherwise, pop the top two elements of the stack, perform the
// operation, then push the result back to the stack.
char op = postfix[i];
float x = numStack.top();
numStack.pop();
float y = numStack.top();
numStack.pop();
float z = doOperation(x, y, op);
numStack.push(z);
}
i++;
cout << i << endl;
};
// Once the entire string has been scanned through, there should be a float
// left in the stack, simply return that.
return numStack.top();
}
int main ()
{
cout << "Please enter an expression in postfix notation: ";
string postfix;
cin >> postfix;
float eval = evalPostfix(postfix);
cout << "Your expression evaluates to: " << eval;
return 0;
}
You have a few issues one of the major one being a typo, you have a misplaced ) this:
else if (OPS.find( postfix[i] != -1 ) ) {
^ ^
should be:
else if (OPS.find( postfix[i] ) != std::string::npos) {
^ ^
so you are comparing the char at position i to -1 and then doing a find on the boolean result. Next you should be using -1 to compare the results of find but std::string::npos
As Jonathan pointed out:
cin >> postfix ;
only read up to the first black or newline. Using getline will fix that problem:
if (getline(cin, postfix))
One primary problem was that the input cin >> postfix; statement only reads the first word. Echo inputs to ensure that the program is seeing what you think it is seeing.
Shafik Yaghmour points out another problem.
Points to learn:
echo inputs to make sure the program is seeing what you think it is seeing;
trace key variables with suitable printing messages;
post SSCCE (Short, Self-Contained, Correct Example) — code that can be compiled;
post example input and the output you're getting from it.
This code works on input 555 666+:
#include <iostream>
#include <string>
#include <stack>
using namespace std;
static float doOperation(float x, float y, char op)
{
cout << "doOp: x = " << x << ", y = " << y << ", op = " << op << endl;
if (op == '+')
x += y;
return x;
}
string getNextNum(string equation, int i)
{
string num = "";
const string DELIM = "+-*/%^ ";
while (i<equation.length()) {
// Iterate through equation until you hit a delimiter.
if (DELIM.find(equation[i]) != -1) {
break;
}
num += equation[i];
i++;
}
return num;
}
float evalPostfix(string postfix)
{
const string OPS = "+-*/%^";
const string NUMS = "0123456789";
int strLength = postfix.length();
stack<float> numStack;
int i = 0;
while (i<strLength) {
cout << "Top - i: " << i << ", strLength: " << strLength << endl;
if (NUMS.find(postfix[i]) != -1) {
// If a character is a digit, then you should get the
// value and push it to the stack (could be multiple characters long).
string sNextNum = getNextNum(postfix, i);
float fNextNum = atof(sNextNum.c_str());
numStack.push(fNextNum);
cout << sNextNum << endl;
i += (sNextNum.length() - 1);
}
else if (OPS.find(postfix[i])!= -1) {
// Otherwise, pop the top two elements of the stack, perform the
// operation, then push the result back to the stack.
char op = postfix[i];
float x = numStack.top();
numStack.pop();
float y = numStack.top();
numStack.pop();
float z = doOperation(x, y, op);
numStack.push(z);
}
i++;
cout << "End - i: " << i << ", strLength: " << strLength << endl;
}
cout << "After - i: " << i << ", strLength: " << strLength << endl;
// Once the entire string has been scanned through, there should be a float
// left in the stack, simply return that.
return numStack.top();
}
int main ()
{
cout << "Please enter an expression in postfix notation: ";
string postfix;
//cin >> postfix;
if (getline(cin, postfix))
{
cout << "Evaluating: " << postfix << endl;
float eval = evalPostfix(postfix);
cout << "Your expression evaluates to: " << eval << endl;
}
return 0;
}
Sample trace:
Please enter an expression in postfix notation: 555 666+
Evaluating: 555 666+
Top - i: 0, strLength: 8
555
End - i: 3, strLength: 8
Top - i: 3, strLength: 8
End - i: 4, strLength: 8
Top - i: 4, strLength: 8
666
End - i: 7, strLength: 8
Top - i: 7, strLength: 8
doOp: x = 666, y = 555, op = +
End - i: 8, strLength: 8
After - i: 8, strLength: 8
Your expression evaluates to: 1221
Clearly, you can lose much of the diagnostic output once the specific problem you are solving is resolved, but being prepared to add it along the lines shown can dramatically speed up the process of solving it.