How can I get a substring of a std::wstring which includes some non-ASCII characters?
The following code does not output anything:
(The text is an Arabic word contains 4 characters where each character has two bytes, plus the word "Hello")
#include <iostream>
#include <string>
using namespace std;
int main()
{
wstring s = L"سلام hello";
wcout << s.substr(0,3) << endl;
wcout << s.substr(4,5) << endl;
return 0;
}
This should work: live on Coliru
#include <iostream>
#include <string>
#include <boost/regex/pending/unicode_iterator.hpp>
using namespace std;
template <typename C>
std::string to_utf8(C const& in)
{
std::string result;
auto out = std::back_inserter(result);
auto utf8out = boost::utf8_output_iterator<decltype(out)>(out);
std::copy(begin(in), end(in), utf8out);
return result;
}
int main()
{
wstring s = L"سلام hello";
auto first = s.substr(0,3);
auto second = s.substr(4,5);
cout << to_utf8(first) << endl;
cout << to_utf8(second) << endl;
}
Prints
سلا
hell
Frankly though, I think your substring calls are making weird assumptions. Let me suggest a fix for that in a minute:
Related
How can I store the output from cout into a variable of string or character type?
I have written following code but it doesn't work:
#include<iostream>
#include<stdio.h>
using namespace std;
int main(){
string n;
n = (cout<<"\nHello world");
cout<<n;
return 0;
}
#include <sstream>
std::ostringstream a;
a << "Hello, world!";
std::string b = a.str(); // Or better, `std::move(a).str()`.
std::cout << b;
Other answers have shown you how to capture formatted output using a std::(o)stringstream object directly. But, if for some reason, you really need to capture the output of std::cout, then you can temporarily redirect std::cout to use a std::ostringstream's buffer, eg:
#include <iostream>
#include <sstream>
using namespace std;
int main(){
ostringstream oss;
auto cout_buff = cout.rdbuf(oss.rdbuf());
cout << "\nHello world";
cout.rdbuf(cout_buff);
string n = oss.str();
cout << n;
return 0;
}
Online Demo
Of course there's a way! But you have to use a different kind of stream:
std::ostringstream ss;
ss << "\nHello world";
std::string result = ss.str();
Also, in C++20, you can simply use std::format:
std::string n = std::format("Hello {}! I have {} cats\n", "world", 3);
// n == "Hello world! I have 3 cats\n"
Extraction Function
string extractStr(string str, string regExpStr) {
regex regexp(regExpStr);
smatch m;
regex_search(str, m, regexp);
string result = "";
for (string x : m)
result = result + x;
return result;
}
The Main Code
#include <iostream>
#include <regex>
using namespace std;
string extractStr(string, string);
int main(void) {
string test = "(1+1)*(n+n)";
cout << extractStr(test, "n\\+n") << endl;
cout << extractStr(test, "(\\d)\\+\\1") << endl;
cout << extractStr(test, "([a-zA-Z])[+-/*]\\1") << endl;
cout << extractStr(test, "([a-zA-Z])[+-/*]([a-zA-Z])") << endl;
return 0;
}
The Output
String = (1+1)*(n+n)
n\+n = n+n
(\d)\+\1 = 1+11
([a-zA-Z])[+-/*]\1 = n+nn
([a-zA-Z])[+-/*]([a-zA-Z]) = n+nnn
If anyone could kindly point the error I've done or point me to a similar question in SO that I've missed while searching, it would be greatly appreciated.
Regexes in C++ don't work quite like "normal" regexes. Specialy when you are looking for multiple groups later. I also have some C++ tips in here (constness and references).
#include <cassert>
#include <iostream>
#include <sstream>
#include <regex>
#include <string>
// using namespace std; don't do this!
// https://stackoverflow.com/questions/1452721/why-is-using-namespace-std-considered-bad-practice
// pass strings by const reference
// 1. const, you promise not to change them in this function
// 2. by reference, you avoid making copies
std::string extractStr(const std::string& str, const std::string& regExpStr)
{
std::regex regexp(regExpStr);
std::smatch m;
std::ostringstream os; // streams are more efficient for building up strings
auto begin = str.cbegin();
bool comma = false;
// C++ matches regexes in parts so work you need to loop
while (std::regex_search(begin, str.end(), m, regexp))
{
if (comma) os << ", ";
os << m[0];
comma = true;
begin = m.suffix().first;
}
return os.str();
}
// small helper function to produce nicer output for your tests.
void test(const std::string& input, const std::string& regex, const std::string& expected)
{
auto output = extractStr(input, regex);
if (output == expected)
{
std::cout << "test succeeded : output = " << output << "\n";
}
else
{
std::cout << "test failed : output = " << output << ", expected : " << expected << "\n";
}
}
int main(void)
{
std::string input = "(1+1)*(n+n)";
test(input, "n\\+n", "n+n");
test(input, "(\\d)\\+\\1", "1+1");
test(input, "([a-zA-Z])[+-/*]\\1", "n+n");
return 0;
}
We have a char. We need to replace all ab characters from our char with the letter c.
Example we have :
abracadabra
the output will be :
cracadcra
I tried to use replace() function from C++, but no success.
#include <iostream>
#include <cstring>
using namespace std;
int main()
{
string test;
cin>>test;
for(int i=0;i<(strlen(test)-1);i++)
{
if((test[i]=='a')&&(test[i+1]=='b')){
test.replace( test[i], 'c' );
test.replace( test[i+1] , ' ' );
}
}
cout << test << endl;
return 0;
}enter code here
You can use C++11 regex:
#include <iostream>
#include <regex>
#include <string>
int main() {
std::string str = "abracadabra";
std::regex r("ab");
std::cout << std::regex_replace(str, r, "c") << "\n"; // cracadcra
}
Problem:
That is not the syntax of std::string::replace.
Solution:
As is mentioned here the syntax is std::string::replace(size_t pos, size_t len, const string& str). Do test.replace(i, 2, "c" ) instead of test.replace(test[i],'c').
Or use regular expressions as dtell pointed.
Adittional information:
using namespace std; is considered a bad practice (More info here).
You should use std::string::size instead of strlen when you're working with std::string.
To work with std::string you should use #include <string> instead of #include <cstring>.
Full code:
#include <iostream>
int main()
{
std::string test;
std::cin >> test;
for(unsigned int i = 0; i < test.size() - 1; i++)
{
if((test[i]=='a') && (test[i+1]=='b'))
{
test.replace(i, 2, "c" );
}
}
std::cout << test << std::endl;
return 0;
}
The simplest thing you can do by using the standard library is first to find ab and then replace it. The example code I wrote is finding string ab unless there is None in the string and replacing it with c.
#include <iostream>
#include <string>
int main()
{
std::string s = "abracadabra";
int pos = -1;
while ((pos = s.find("ab")) != -1)//finding the position of ab
s.replace(pos, sizeof("ab") - 1, "c");//replace ab with c
std::cout << s << std::endl;
return 0;
}
//OUTPUT
cracadcra
I need a C++ code for the following problem:
i have a text file that i want to start reading from a specific line, then i need to print the output located between the characters --- <\s>
example: hello<\s>
i want the output to be hello
I think i should use text parser but not sure how!
#include <iostream>
#include <cstdlib>
#include <cctype>
#include <cstring>
#include <fstream>
#include <string>
using namespace std;
int main(int argc, char* argv[])
{
std::string line_;
ifstream file_("tty.txt");
if (file_.is_open())
{
while (getline(file_, line_))
{
std::cout << line_ << '\n';
}
file_.close();
}
else
std::cout << "error" << '\n';
std::cin.get();
system("PAUSE");
return 0;
}
You can load all text in one variable, and then with regex search all occurences of your desired pattern (in your case <sth>(any_aplha_numeric_character)*</sth> where * means one or more occurence, you can read about it at any std::regex tutorial)
Example:
std::smatch m;
std::string text = "<a>adsd</a> <a>esd</a>";
std::string::const_iterator searchStart(text.cbegin());
std::regex rgx("<a>[A-Za-z0-9\\s]*</a>");
while (std::regex_search(searchStart, text.cend(), m, rgx))
{
cout << m[0] << endl;
searchStart += m.position() + m.length();
}
gives: <a>adsd</a> and <a>esd</a> as a result, from which is very easy to extract that inner string
lexical_cast throws an exception in the following case. Is there a way to use lexical_cast and convert the string to integer.
#include <iostream>
#include "boost/lexical_cast.hpp"
#include <string>
int main()
{
std::string src = "124is";
int iNumber = boost::lexical_cast<int>(src);
std::cout << "After conversion " << iNumber << std::endl;
}
I understand, I can use atoi instead of boost::lexical_cast.
If I'm understanding your requirements correctly it seems as though removing the non-numeric elements from the string first before the lexical_cast will solve your problem. The approach I outline here makes use of the isdigit function which will return true if the given char is a digit from 0 to 9.
#include <iostream>
#include "boost/lexical_cast.hpp"
#include <string>
#include <algorithm>
#include <cctype> //for isdigit
struct is_not_digit{
bool operator()(char a) { return !isdigit(a); }
};
int main()
{
std::string src = "124is";
src.erase(std::remove_if(src.begin(),src.end(),is_not_digit()),src.end());
int iNumber = boost::lexical_cast<int>(src);
std::cout << "After conversion " << iNumber << std::endl;
}
The boost/lexical_cast uses stringstream to convert from string to other types,so you must make sure the string can be converted completely! or, it will throw the bad_lexical_cast exception,This is an example:
#include <boost/lexical_cast.hpp>
#include <iostream>
#include <string>
#define ERROR_LEXICAL_CAST 1
int main()
{
using boost::lexical_cast;
int a = 0;
double b = 0.0;
std::string s = "";
int e = 0;
try
{
// ----- string --> int
a = lexical_cast<int>("123");//good
b = lexical_cast<double>("123.12");//good
// -----double to string good
s = lexical_cast<std::string>("123456.7");
// ----- bad
e = lexical_cast<int>("abc");
}
catch(boost::bad_lexical_cast& e)
{
// bad lexical cast: source type value could not be interpreted as target
std::cout << e.what() << std::endl;
return ERROR_LEXICAL_CAST;
}
std::cout << a << std::endl; // cout:123
std::cout << b << std::endl; //cout:123.12
std::cout << s << std::endl; //cout:123456.7
return 0;
}