I've only found some answers to this problem in Python and JS, hopefully you can help me to do the same in c++.
So the challenge is to print out the first recurring character of a given string, here is what i came up with, but I don't know if this code actually looks good. This is my first time posting on StackOverflow, hopefully I'll get some feedback =)
#include <iostream>
#include <vector>
int main() {
std::cout << "Enter some letters:\n";
std::string str;
std::cin >> str;
// vector that stores characters that we will come across in the string
std::vector<char> seen(0);
for (char a : str) {
for (int i = 0; i < seen.size(); i++) {
if (a == seen[i]) {
std::cout << a << std::endl;
return 0;
} else { continue; }
}
seen.push_back(a);
}
std::cout << "none\n";
return 0;
}
For speed, how about:
#include <iostream>
int main() {
std::cout << "Enter some letters:\n";
std::string str;
std::cin >> str;
bool seen [256] = { };
for (char a : str) {
unsigned char u = (unsigned char) a;
if (seen [u]) {
std::cout << a << std::endl;
return 0;
}
seen [u] = true;
}
std::cout << "none\n";
return 0;
}
This is O(N), rather than O(N*N/2)
Live demo
For your task check out std::find:
void printRecurring(const std::string& str) {
std::string::const_iterator it = str.begin(), e = str.end();
for (std::string::const_iterator it2 = str.begin(); it2 != str.end(); ++it2) {
it = std::find(it + 1, e, *it2);
if (it != str.end()) {
std::cout << *it2 << std::endl;
return;
}
}
}
I think you can make it a little simpler by using std::find.
#include <iostream>
#include <vector>
#include <algoritm>
int main()
{
std::cout << "Enter some letters:\n";
std::string str;
std::cin >> str;
// vector that stores characters that we will come across in the string
std::vector<char> seen(0);
for (char a : str) {
auto it = std::find(seen.begin(), seen.end(), a);
if (it != seen.end()) {
std::cout << "Found it: " << *it << std::endl;
return 0;
}
seen.push_back(a);
}
std::cout << "none\n";
return 0;
}
Related
I get this error while trying to loop through a string to push each element onto a stack of string type s1 in my isPalindrome() function.
no instance of overloaded function "std::stack<_Ty, _Container>::push
[with _Ty=std::string, _Container=std::deque>]" matches the argument list
When I assign, the element that is at the top of the stack to a string variable an error pops up:
'std::stack>>::top':
non-standard syntax; use '&' to create a pointer to member
Why does it mention std::deque?
#include <iostream>
#include <string>
#include <stack>
#include <algorithm>
class Palindrome
{
public:
Palindrome();
void inputString();
std::string convert2lower();
bool isPalindrome();
private:
std::string userstring;
std::stack<std::string> s1;
};
Palindrome::Palindrome()
{}
void Palindrome::inputString()
{
std::cout << "Enter a string: ";
std::getline(std::cin,userstring);
}
std::string Palindrome::convert2lower()
{
userstring.erase(remove(userstring.begin(), userstring.end(), ' '), userstring.end());
userstring.erase(std::remove_if(userstring.begin(), userstring.end(), ispunct), userstring.end());
transform(userstring.begin(), userstring.end(), userstring.begin(), tolower);
return userstring;
}
bool Palindrome::isPalindrome()
{
size_t n = userstring.size();
for (size_t i = 0; i < n; ++i)
{
s1.push(userstring[i]);
}
std::string reversed;
for (size_t i = 0; i < n; ++i)
{
std::string temp = s1.top;
reversed.insert(i,temp);
s1.pop();
}
if (reversed == userstring)
{
return true;
}
return false;
}
int main()
{
Palindrome p1;
p1.inputString();
std::cout << "\nCalling convert2lower(): " << std::endl;
std::cout << "The new string is " << p1.convert2lower() << std::endl;
std::cout << "\nCalling isPalindrome(): " << std::endl;
if (!p1.isPalindrome())
{
std::cout << "String is NOT a Palindrome!" << std::endl;
}
else
{
std::cout << "String is a Palindrome!" << std::endl;
}
}
Here is your code fixed with the absolute minimum changes...
#include <iostream>
#include <string>
#include <stack>
#include <algorithm>
class Palindrome
{
public:
Palindrome();
void inputString();
std::string convert2lower();
bool isPalindrome();
private:
std::string userstring;
std::stack<char> s1;
};
Palindrome::Palindrome()
{}
void Palindrome::inputString()
{
std::cout << "Enter a string: ";
std::getline(std::cin, userstring);
}
std::string Palindrome::convert2lower()
{
userstring.erase(remove(userstring.begin(), userstring.end(), ' '), userstring.end());
userstring.erase(std::remove_if(userstring.begin(), userstring.end(), ispunct), userstring.end());
transform(userstring.begin(), userstring.end(), userstring.begin(), tolower);
return userstring;
}
bool Palindrome::isPalindrome()
{
size_t n = userstring.size();
for (size_t i = 0; i < n; ++i)
{
s1.push(userstring[i]);
}
std::string reversed;
for (size_t i = 0; i < n; ++i)
{
char temp = s1.top();
reversed.insert(i, &temp, 1);
s1.pop();
}
if (reversed == userstring)
{
return true;
}
return false;
}
int main()
{
Palindrome p1;
p1.inputString();
std::cout << "\nCalling convert2lower(): " << std::endl;
std::cout << "The new string is " << p1.convert2lower() << std::endl;
std::cout << "\nCalling isPalindrome(): " << std::endl;
if (!p1.isPalindrome())
{
std::cout << "String is NOT a Palindrome!" << std::endl;
}
else
{
std::cout << "String is a Palindrome!" << std::endl;
}
}
Here are answers to your questions:
no instance of...this is caused by using string instead of char as the stack type.
non standard syntax...this is because you left the () off of pop.
deque is mentioned because stack is a specialization of deque.
I'm a beginner and I have a question(somehow silly and stupid :) )...Today I decided to challenge myself and I came around the challenge that wanted me to create a program that ciphers (or encrypts) the message using the substitution cipher method...I solved the challenge by myself but mine is way different than the solution itself...I just want to know which one is better and why? and also is there anything I missed in my own code?
So here is the code I've written:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string secretMessage {};
string alphabet {"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"};
string key {"XZNLWEBGJHQDYVTKFUOMPCIASRxznlwebgjhqdyvtkfuompciasr"};
cout << "Enter your secret message: ";
getline(cin, secretMessage);
//Encryption
for(size_t i{0}; i<secretMessage.length(); ++i){
for(size_t j{0}; j<alphabet.length(); ++j){
if (secretMessage.at(i) == alphabet.at(j)){
secretMessage.at(i) = key.at(j);
break;
}
}
}
cout << "Encrypting The Message..." << endl;
cout << "Encrypted Message: " << secretMessage << endl;
//Decryption
for(size_t i{0}; i<secretMessage.length(); ++i){
for(size_t j{0}; j<key.length(); ++j){
if (secretMessage.at(i) == key.at(j)){
secretMessage.at(i) = alphabet.at(j);
break;
}
}
}
cout << "\nDecrypting The Encryption..." << endl;
cout << "Decrypted: " << secretMessage << endl;
return 0;
}
And here is the solution:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string secretMessage {};
string alphabet {"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"};
string key {"XZNLWEBGJHQDYVTKFUOMPCIASRxznlwebgjhqdyvtkfuompciasr"};
string encryptedMessage {};
string decryptedMessage {};
cout << "Enter your secret message: ";
getline(cin, secretMessage);
cout << "\nEncrypting Message..." << endl;
//Encryption
for(char c:secretMessage){
size_t position = alphabet.find(c);
if (position != string::npos){
char newChar {key.at(position)};
encryptedMessage += newChar;
} else{
encryptedMessage += c;
}
}
cout << "Encrypted Message: " << encryptedMessage << endl;
//Decryption
cout << "\nDecrypting Message..." << endl;
for(char c:encryptedMessage){
size_t position = key.find(c);
if (position != string::npos){
char newChar {alphabet.at(position)};
decryptedMessage += newChar;
} else{
decryptedMessage += c;
}
}
cout << "Decrypted Message: " << decryptedMessage << endl;
return 0;
}
Note:I have also included the decryption part too
I find both code snipets rather complex.
Please have a look at this more easy solution
#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;
}
This is using more modern C++ language elements. Encrypting and decrypting is implemented via one std::transform statement each.
Of course you should never use such encoding in real live, because the key is visible in the exe file.
Anyway, maybe it helps you to have some more ideas . . .
I'm working on a project which needs to find the number of words and the indices of each word in the paragraph ...I have written the code which is counting the number of word in a string but I stuck with finding the indices of words,
such as : Hi John How are you I miss you ..
I need to print the indices like : 0 1 2 3 4 5 6 7
here is the code:
int _tmain(int argc, _TCHAR* argv[])
{
int count_words(std::string);
std::string input_text;
std::cout<< "Enter a text: ";
std::getline(std::cin,input_text);
int number_of_words=1;
int counter []={0};
for(int i = 0; i < input_text.length();i++)
if(input_text[i] == ' ')
number_of_words++;
std::cout << "Number of words: " << number_of_words << std::endl;
//std:: cout << number_of_words << std::endl;
system ("PAUSE");
}
Hopefully this helps. Edited to include use of count_words function.
#include <iostream>
#include <sstream>
void count_words(std::string);
int main(){
std::string input_text, output_text;
std::cout<< "Enter a text: ";
std::getline(std::cin,input_text);
count_words(input_text);
system ("PAUSE");
return 0; //MUST RETURN AN INTEGER VALUE FROM 'INT MAIN'
}
void count_words(std::string inputString){
std::string output_text;
std::stringstream indexes;
int number_of_words=0; //If there are no words, it would be false, make it 0.
//int counter []={0}; //This serves no purpose.
if(!inputString.empty()){// test to make sure it isn't empty.
number_of_words++;
for(int i = 0; i < inputString.length();i++){ // For loops should have curly braces {} containing their statement.
if(inputString[i] == ' '){
number_of_words++;
}
if((isalpha(inputString[i]))&&inputString[i-1]==' '){ //test for following space separated word
indexes << i << " ";
}
}
}
output_text = indexes.str(); //convert stringstream to string
std::cout << "Number of words: " << number_of_words << std::endl;
//std:: cout << number_of_words << std::endl; //duplicate info
std::cout << "Indexes: " << output_text << std::endl;
}
I'm not sure if i understand the question. You only need print the "indices"?? like this? (Using your own code)
#include <iostream>
#include <vector>
#include <string>
void stringTokenizer(const std::string& str, const std::string& delimiter, std::vector<std::string>& tokens) {
size_t prev = 0, next = 0, len;
while ((next = str.find(delimiter, prev)) != std::string::npos) {
len = next - prev;
if (len > 0) {
tokens.push_back(str.substr(prev, len));
}
prev = next + delimiter.size();
}
if (prev < str.size()) {
tokens.push_back(str.substr(prev));
}
}
int main()
{
std::vector <std::string> split;
std::string input_text;
std::cout<< "Enter a text: ";
std::getline(std::cin,input_text);
stringTokenizer(input_text, " ", split);
int number_of_words = 0;
for (std::vector<std::string>::iterator it = split.begin(); it != split.end(); it++, number_of_words++) {
std::cout << *it << " " << number_of_words << std::endl;
}
}
This question already has answers here:
Right way to split an std::string into a vector<string>
(12 answers)
Closed 7 years ago.
I'm writing 2 programs, the first program has an array of integers
vector<int> v = {10, 200, 3000, 40000};
Then it converts the vector into string
int i;
stringstream sw;
string stringword;
for (i=0;i<v.size();i++)
{
sw << v[i] << ',';
}
stringword = sw.str();
cout << "Vector in string : "<< stringword << endl;
And then write it in a file
ofstream myfile;
myfile.open ("writtentext");
myfile << stringword;
myfile.close();
The output :
Vector in string : 10,200,3000,40000
The second program will read the file, convert the string back to integer, and then push it back to vector.
The code :
string stringword;
ifstream myfile;
myfile.open ("writtentext");
getline (myfile,stringword);
cout << "Read From File = " << stringword << endl;
cout << "Convert back to vector = " ;
for (int i=0;i<stringword.length();i++)
{
if (stringword.find(','))
{
int value;
istringstream (stringword) >> value;
v.push_back(value);
stringword.erase(0, stringword.find(','));
}
}
for (int j=0;j<v.size();j++)
{
cout << v.at(j) << " " ;
}
The problem is, it can only convert and push back the first element, the rest is erased. Here is the output :
Read From File = 10,200,3000,40000,
Convert back to vector = 10
What did I do wrong? Thanks
There's problem with your for loop
Consider this:
while(1) //Use a while loop, "i" isn't doing anything for you
{
//if comman not found find return string::npos
if (stringword.find(',')!=std::string::npos)
{
int value;
istringstream (stringword) >> value;
v.push_back(value);
//Erase all element including comma
stringword.erase(0, stringword.find(',')+1);
}
else
break; //Come out of loop
}
Instead, just use std::stringstream to read back from file
std::stringstream ss(stringword);
int value;
while (ss >> value)
{
v.push_back(value);
if (ss.peek() == ',')
ss.ignore();
}
for (int j=0;j<v.size();j++) //Fix variables
{
cout << v.at(j) << " " ; // Can use simply v[j]
}
for (int j=0;j<v.size();i++)
{
cout << v.at(i) << " " ;
}
should be
for (int j=0;j<v.size();j++)
{
cout << v.at(j) << " " ;
}
i is not declared in the for loop
You can skip the string conversion. All stream can handle int types.
std::vector<int> to output:
#include <iostream>
#include <iterator>
#include <vector>
int main() {
std::vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
std::ostream_iterator<int> output_iterator(std::cout, ",");
std::copy(v.begin(), v.end(), output_iterator);
}
input to std::vector<int>:
#include <iostream>
#include <vector>
#include <sstream>
using namespace std;
int main() {
std::vector<int> v;
int value;
std::string line;
while(getline(cin, line, ',')) {
std::stringstream ss(line);
ss >> value
v.push_back(value);
}
typedef std::vector<int>::iterator iter;
iter end = v.end();
for(iter it = v.begin(); it != end; ++it) {
std::cout << *it << endl;
}
}
this is only a mistake you did:
for (int j=0;j<v.size();i++)
{
cout << v.at(i) << " " ;
}
but the implement is too inefficient here:
for (int i=0;i<stringword.length();i++)
{
if (stringword.find(','))
{
int value;
istringstream (stringword) >> value;
v.push_back(value);
stringword.erase(0, stringword.find(','));
}
}
you may do like this, just a suggestion:
#include <iostream>
#include <string>
#include <vector>
#include <stdlib.h>
int ConvertStringToInt(const std::string &str, std::vector<int> &ints)
{
int count_int = 0;
std::string string_int;
size_t start = 0;
size_t end = 0;
while ((end = str.find(',', start)) != std::string::npos)
{
string_int.assign(str, start, end - start);
ints.push_back(atoi(string_int.c_str()));
start = end + 1;
++count_int;
}
if (start != str.size())
{
ints.push_back(atoi(str.c_str() + start));
++count_int;
}
return count_int;
}
int main(int argc, char *const argv[])
{
std::vector<int> ints;
std::string str = "123,456,789 ";
std::cout << ConvertStringToInt(str, ints) << std::endl;
for (size_t i = 0; i != ints.size(); ++i)
{
std::cout << ints[i] << std::endl;
}
return 0;
}
You can make your programs simpler:
#include <algorithm>
#include <fstream>
#include <iostream>
#include <iterator>
#include <vector>
// output
int main()
{
// my compiler doesn't support initializer lists yet :(
std::vector<int> v(4);
v[0] = 10;
v[1] = 200;
v[2] = 3000;
v[3] = 40000;
std::ofstream fout("mytestfile.txt");
std::copy(v.begin(), v.end(), std::ostream_iterator<int>(fout, ","));
fout.close();
return 0;
}
// input
struct int_reader : std::ctype<char>
{
int_reader() : std::ctype<char>(get_table()) {}
static std::ctype_base::mask const* get_table()
{
static std::vector<std::ctype_base::mask> rc(table_size, std::ctype_base::mask());
rc[','] = std::ctype_base::space;
rc['\n'] = std::ctype_base::space;
return &rc[0];
}
};
int main()
{
std::vector<int> v;
std::ifstream fin("mytestfile.txt", std::ifstream::in);
fin.imbue(std::locale(std::locale(), new int_reader()));
std::copy(std::istream_iterator<int>(fin), std::istream_iterator<int>(), std::back_inserter<std::vector<int>>(v));
fin.close();
std::cout << "You read in: ";
std::copy(v.begin(), v.end(), std::ostream_iterator<int>(std::cout, " "));
return 0;
}
Though this is handcrafted instead of using std::stringstream, I find it quite easy to understand.
std::vector<std::string> StringToVector (const std::string s,
const char token)
{
std::vector<std::string> v;
size_t posLast = 0, pos = 0;
while((pos = s.find(token, pos)) != std::string::npos)
{
if(s[pos] != s[posLast])
v.push_back(s.substr(posLast, pos - posLast));
posLast = ++pos;
}
if(s[posLast] != 0) // If there is no terminating token found
v.push_back(s.substr(posLast));
return v;
}
Demo with various test cases.
Is it possible to implement a C++ function which gives a string representation of every std::vector<T>, as long as the element of type T can be appended to an output stream like
T x;
...
std::cout << x << std::endl;
The string representation should look like
[x, y, z]
I've attempted the following, but what should ? be?
template <typename T> std::string vectorToString(std::vector<T>& vec) {
std::string s;
for (T element : vec) {
?
}
return s;
}
You'll want a stringstream to do the formatting:
std::ostringstream ss;
ss << '['
bool first = true;
for (T const & element : vec) {
if (!first) {
ss << ", ";
}
ss << element;
first = false;
}
ss << ']';
return ss.str();
Use a std::ostringstream instance for ? and return std::ostringstream::str():
std::ostringstream s;
s << "[";
for (auto i(vec.begin()); i != vec.end(); i++)
{
if (vec.begin() != i) s << ", ";
s << *i;
}
s << "]";
return s.str();
If you are working on C++11, you can use this simple version:
#include <sstream>
#include <algorithm>
using namespace std;
template<typename T>
string format(vector<T> const& v)
{
if (v.empty()) return "[]";
ostringstream ss;
ss << "[" << v[0];
for_each(begin(v) + 1, end(v), [&ss] (T const& s) { ss << ", " << s; });
ss << "]";
return ss.str();
}
If you want to make it generic for other types of collections (not just vector) or even for sub-ranges of a collection, you can generalize it this way:
#include <sstream>
#include <algorithm>
using namespace std;
template<typename It>
string format(It b, It e)
{
if (b == e) return "[]";
ostringstream ss;
ss << "[" << *b;
for_each(++b, e, [&ss] (decltype(*b)& s) { ss << ", " << s; });
ss << "]";
return ss.str();
}
template<typename C>
string format(C const& c)
{
return format(begin(c), end(c));
}
int main()
{
vector<int> v = { 4, 5, 5, 8 };
cout << format(v) << endl;
return 0;
}
Using algorithms, which usually simplify code (not sure if in this case, but added for the sake of completion):
template <typename T>
std::string toString( std::vector<T> const & v ) {
if (v.empty())
return "[]";
typename std::vector<T>::const_iterator last = std::prev(v.end());
std::ostringstream st;
st << "[ ";
std::copy( v.begin(), last, std::ostream_iterator<T>(st,", ") );
st << *last << " ]";
return st.str();
}
A little bit faster version
template <typename T> std::string vectorToString( const std::vector<T>& vec ) {
if ( vec.empty() ) {
return "[]";
}
std::ostringstream s;
s << "[" << vec.front();
for (auto i = vec.begin() + 1, e = vec.end(); i != e; i++)
{
s << ", " << *i;
}
s << "]";
return s.str();
}
Another moment: maybe it would be right to specialize this function for strings and quote them, because if a string in vector begins or ends with , it would be hard to understand how many strings was printed.
template <>
std::string vectorToString< std::string >( const std::vector<std::string>& vec ) {
if ( vec.empty() ) {
return "[]";
}
std::ostringstream s;
s << "[" << vec.front();
for (auto i = vec.begin() + 1, e = vec.end(); i != e; i++)
{
s << ", \"" << *i << "\"";
}
s << "]";
return s.str();
}