The assignment is relatively simple reverse the array in main using the ReverseStringRecursive function. However the limitation is I can only use a single int and a char nothing else that declares a variable (this includes the banning of for loops and so on). Additionally no extra libraries may be used I am limited to iostream and conio.h. The problem I'm having is that the string will be printed forward and then backwards when I just need it to be printed backwards. the reverseMe variable is pointing to a string in main that contains "abcdefghijklmnopqrstuvwxyz". This function is not suppose to print the string just reverse is then main will print the string.
// INCLUES AND NAMESPACES
#include <iostream>
#include<conio.h>
using namespace std;
// CONSTANTS
const int STRING_SIZE = 100;
// PROTOTYPES
int ReverseStringRecursive(char*);
// MAIN
int main() {
// create a string
char someString[STRING_SIZE] = "abcdefghijklmnopqrstuvwxyz";
// display the string before being reversed
cout << "The string contains: " << endl;
cout << someString << endl << endl;
// make the call to the recursive function
cout << "CALL THE REVERSING FUNCTION" << endl << endl;
ReverseStringRecursive(someString);
// display the string after being reversed
cout << "The string contains: " << endl;
cout << someString << endl;
// exit program
_getch();
return 0;
}
int ReverseStringRecursive(char* reverseMe) {
// YOUR IMPLEMENTATION GOES HERE...
int position = 0;
char holder = ' ';
if (reverseMe[0] == '\0') {
return 1;
}
else {
holder = reverseMe[position];
}
ReverseStringRecursive(reverseMe + 1);
while (reverseMe[position] != '\0') {
position++;
}
reverseMe[position] = holder;
return position;
}
Example output that I am getting:
"abcdefghijklmnopqrstuvwxyz zyxwvutsrqponmlkjihgfedcba"
what I'm suppose to get:
"zyxwvutsrqponmlkjihgfedcba"
Tough problem. You have to shorten the inner string on each recursion by placing a '\0' on the last character before calling the recursive function and then performing the swap after the recursive call.
algorithm:
0. save the index of the last character in the string
1. Save the last character of the current string
2. Set the last character of the current string to null (use the saved index)
3. Call the recursive function starting one character in which will recurse the algorithm for the next inner string (we have already shortened the end of the recursed string)
4. Once the recursion has finished, set the last character to the first char of the current string; then
5. set the first character of the current string to the saved character (which was at the end)
This will work for odd-length strings as well.
The following code should work on a windows system. To make it work on Linux, simply comment out the conio.h include line, comment the __getch() line and uncomment the cin.getch() line.
// INCLUES AND NAMESPACES
#include <iostream>
#include <conio.h>
using namespace std;
// CONSTANTS
const int STRING_SIZE = 100;
// PROTOTYPES
int ReverseStringRecursive(char *);
char *orig;
// MAIN
int main()
{
// create a string
char someString[STRING_SIZE] = "abcdefghijklmnopqrstuvwxyz";
orig = someString;
// display the string before being reversed
cout << "The string contains: " << endl;
cout << someString << endl << endl;
// make the call to the recursive function
cout << "CALL THE REVERSING FUNCTION" << endl << endl;
ReverseStringRecursive(someString);
// display the string after being reversed
cout << "The string contains: " << endl;
cout << someString << endl;
// exit program
_getch(); // uncoment conio.h on a windows system
// std::cin.get(); // use this if on a linux system
return 0;
}
int ReverseStringRecursive(char *reverseMe)
{
int last_index = 0;
while (reverseMe[last_index + 1] != '\0')
last_index++;
char save_char = reverseMe[last_index];
if (*reverseMe != '\0') {
reverseMe[last_index] = '\0'; // shorten the inner string by one
// recurse on the shorter string
ReverseStringRecursive(reverseMe + 1);
// save the outer two characters
reverseMe[last_index] = *reverseMe;
*reverseMe = save_char;
}
}
You are overwriting your terminating '\0' and therefore corrupting your string. When your while loop exists, reverseMe[position] is at '\0' and then you overwrite it with the value holder. Your string is no longer null-terminated and you are getting undefined behavior on your next while loop as it accesses outside the bounds of your array.
Related
I am writing a program that uses a substitution cipher.
I am trying to replace each char in a string (that the user entered) with a char from another string (the encryption key string).
But I am having a bunch of issues doing this with the string.replace() function. It does not replace the the char in the userMessage with the correct char. Although this is not an issue when using a string literal as initialization value for letterReplacement. In addition to this, it somehow temporarily increases the size of the userMessage resulting in the loop running for e.g 5 times in a message 3 char long (no matter how letterReplacement was initialized). I would appreciate any information on why this happens.
#include <iostream>
#include <string>
#include <vector>
int main()
{
std::string userMessage;
std::cout << "\nWelcome to my Military Grade* Encryption Software!" << std::endl;
std::cout << "--------------------------------------------------" << std::endl << std::endl;
std::cout << "Please enter a secret message you would like to encrypt:\n-" << std::endl;
getline(std::cin, userMessage);
std::cout << "-" << std::endl << std::endl;
const std::vector <std::string> encryptionKey {"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZT.,<>!?+- '",
"ß?pl ,;0=}okm9)]ijN8([uhb7/{zgv6&ctf%xdrys4$e3w|<2Q>1!+#ä-:*GnB"};
for(size_t i {0}; i < userMessage.size(); ++i) // Here we encrypt the Message
{
char currentCharInUM {userMessage.at(i)};
size_t currentKeyPosition {encryptionKey.at(0).find(currentCharInUM)}; //finds the position that currentChar is at in first encryptionKey String
std::cout << "currentKeyPosition: " << currentKeyPosition << " - " << i << std::endl;
if(currentKeyPosition == std::string::npos) // is letter in userMessage is not in encryptionKey just keep it (skip iteration)
continue;
std::string letterReplacement {encryptionKey.at(1).at(currentKeyPosition)};
userMessage.replace(i,1,letterReplacement);
}
std::cout << userMessage;
return 0;
}
The first character of 2nd element of the vector encryptionKey 'ß' is equal to 2 bytes. So that when you enter 'a' it returns '├' and when you enter b it returns 'ş'. You can try to put another character instead of 'ß'.
If your intention was indeed to store non-ASCII characters, it would have been more advantageous to use a lookup table.
The table could be a std::unordered_map<char, wchar_t> to map the English letters to the encrypted characters:
#include <iostream>
#include <string>
#include <unordered_map>
int main()
{
// Strings
const char encryptionKeyA[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZT.,<>!?+- '";
const wchar_t encryptionKeyW[] = L"ß?pl ,;0=}okm9)]ijN8([uhb7/{zgv6&ctf%xdrys4$e3w|<2Q>1!+#ä-:*GnB";
// Create the lookup table bassed on the above strings
std::unordered_map<char, wchar_t> encryptionMap;
for (int i = 0; i < sizeof(encryptionKeyA); ++i)
encryptionMap[encryptionKeyA[i]] = encryptionKeyW[i];
// Test
std::string userMessage = "abcTest";
// The output string
std::wstring encryptedString;
// Now go through each character of the userMessage
for(auto ch : userMessage)
{
// If the character exists, append the associated encrypted character
auto iter = encryptionMap.find(ch);
if (iter != encryptionMap.end())
encryptedString += iter->second;
else
encryptedString += L' '; // Just append a space if it didn't exist
}
std::wcout << encryptedString;
}
Output:
ss?p1 N8
Note that the output is what is displayed if the locale is English. If the terminal/output were set to German, I would assume that the output would be:
ß?p1 N8
since the first character is the "double-s".
Also note that I am assuming that both the original and encrypted character strings are of the same size (in terms of the number of characters) when building the map. If they're not the same size, then the loop to build the map should be adjusted accordingly.
I'm trying to reverse a string in my C++ code line below revStr.at(j) = str.at(size);
But it doesn't change any of the elements in revStr.
Is there another way to do it without using any libraries.
#include <iostream>
#include<sstream>
#include <iterator>
using namespace std;
int main() {
ostringstream d;
long long c = 123456789;
d << c;
//cout << c << endl;
string str = d.str();
//cout << str.at(0) << endl;
int size = str.size() - 1;
//cout << size << endl;
ostringstream e;
e << str;
string revStr = e.str();
for (int i = size; size==0; size--) {
//cout << str.at(size);
int j = 0;
revStr.at(j) = str.at(size);
j++;
} // End For
cout << "Original String is :" << str << endl;
cout << "Reversed String is :" << revStr << endl;
}
Use std::reverse:
#include <string>
#include <algorithm>
#include <iostream>
int main()
{
std::string test{"Hello"};
std::cout << "Original string: " << test << std::endl;
std::reverse(test.begin(), test.end());
std::cout << "Reversed string: " << test << std::endl;
return 0;
}
Output:
Original string: Hello
Reversed string: olleH
If you just want to reverse a string, you should use std::reverse, as described by Tyler Lewis. It is the best option.
If you want to learn C++, then writing your own version is good practice.
The line
for (int i = size; size==0; size--)
means “Create a new int called i and set it to size initially. Then, while size is zero, do the following and then decrement size”.
There are three problems with this:
Size is not zero unless you entered a one-character string
Since you never use i, there’s no point in declaring it
Inside the loop you use j which is set to zero each time.
You can fix the first by changing the middle part of the for loop to size >= 0 (but be careful—if you later change it so that size is an unsigned type, because it doesn’t make sense for it to be negative, that code won’t work; it’s generally better to increment going up instead). You can fix the second by using i everywhere in the loop statement, and not changing size. You can fix the third by using i in the loop body, and not declaring a new variable inside the loop.
I noticed you used std::string so I used std function swap and string. Depending on if you consider this as a 'library'. There are several definitions of 'reverse'. You could reverse the word order in a string, or a pure char to char reversal like I wrote. Reversal could also mean changing character case, etc... but this is simply swap first and last. Then swap the 2nd and 2nd to last, then swap the 3rd and 3rd to last, etc...
So some points from your code. You only need to loop half the string length. The swap is from the ith and the ith to last. So the last is numCharacters - 1, thus the ith to last would be Last - i or numCharacters - 1 - i. I believe this is what you intended by using a farLeft(i) and a farRight(j) index.
#include <iostream>
void reverseStringInPlace(std::string &stringToReverse)
{
int numCharacters = stringToReverse.length();
for (int i=0; i<numCharacters/2; i++)
{ std::swap(stringToReverse[i], stringToReverse[numCharacters-i-1]); }
}
int main()
{
std::string stringToReverse = "reversing a string";
std::cout << stringToReverse << std::endl;
reverseStringInPlace(stringToReverse);
std::cout << stringToReverse << std::endl;
return 0;
}
Output:
reversing a string
gnirts a gnisrever
Changes made to the piece of code in question, it works.
for (unsigned int i = size; size >= 0; size--) {
revStr[j] = str[size];
j++;
}
I just needed to reverse a string, so I declared a new string variable and iteratively copied the elements. Now i want to print the reversed string through cout << reversed; but this is printing nothing. I can print it through a for loop through reverse[i] until the size but is there any better way?
#include <iostream>
#include <string>
using namespace std;
int main()
{
string original = "hello";
string reverse;
int i, j = 0, size = original.length();
for (i = size - 1; i >= 0; i--) // original's last as reversed's first
{
reverse[j] = original[i];
j++;
}
reverse[j] = '\0'; //last value as null
cout << "original string = " << original << endl;
cout << "reversed string = " << reverse << endl;
system("pause");
return 0;
}
A better solution is to use std::reverse:
std::string original = "whatever";
std::string rev = original;
std::reverse(rev.begin(), rev.end());
You can use reverse iterators to instantiate the reversed string from the original:
string original = "hello";
string reverse(original.rbegin(), original.rend());
Then
std::cout << "reversed string = " << reverse << std::endl;
Note: avoid using namespace std;. There is an algorithm called std::reverse, whose name you could be inadvertently pulling into the global namespace. And you do have a variable with that name.
See this working demo.
The major problem with your code is that reverse is empty, so using any index leads to you indexing out of bounds and undefined behavior.
As a side-note, you don't have to terminate std::string objects, they are automatically terminated.
you should notice that string reverse doesn't have a size , so when you do something like this
for (i = size - 1; i >= 0; i--) // original's last as reversed's first
{
reverse[j] = original[i];
j++;
}
Here, you are accessing an index that is not found in string reverse,as it's size is 0 . You should take care of something like that.
There are plenty of answers that your received about this question , I just wanted to make you notice this mistake
instead , you can make
reverse+=original[i];
You don't even need to create a new string to hold the reversed string. Just iterator over the original string.
void print_reversed(const std::string& str)
{
std::copy(str.crbegin(), str.crend(), std::ostream_iterator<char>(std::cout));
}
Please tell me why my code to reverse the input string is giving me various errors.
#include<iostream>
#include<string>
#include<cstdlib>
using namespace std;
void ReverseString(string &aString);
int main(){
string info;
cout << "What's your string?" << endl;
getline(cin, info);
ReverseString(info);
cout << ReverseString(string info) << " compare with: " << info << endl;
system("pause");
return 0;
}
void ReverseString(string &aString){
for(int i = 0; i < aString.length(); i++)
{
string temp = 0; // initialize temporary string
temp = temp + aString.at(aString.length() - 1 - i); // hold temporary string
if(i => aString.length()) /*assign temp string to aString when all chars are processed*/
{
temp = &aString;
}
}
}
Hi you could simplify your code a lot by using the STL
for example:
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
std::string str = "Hello World";
cout << str << endl;
std::reverse(str.begin() , str.end());
cout << str << endl;
return 0;
}
let me know if this is not suitable to your needs as theres a few other ways to do it too.
Without STL:
There are some corrections/changes to your code required, which I have supplied below. However you may want to look at some documentation on referencing variables to get an idea of how it works, such as:
http://www.cprogramming.com/tutorial/references.html
http://www.thegeekstuff.com/2013/05/cpp-reference-variable/
http://en.wikipedia.org/wiki/Reference_(C++)
What is a reference variable in C++?
http://www.tutorialspoint.com/cplusplus/cpp_references.htm
Correct reference and pointer use is a major part of C++ and allows for some of the most powerful functionality in the language, provided it is used correctly, or major headaches and mental scarring if used incorrectly, so it is worth, even essential, to have a firm grasp of them.
And even then expect the odd misuse to crop up every-so-often. :)
#include<iostream>
#include<string>
#include<cstdlib>
using namespace std;
void ReverseString(string &aString);
int main(){
string info;
cout << "What's your string?" << endl;
getline(cin, info);
cout << info << " compare with: ";
ReverseString(info);
cout << info << endl;
system("pause");
return 0;
}
void ReverseString(string &aString)
{
int len = aString.length();
string temp = aString;// initialize temporary string
aString ="";
for(int i = 0; i < len; i++)
{
aString += temp[len - (1+ i)]; // assigns the reversed value to the referenced string
}
}
Just noticed the quote below from #zac-howland : so true, I have however left the code in as an illustrative piece. Provided some reading is done on this as well as plenty of experimentation I hope NewProgrammer will get the information and skill-set he needs to go forward.
#include<iostream>
#include<string>
#include <algorithm>
using namespace std;
string info;
string rvrs(string &str)
{
std::reverse(str.begin(),str.end());
return str;
}
int main()
{
cout<<"What is your string :: ";
getline(cin,info);
cout<<rvrs(info);
cout<<endl;
return 0;
}
You have a few syntactical errors in addition to your logical ones:
cout << ReverseString(string info) << " compare with: " << info << endl;
ReverseString(string info) will pass in an empty string to your ReverseString function (if it even compiles - which looks like it should not since you have 2 info's in the same scope). What you wanted is:
cout << ReverseString(info) << " compare with: " << info << endl;
In your reverse function, you only need to go to length() / 2.
Since you are passing by reference, changes you make to the string within the function will be reflected in the object you passed into it. That is, the original info will be reversed. If you want it to operate on a copy, you need to pass it by copy, not by reference.
Finally, cout << ReverseString(info) is not useful (if it even compiles) as ReverseString returns a void. You should have it return a string (the reversed string).
You have a number of problems.
string temp = 0; // initialize temporary string
It doesn't really make sense to initialize a string to 0. Just string temp; would be fine here.
temp = temp + aString.at(aString.length() - 1 - i); // hold temporary string
That's not quite how I'd do things, but I guess it should work.
if(i => aString.length())
This condition doesn't seem to make sense. Your loop is defined to iterate with i going from 0 to the length of the string -1, so it can never be greater than or equal to the string length.
/*assign temp string to aString when all chars are processed*/
{
temp = &aString;
}
Here the code doesn't match the comment. The comment says you're going to assign to aString, but the code assigns something to temp. The comment is probably closer to what you really want. But you still need to fix the condition, and probably want to do this after the loop has finished executing. So in pseudo-code, you'd end up with something like:
for (all characters in the string)
add the next character in the string to the end of temp
assign temp back to the original string
I'm working on a small little thing here for school. After hours of researching, and a ton of errors and logic reworking I've almost completed my little program here.
I'm trying to take user input, store it into the string, get a character array from the string ( dont ask why, I just have to put this into a character array ), then get the reversed order of the phrase that the user entered. Here is my code:
#include "stdafx.h"
#include <iostream>
#include <String>
#include <cstring>
using namespace std;
using namespace System;
#pragma hdrstop
char* getCharArray(string);
string reversePhrase( int, char* );
void main(void)
{
string sPhrase = "";
int sSize = 0;
string sReversed = "";
char* cPhrase = NULL;
cout << "Welcome to the You Type It & We'll Reverse it! [Version 1.0] " << endl;
cout << "This program will reverse your phrase, and count how many characters are in it!" << endl;
cout << "To begin just enter a phrase." << endl;
cout << "Enter a phrase: ";
getline( cin, sPhrase);
sSize = sPhrase.length();
cout << endl;
cPhrase = getCharArray(sPhrase);
sReversed = reversePhrase( sSize, cPhrase );
cout << sReversed;
system("pause");
}
string reversePhrase(int size , char* cPhrase)
{
string sReversed = "";
int place = size;
for ( int i = 0; i < size ; i ++ )
{
sReversed.append(1, cPhrase[place]);
cout << "Current string: " << sReversed << endl;
cout << "Current character: " << cPhrase[place] << endl;
place--;
}
return sReversed;
}
char* getCharArray(string sPhrase)
{
int size = 1;
size = sPhrase.length();
char* cArray = NULL;
cArray = new char[size];
for (int i = 0 ; i < size ; i++)
{
cArray[size] = sPhrase.at(i);
}
return cArray;
}
When I type in "ownage" into the program, this is what I get returned:
It is almost like my Character Array is getting garbage collected before it can use all of the characters. This is probably an easy fix but, I just don't see how I can get around this one.
Try rewriting getCharArray like this
char* getCharArray(string sPhrase)
{
int size = 1;
size = sPhrase.length();
char* cArray = NULL;
cArray = new char[size+1]; // NOTE
for (int i = 0 ; i < size ; i++)
{
cArray[i] = sPhrase.at(i); // NOTE
}
}
cArray[size]=0; // NOTE
return cArray;
}
Note that the assignment in the loop now uses the index variable. Also, you need to allocate one extra char in the array to set the null terminator for the string and then you need to set it at the end.
You'll also need to think about deallocating the array at some point
The bug is in this line:
cArray[size] = sPhrase.at(i);
That size should be your loop index.
You should probably look at using std::string more, and not poke around with character arrays when there's no need to.
Why use a char array at all? It's not only useless – it complicates the code substantially (the usage of your function is more difficult, and you've forgotten to free the memory allocated by new!). Why not just have the following function:
string reverse(string const& input);
(Passing the argument by const reference instead of by value saves you a copy!)
In fact, implementing the function only takes a single line using the features of the string class (one of its constructors takes two iterators):
string reverse(string const& input) {
return string(input.rbegin(), input.rend());
}
reversePhrase is also not correct. Try something like this:
string reversePhrase(int size , char* cPhrase)
{
string sReversed = "";
sReversed.resize(size);
int place = size - 1;
for ( int i = 0; i < size ; i ++ )
{
sReversed [i] = cPhrase[place];
cout << "Current string: " << sReversed << endl;
cout << "Current character: " << cPhrase[place] << endl;
place--;
}
return sReversed;
}
First, start the array with -1. After that, use a for loop with -1 and increment inside the loop. Then, you can get the first element of the array.