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;
}
Related
I am a beginner and i made a code in C++ to convert 3 characters to caesar cipher but my problem is that i can print only characters to a - w. How can i print x, y ,z using only if else statement. I have tried else if and many other things but it prints for x,y,z {|} which is +3 i know i need to do -23 but i cant get it to work pls help. This is my code for only to a - w. Edit : i still don’t get how to go from x,y,z to a,b,c if some1 has an code example i would appreciate it cus im trying but it for some reason keeps printing {|} which is ch = ch + 3; and not ch = ch - 23; which is the one i want to do with else if statement
char ch1;
char ch2;
char ch3;
cout << "Insert three characters: " << endl;
cin >> ch1;
cin >> ch2;
cin >> ch3;
if (ch1 >= '97' && ch1 <= '119' || ch2 <= '97' && ch2 <= '119' || ch3 >= '97' && ch3 <= '119') {
ch1 = ch1 + 3;
ch2 = ch2 + 3;
ch3 = ch3 + 3;
cout << "Caesar Cipher: " << ch1 << ch2 << ch3 << endl;
}
To wrap your characters around, you need the modulo operator, %. But first you must transform the letter to a zero-based value. After that, you have a number in the range [0, 25] and you can offset it. You then take the modulo to wrap the new value to the same range and finally transform it back to an alphabet character.
Example:
ch1 = 'a' + (ch1 - 'a' + 3) % 26;
Notice I'm using a character literal here. You should always avoid hard-coding character values, as that just makes your code more difficult to read and less portable. To test if a value is lowercase, there's a standard library function std::islower (and a corresponding std::isupper) found in the header <cctype>.
Fixing your code up a bit, it becomes:
if (std::islower(ch1)) ch1 = 'a' + (ch1 - 'a' + 3) % 26;
if (std::islower(ch2)) ch2 = 'a' + (ch2 - 'a' + 3) % 26;
if (std::islower(ch3)) ch3 = 'a' + (ch3 - 'a' + 3) % 26;
cout << "Caesar Cipher: " << ch1 << ch2 << ch3 << endl;
But look at all the code duplication! What if you want to change the key, or use more or less characters, or change the encoding algorithm completely? That's where a function comes in handy:
char EncodeChar(char c, int key)
{
if (std::islower(c))
c = 'a' + (c - 'a' + key) % 26;
return c;
}
Now you can use it like this:
const int key = 3;
ch1 = EncodeChar(ch1, key);
ch2 = EncodeChar(ch2, key);
ch3 = EncodeChar(ch3, key);
Even better, read your characters into a std::string and encode it in-place. You're no longer restricted to exactly three characters:
void CaesarEncode(std::string& s, int key)
{
for (char& c : s) c = EncodeChar(c, key);
}
Call that like this:
std::string text = "Hello, world!";
CaesarEncode(text, 3);
std::cout << text << "\n";
Now, this will work for positive offsets, but not negatives. If you need to apply a negative offset, you need to add an additional 26 before modulo which ensures you never go below zero. It's useful to support both, because you probably want to decode the ciphertext at some point. You can use the same function but make the key negative.
One way to approach this is to modify a negative key at the last minute with a recursive call in your CaesarEncode function:
void CaesarEncode(std::string& s, int key)
{
if (key < 0)
{
CaesarEncode(s, 26 - (-key % 26));
return;
}
for (char& c : s) c = CaesarEncode(c, key);
}
Let's continue. What about capital letters? You can handle those too:
char EncodeChar(char c, int key)
{
if (std::isalpha(c))
{
char base = std::islower(c) ? 'a' : 'A';
c = base + (c - base + key) % 26;
}
return c;
}
As you can see, using functions makes life much easier, because you don't need to create a mess when beefing up your encoding method. You just change the core logic in one place.
Rolling this all together, and with a few extra helpers from the standard library, you get a reasonably compact program that can encode and decode:
#include <algorithm>
#include <cctype>
#include <iostream>
#include <iterator>
#include <string>
std::string CaesarEncode(const std::string& s, int key)
{
if (key < 0)
{
return CaesarEncode(s, 26 - (-key % 26));
}
auto fnEncodeChar = [key](unsigned char c) -> unsigned char
{
if (std::isalpha(c))
{
char base = std::islower(c) ? 'a' : 'A';
c = base + (c - base + key) % 26;
}
return c;
};
std::string encoded;
std::transform(s.begin(), s.end(), std::back_inserter(encoded), fnEncodeChar);
return encoded;
}
std::string CaesarDecode(const std::string& s, int key)
{
return CaesarEncode(s, -key);
}
int main()
{
const int KEY = 3;
std::string line;
while (std::getline(std::cin, line))
{
std::string encoded = CaesarEncode(line, KEY);
std::string decoded = CaesarDecode(encoded, KEY);
std::cout << "Original : " << line << "\n";
std::cout << "Encoded : " << encoded << "\n";
std::cout << "Decoded : " << decoded << "\n";
}
}
Input:
This is a test.
Output:
Original : This is a test.
Encoded : Wklv lv d whvw.
Decoded : This is a test.
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.
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] << " ";
}
Alright so I've been looking though Google and on forums for hours and can't seem to understand how to solve this problem.
I need to write a program that first determines if the number entered by the user is a base 5 number (in other words, a number that only has 0s, 1s, 2s, 3s, and 4s in it). Then, I have to count how many 0s, 1s, 2s, etc are in the number and display it to the user.
I've seen people saying I should convert int to a string and then using cin.get().
I noticed that I can't use cin.get() on a string, it needs to be a char.
I can only use a while loop for this assignment, no while... do loops.
Any help is appreciated!!
Here's what I have so far, obviously with all my mistakes in it:
//----------------------------------------------
// Assignment 3
// Question 1
// File name: q1.cpp
// Written by: Shawn Rousseau (ID: 7518455)
// For COMP 218 Section EC / Winter 2015
// Concordia University, Montreal, QC
//-----------------------------------------------
// The purpose of this program is to check if the
// number entered by the user is a base of 5
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
int main()
{
// Declaring variables
int number;
int zeros;
int ones;
int twos;
int threes;
int fours;
bool base5;
// Get data and calculate
cin >> number;
string numberString = to_string(number);
// Determine if the number is a base 5 number
while (cin.get(numberString) == 0 || cin.get(numberString) == 1 ||
cin.get(numberString) == 2 || cin.get(numberString) == 3 ||
cin.get(numberString) == 4)
base5 = true;
// Determine the number of each digits
zeros = 0;
ones = 0;
twos = 0;
threes = 0;
fours = 0;
return 0;
}
Several things you need to beware of:
One way to get a specific character from a std::string is by []. e.g.
std::string myString{"abcdefg"};
char myChar = myString[4]; // myChar == 'e'
cin.get(aString) is not trying to get data from aString. It continues to get data from stdin and store in aString. Once you have get the data and put into the string, you can simply manipulate the string itself.
a short piece of code that will count number of vowel in a string. If you can understand it, there should be no problem doing your work. (Haven't compiled, probably some typos)
std::string inputString;
std::cin >> inputString;
// you said you need a while loop.
// although it is easier to with for loop and iterator...
int i = 0;
int noOfVowels = 0;
while (i < inputString.length()) {
if (inputString[i] == 'a'
|| inputString[i] == 'e'
|| inputString[i] == 'i'
|| inputString[i] == 'o'
|| inputString[i] == 'u' ) {
++noOfVowels;
}
++i;
}
std::cout << "number of vowels : " << noOfVowels << std::endl;
Well you can try this approach. This will solve your needs I guess.
#include <iostream>
#include <string>
#include <sstream>
#include <conio.h>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
int number=0;
int zeros=0;
int ones=0;
int twos=0;
int threes=0;
int fours=0;
bool valid=true;;
int counter = 0;
cout<<"Enter the number: ";
cin >> number;
stringstream out;
out << number; //int to string
string numberString = out.str();
cout<<"\n\nNumber after string conversion : "<<numberString;
cout<<"\nPrinting this just to show that the conversion was successful\n\n\n";
while (counter < numberString.length())
{
if (numberString[counter] == '0')
zeros++;
else if(numberString[counter] == '1')
ones++;
else if(numberString[counter] == '2')
twos++;
else if(numberString[counter] == '3')
threes++;
else if(numberString[counter] == '4')
fours++;
else
valid=false;
counter++;
}
if(valid==true)
{
cout<<"\nZeros : "<<zeros;
cout<<"\nOnes : "<<ones;
cout<<"\nTwos : "<<twos;
cout<<"\nThrees : "<<threes;
cout<<"\nFours : "<<fours;
}
else
cout<<"\n\nInvalid data...base of 5 rule violated";
_getch();
return 0;
}
If you don't want to use std::string then use characters, first loop over the input from the user until ENTER is pressed.
char ch = 0;
while ((ch = cin.get()) != '\n')
{
...
}
For each character read, check if it is a digit (std::isdigit) and if it is in the range 0..4, if not quit and give some message of not being base 5
have an array of ints to keep track of the frequency of the digits
int freq[5] = {0,0,0,0,0};
after you have checked that the character is valid subtract the ascii value from the digit and use that as index in the array, increment that:
freq[ch - '0']++;
e.g.
char ch;
int freq[5] = {0};
while ((ch = cin.get()) != '\n')
{
cout << ch;
freq[ch-'0']++;
}
for (int i = 0; i < sizeof(freq)/sizeof(freq[0]); ++i)
{
cout << static_cast<char>(48+i) << ":" << freq[i] << endl;
}
Here's a useful function that counts digits:
// D returns the number of times 'd' appears as a digit of n.
// May not work for n = INT_MIN.
int D(int n, int d) {
// Special case if we're counting zeros of 0.
if (n == 0 && d == 0) return 1;
if (n < 0) n = -n;
int r = 0;
while (n) {
if (n % 10 == d) r++;
n /= 10;
}
return r;
}
In your code you can use this naively to solve the problem without any further loops.
if (D(n, 5) + D(n, 6) + D(n, 7) + D(n, 8) + D(n, 9) != 0) {
cout << "the number doesn't consist only of the digits 0..4."
}
cout << "0s: " << D(n, 0) << "\n";
cout << "1s: " << D(n, 1) << "\n";
cout << "2s: " << D(n, 2) << "\n";
cout << "3s: " << D(n, 3) << "\n";
cout << "4s: " << D(n, 4) << "\n";
You could also (or should also) use loops here to reduce the redundancy.
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.