Determine if 2 strings are anagrams - c++

Write a function that accepts a c-string and a character as parameters. Returns the number of times the character appears in the string.
I also have to do this in my program:
Convert strings A and B to all lower case. For each letter in string A, call function on A and B.
This is the code I have so far:
#include <iostream>
#include <cstring>
#include <cctype>
using namespace std;
char tolower(char c) {
return c;
}
int countChars(const char* string, char ch)
{
int count = 0;
int i;
int length = strlen(string);
for (i = 0; i < length; i++)
{
if (string[i] == ch)
{
count++;
}
}
return count;
}
int main() {
char stringA[50];
char stringB[50];
cout << "Please enter first string: ";
cin.getline(stringA, 50);
cout << "Please enter second string: ";
cin.getline(stringB, 50);
cout << "String 1: " << stringA << endl;
cout << "String 2: " << stringB << endl;
if (strcmp(stringA, stringB) == 0) {
cout << "These strings are anagrams" << endl;
}
else {
cout << "These strings are not anagrams" << endl;
}
}

If you want to do so in a simple and readable way, consider the following code:
#include <string>
#include <iostream>
#include <algorithm>
bool is_anagram(std::string s1, std::string s2)
{
std::sort(s1.begin(), s1.end());
std::sort(s2.begin(), s2.end());
return s1 == s2;
}
int main(void)
{
std::string s1, s2;
std::cout << "Input first string: ";
getline(std::cin, s1);
std::cout << "Input second string: ";
getline(std::cin, s2);
if (is_anagram(s1, s2))
std::cout << "Strings are anagrams." << std::endl;
else
std::cout << "Strings are NOT anagrams." << std::endl;
return 0;
}
The function is_anagram() returns true when the sorted strings (used algorithm library for it) are same.
Note: The strings are case-sensitive. Hello and hello are different.
Hope it helps you. :D

Just sort the both the strings and then compare it.
sort(stringA, stringA+strlen(stringA))
sort(stringB, stringB+strlen(stringB))
just before the if statement.
You were checking if the 2 strings are exactly equal. But anagrams can have different arrangement of letters but must have same letters.
Though you need to check may need to check if the 2 strings are same (if you don't consider a string to be an anagram of itself).
PS- a google search would have instantly provided you ans.

The easiest way to do this is to count the number of each letter. Note you don't need to count every letter just the ones are in the string. To compare them store the results in a map.
#include <iostream>
#include <string>
#include <map>
#include <array>
class AnagramCheck
{
// I am going to be lazy and use map to store the counts.
// But you can do this much smarter and get a better complexity
// by using an array. But that involves more checks
std::map<char, int> data;
public:
explicit AnagramCheck(std::string const& str)
{
for(auto x: str) {
++data[std::tolower(x)]; // If you want to be smart ignore space/punctuation
}
}
bool operator==(AnagramCheck const& rhs) const
{
return data == rhs.data;
}
};
int main()
{
std::string line1;
std::getline(std::cin, line1);
AnagramCheck line1Check(line1);
std::string line2;
std::getline(std::cin, line2);
AnagramCheck line2Check(line2);
if (line1Check == line2Check) {
std::cout << "Anagram\n";
}
}

Related

how do I check if all characters in a string is space or alphabet? C++

I need to make a program which converts all letters to uppercase.
But first I need to get an input from the user. And I need to check if there are characters that are not space or alphabet.
This is what I tried.
#include <iostream>
#include <cctype>
using namespace std;
int main()
{
string s;
cout << "Enter a string: ";
while (getline(cin, s)){
for (int i = 0; i<s.length(); i++){
if ((isspace(s[i]) || isalpha(s[i]))){
for (int i = 0; i < s.length(); i++){
s[i] = toupper(s[i]);
}
cout << s << endl;
return 1;
}
cout << "Invalid string. Please input only alphabets or space character. " << endl << "Enter a string: ";
}
}
//if the input value is valid convert and print
return 0;}
This program successfully make error messages to pure numbers and pure question marks. But the problem is if there are invalid characters and valid characters mixed in the input, it cannot distinguish it.
For example, if input is "Hi?", the program thinks its a valid input. But with questions marks, the string should be invalid.
I think the for statement is the problem. How can I solve this?
I've made a few changes to deal with the break out conditions in your loops without changing the structure of your program too much.
Here's one example how you could get it to work. Comments in the code.
#include <cctype>
#include <iostream>
#include <string>
int main() {
std::string s;
while(std::cout << "Enter a string: " && std::getline(std::cin, s)) {
bool valid = true; // will stay true unless at least one char is invalid
for(char& ch : s) { // use a range-based for loop
// ch is now a reference to the char in the string
// convert to unsigned char - these functions are not safe
// otherwise:
if(std::isspace(static_cast<unsigned char>(ch)) ||
std::isalpha(static_cast<unsigned char>(ch)))
{
ch = std::toupper(static_cast<unsigned char>(ch));
continue; // continue to check the next character
}
std::cout << "Invalid character ('" << ch << "') in string.\n"
"Please input only alphabets or space character.\n";
valid = false; // to let the user enter a new string
break; // no need to check more characters, the string is invalid
}
if(valid) break; // break out only if all characters are valid
}
if(std::cin)
std::cout << "The valid string is now " << s << '\n';
}
A similar program could use algorithms from <algorithm> to do the check and the transformation of the string to uppercase.
Example:
#include <algorithm>
#include <cctype>
#include <iostream>
#include <string>
int main() {
std::string s;
// the manual loop replaced by a simple algorithm that checks if any
// character in the string is invalid by using a lambda, here called
// "is_invalid":
auto is_invalid = [](unsigned char ch) {
return !(std::isspace(ch) || std::isalpha(ch));
};
while(std::cout << "Enter a string: " &&
std::getline(std::cin, s) &&
std::any_of(s.begin(), s.end(), is_invalid))
{
std::cout << "Invalid character in string.\n"
"Please input only alphabets or space character.\n";
}
if(std::cin) {
// transform the valid string to uppercase using another lambda.
// the lambda is here only to make the chars into unsigned chars
// to make the use of std::toupper safe
auto to_upper = [](unsigned char ch) { return std::toupper(ch); };
std::transform(s.begin(), s.end(), s.begin(), to_upper);
std::cout << "The valid string is now " << s << '\n';
}
}

Convert char array to a string with cin.getline(.)

hi guys so my question is how to convert a char array to a string. here is my code:
#include<iostream>
using namespace std;
int main()
{
while (true) {
char lol[128];
cout << "you say >> ";
cin.getline(lol,256);
cout << lol << endl;;
}
return 0;
}
so I want to convert lol to a string variable like "stringedChar" (if thats even english lol)
so I can do stuff like:
string badwords[2] = {"frick","stupid"};
for (int counter = 0; counter < 2;counter++) {
if(strigedChar == badwords[counter]) {
bool isKicked = true;
cout << "Inappropriate message!\n";
}
}
Sorry im just a c++ begginer lol
Do something like this :
as char lol[128];
into string like: std::string str(lol);
Line : cin.getline(lol,256); <--> should be changed to cin.getline(lol,128)
Just invoke std::getline() on a std::string object instead of messing about with a char array, and use std::set<std::string> for badwords as testing set membership is trivial:
#include <iostream>
#include <set>
#include <string>
static std::set<std::string> badwords{
"frick",
"stupid"
};
int main() {
std::string line;
while (std::getline(std::cin, line)) {
if (badwords.count(line) != 0) {
std::cout << "Inappropriate message!\n";
}
}
return 0;
}
Note that this tests whether the entire line is equal to any element of the set, not that the line contains any element of the set, but your code appears to be attempting to do the former anyway.
First off, you have a mistake in your code. You are allocating an array of 128 chars, but you are telling cin.getline() that you allocated 256 chars. So you have a buffer overflow waiting to happen.
That said, std::string has constructors that accept char[] data as input, eg:
#include <iostream>
using namespace std;
int main()
{
while (true) {
char lol[128];
cout << "you say >> ";
cin.getline(lol, 128);
string s(lol, cin.gcount());
cout << s << endl;;
}
return 0;
}
However, you really should use std::getline() instead, which populates a std::string instead of a char[]:
#include <iostream>
#include <string>
using namespace std;
int main()
{
while (true) {
string lol;
cout << "you say >> ";
getline(cin, lol);
cout << lol << endl;;
}
return 0;
}

How to get the strings to print in order after they have been reversed

The goal of this program is to get user input and then print the words backwards, but still in the order the user typed them in. For example, the user input- "cats and mice are cool", then the program should output "stac dna ecim era looc", but what I am getting is "looc era ecim dna stac". I think that rearranging the words would happen in the main function, but I'm not sure how to get it to print in order. Any help greatly appreciated!
#include <iostream>
#include <cstring>
using namespace std;
void reverse(string input) {
int size = (int)input.size();
if(size==1){
cout << input[size-1];
}
else {
cout << input[size-1];
reverse(input.substr(0, size-1));
}
}
int main() {
string input;
char choice;
cout << "Please enter a string with spaces." << endl;
getline(cin, input);
reverse(input);
cout << endl;
}
You're reversing the entire string... split string on spaces, then cycle on splits and call reverse() on every split before printing it.
Furthermore, you can use C++ STL classes for reversing and even result useful in splitting:
#include <iostream>
#include <string>
#include <vector>
#include <sstream>
std::vector<std::string> split(std::string text, char delimiter)
{
std::vector<std::string> res;
std::istringstream f(text);
std::string s;
while (std::getline(f, s, delimiter)) {
res.push_back(s);
}
return(res);
}
int main() {
std::string input;
std::cout << "Please enter a string with spaces." << std::endl;
std::getline(std::cin, input);
for(auto s : split(input, ' '))
{
std::reverse(s.begin(), s.end());
std::cout << s << " ";
}
std::cout << std::endl;
}

How to erase non-alphabet characters from a string without going out of range

I am trying to this function to return without numbers, spaces, or other characters and I am supposed to use the .erase function. I understand that my loop keeps going out of range, but I have no clue how to fix it and I've been stuck on this for a while. If the user types "dogs are a lot of fun" and I need the function to return and output "dogsarealotoffun" Thanks for the help.
#include <iostream>
#include <cctype>
#include <cstring>
using namespace std;
//function to output string without spaces, numbers, or punctuations
string alphabetOnly (string input){
int size;
int i= 0;
size = (int)input.size();
while (input[i] < size){
if (isalpha(input[i])){
i++;
}
else
input.erase(input[i]);
}
return input;
}
int main() {
string input;
cout << "Enter a string to test: ";
getline(cin, input);
cout << "alphabetOnly: " << alphabetOnly(input) << endl;
}
EDITED: I was too hasty in my previous answer (as I am learning I need to speak from tested code rather than off the top of my head) and needed to debug. The problem is in the else case you need to erase the char, NOT increment i because the length of the string just changed, and also since the length of the string changed you need to reset size to be the new length. Sorry for the hasty answer earlier, I was speaking without actually using the compiled code.
#include <iostream>
#include <cctype>
#include <string>
//function to output string without spaces, numbers, or punctuations
std::string alphabetOnly (std::string input){
int size;
int i= 0;
size = (int)input.size();
while (i < size){
if (isalpha(input[i])){
i++;
}
else{
input.erase(i,1);
//do not increment i here since the index changed becauase of erase
size = (int)input.size();
}
}
return input;
}
int main() {
std::string input;
std::cout << "Enter a string to test: ";
std::getline(std::cin, input);
std::cout << input;
std::cout << "alphabetOnly: " << alphabetOnly(input) << std::endl;
return 0;
}
something like this:
#include <iostream>
#include <string>
#include <algorithm>
//function to output string without spaces, numbers, or punctuations
std::string alphabetOnly (std::string input)
{
auto not_alpha = [](char c) { return !std::isalpha(c); };
input.erase(std::remove_if(begin(input),
end(input),
not_alpha),
std::end(input));
return input;
}
int main() {
std::string input;
std::cout << "Enter a string to test: ";
getline(std::cin, input);
std::cout << "alphabetOnly: " << alphabetOnly(input) << std::endl;
}
http://coliru.stacked-crooked.com/a/340465d41ecd8c8e
There's quite a few things wrong with your code, but to start with here's your main error corrected.
#include <iostream>
#include <cctype>
#include <cstring>
using namespace std;
//function to output string without spaces, numbers, or punctuations
string alphabetOnly (string input){
int size;
int i= 0;
size = (int)input.size();
while (i < size){
if(isalpha(input[i]))
{
i++;
}
else
input.erase(input.begin( ) + i );
}
return input;
}
int main() {
string input;
cout << "Enter a string to test: ";
getline(cin, input);
cout << "alphabetOnly: " << alphabetOnly(input) << endl;
}
But this is awfully inefficient because you swhift all the remaining unchecked characters each time you delete.
You should use something like
input.erase( remove_if( input.begin(), input.end(), not( isalpha ) ), input.end( ));
This is known as the remove-erase idiom, whihc you can lookup anywhere.

Insert a character into a string

I need to insert a character into a string at every instance of that character. For example if my string was, "This is a test" and my character was 's' then my output would need to look like this: "Thiss iss a tesst"
any idea why this isn't working? Here's what I have so far. I am not supposed to add any extra preprocessor instructions or anything, just using what's here I need to figure this out.
#include <iostream>
#include <string>
using namespace std;
int main(){
string userString;
char userChar;
cin >> userString;
cin >> userChar;
for (int i = 0; i < userString.size(); i++){
if(userString.at(i) == userChar){
userString.insert(userString.begin() + i, userChar);
}
}
cout << userString;
return 0;
Update:
Here's the solution I worked out.
#include <iostream>
#include <string>
using namespace std;
int main(){
string userString;
char userChar;
cout << "enter a string" << endl;
getline(cin, userString);
cout << "enter a character" << endl;
cin >> userChar;
for (int i = userString.size()-1; i >= 0; i--){
if(userString.at(i) == userChar){
userString.insert(userString.begin() + i, userChar);
}
}
cout << userString;
return 0;
}
I don't know why you want to go through the string backwards. Anyway. Your problem is that once you insert a character at some position, your loop will encounter the inserted character again in the next iteration and insert another. Ad infinitum.
#include <cstddef> // std::size_t, the correct type for indexes and sizes of objects in mem
#include <string>
#include <iostream>
int main()
{
std::cout << "Enter a string: ";
std::string userString; // define variables as close
std::getline(std::cin, userString);
std::cout << "Enter a character: ";
char userChar; // to where they're used as possible
std::cin >> userChar;
for (std::size_t i{}; i < userString.size(); ++i) {
if (userString[i] == userChar) { // no need to use std::string::at() 1)
userString.insert(userString.begin() + i, userChar);
++i; // advance the index to not read the same character again.
}
}
std::cout << userString << '\n';
}
1) since it is allready sure that the index will be in a valid range.
Your first solution probably ends up looping infinitely if you ever find one of the chosen character because you always insert one more copy ahead and keeps finding the same char ever after.
std::basic_string has a find function. It's always better to use code offered by a library than self made code. Here's my proposed solution:
std::string& duplicate_char(std::string& str, char val)
{
using std::string;
auto pos = str.find(val); // finds first index of character val or npos if unsuccessful
while (pos != string::npos)
{
str.insert(pos, 1, val); // insert at pos one character val
pos = str.find(val, pos + 2); // find the next occurence of val starting after the newly inserted character
}
return str;
}
You may use this function like this:
int main()
{
std::string testStr{"Thiss iss a tesst"};
duplicate_char(testStr, 's');
std::cout << testStr << std::endl;
}