Convert string "\ u0026" to "&" in C ++ - c++

I'm getting a string from a Post but the string comes like this:
?re=784D30879\u0026rr=POH0525\u0026tt=525.100000\u0026id=0958567C-20DC-44B4-9FD0-1AD13453DEBF4
And i want:
?re=784D30879&rr=POH0525&tt=525.100000&id=0958567C-20DC-44B4-9FD0-1AD13453DEBF4
I am using a function to replace characters in a String but it sends me the following error: a universal character name cannot designate a character in the basic character set
So I'm calling the function:
message = replaceChars(message, string("\u0026"), string("&"));
And this is the function:
string replaceChars(string stringToChange, const string& charToChange, const string& newChar)
{
size_t initialPosition = 0;
while((initialPosition= stringToChange.find(charToChange, initialPosition)) != string::npos)
{
stringToChange.replace(initialPosition, charToChange.length(), newChar);
initialPosition += newChar.length();
}
return stringToChange;
}
I cant understand the error.

You should use "\\u0026" instead of "\u0026"

Related

String includes just valid chars?

I'd like to valid a string to check if the string just includes valid characters or not using C++.
Valid characters should be given to the function like as charset of valid characters: "abc123".
A string that just includes the characters given in the charset above should return true while a string that also includes other characters then given should return false. Obviously a easy task :)
--> using charset abc123:
string myString_1 = "bbbac1" // should get true
string myString_2 = "bbbac132aacc" // should get true
string myString_3 = "xxxxxx" // should get false
string myString_4 = "bbbac12533cc" // should get false
How can I implement a call like this in C++?
Note: I though about using something like the code below but I'm pretty sure theres a way better solution.
string charset = "abc123";
string myString = "bbbac1";
for (int i=0; i<charset.length(); i++) {
std::replace( myString.begin(), myString.end(), charset[i], '');
}
bool isValid = (myString.length() == 0);
AS igor-tandetnik pointed in comments this is a job for std::find_first_not_of:
auto validate(const std::string& str, const std::string& charset) -> bool
{
return str.find_first_not_of(charset) == std::string::npos;
}
You can write your own check function:
bool checkstring(std::string &checkstring, std::string &legalchars) {
for (char c : checkstring) {
// resetting the bool
bool isLegal = false;
for (char d : legalchars) {
// comparing the chars
if (c == d) { isLegal = true; }
}
// if a non-legal char was found, return false
if (!isLegal) { return false; }
}
// if no non-legal character was found, return true
return true;
}
Although there might be a better alternative using the standard libraries, especially if you need to compare very long strings with a large set of legal characters.

QString replace only first occurrence

Is there simple way of replacing only first occurrence of some substring by other substring in QString? It can be at any position.
You could try this:
QString str("this is a string"); // The initial string.
QString subStr("is"); // String to replace.
QString newStr("at"); // Replacement string.
str.replace(str.indexOf(subStr), subStr.size(), newStr);
Resulting string will be:
that at a string
There is no convenience method for the operation you wish to have. However, you can use the following two methods to build your custom operation:
int QString::indexOf(const QString & str, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
Returns the index position of the first occurrence of the string str in this string, searching forward from index position from. Returns -1 if str is not found.
If cs is Qt::CaseSensitive (default), the search is case sensitive; otherwise the search is case insensitive.
and
QString & QString::replace(int position, int n, const QString & after)
Replaces n characters beginning at index position with the string after and returns a reference to this string.
Note: If the specified position index is within the string, but position + n goes outside the strings range, then n will be adjusted to stop at the end of the string.
Now, putting all that into practice, you could write something as follows:
main.cpp
#include <QString>
#include <QDebug>
int main()
{
QString initialString = QLatin1String("foo bar baz");
QString fooString = QLatin1String("foo");
initialString.replace(initialString.indexOf(fooString),
fooString.size(), QLatin1String("stuff"));
qDebug() << initialString;
return 0;
}
main.pro
TEMPLATE = app
TARGET = main
QT = core
SOURCES += main.cpp
Build and Run
qmake && make && ./main
Output
"stuff bar baz"
This is pretty much the way QString::replace(QRegularExpression, ... does it. Since it's possible that literal backslashes could be part of replace pattern, those need to be captured differently. Note that actual replacement happens right-to-left to preserve leftward offset validity. It's possible to put this more compactly, but easier to debug in this form.
QRegularExpression regex = QRegularExpression(regex_pattern);
if (regex.isValid() and
(regex_pattern.length() > 0)) {
QRegularExpressionMatchIterator regex_iterator =
regex.globalMatch(target_text, Apply_Target_Offset,
QRegularExpression::PartialPreferCompleteMatch);
if (regex_iterator.hasNext()) {
// At least one found
QRegularExpressionMatch match = regex_iterator.next();
if (match.hasMatch() and (not match.hasPartialMatch())) {
// This is the first match, and it's complete
int match_begin = match.capturedStart();
int match_end = match.capturedEnd();
int match_length = match.capturedLength();
QStringList captured;
const int capture_groups_count = regex.captureCount() + 1;
for (int capture_group_idx = 0; capture_group_idx < capture_groups_count; ++capture_group_idx) {
captured.append(match.captured(capture_group_idx));
}
QString replace_pattern = Apply_Replace_Pattern->toPlainText();
QString replace_text = replace_pattern;
QList<QRegularExpressionMatch> replace_pattern_match_list;
QRegularExpression replace_pattern_regex = QRegularExpression("(?:\\\\\\\\)+|(?:\\\\(\\d+))");
if (replace_pattern_regex.isValid()) {
QRegularExpressionMatchIterator replace_pattern_regex_iterator =
replace_pattern_regex.globalMatch(replace_pattern);
while (replace_pattern_regex_iterator.hasNext()) {
QRegularExpressionMatch replace_pattern_match = replace_pattern_regex_iterator.next();
bool no_error;
replace_pattern_match.captured().right(1).toInt(&no_error);
// Only accept backreferences w/ numbers
if (no_error) replace_pattern_match_list.append(replace_pattern_match);
}
while (replace_pattern_match_list.count() > 0) {
QRegularExpressionMatch replace_pattern_match = replace_pattern_match_list.takeLast();
int cap_idx = replace_pattern_match.captured(1).toInt();
if (cap_idx < captured.count()) {
replace_text.replace(replace_pattern_match.capturedStart(),
(replace_pattern_match.capturedEnd() -
replace_pattern_match.capturedStart()),
captured[cap_idx]);
}
}
// Render '\' characters properly
replace_text.replace("\\\\", "\\");
}
target_text.replace(match_begin, (match_end - match_begin), replace_text);
}
}
}
//------------------------------------------------------------------
QString & replace_first(QString &io_haystack, const QString & sub_str, const QString & new_str)
{
io_haystack.replace(io_haystack.indexOf(sub_str), sub_str.size(), new_str);
return io_haystack;
} // replace_first
//------------------------------------------------------------------
QString & replace_first(QString &io_haystack, const QRegularExpression & sub_regx, const QString & new_str)
{
QRegularExpressionMatch match;
match = sub_regx.match(io_haystack);
if (match.hasMatch()) {
QString sub_str = match.captured(0);
io_haystack.replace(io_haystack.indexOf(sub_str), sub_str.size(), new_str);
}
return io_haystack;
} // replace_first

Search a string against multiple string arrays

I have a input string and need to run through it and see if it matches certain words. I have multiple string arrays but not sure whats an efficient way to check the string agianst all the arrays.
String Arrays:
string checkPlayType(string printDescription)
{
const string DeepPassRight[3] = {"deep" , "pass" , "right"};
const string DeepPassLeft[3] = {"deep" , "pass" , "left"};
const string DeepPassMiddle[3] = {"deep" , "pass" , "middle"};
const string ShortPassRight[3] = {"short" , "pass" , "right"};
const string ShortPassLeft[3] = {"short" , "pass" , "left"};
const string ShortPassMiddle[3] = {"short" , "pass" , "middle"};
//Must contain right but not pass
const string RunRight = "right";
//Must contain right but not pass
const string RunLeft = "left";
//Must contain middle but not pass
const string RunMiddle = "middle";
const string FieldGoalAttempt[2] = {"field" , "goal" };
const string Punt = "punt";
}
Sample Input: (13:55) (Shotgun) P.Manning pass incomplete short right to M.Harrison.
Assuming this is our only input...
Sample Output:
Deep Pass Right: 0%
Deep Pass Left: 0%
Deep Pass Middle: 0%
Short Pass Right: 100%
Shor Pass Left:0%
...
..
..
you may want something similar to:
void checkPlayType(const std::vector<std::string>& input)
{
std::set<std::string> s;
for (const auto& word : input) {
s.insert(word);
}
const bool deep_present = s.count("deep");
const bool pass_present = s.count("pass");
const bool right_present = s.count("right");
const bool left_present = s.count("left");
// ...
if (deep_present && pass_present && right_present) { /* increase DeepPassRight counter */}
if (deep_present && pass_present && left_present) { /* increase DeepPassLeft counter */}
// ...
}
Try regular expressions:
if found "pass" then
if regexp "(deep|short).*(left|right|middle)"
Hooray!
else if regexp "(left|right|middle).*(deep|short)"
Hooray!
else
Aye, Caramba!
else
Aye, Caramba!
You can go over your arrays and search for the words are stored in the array within the input string. Use std functions for better performance. For example:
const string DeepPassRight[3] = {"deep" , "pass" , "right"};
int i = 0;
for(;i<3;i++)
{
string s = " ";
s.append(DeepPassRight[i]);
s.append(" ");
std::size_t found = printDescription.find(s);
if (found ==std::string::npos)
break;
}
if(i == 3)
// printDescription contains all DeepPassRight's members!
if(i== 2)
// just two words were found

extract domain between two words

I have in a log file some lines like this:
11-test.domain1.com Logged ...
37-user1.users.domain2.org Logged ...
48-me.server.domain3.net Logged ...
How can I extract each domain without the subdomains? Something between "-" and "Logged".
I have the following code in c++ (linux) but it doesn't extract well. Some function which is returning the extracted string would be great if you have some example of course.
regex_t preg;
regmatch_t mtch[1];
size_t rm, nmatch;
char tempstr[1024] = "";
int start;
rm=regcomp(&preg, "-[^<]+Logged", REG_EXTENDED);
nmatch = 1;
while(regexec(&preg, buffer+start, nmatch, mtch, 0)==0) /* Found a match */
{
strncpy(host, buffer+start+mtch[0].rm_so+3, mtch[0].rm_eo-mtch[0].rm_so-7);
printf("%s\n", tempstr);
start +=mtch[0].rm_eo;
memset(host, '\0', strlen(host));
}
regfree(&preg);
Thank you!
P.S. no, I cannot use perl for this because this part is inside of a larger c program which was made by someone else.
EDIT:
I replace the code with this one:
const char *p1 = strstr(buffer, "-")+1;
const char *p2 = strstr(p1, " Logged");
size_t len = p2-p1;
char *res = (char*)malloc(sizeof(char)*(len+1));
strncpy(res, p1, len);
res[len] = '\0';
which is extracting very good the whole domain including subdomains.
How can I extract just the domain.com or domain.net from abc.def.domain.com ?
is strtok a good option and how can I calculate which is the last dot ?
#include <vector>
#include <string>
#include <boost/regex.hpp>
int main()
{
boost::regex re(".+-(?<domain>.+)\\s*Logged");
std::string examples[] =
{
"11-test.domain1.com Logged ...",
"37-user1.users.domain2.org Logged ..."
};
std::vector<std::string> vec(examples, examples + sizeof(examples) / sizeof(*examples));
std::for_each(vec.begin(), vec.end(), [&re](const std::string& s)
{
boost::smatch match;
if (boost::regex_search(s, match, re))
{
std::cout << match["domain"] << std::endl;
}
});
}
http://liveworkspace.org/code/1983494e6e9e884b7e539690ebf98eb5
something like this with boost::regex. Don't know about pcre.
Is the in a standard format?
it appears so, is there a split function?
Edit:
Here is some logic.
Iterate through each domain to be parsed
Find a function to locate the index of the first string "-"
Next find the index of the second string minus the first string "Logged"
Now you have the full domain.
Once you have the full domain "Split" the domain into your object of choice (I used an array)
now that you have the array broken apart locate the index of the value you wish to reassemble (concatenate) to capture only the domain.
NOTE Written in C#
Main method which defines the first value and the second value
`static void Main(string[] args)
{
string firstValue ="-";
string secondValue = "Logged";
List domains = new List { "11-test.domain1.com Logged", "37-user1.users.domain2.org Logged","48-me.server.domain3.net Logged"};
foreach (string dns in domains)
{
Debug.WriteLine(Utility.GetStringBetweenFirstAndSecond(dns, firstValue, secondValue));
}
}
`
Method to parse the string:
`public string GetStringBetweenFirstAndSecond(string str, string firstStringToFind, string secondStringToFind)
{
string domain = string.Empty;
if(string.IsNullOrEmpty(str))
{
//throw an exception, return gracefully, whatever you determine
}
else
{
//This can all be done in one line, but I broke it apart so it can be better understood.
//returns the first occurrance.
//int start = str.IndexOf(firstStringToFind) + 1;
//int end = str.IndexOf(secondStringToFind);
//domain = str.Substring(start, end - start);
//i.e. Definitely not quite as legible, but doesn't create object unnecessarily
domain = str.Substring((str.IndexOf(firstStringToFind) + 1), str.IndexOf(secondStringToFind) - (str.IndexOf(firstStringToFind) + 1));
string[] dArray = domain.Split('.');
if (dArray.Length > 0)
{
if (dArray.Length > 2)
{
domain = string.Format("{0}.{1}", dArray[dArray.Length - 2], dArray[dArray.Length - 1]);
}
}
}
return domain;
}
`

Remove '\n.\n' C++

If i have a string as such
"I am not here... \n..Hello\n.\n....Whats happening"
I want to replace the above string so:
"I am not here... \n..Hello\n. \n....Whats happening"
^ Space added
Just a bit of a background on what im doing. Im using sendmail in C++ and \n.\n is End Of Message Equivalent of sendmail. I just created a class that uses sendmail to send mails. but obviously if the user from the outsite gives sendmail that command i want it to be removed. Here is my message function just incase.:
//Operator to add to the message
void operator<<(string imessage){
if (imessage != ""){ message += imessage; }
}
How would i go about doing this. Thanks in advance :D
This is my last version :)
This code handles the case mentioned by #Greg Hewgill
string& format_text(string& str)
{
const string::size_type dot_offset = 2;
string::size_type found_at_start = str.find("\n.\n"),
found_at = str.find("\n.\n");
if(found_at_start != string::npos)
str.insert(0, " ");
while(found_at != string::npos)
{
str.insert(found_at+dot_offset+1, " ");
found_at = str.find("\n.\n", found_at+1);
}
return str;
}
int main()
{
string text = ".\nn\n.\nn";
std::cout << format_text(text);
}
Look up String.find and String.replace
For example (not tested)
string endOfMessage = "\n.\n";
string replacement = "\n. \n";
size_t position;
while (position = message.find(endOfMessage))
{
message.replace(position, endOfMessage.length(), replacement);
}
This is derived from Dan McG's answer so upvote him ;)
string endOfMessage = "\n.\n";
string replacement = "\n. \n";
size_t position;
while (position = message.find(endOfMessage, position) != message.npos)
{
message.replace(position, endOfMessage.length(), replacement);
position += replacement.length();
}
Boost has Boost.Regex (a regular expression module). Might be overkill if this is the only replacement you need to do.
Use std::search and the insert method of sequence containers such as string, deque, or whatever you use to store the message text.
typedef std::string::iterator SIter; // or whatever container you use
static const char *end_seq = "\n.\n";
for ( SIter tricky_begin = msg.begin();
tricky_begin = std::search( tricky_begin, msg.end(), end_seq, end_seq+3 ),
tricky_begin != msg.end(); ) {
tricky_begin = msg.insert( tricky_begin + 2, ' ' );
}