I'm trying to replace characters from the following map: const map<char, vector<char>> ass, note I have this string pasand I want to replace all (map value) vector chars to the Corresponding map key, I tried to iterate the map with a for cycle like this: (I got this code from another question on stackoverflow)
for (auto const &ent1 : ass) {
//ent1.first = first key
//ent1.second = second key
}
So I tried to iterate the map value vector like this:
string char1;
string char2;
string wr;
for (auto const &ent1 : ass) {
for (int i = 0; i < ent1.second.size(); i++) {
specialValues += ent1.second[i];
char2 = ent1.second[i];
char1 = ent1.first;
regex e("([" + char1 + "])");
cout << ("([" + char1 + "])");
cout << char2;
wr = regex_replace("c1a0", e, char2);
}
}
So I want the string "c1a0" to become "ciao" after the loops, but it just doesn't change anything,
I also tried:
wr = regex_replace("c1a0", e, "o");
output : c1a0
regex e("([0])");
wr = regex_replace("c1a0", e, char2);
output : c1a2
I don't know, it makes no sense for me. I don't understand, can you help me figure out what's wrong in my code?
Of course if I write:
regex e("([0])");
wr = regex_replace("c1a0", e, "o");
It gives me "c1ao" that's what I want.
Following code works for me:
#include <string>
#include <map>
#include <regex>
#include <iostream>
using namespace std;
int main() {
const map<char, vector<char>> ass = {
{ '1', {'i'} },
{ '0', {'o'} },
};
string char1;
string char2;
string wr = "c1a0";
for (auto const &ent1 : ass) {
for (int i = 0; i < ent1.second.size(); i++) {
//specialValues += ent1.second[i];
char2 = ent1.second[i];
char1 = ent1.first;
regex e("([" + char1 + "])");
cout << ("([" + char1 + "])") << std::endl;
cout << char2<< std::endl;
wr = regex_replace(wr, e, char2);
cout << wr << std::endl;
}
}
}
But IMHO, regex here is overkill. You can iterate over string manually and replace character like in the following snippet:
#include <string>
#include <set>
#include <iostream>
#include <vector>
using namespace std;
struct replace_entry {
char with;
std::set<char> what;
};
int main() {
const std::vector<replace_entry> replaceTable = {
{ 'i', {'1'} },
{ 'o', {'0'} },
};
string input = "c1a0";
for (auto const &replaceItem : replaceTable) {
for (char& c: input ) {
if(replaceItem.what.end() != replaceItem.what.find(c)) {
c = replaceItem.with;
}
}
}
cout << input << std::endl;
}
Yet another approach is to create 256 elements array of chars
#include <string>
#include <iostream>
class ReplaceTable {
private:
char replaceTable_[256];
public:
constexpr ReplaceTable() noexcept
: replaceTable_()
{
replaceTable_['0'] = 'o';
replaceTable_['1'] = 'i';
}
constexpr char operator[](char what) const noexcept {
return replaceTable_[what];
}
};
// One time initialization
ReplaceTable g_ReplaceTable;
int main() {
std::string input = "c1a0";
// Main loop
for (char& c: input ) {
if(0 != g_ReplaceTable[c] ) c = g_ReplaceTable[c];
}
std::cout << input << std::endl;
}
Related
I'm making a code for cipher that reads alphabet in it's binary code. Is there a way to implement custom alphabet (not using ASCII)? For example alphabet={a,b,c,d,e,...,z,],[,.,..., ,-} and for each character there's a number 0,1,...,63. So, the bijetion will be from element of alphabet to 6 bit number.
How to make this implementation using simple functions in C++? I tried to make a strings length 1 and corresponding number using if statements and then plug them into .txt file, but it didn't work out.
string str1, ..., str63;
string sometext;
str1 = 'a';
// ...
cin >> sometext;
int k;
k = sometext.length();
string res;
ofstream out;
out.open("cipher.txt");
for (int i = 0; i < k; i++) {
res = sometext.substr(i, 1);
if (res == str1) {
res = '000000';
}
// ...
if (res == str63) {
res = '111111';
}
out << res;
}
I made a simple class Alphabet achieving your task. It uses std::unordered_map to store mapping between characters and binary representation, and uses this mapping to convert between those two representations. Also it computes binary representation. Class can be given any alphabet.
For testing I do two conversions between char and binary and output results to console. If requested values are out of range then std::exception is thrown.
Try it online!
#include <string>
#include <unordered_map>
#include <cmath>
#include <stdexcept>
#include <iostream>
class Alphabet {
public:
Alphabet(std::string const & _chars)
: chars(_chars) {
size_t num_bits = std::ceil(std::log(std::max(size_t(1), chars.size()))
/ std::log(2) - 1e-6);
for (size_t i = 0; i < chars.size(); ++i) {
std::string bin;
for (ptrdiff_t j = num_bits - 1; j >= 0; --j)
bin += i & (1 << j) ? "1" : "0";
c2b[chars[i]] = bin;
b2c[bin] = chars[i];
}
}
std::string ToBin(char c) const {
auto it = c2b.find(c);
if (it == c2b.end())
throw std::runtime_error("Character '" +
std::string(1, c) + "' not in alphabet!");
return it->second;
}
char ToChar(std::string const & bin) const {
auto it = b2c.find(bin);
if (it == b2c.end())
throw std::runtime_error("Binary '" + bin + "' is out of range!");
return it->second;
}
std::string const & Chars() const {
return chars;
}
private:
std::string chars;
std::unordered_map<char, std::string> c2b;
std::unordered_map<std::string, char> b2c;
};
int main() {
try {
Alphabet alph("abcdef{}123");
std::cout << alph.ToBin('f') << std::endl;
std::cout << alph.ToChar("0011") << std::endl;
std::cout << alph.Chars() << std::endl;
return 0;
} catch (std::exception const & ex) {
std::cout << "Exception: " << ex.what() << std::endl;
return -1;
}
}
Output:
0101
d
abcdef{}123
I've written a function that removes spaces and dashes from a string. It then inserts a space after every 3rd character. My question is can anybody suggest a different way to do this not using stringstream?
#include <iostream>
#include <string>
#include <algorithm>
#include <sstream>
using namespace std;
string FormatString(string S) {
/*Count spaces and dashes*/
auto newEnd = remove_if(S.begin(), S.end(), [](char c){return c == ' ' || c == '-';});
S.erase(newEnd, S.end());
std::stringstream ss;
ss << S[0];
for (unsigned int i = 1; i < S.size(); i++) {
if (i%3==0) {ss << ' ';}
ss << S[i];
}
return ss.str();
}
int main() {
std::string testString("AA BB--- ash jutf-4499--5");
std::string result = FormatString(testString);
cout << result << endl;
return 0;
}
How about using the input string as the output:
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
string FormatString(string S) {
auto newEnd = remove_if(S.begin(), S.end(), [](char c){return c == ' ' || c == '-';});
S.erase(newEnd, S.end());
auto str_sz = S.length();
/* length + ceil(length/3) */
auto ret_length = str_sz + 1 + ((str_sz - 1) / 3);
S.resize(ret_length);
unsigned int p = S.size()-1;
S[p--] = '\0';
for (unsigned int i = str_sz-1; i>0; i--) {
S[p--] = S[i];
if (i%3 == 0)
S[p--] = ' ';
}
return S;
}
int main() {
std::string testString("AA BB--- ash jutf-4499--5");
std::string result = FormatString(testString);
cout << result << endl;
// AAB Bas hju tf4 499 5
return 0;
}
I have a vector of type struct with some elements, and trying to count the number of occurrences of an element(value) in its corresponding column of the vector. I know how to count on a simple vector, e.g on vector of type string. But am stuck on vector<struct>. Any possible solution or suggestion?
Sample code:
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
struct my_struct
{
std::string first_name;
std::string last_name;
};
int main()
{
std::vector<my_struct> my_vector(5);
my_vector[0].first_name = "David";
my_vector[0].last_name = "Andriw";
my_vector[1].first_name = "Jhon";
my_vector[1].last_name = "Monta";
my_vector[2].first_name = "Jams";
my_vector[2].last_name = "Ruth";
my_vector[3].first_name = "David";
my_vector[3].last_name = "AAA";
my_vector[4].first_name = "Jhon";
my_vector[4].last_name = "BBB";
for(int i = 0; i < my_vector.size(); i++)
{
int my_count=count(my_vector.begin(), my_vector.end(),my_vector[i].first_name);
/*I need help to count the number of occerencess of each "First_name" in a vector
For example: First_Name:- David COUNT:- 2 ...and so on for each first_names*/
std::cout << "First_Name: " << my_vector[i].first_name << "\tCOUNT: " << my_count << std::endl;
}
return 0;
}
but, the same code for a vector of type string,std::vector<std::string> works properly. see below:
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
int main()
{
std::vector<std::string> my_vector;
my_vector.push_back("David");
my_vector.push_back("Jhon");
my_vector.push_back("Jams");
my_vector.push_back("David");
my_vector.push_back("Jhon");
for(int i = 0; i < my_vector.size(); i++)
{
int my_count = count(my_vector.begin(), my_vector.end(),my_vector[i]); //this works good
std::cout << "First_Name: " << my_vector[i] << "\tCOUNT: " << my_count << std::endl;
}
return 0;
}
You have to use std::count_if with correct predicate:
int my_count = std::count_if(my_vector.begin(), my_vector.end(),
[&](const my_struct& s) {
return s.first_name == my_vector[i].first_name;
});
Demo
The functor to replace lambda in C++03:
struct CompareFirstName
{
explicit CompareFirstName(const std::string& s) : first_name(s) {}
bool operator () (const my_struct& person) const
{
return person.first_name == first_name;
}
std::string first_name;
};
and then
int my_count = std::count_if(my_vector.begin(), my_vector.end(),
CompareFirstName(my_vector[i].first_name));
Demo
There is a string like this: M90I4D7
I need to push it in to this kind of struct:
struct CigarOp {
char Type; //!< CIGAR operation type (MIDNSHPX=)
uint32_t Length; //!< CIGAR operation length (number of bases)
//! constructor
CigarOp(const char type = '\0',
const uint32_t& length = 0)
: Type(type)
, Length(length)
{ }
};
which means I need to split it into 3 groups and each of them is a CigarOp( 'M' ,90 'I', 4 'D' ,7 )
Assuming that the string is of the form ([A-Z][0-9]+)*, you could quite simply do something like this:
#include <sstream>
...
std::vector<CigarOp> cigars;
std::istringstream parser("M90I4D7");
char c;
std::uint32_t l;
while(parser >> c >> l) {
cigars.push_back(CigarOp(c, l));
}
Note that this code doesn't do any sort of validation. If validation is necessary, one way to achieve it is to use Boost.Spirit (found on http://boost.org):
#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/adapted/struct.hpp>
#include <cstdint>
#include <iostream>
struct CigarOp {
char Type;
std::uint32_t Length;
};
BOOST_FUSION_ADAPT_STRUCT(CigarOp, (char, Type) (std::uint32_t, Length))
int main() {
using boost::spirit::qi::phrase_parse;
using boost::spirit::qi::char_;
using boost::spirit::qi::uint_;
using boost::spirit::qi::standard::space;
std::vector<CigarOp> cigars;
std::string s = "M90I4D7";
std::string::const_iterator first = s.begin(), last = s.end();
bool r = phrase_parse(first, last, *(char_ >> uint_), space, cigars);
if(r && first == last) {
// string was well-formed
for(auto const &cigar : cigars) {
std::cout << cigar.Type << ", " << cigar.Length << '\n';
}
}
}
how about:
#include <cstdio>
#include <cctype>
#include <vector>
#include <iostream>
#include <cstdlib>
using namespace std;
struct CigarOp {
char op; //!< CIGAR operation type (MIDNSHPX=)
int size; //!< CIGAR operation length (number of bases)
static int parse(const char* s,vector<CigarOp>& v)
{
char* p=(char*)(s);
while(*p!=0)
{
char* endptr;
CigarOp c;
c.op = *p;
if(!isalpha(c.op)) return -1;
++p;
if(!isdigit(*p)) return -1;
c.size =strtol(p,&endptr,10);
if(c.size<=0) return -1;
v.push_back(c);
p=endptr;
}
return 0;
}
};
int main(int argc,char** argv)
{
vector<CigarOp> cigar;
if(CigarOp::parse("M90I4D7",cigar)!=0) return -1;
for(size_t i=0;i< cigar.size();++i)
{
cout << cigar[i].op << ":" << cigar[i].size << endl;
}
return 0;
}
btw , for bioinformatics, you should ask biostars.org.
What do I have to do so that when I
string s = ".";
If I do
cout << s * 2;
Will it be the same as
cout << "..";
?
std::string has a constructor of the form
std::string(size_type count, char c);
that will repeat the character. For example
#include <iostream>
int main() {
std::string stuff(2, '.');
std::cout << stuff << std::endl;
return 0;
}
will output
..
I used operator overloading to simulate this behavior in c++.
#include <iostream>
#include <string>
using namespace std;
/* Overloading * operator */
string operator * (string a, unsigned int b) {
string output = "";
while (b--) {
output += a;
}
return output;
}
int main() {
string str = "abc";
cout << (str * 2);
return 0;
}
Output:
abcabc
No, std::string has no operator *. You can add (char, string) to other string. Look at this http://en.cppreference.com/w/cpp/string/basic_string
And if you want this behaviour (no advice this) you can use something like this
#include <iostream>
#include <string>
template<typename Char, typename Traits, typename Allocator>
std::basic_string<Char, Traits, Allocator> operator *
(const std::basic_string<Char, Traits, Allocator> s, size_t n)
{
std::basic_string<Char, Traits, Allocator> tmp = s;
for (size_t i = 0; i < n; ++i)
{
tmp += s;
}
return tmp;
}
template<typename Char, typename Traits, typename Allocator>
std::basic_string<Char, Traits, Allocator> operator *
(size_t n, const std::basic_string<Char, Traits, Allocator>& s)
{
return s * n;
}
int main()
{
std::string s = "a";
std::cout << s * 5 << std::endl;
std::cout << 5 * s << std::endl;
std::wstring ws = L"a";
std::wcout << ws * 5 << std::endl;
std::wcout << 5 * ws << std::endl;
}
http://liveworkspace.org/code/52f7877b88cd0fba4622fab885907313
There is no predefined * operator that will multiply a string by an int, but you can define your own:
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
string operator*(const string& s, unsigned int n) {
stringstream out;
while (n--)
out << s;
return out.str();
}
string operator*(unsigned int n, const string& s) { return s * n; }
int main(int, char **) {
string s = ".";
cout << s * 3 << endl;
cout << 3 * s << endl;
}
They can't be multipled but I think you can write your own function to do this, something like -
#include <iostream>
#include <string>
std::string operator*(std::string s, size_t count)
{
std::string ret;
for(size_t i = 0; i < count; ++i)
{
ret = ret + s;
}
return ret;
}
int main()
{
std::string data = "+";
std::cout << data * 10 << "\n";
}
It's probably not the best idea though, it will be very confusing to anyone looking at the code and not expecting this,
Strings cannot be multiplied.
If s is a char
'.' // This has ASCII code 46
then
cout << (char)((int)s * 2);
will give you
'/' // This has ASCII code 92
Like JRG did, but in a single line
std::cout << std::string(70,'-') << std::endl;
This will create a string, filled with - (dashes), 70 characters long, and breaking the line at the end with std::endl;
You can do this:
#include <iostream>
using namespace std;
int main()
{
string text, new_text;
int multiply_number;
cin >> text >> multiply_number;
/*
First time in the 'for' loop: new_text = new_text + text
new_text = "" + "your text"
new_text = "your text"
Second time in the 'for' loop: new_text = new_text + text
new_text = "your text" + "your text"
new_text = "your textyour text"...n times
*/
for(int i=0; i<multiply_number; i++)
{
new_text += text;
}
cout << new_text << endl; // endl="\n"
system("pause");
return 0;
}
In Python you can multiply string like this:
text = "(Your text)"
print(text*200)
std::string StrMultiply(const char* str, size_t count) {
size_t stringsize = strlen(str);
size_t buffersize = stringsize * count + 1;
string res(buffersize,'\0');
char* end = res._Unchecked_end();
char* offset = res._Unchecked_begin();
for (size_t i = 0;i < count; offset += stringsize,i++)
{
memcpy(offset, str, stringsize);
}
// mark the end
res[buffersize - 1] = '\0';
return res;
}
inline std::string operator*(std::string left, size_t right) {
return StrMultiply(left.c_str(), right);
}
here is a ram-friendly solution, 10 times faster than using stringstreams or string::append
It's surprising that nobody talked about this yet. For assigning char*int to a variable, you can do str.assign(n, char). https://en.cppreference.com/w/cpp/string/basic_string/assign
For example, str.assign(2, 's') would yield ss for the value of str. Other methods to actually achieve the objective have already been mentioned.