replace characters from one array to another to a string - c++

I expected this to be straightforward using a for loop with replace(str.begin(), str.end(), "x", "y") but instead "x" and "y" are a certain character in an array, so: replace(str.begin(), str.end(), arrX[1], arrY[1]) in the loop:
for (int i = 0; i < arraySize; i++) {
replace( str.begin(), str.end(), arrX[i], arrY[i]);
}
but in my code:
#include <iostream>
#include <algorithm>
#include <iostream>
#include <string>
using namespace std;
string Caesar(string str) {
char alph[] = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};
string caesar = "abcdefghijklmnopqrstuvwxyz";
const int arraySize=sizeof(alph)/sizeof(alph[0]);
rotate(caesar.begin(), caesar.begin()+3, caesar.end());
for (int i = 0; i < arraySize; i++) {
replace(str.begin(), str.end(), alph[i], caesar[i]);
}
return str;
}
int main() {
cout << Caesar("hello");
}
caeser string is alph rotated by three.
Outputting caesar gives expected results. (abcdef... becomes xyzabc... when just printing caesar.)
My loop seems to be the thing messing it up, when given hello it produces ccaaa. I tested replacing one letter and it worked but it seems my for loop is what the problem is, but I can't seem to find out what is wrong.
UPDATE:
I found out a way to do it that supports non alphabetical characters using a while loop that checks if it is alphabetical and then goes through the alphabet comparing each letter to a letter in the string until they match and than replace that with the rotated Caesar alphabet, if they don't match it goes to the next one and when found it resets 'j' to 0 so it can do it again for the next letter by increment 'i' this time, if the char is not a letter it just increases 'i' to the next char to just skip over it until it reaches the new letter or the end of the string.
#include <iostream>
#include <algorithm>
using namespace std;
bool IsInArray(string array, char element) {
for(int i = 0; i < array.length(); i++){
if(array[i] == element){
break;
}
}
}
string rot(int n, string str) {
transform(str.begin(), str.end(), str.begin(), ::tolower);
string alph = "abcdefghijklmnopqrstuvwxyz";
string ciph = alph;
rotate(ciph.begin(), ciph.begin() + n, ciph.end());
int i = 0;
int j = 0;
while (i < str.length()) {
if (IsInArray(alph, str[i])) {
if (str[i] == alph[j]) {
str[i] = ciph[j];
i++;
j = 0;
}
else {
j++;
}
}
else {
i++;
}
}
return str;
}
int main() {
cout << rot(2, "This cipher works with more than just alpha chars!");
return 0;
}

Here's one way to do it using standard functions and a lambda function:
string Caesar(std::string str) {
std::string caesar = "abcdefghijklmnopqrstuvwxyz";
std::rotate(caesar.begin(), caesar.end()-3, caesar.end());
std::transform(str.begin(), str.end(), str.begin(),
[caesar](char c) -> char { return caesar[c - 'a']; });
return str;
}
Note: it uses the char code to get the index, so it would have to be changed to handle anything other than "abc...xyz".

As an optimization: if you're using just letters a-z lowercase, you can do it without using the two arrays and without using the function leftRotatebyOne. Instead use the ASCII values.
std::string Caesar(std::string str){
int delta = 'z' - 'a' + 1;
int rotateBy = 3;
for(int i = 0; i < str.length(); i++){
char c = str[i] - rotateBy;
if(c < 'a')
c += delta;
str[i] = c;
}
return str;
}

Related

Replace every letter with its position in the alphabet for a given string

The first step, I changed the string to a lowercase, after that I removed all the non letters from the string, now I am struggling to replace each letter with the alphabet position.
does anyone know how to do such a thing?
Thank you!
string alphabet_position(string message){
string alphabet= "abcdefghijklmnopqrstuvwxyz";
int aplha_numbers[100];
for_each(message.begin(), message.end(), [](char & c){
c = ::tolower(c);
});
for(int i=0; i< message.size(); i++){
if(message[i] < 'a' || message[i] > 'z'){
message.erase(i, 1);
i--;
}
}
for(int j=0; j<message.size(); j++){
int index = alphabet.find(message[j]);
aplha_numbers[j]= index +1;
}
std::ostringstream os;
for(int z: aplha_numbers){
os<<z;
}
std::string str(os.str());
return str;
}
Now I have a different issue , I am getting the alphabet positions but I also get a lot of garbage values after the last letter.
As an example Input: abc
output 123 and after that a lot of numbers 32761004966.....
There are a few issues in your code:
Your main bug was that in this line:
for (int z : aplha_numbers)
You go over all the 100 elements in the allocated array, not just the valid entries.
In my solution there's no need for such an array at all. The stringstream objec is updated directly.
The position of a lower case character c is simply c-'a'+1. No need for a lookup table (at least assuming ascii input).
There's no need to actually change the input string by making it a lower case. This can be done on the fly as you traverse it.
Here's a complete fixed version:
#include <string>
#include <sstream>
#include <iostream>
#include <cctype>
std::string alphabet_position(std::string message)
{
std::ostringstream os;
for (auto const & c : message)
{
char c_lower = std::tolower(c);
if (c_lower < 'a' || c_lower > 'z') continue;
int pos = c_lower - 'a' + 1;
os << pos;
}
return os.str();
}
int main()
{
std::string s_in = "AbC";
std::string s_out = alphabet_position(s_in);
std::cout << "in:" << s_in << ", out:" << s_out << std::endl;
return 0;
}
Output:
in:AbC, out:123
A side note: it's better to avoid using namespace std;. See here: Why is "using namespace std;" considered bad practice?

How to get the first letter of every words in a string that separated by more than one dot or space

This is the problem example :
Input :
Spy..enigma.....long...address.muscle...anime....time
Output:
Selamat
I can make the '.' disappear but I can't get the first letter of each words.
Thanks.
this is my code :
char dot[] = {'.'};
bool isDot(char c) {
for (int i = 0; i < 1; i++) {
if (c == dot[i]) {
return true;
}
}
return false;
}
int main() {
string str;
cin >> str;
cout << str[0];
for (int i = 0; i < str.length(); i++) {
if (!isDot(str[i])) {
cout << str[i+1];
}
}
return 0;
}
Remove additional dots so you have Spy.enigma.long.address.muscle.anime.time
Run for loop to find every character after dot
Here is the code:
#include <iostream>
using namespace std;
int main() {
string str;
cin >> str;
cout << str[0];
// Remove additional dots
for (int i = 0; i < str.size() - 1; i++) {
if (str[i] == '.' && str[i + 1] == '.') str.erase(i, 1), i--;
}
// print every character after dots
for (int i = 0; i < str.size(); i++) {
if (str[i] == '.') cout << str[i + 1];
}
return 0;
}
Note: This code will not work if first character is '.', but based on your code I'm assuming it's not.
Or just run a simple if (s[i] == '.' && s[i + 1] != '.')
#include <iostream>
using namespace std;
int main() {
string str;
cin >> str;
cout << str[0];
for (int i = 0; i < str.size(); i++) {
if (str[i] == '.' && str[i + 1] != '.') cout << str[i + 1];
}
return 0;
}
I'd use the C++11 regular expression library:
#include <regex>
#include <string>
std::string first_letters(const std::string& input_string) {
std::string result;
std::regex word_regex { "[^\\.\\s]*" };
std::sregex_iterator i { input_string.begin(), input_string.end(), word_regex };
std::sregex_iterator end;
while (i != end) {
result.push_back(i->str().front());
++i;
}
return result;
}
If you're interested, you could learn to use regular expressions. It does require learning how to make regular expression patterns, but there are websites which can help you test your expressions.
Here's an example:
#include <boost/regex.hpp>
#include <string>
#include <vector>
#include <iostream>
using namespace std;
char* acronymMaker(vector<string> wordList) { // reusable function for any string vectors
if (wordList.size() > 0 ) { // if there is at least one word in the vector
char* result = new char[wordList.size() + 1]; // create array big enough for all first characters of each string, and terminating char
int i = 0; // i is declared outside to be used again
for (; i < wordList.size(); i++) // for each word
result[i] = wordList[i][0]; // take first character of each word
result[i] = '\0'; // add terminating character at end
return result; // return completed acronym
}
return (char*)""; // return empty acronym for 0 words
}
int main(void) { // example using boost::regex and function from above
string str = "Spy..enigma.....long...address.muscle...anime....time"; //input string
vector<string> words; // dynamic storage for words
char* acronym; // acronym to be filled later;
boost::regex exp{"(\\w+)"}; // regular expression to capture separated words only
boost::sregex_iterator iter(str.begin(), str.end(), exp); // define iterator parameters
boost::sregex_iterator end; // empty iterator, same state if no more matches exist or no matches at all
for (; iter != end; ++iter) { // for each word captured (++ before iter skips first capture, which is the full string being evaluated)
words.push_back(iter->str()); // push it to the back of the word container
}
acronym = acronymMaker(words); // call function
cout << acronym << endl; // display result on screen
return 0;
}
If you compile this code it will return Selamat as requested. However I am using the boost libraries for my regex, so you'll need to get those too to compile my code. Technically it should also work with the c++11 regex library as the inputs/outputs are the same, but I have had no luck getting it to work, I'll be looking up as to why after this post.
This doesn't exactly answer your question, but I just have to say...
Take a look at this code:
char dot[] = {'.'};
bool isDot(char c) {
for (int i = 0; i < 1; i++) {
if (c == dot[i]) {
return true;
}
}
return false;
}
That is a seriously convoluted way to determine if a character is a dot or not (:
Writing a for loop to do a single iteration?
Creating an array to hold a single value?
Howabout this, instead:
bool isDot(char c) {
return c == '.';
}
As to your actual question, other people have suggested regex, but you know what they say about that.
You can just loop through your input, keeping track of your current state.
How many states can you be in, that you care about?
The first letter of a word (you want to output these)
The non-first letter of a word
A dot (these separate words)
If we call these states A, B, and C, respectively, your example looks like this:
Spy..enigma.....long...address.muscle...anime....time
ABBCCABBBBBCCCCCABBBCCCABBBBBBCABBBBBCCCABBBBCCCCABBB
This can easily be tracked as you scan your input, left-to-right.
Then you just want to print out the A states.
If you want to be slightly clever, you can use only two states:
The first character after a dot
Perhaps with a special exception for the very first character in your input, if it's a non-dot.
Anything else
With these states, you have:
Spy..enigma.....long...address.muscle...anime....time
ABBBBABBBBBBBBBBABBBBBBABBBBBBBABBBBBBBBABBBBBBBBABBB

C++ find words with first and last same letter and sort them in alphabetical order

i can't make program that reads from file words ( there is no limit of words or length to them ) with same first letter and last. I use class and object and first of all i can't make reading them
#include <iostream>
#include <string>
#include <sstream>
#include <fstream>
using namespace std;
class Texts{
public:
void Realding(string &All);
void Searching(string &text, char *Word);
};
int main()
{
Texts A;
string Text; char word[40];
A.Reading(Text);
A.Searching(Text, word);
system("PAUSE");
}
void Texts::Reading(string &All)
{
string temp;
ifstream read("Text.txt");
while (getline(read, temp)) { All += temp; All += "\n"; }
cout << All;
}
void Texts::Searching(string &text, char *Word)
{
int i = 0;
int j = 0;
int letters = 0;
int zodz = 0;
int index = 0;
while (1)
{
if (text[i] == ' ' || text[i] == '\0')
{
zodz++;
if (text[0] == text[i - 1])
{
letters = j;
for (int l = 0; l < letters; l++)
{
//cout << text[l];
}
j = 0;
}
if (text[i + 1 - j] == text[i - 1])
{
letters = j;
for (int l = i - j; l < letters; l++)
{
// cout << text[l];
}
j = 0;
}
}
if (text[i] == '\0') break;
else
i++;
j++;
}
}
I can't make it properly read from file... Text.txt looks like
asdfa su egze hah ktis faf
And how later when selected words with first and last same letter to assign to array, that later to sort them in alphabetical order. Thanks if someone helps me.
Reading from file:
std::ifstream in(NameOfFile);
std::string word;
while (in >> word) //will stop when word can't be read. probably bad file or end of file
{
// do something with word
}
Find word with same first and last letter
if (word.front() == word.back())
{
// do something with word
}
Note this does not handle words with capitalized letters. It would not find "Mom". It will likely crash over empty words. Both have trivial fixes.
Assign word to array
array[index++] == word;
This assumes you want to advance the index after inserting into the array. Please note the program will behave poorly if the array is overfilled. If you are allowed to by the assignment, please consider using a std::vector.
Sorting the array
std::sort(array, array + index);
This assumes you are allowed to use std::sort. Again, if possible use a std::vector in place of the array. index is assumed to be the value of index from the adding example above after all of the adding has been done. If you are NOT allowed to use std::sort ask another question. It's a lengthy topic.

How can I check if string value exists in array of chars?

#include <iostream>
using namespace std;
int main()
{
string str = "cab";
string d = "";
char s[] = {'a', 'b', 'c', 'd', 'e'};
for(int i = 0; i < sizeof(s) / sizeof(s[0]); i++){
for(int j = 0; j < str.length(); j++){
if(str[j] == s[i]){
d += s[i];
}
}
}
cout << d << endl;
return 0;
}
I wanna check if the string "cab" for example exists in array of chars like in my case, it should exist, no matter of position in the element in the array of chars.
Assuming that your sub string will not have duplicates, you could use an unordered_set. So you essentially iterate over your s[] and for each character, you will check if the set contains that particular character.
The unordered_set allows O(1) searching, so your algorithm should run in O(n) (n = size of s).
When you find a character in the set which is also within the array, you remove it and continue traversing the array. If by the time your are done traversing the array the set is empty, then you know that your array contains that substring. You can also check to see that the set is not empty each time you remove a character from it, this should reduce execution time.
Not my code:
#include <string>
#include <iostream>
#include <algorithm>
void print(std::string::size_type n, std::string const &s)
{
if (n == std::string::npos) {
std::cout << "not found\n";
} else {
std::cout << "found: " << s.substr(n) << '\n';
}
}
int main()
{
std::string str = "cab";
std::string::size_type n;
std::string const s = "This is a string";
// search from beginning of string
n = s.find("is");
print(n, s);
// search from position 5
n = s.find("is", 5);
print(n, s);
// find a single character
n = s.find('a');
print(n, s);
// find a single character
n = s.find('q');
print(n, s);
//not the best way
for(char c : s)
s.find(c); //will be npos if it doesn't exist
//better
std::includes( s.begin(), s.end(),
str.begin(), str.end() );
}

Concatenating 2 strings together

I have two strings:
string word;
string alphabet;
word has some input that I passed on to; let's say "XYZ".
alphabet has the alphabet except XYZ, so it's "ABCDEFGHIJKLMNOPQRSTUVW"
When I tried to concat them with "+=", all I get is word (i.e. "XYZ"). I want to make it look like this:
XYZABCDEFGHIJKLMNOPQRSTUVW
What am I doing wrong? Code is basicly this vvvv
===========================encryption.cpp=================================================
#include <cstdlib>
#include <iostream>
#include "encryption.h"
#include <string>
encryption::encryption()
{
alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
}
string encryption::removeletter(string word,char letter)
{
//remove letter
string temp;
int indis=0;
for(int i = 0; word[i] != '\0'; i++)
{
if(word[i] != letter)
{
temp[indis]=word[i] ;
indis++;
}
}
word=temp;
return word;
}
This is the function i have proplems with :
void encryption::encrypt(string word)//main.cpp is just calling this atm
{
string temp;
int pos;
//getting rid of the repeating letters
for(int i = 0; i < word.length(); i++)
{
if( (pos = temp.find(kelime[i])) < 0)
temp += word[i];
}
word=temp;//that ends here
//taking words letters out of the alphabet
for(int i = 0; i < word.length(); i++)
{
alfabet=removeletter(alfabe,word[i]);
}
for(int i = 0; i < word.length()-1; i++)
{
for(int j=0;alfabet[j] !='\0'; j++)
if(alfabet[j+1] =='\0') alfabet[j]='\0';
}
/* I tried += here */
}
===========================encryption.h====================================================
#ifndef encryption_h
#define encryption_h
#include<string>
class encryption
{
public:
encryption();
void encrypt(string word);
string removeletter(string word,char letter);
//some other functions,i deleted them atm
public:
string alphabet;
string encryptedalphabet;
//staff that not in use atm(deleted)
};
#endif
===========================main.cpp======================================================
#include <cstdlib>
#include <iostream>
#include "encryption.h"
#include <string>
string word;
encryption encrypted;
cin>>word;
encrypted.encrypt( word);
+= is how you do it, you must be doing something else.
string word = "XYZ";
string alphabet = "ABCDEFGHIJKLMNOPQRSTUVW";
alphabet += word;
cout << alphabet << "\n";
output
ABCDEFGHIJKLMNOPQRSTUVWXYZ
Use
word.append(alphabet);
Note that when you want to concatenate many strings, it's more efficient to use a stringstream to avoid unnecessary string copying.
string word = "XYZ";
string alphabet = "ABCDEFGHIJKLMNOPQRSTUVW";
word += alphabet;
Now you can print 'word', and you will find your answer.