Find the different characters present in a string - c++

Is there any way to find the all the unique characters present in a string without finding all the occurrences of the string ?
For example, Let it be string a="mississippi" , the output should be {i,m,p,s}. Is there any inbuilt functions to find that in c++?

You can do that using std::sort, std::unique, std::string::erase
Note : original string will be modified [If you don't want that make a copy of it]
std::string str = "mississippi";
std::sort(std::begin(str), std::end(str));
auto last = std::unique(std::begin(str), std::end(str));
str.erase(last, std::end(str));

Make a set of characters and put all items from string to it, then you will have set with "alphabet" of your string.
E.g.:
#include <string>
#include <iostream>
#include <set>
int main(void)
{
std::string a = "mississippi";
std::set<char> alphabet;
alphabet.insert(a.begin(), a.end());
std::cout << "Set of chars has " << alphabet.size() << " items." << std::endl;
for (auto a : alphabet)
{
std::cout << a << std::endl;
}
}
Original string is not modified in that example and there is no need to pre-sort.

Sounds uncommon enough that it's not part of the STL.
I'd simply try iterating through the string and creating / incrementing the count of numbers in a Hashset. Then, grab all the Keys to determine unique values.
Good Luck

Related

Trying to remove specific characters from a string C++

i need help with removing some non-alphabetical characters from strings. I've been using a method where you look for ascii symbols that dont lay within the a-z and A-Z area. It removes some characters like " ! ", and " ? ", but it dosent remove " " " and " ) " from the end of words.
for(j=0;j<word.size();j++){
if(word[j]<'A' || word[j]>'Z'
word[j]<'a' || word[j]>'z'){
word.erase(j,1);
j--;
wordsave.push_back(word)}}
This code gets data from a textfile, with a random story in it, it saves the word that is modified to a vector called "wordsave". word is just the string, saving the word from the file temporarily.
The word goes through the whole program because at the end of the program i have a cout that proves that it went through the program.
What could be the problem behind this code, that makes it skip out on removing some characters?
Here is a method using a well-established idiom, aptly called the erase/remove idiom. It's more efficient than multiple random erases. It takes advantage of a few Standard Library functions, and doesn't require an unnecessary copy.
#include <algorithm>
#include <cctype>
#include <iostream>
#include <string>
int main() {
std::string str("a678b##$c");
std::cout << str << '\n';
str.erase(std::remove_if(str.begin(), str.end(),
[](char c) { return !std::isalpha(c); }),
str.end());
std::cout << str << '\n';
}
Output:
a678b##$c
abc
You could pull this code out into its own function, and iterate over your vector, calling the function for each element.

Why do you need two range for loops to change these elements of a vector in C++?

For this problem:
Read a sequence of words from cin and store the values a vector. After
you’ve read all the words, process the vector and change each word to
uppercase. Print the transformed elements, eight words to a line
This code completes the exercise:
#include <iostream>
#include <vector>
#include <string>
using std::cin;
using std::cout;
using std::endl;
using std::vector;
using std::string;
int main()
{
vector<string> vec;
string word;
while (cin >> word)
vec.push_back(word);
for (auto &str : vec)
for (auto &c : str)
c = toupper(c);
for (decltype(vec.size()) i=0; i != vec.size(); ++i)
{
if (i!=0&&i%8 == 0) cout << endl;
cout << vec[i] << " ";
}
cout << endl;
return 0;
}
I was just wondering why you have to have two range for loops in this block:
for (auto &str : vec)
for (auto &c : str)
c = toupper(c);
...to actively change the elements of the vector to uppercase, as opposed to this:
for (auto &str : vec)
str = toupper(str);
toupper() converts a single character, and there is no (standard) variant that converts all characters in a string.
The inner loop causes toupper() to be applied to every characters in a single string. The outer loop causes the inner loop to be applied to every string in the vector<string>.
The combined effect is converting every character in every string in the vector to uppercase.
I was just wondering why you have to have two range for loops in this block:
A std::vector<std::string> is analogous to an array of strings.
A std::string is analogous to an array of characters.
When you need to convert a word to all upper case letters, you will need to change each character of the word to upper case. Hence, you need two for loops.
You could use:
str = toupper(str);
if you implement toupper with the right signature. The standard library doesn't come with one. The version of toupper that comes with the standard library can only convert one character.
toupper() requires an argument of type char and hence you cannot place a direct string into it as there is no conversion.
And now,
for (auto &str : vec)
for (auto &c : str)
c = toupper(c);
We are required to do the above thing. I can explain it like this:
vec is a vector and hence is a container, and this container has elements which are stringS.
You can think of string as a container of charS.
Now at the last part of the code, we take each character from the string sequentially and turn it into its uppercase form.

How to remove first word from a string?

Let's say I have
string sentence{"Hello how are you."}
And I want string sentence to have "how are you" without the "Hello". How would I go about doing that.
I tried doing something like:
stringstream ss(sentence);
ss>> string junkWord;//to get rid of first word
But when I did:
cout<<sentence;//still prints out "Hello how are you"
It's pretty obvious that the stringstream doesn't change the actual string. I also tried using strtok but it doesn't work well with string.
Try the following
#include <iostream>
#include <string>
int main()
{
std::string sentence{"Hello how are you."};
std::string::size_type n = 0;
n = sentence.find_first_not_of( " \t", n );
n = sentence.find_first_of( " \t", n );
sentence.erase( 0, sentence.find_first_not_of( " \t", n ) );
std::cout << '\"' << sentence << "\"\n";
return 0;
}
The output is
"how are you."
str=str.substr(str.find_first_of(" \t")+1);
Tested:
string sentence="Hello how are you.";
cout<<"Before:"<<sentence<<endl;
sentence=sentence.substr(sentence.find_first_of(" \t")+1);
cout<<"After:"<<sentence<<endl;
Execution:
> ./a.out
Before:Hello how are you.
After:how are you.
Assumption is the line does not start with an empty space. In such a case this does not work.
find_first_of("<list of characters>").
the list of characters in our case is space and a tab. This will search for first occurance of any of the list of characters and return an iterator. After that adding +1 movers the position by one character.Then the position points to the second word of the line.
Substr(pos) will fetch the substring starting from position till the last character of the string.
You can for example take the remaining substring
string sentence{"Hello how are you."};
stringstream ss{sentence};
string junkWord;
ss >> junkWord;
cout<<sentence.substr(junkWord.length()+1); //string::substr
However, it also depends what you want to do further
There are countless ways to do this. I think I would go with this:
#include <iostream>
#include <string>
int main() {
std::string sentence{"Hello how are you."};
// First, find the index for the first space:
auto first_space = sentence.find(' ');
// The part of the string we want to keep
// starts at the index after the space:
auto second_word = first_space + 1;
// If you want to write it out directly, write the part of the string
// that starts at the second word and lasts until the end of the string:
std::cout.write(
sentence.data() + second_word, sentence.length() - second_word);
std::cout << std::endl;
// Or, if you want a string object, make a copy from the start of the
// second word. substr copies until the end of the string when you give
// it only one argument, like here:
std::string rest{sentence.substr(second_word)};
std::cout << rest << std::endl;
}
Of course, unless you have a really good reason not to, you should check that first_space != std::string::npos, which would mean the space was not found. The check is omitted in my sample code for clarity :)
You could use string::find() to locate the first space. Once you have its index, then get the sub string with string::substr() from the index after the index of the space up to the end of the string.
One liner:
std::string subStr = sentence.substr(sentence.find_first_not_of(" \t\r\n", sentence.find_first_of(" \t\r\n", sentence.find_first_not_of(" \t\r\n"))));
working example:
#include <iostream>
#include <string>
void main()
{
std::string sentence{ "Hello how are you." };
char whiteSpaces[] = " \t\r\n";
std::string subStr = sentence.substr(sentence.find_first_not_of(whiteSpaces, sentence.find_first_of(whiteSpaces, sentence.find_first_not_of(whiteSpaces))));
std::cout << subStr;
std::cin.ignore();
}
Here's how to use a stringstream to extract the junkword while ignoring any space before or after (using std::ws), then get the rest of the sentence, with robust error handling....
std::string sentence{"Hello how are you."};
std::stringstream ss{sentence};
std::string junkWord;
if (ss >> junkWord >> std::ws && std::getline(ss, sentence, '\0'))
std::cout << sentence << '\n';
else
std::cerr << "the sentence didn't contain ANY words at all\n";
See it running on ideone here....
#include <iostream> // cout
#include <string> // string
#include <sstream> // string stream
using namespace std;
int main()
{
string testString = "Hello how are you.";
istringstream iss(testString); // note istringstream NOT sstringstream
char c; // this will read the delima (space in this case)
string firstWord;
iss>>firstWord>>c; // read the first word and end after the first ' '
cout << "The first word in \"" << testString << "\" is \"" << firstWord << "\""<<endl;
cout << "The rest of the words is \"" <<testString.substr(firstWord.length()+1) << "\""<<endl;
return 0;
}
output
The first word in "Hello how are you." is "Hello"
The rest of the words is "how are you."
live testing at ideon

How to capitalize a word in a C++ string?

I have a std::string and wish for the first letter to be capitalized and the rest lower case.
One way I could do this is:
const std::string example("eXamPLe");
std::string capitalized = boost::to_lower_copy(example);
capitalized[0] = toupper(capitalized[0]);
Which would yield capitalized as:
"Example"
But perhaps there is a more straight forward way to do this?
If the string is indeed just a single word, std::string capitalized = boost::locale::to_title (example) should do it. Otherwise, what you've got is pretty compact.
Edit: just noticed that the boost::python namespace has a str class with a capitalize() method which sounds like it would work for multi word strings (assuming you want what you described and not title case). Using a python string just to gain that functionality is probably a bad idea, however.
A boost-less solution is:
#include <iostream>
#include <string>
#include <algorithm>
int main()
{
const std::string example("eXamPLe");
std::string s = example;
s[0] = toupper(s[0]);
std::transform(s.begin()+1, s.end(), s.begin()+1, tolower);
std::cout << s << "\n";
}
I think the string variable name is example and the string stored in it is "example".
So try this:
example[0] = toupper(example[0]);
for(int i=1 ; example[i] != '\0' ; ++i){
example[i] = tolower(example[i]);
}
cout << example << endl;
This might give you the first character CAPITALIZED and the rest of the string becomes lowercase.
It's not quite different from the original solution but just a different approach.

How do I split a user-defined sentence into words in C++ using substr and find?

I used this function but it is wrong.
for (int i=0; i<sen.length(); i++) {
if (sen.find (' ') != string::npos) {
string new = sen.substr(0,i);
}
cout << "Substrings:" << new << endl;
}
Thank you! Any kind of help is appreciated!
new is a keyword in C++, so first step is to not use that as a variable name.
After that, you need to put your output statement in the "if" block, so that it can actually be allowed to access the substring. Scoping is critical in C++.
First: this cannot compile because new is a language keyword.
Then you have a loop running through every character in the string so you shouldn't need to use std::string::find. I would use std::string::find, but then the loop condition should be different.
This doesn't use substr and find, so if this is homework and you have to use that then this won't be a good answer... but I do believe it's the better way to do what you're asking in C++. It's untested but should work fine.
//Create stringstream and insert your whole sentence into it.
std::stringstream ss;
ss << sen;
//Read out words one by one into a string - stringstream will tokenize them
//by the ASCII space character for you.
std::string myWord;
while (ss >> myWord)
std::cout << myWord << std::endl; //You can save it however you like here.
If it is homework you should tag it as such so people stick to the assignment and know how much to help and/or not help you so they don't give it away :)
No need to iterate over the string, find already does this. It starts to search from the beginning by default, so once we found a space, we need to start the next search from this found space:
std::vector<std::string> words;
//find first space
size_t start = 0, end = sen.find(' ');
//as long as there are spaces
while(end != std::string::npos)
{
//get word
words.push_back(sen.substr(start, end-start));
//search next space (of course only after already found space)
start = end + 1;
end = sen.find(' ', start);
}
//last word
words.push_back(sen.substr(start));
Of course this doesn't handle duplicate spaces, starting or trailing spaces and other special cases. You would actually be better off using a stringstream:
#include <sstream>
#include <algorithm>
#include <iterator>
std::istringstream stream(sen);
std::vector<std::string> words(std::istream_iterator<std::string>(stream),
std::istream_iterator<std::string>());
You can then just put these out however you like or just do it directly in the loops without using a vector:
for(std::vector<std::string>::const_iterator iter=
words.begin(); iter!=words.end(); ++iter)
std::cout << "found word: " << *iter << '\n';