Making up a string from second string, order of characters - c++

Basically I need to check if the characters found in second string can make the first string. The program works, however I have this problem that it doesn't take the character order in mind.
For example if I input:
UMC UniverseCeeMake ==> Yes
but it should input No because UMC != UCM, how can I make it check the character order aswell? can someone assist?
#include <iostream>
#include <string>
using namespace std;
const int MAX = 256;
bool canMakeStr2(string str1, string str2)
{
int count[MAX] = {0};
for (int i = 0; i < str1.length(); i++)
count[str1[i]]++;
for (int i = 0; i < str2.length(); i++)
{
if (count[str2[i]] == 0)
return false;
count[str2[i]]--;
}
return true;
}
int main()
{
int n;
string str1;
string str2;
cin>>n;
for(int i =0;i<n;i++){
cin >> str1 >> str2;
if(str1.length()<=10000 && str2.length()<=10000)
if (canMakeStr2(str2, str1))
cout << "Yes";
else
cout << "No";
}
return 0;
}

As Fabian has alread stated. You approach with counting letters will not work. You will never cover the sequence.
You need to select a different approach. The most easy one is to use the std::strings existing find function.
So, you will go over all characters in the given character set in the correct sequence with a simple range based for loop. Then you can use the find function to check, if the character is existing in the other string.
To ensure the sequence, you must not search always from the beginning, but from the last poasition (+1) where a character was found. This will keep the ensure the sequence.
Example:
UMC UniverseCeeMake
Search for the 'U' starting from the beginning
'U' Found at position 0. Increment start position to 1
Search for 'M' staring from position 1
'M' found at position 11 (already behind the 'C'). Increment start position to 12
Search for a 'C' starting at position 12
Cannot be found --> Result will be "No"
This can be implemented very easyly:
#include <iostream>
#include <string>
bool canMakeStr(std::string toBeChecked, std::string characterSet) {
// Result of function. We assume that it will work
bool result{ true };
// position, where we find a charcted in the string to be checked
size_t position{};
// Go through all characters from the given character set
for (const char c : characterSet) {
// Look, where this character has been found
position = toBeChecked.find(c, position);
// If we could not find the character in the string to be checked
if (position == std::string::npos) {
// Then the result is false
result = false;
break;
}
else {
// Character was found. Now, we implement the solution to check for the sequence
// We will not start to search again at the beginning, but after the just found character
// This will ensure that we keep the sequence
++position;
}
}
return result;
}
int main()
{
// Read the number of test cases
unsigned int numberOfTestCases; std::cin >> numberOfTestCases;
// Work on all test cases
while (numberOfTestCases--) {
// Read the 2 strings
std::string characterSet, toBeChecked; std::cin >> characterSet >> toBeChecked;
// And check for the result
if (canMakeStr(toBeChecked, characterSet))
std::cout << "Yes\n";
else
std::cout << "No\n";
}
return 0;
}

Related

Check if every string in a set contains equal number of 'a' and 'b' okay I tried again will some one work something out now?

Will some one explain or make a program in c++ of this for me? Got assignment but don't know how to do it.
Question: You are given a set of strings which contain only as and bs, your program should be able to check whether each string has the same number of as and bs in it or not.
e.g. The program will respond true if it get {ab, aabb, aaabbbb, bbbaaa} and say false when it gets {aab, bbba, aaabbbb}
Solve it using stack
#include <iostream>
#include <string>
#include <stack>
#include <algorithm>
using namespace std;
int count1 = 0;
int count2 = 0;
bool isInLanguageL (string w);
int main()
{
string input;
cout << "Input any string; ";
getline(cin,input);
if (input.length() % 2 != 0)
cout <<"Pattern entered does not match the language ";
else
isInLanguageL(input);
return 0;
}
bool isInLanguageL (string w)
{
stack<string> word1, word2;
string a, b;
for (unsigned i = 0; i < w.length()/2; i++)
{
a = w.at(i);
word1.push(a);
}
reverse(w.begin(), w.end());
for (unsigned i = 0; i < w.length()/2; i++)
{
b = w.at(i);
word2.push(b);
}
while(!word1.empty() && !word2.empty())
{
word1.pop();
count1 = count1++;
word2.pop();
count2 = count2++;
}
if(count1 == count2)
return true;
else
return false;
}
This solution is using stack, please refer to the comments written in the code. If you have any doubt you can comment them.
Code:
#include <iostream>
#include <stack>
#include <string>
using namespace std;
void checkString(string s) {
if (s.size() % 2 != 0) {
cout << "Doesn't satisfy the conditon\n";
return;
}
stack<char> st;
int n = s.size();
for (int i = 0; i < n; ++i) {
/*
case - 1 : If the stack is empty you can directly push the current character into the stack
case - 2 : If there are elements present in the stack, then if the current character is equal to the top character on the stack then we can push the current character
beacuse we didn't find any new character to match them.
*/
if (st.empty() || (st.top() == s[i])) {
st.push(s[i]);
}
/*
case-3 : If the stack is not emtpy and current character is different from the top character on the stack then we found a match like a-b (OR) b-a, so then we will
remove the top element from the stack and move to next character of the string
*/
else if (st.top() != s[i]) {
st.pop();
}
}
/*
case - 1 : After iterating through all the characters in the string, if we find the stack is emtpy then we can say all characters are not matched
case - 2 : If stack is emtpy, then that means all the characters are matched.
*/
(st.empty()) ? (cout << "Yes, satisfies the conditon\n") : (cout << "Doesn't satisfy the conditon\n");
}
int main() {
string s = "";
cin >> s;
checkString(s);
return 0;
}
Your solution has a number of mistakes that you should probably solve by using a debugger. Here's a reference.
This solution doesn't use a stack as you asked for, but you can write this function that uses algorithms to solve your problem:
namespace rs = std::ranges;
bool all_equal_as_and_bs(auto const & strings)
{
return rs::all_of(strings, [](auto const & string)
{
return rs::count(string, 'a') == rs::count(string, 'b');
});
}
And use it like this:
all_equal_as_and_bs(std::vector<std::string>{"ab", "aabb", "aaabbb", "bbbaaa"}); // true
all_equal_as_and_bs(std::vector<std::string>{"aab", "bba", "aaabbbb", "bbbaaa"}); // false

Replace a character in one string with a character from another string in C++

I am making a cypher program for my C++ project. My approach is to declare and initialise two strings, the first one being alphabet and the other being key, as shown below.
string alphabet {"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"};
string key {"ZYXWVUTSRQPONMLKJIHGFEDCBAzyxwvutsrqponmlkjihgfedcba"};
I want to pair all these 52 letters to one another in the cypher. That is, small a is replaced with capital Z, small b with Y and so on.
The user will be prompted to enter a string, which will be stored in input. My idea is to loop through the input string and match it with alphabet, and hence find out its pair in key string. This is easy, since the pairs will have the same index. However, how do I swap them? I can use a loop in swap(input[i], key[i]) but that will just make every string as ZYXW... I am not able to write the logic here... Below is my code till now in entirety.
#include <iostream>
#include <string>
using namespace std;
int main()
{
string alphabet {"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"};
string key {"ZYXWVUTSRQPONMLKJIHGFEDCBAzyxwvutsrqponmlkjihgfedcba"};
int choice {};
cout<<"Welcome to the Cypher Program";
cout<<"\nYou can encode and decode your messages to make sure they remain secret!";
cout<<"\nWould you like to encode(Press 1) or decode(Press 2) a message?"<<endl;
cin>>choice;
//Encoding
if (choice == 1)
{
string input {};
cout<<"Enter a string to encrypt"<<endl;
getline(cin.ignore(), input); //testString
cout<<"Your encrypted message is: "<<endl;
for(int i {0}; i<input.length(); i++){
swap(input[i], key[i]);
}
cout<<input; //ZYXWVUTSRQ
}
return 0;
}
What I really want to do is:
Get input from user
For each letter in input, find out its index in alphabet
Using this index, swap the character with key.
Display the new string back to user.
I'm going to discuss two simple approaches here.
First is to just do what you've suggested in the first place, find the index of the letter from alhphabet and use that index to find encoded letter from key.
You can use a simple trick here by observing the pattern in your encoding. Whenever it's an uppercase letter, you can just subtract 'A' from its ASCII value to get offset and subtract that offset from ASCII value of z to get encoded letter. You can notice similar pattern when it's a lowercase letter.
Below is the sample code for both approaches.
#include <iostream>
#include <string>
using namespace std;
int main(){
string alphabet {"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"};
string key {"ZYXWVUTSRQPONMLKJIHGFEDCBAzyxwvutsrqponmlkjihgfedcba"};
string input1 {"testString"}, input2 {"testString"};
cout<<"Your encrypted message is (Approach 1) : "<<endl;
// Approach 1
for(int i {0}; i<input1.length(); i++){
int idx;
for(idx=0;idx<alphabet.length();idx++) // find index from alphabet
if(input1[i]==alphabet[idx])
break;
input1[i] = key[idx]; // replace with key
}
cout<<input1<<endl; //GVHGhGIRMT
// Approach 2
cout<<"Your encrypted message is (Approach 2) : "<<endl;
for(int i {0}; i<input2.length(); i++){
if(input2[i] >= 'A' && input2[i]<='Z')
input2[i] = 'z' - (input2[i]-'A');
else if(input2[i] >= 'a' && input2[i]<='z')
input2[i] = 'A' + ('z'-input2[i]);
}
cout<<input2; //GVHGhGIRMT
return 0;
}
Output
Your encrypted message is (Approach 1) :
GVHGhGIRMT
Your encrypted message is (Approach 2) :
GVHGhGIRMT
Step 1: Find index of character in original string
if (input[i] >= 97)
{
index = input[i]-97;
}
else
{
index = (input[i]-65) + 26;
}
now use
input[i] = key[index];
Hm, your original code was not that bad. You just need to replace the swap with an assignment. That leaves you originla data untouched.
input[i] = key[alphabet.find(input[i])];
Youd should add const before "alphabet" and "key" then the compiler would have prevented your code.
By the way, with this symmetric key, encoding and decoding is the same.
Not sure why you are writing getline(cin.ignore(), input); instead of getline(cin, input);. That should be corrected.
The calculation approach has the advantage that the key string will not be in exe file.
You could calculate the result also with XOR 255 (result += input[i] ^255, which flips all bits, or with 256-input[i];
Below a "more modern" C++ solution using the std::transform-algorithm
#include <iostream>
#include <string>
#include <algorithm>
int main()
{
// The encoding alphabet and key
constexpr std::string_view alphabet{ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ _" };
constexpr std::string_view key{ "ZYXWVUTSRQPONMLKJIHGFEDCBAzyxwvutsrqponmlkjihgfedcba_ " };
// String to encrypt
std::string message{"Hello world"};
// Here we will store the result
std::string result;
std::transform(message.begin(), message.end(), std::back_inserter(result), [&key, &alphabet](const char c)
{ size_t pos{ alphabet.find(c) }; return (pos != std::string::npos) ? key[pos] : '_'; });
// Show result
std::cout << "\nEncrypted: " << result << "\n";
message = result;
result.clear();
std::transform(message.begin(), message.end(), std::back_inserter(result), [&key, &alphabet](const char c)
{ size_t pos{ alphabet.find(c) }; return (pos != std::string::npos) ? key[pos] : '_'; });
// Show result
std::cout << "\nDecrypted: " << result << "\n";
return 0;
}

Using isalpha function with string pointers

Hey I'm quite new to programming and I'm having trouble using the isalpha function in my programme. This a part of the code for a palindrome class. What I'm trying to do is remove all the non alphabetic characters from the input. So if the user inputs "Hi, How are you" I need to first count the size of the array of just the letters then in my removeNonLetters subclass, I need to get rid of the non alphabetical characters. Can someone please help me with this. Thank you so much!
#include <iostream>
#include <string>
#include <stdio.h>
#include <algorithm>
#include <cctype>
#include <cstring>
#include <ctype.h>
using namespace std;
class palindrome
{
private:
int only_letters_size;
string input_phrase;
string* only_letters;
public:
string inputPhrase();
string removeNonLetters();
string* new_Array;
int size_new_Array;
};
string palindrome::inputPhrase()
{
cout << "Input phrase: "; //asks the user for the input
getline(cin,input_phrase);
size_new_Array = input_phrase.length(); //creating a dynamic array to store
the input phrase
new_Array = new string[size_new_Array];
int i;
for (i=0; i<size_new_Array; i++)
{
new_Array[i]=input_phrase[i];
}
only_letters_size = 0;
while(new_Array[i])
{
if (isalpha(new_Array[i])) //PROBLEM OCCURS HERE
{
only_letters_size=only_letters_size+1;
}
}
cout << only_letters_size << endl;
return new_Array;
}
string palindrome::removeNonLetters()
{
int j=0;
int str_length = new_Array.length(); //string length
only_letters = new string[only_letters_size];
for (int i=0;i<size_new_Array;i++) //PROBLEM OCCURS HERE AS WELL
{
if (isalpha(new_Array[i]))//a command that checks for characters
{
only_letters[j] = new_Array[i];//word without non alphabetical c
characters is stored to new variable
j++;
}
}
cout << only_letters << endl;
return only_letters;
}
I've found the best way to determine if a string is a palindrome is to walk toward the center from both sides. In your case I would just opt to skip non-alpha characters like so.
bool is_palindrome(string mystring)
{
int start = 0, end = mystring.length() - 1;
while (start < end)
{
// Skip over non-alpha characters
while (!isalpha(mystring[start]))
{
start++;
}
while (!isalpha(mystring[end]))
{
end--;
}
if (tolower(mystring[start]) != tolower(mystring[end]))
{
return false;
}
else
{
start++;
end--;
}
}
return true;
}
If you must save the input first and remove nonalpha characters, I would do it like this.
string remove_non_alpha(string mystring)
{
string ret_string = "";
for (int i = 0; i < mystring.length(); i++)
{
if (isalpha(mystring[i]))
{
ret_string += tolower(mystring[i]);
}
}
return ret_string;
}
And then feed the result into the above function.
Sorry for being hard, but your trying far too much copying around. You can achieve all this with one single loop after retrieving your data and all on one single string object (unless you want to keep the original input for some other purposes):
getline(cin,input_phrase);
std::string::iterator pos = input_phrase.begin();
for(char c : input_phrase)
{
if(isalpha(c))
{
*pos++ = tolower(c);
}
}
input_phrase.erase(pos, input_phrase.end());
After that, your string is ready to use...
Explanation:
std::string::iterator pos = input_phrase.begin();
An iterator something similar than a pointer to the internal data of the string. We keep the position to move the alpha only characters to, skipping the non-alpha ones.
for(char c : input_phrase)
Simply iterating over all characters...
if(isalpha(c))
The essential check, is the current character an alpha one?
*pos++ = tolower(c);
If so, convert it to lower case immediately. Assign it to the current string position, and advance the "pointer" (iterator!).
input_phrase.erase(pos, input_phrase.end());
And at very last, drop the remaining part of the string occupied with surplus characters. You might note that there might be some characters you wanted to keep within, but you copied these to a position more to the left already...

Check input string to see if it is a number in C++ [duplicate]

This question already has answers here:
How to check if input is numeric in C++
(8 answers)
Closed 6 years ago.
I'm new to C++,
can I ask is there a way to check if a input string is a number?
If it is a number, change it to integer.
I know we can use either atoi or stoi.
But how can we create it in a function?
Construct a std::istringstream from the std::string.
Extract a number from it. If extraction is successful, use the number. If not, move on to the next thing.
std::string s = "123";
std::istringstream str(s);
int n;
if ( str >> n )
{
// Extraction is successful.
// Use n.
}
Further Enahncements
To make your program more robust, you can add a further check to make sure that:
"123FAST" is not treated as an integer.
"123.56" is not treated as an integer.
"123.56xyz" is not treated as an integer.
std::string s = "123";
std::istringstream str(s);
int n;
if ( str >> n )
{
// Extraction is successful.
// Add another check.
// Get the next character.
// It has to be a whitespace character or EOF for the input
// to be an integer.
// If it is neither, don't accept the input as an integer.
std::istream::int_type c = str.get();
if ( std::isspace(c) || str.eof() )
{
// Use n.
}
}
You just check each character in your input string is a number, I have a simple example for your problem:
#include <stdio.h>
#include <string.h>
bool is_number(const char * s)
{
int length = strlen(s);
for (int i = 0; i < length; i++)
{
if (s[i] < '0' || s[i] > '9')
return false;
}
return true;
}
int main()
{
printf("Enter a string: ");
char myString[10];
gets(myString);
if (is_number(myString))
printf("%s is a number", myString);
else
printf("%s is not a number", myString);
}
I don't think you even need to check. According to the C++ API:
If the first sequence of non-whitespace characters in str is not a
valid integral number, or if no such sequence exists because either
str is empty or it contains only whitespace characters, no conversion
is performed and zero is returned.
SEE:
http://www.cplusplus.com/reference/cstdlib/atoi/
-
So, you should just be able to do:
// Convert the string
int value = atoi( myString.c_str() );
if ( value == 0 )
{
// The string was not a valid integer
}
else
{
// The string was a valid integer
}
'isnum()' function below checks if given string is comprised of numbers only. However it might not work if number is very large.
#include <bits/stdc++.h>
using namespace std;
bool isnum(string str){
for(int i=0;i<str.length();i++){
if((str[i]<'0') || (str[i]>'9'))return false;
}
return true;
}
int main() {
// your code goes here
int n=0,r=1;
string num;
cin>>num;
if(isnum(num)){
for(int i=num.length()-1;i>=0;i--){
n+=(r)*(int)(num[i]-'0');
r*=10;
}
cout<<n;
}
return 0;
}
You can check if there is any non-digit character in the string:
#include <iostream>
#include <string>
#include <algorithm>
#include <cctype>
int main()
{
std::string test;
std::cin >> test;
if(std::find_if(test.begin(), test.end(), [](auto x){return !isdigit(x);}) == test.end())
std::cout << "its a number" << std::endl;
else
std::cout << "not a number" << std::endl;
}

Read integer from string

I have a string in form "blah-blah..obj_xx..blah-blah" where xx are digits. E.g. the string may be "root75/obj_43.dat".
I want to read "xx" (or 43 from the sample above) as an integer. How do I do it?
I tried to find "obj_" first:
std::string::size_type const cpos = name.find("obj_");
assert(std::string::npos != cpos);
but what's next?
My GCC doesn't support regexes fully, but I think this should work:
#include <iostream>
#include <string>
#include <regex>
#include <iterator>
int main ()
{
std::string input ("blah-blah..obj_42..blah-blah");
std::regex expr ("obj_([0-9]+)");
std::sregex_iterator i = std::sregex_iterator(input.begin(), input.end(), expr);
std::smatch match = *i;
int number = std::stoi(match.str());
std::cout << number << '\n';
}
With something this simple you can do
auto b = name.find_first_of("0123456789", cpos);
auto e = name.find_first_not_of("0123456789", b);
if (b != std::string::npos)
{
auto digits = name.substr(b, e);
int n = std::stoi(digits);
}
else
{
// Error handling
}
For anything more complicated I would use regex.
How about:
#include <iostream>
#include <string>
int main()
{
const std::string test("root75/obj_43.dat");
int number;
// validate input:
const auto index = test.find("obj_");
if(index != std::string::npos)
{
number = std::stoi(test.substr(index+4));
std::cout << "number: " << number << ".\n";
}
else
std::cout << "Input validation failed.\n";
}
Live demo here. Includes (very) basic input validation (e.g. it will fail if the string contains multiple obj_), variable length numbers at the end, or even more stuff following it (adjust the substr call accordingly) and you can add a second argument to std::stoi to make sure it didn't fail for some reason.
Here's another option
//your code:
std::string::size_type const cpos = name.find("obj_");
assert(std::string::npos != cpos);
//my code starts here:
int n;
std::stringstream sin(name.substr(cpos+4));
sin>>n;
Dirt simple method, though probably pretty inefficient, and doesn't take advantage of the STL:
(Note that I didn't try to compile this)
unsigned GetFileNumber(std::string &s)
{
const std::string extension = ".dat";
/// get starting position - first character to the left of the file extension
/// in a real implementation, you'd want to verify that the string actually contains
/// the correct extension.
int i = (int)(s.size() - extension.size() - 1);
unsigned sum = 0;
int tensMultiplier = 1;
while (i >= 0)
{
/// get the integer value of this digit - subtract (int)'0' rather than
/// using the ASCII code of `0` directly for clarity. Optimizer converts
/// it to a literal immediate at compile time, anyway.
int digit = s[i] - (int)'0';
/// if this is a valid numeric character
if (digit >= 0 && digit <= 9)
{
/// add the digit's value, adjusted for it's place within the numeric
/// substring, to the accumulator
sum += digit * tensMultiplier;
/// set the tens place multiplier for the next digit to the left.
tensMultiplier *= 10;
}
else
{
break;
}
i--;
}
return sum;
}
If you need it as a string, just append the found digits to a result string rather than accumulating their values in sum.
This also assumes that .dat is the last part of your string. If not, I'd start at the end, count left until you find a numeric character, and then start the above loop. This is nice because it's O(n), but may not be as clear as the regex or find approaches.