C++ regular expression sscanf - c++

I wanto to use sscanf to extrat the 2 first integer (5 and 10) in a string
rssi = 5
ber = 10
like this :
#include <stdio.h>
#include <iostream>
#include <string>
using namespace std;
int main() {
std::string str = "\r\n+CSQ: 5,10\r\n\r\nOK\r\n7556\r\n";
unsigned char lBufRX[100];
char *rssi, *ber;
if((sscanf(str.c_str(), "%*[^:]: %s,%s[^\n]", rssi, ber)) != 2) {
std::cout <<"[" << rssi << "]" << "[" << ber << "]" << std::endl;
}
return 0;
}
The result is bad. Can anyone help me ?
My output is : "[5,10][" with " %*[^:]: " i read until the first integer so "5" with ",%s[^\n]" i read the second integer so "10" until \r\n
Thanks

You have several errors. You're using char* although you want to read two ints. But then you don't allocate memory for them. Also, you're expecting two successful parses but check with != 2. Here is some code that works:
int main() {
std::string str = "\r\n+CSQ: 5,10\r\n\r\nOK\r\n7556\r\n";
int rssi, ber;
if((sscanf(str.c_str(), "%*[^:]: %d,%d", &rssi, &ber)) == 2) {
std::cout <<"[" << rssi << "]" << "[" << ber << "]" << std::endl;
}
return 0;
}

Related

What am I doing wrong here with find and string?

I am asking user to enter date in format with slashes. Then I try to find the slashes in the string using find. I get error saying I cannot compare pointer with integer on my if statement. Here is code.
// test inputing string date formats
#include <iostream>
#include <string>
#include <algorithm>
int main() {
std::string dateString;
int month,day,year;
std::cout << "Enter a date in format of 5/14/1999: ";
std::getline(std::cin,dateString);
std::cout << "You entered " << dateString << std::endl;
if (std::find(dateString.begin(),dateString.end(),"/") != dateString.end()) {
std::cout << "Found slash in date.\n";
}
else {
std::cout << "screwed it up.\n";
}
}
Any help is appreciated.
if (std::find(dateString.begin(),dateString.end(),"/") != dateString.end()) {
"/" is a literal string, or a const char * (actually a const char[2] in this case, to be pedantic, but this is not germane) . The third parameter to std::find, in this case, should be a char, a single character.
You probably meant
if (std::find(dateString.begin(),dateString.end(),'/') != dateString.end()) {
I think you can use
if (dateString.find("/") != std::string::npos) {
std::cout << "Found slash in date.\n";
} else {
std::cout << "screwed it up.\n";
}
to find substring/char in a string. Note that std::string::find() works for char, const char * and std::string.

Find substring in string using locale

I need to find if a string contains a substring, but according to the current locale's rules.
So, if I'm searching for the string "aba", with the Spanish locale, "cabalgar", "rábano" and "gabán" would all three contain it.
I know I can compare strings with locale information (collate), but is there any built-in or starightforward way to do the same with find, or do I have to write my own?
I'm fine using std::string (up to TR1) or MFC's CString
For reference, here is an implementation using boost locale compiled with ICU backend:
#include <iostream>
#include <boost/locale.hpp>
namespace bl = boost::locale;
std::locale usedLocale;
std::string normalize(const std::string& input)
{
const bl::collator<char>& collator = std::use_facet<bl::collator<char> >(usedLocale);
return collator.transform(bl::collator_base::primary, input);
}
bool contain(const std::string& op1, const std::string& op2){
std::string normOp2 = normalize(op2);
//Gotcha!! collator.transform() is returning an accessible null byte (\0) at
//the end of the string. Thats why we search till 'normOp2.length()-1'
return normalize(op1).find( normOp2.c_str(), 0, normOp2.length()-1 ) != std::string::npos;
}
int main()
{
bl::generator generator;
usedLocale = generator(""); //use default system locale
std::cout << std::boolalpha
<< contain("cabalgar", "aba") << "\n"
<< contain("rábano", "aba") << "\n"
<< contain("gabán", "aba") << "\n"
<< contain("gabán", "Âbã") << "\n"
<< contain("gabán", "aba.") << "\n"
}
Output:
true
true
true
true
false
You could loop over the string indices, and compare a substring with the string you want to find with std::strcoll.
I haven't used this before, but std::strxfrm looks to be what you could use:
http://en.cppreference.com/w/cpp/locale/collate/transform
#include <iostream>
#include <iomanip>
#include <cstring>
std::string xfrm(std::string const& input)
{
std::string result(1+std::strxfrm(nullptr, input.c_str(), 0), '\0');
std::strxfrm(&result[0], input.c_str(), result.size());
return result;
}
int main()
{
using namespace std;
setlocale(LC_ALL, "es_ES.UTF-8");
const string aba = "aba";
const string rabano = "rábano";
cout << "Without xfrm: " << aba << " in " << rabano << " == " <<
boolalpha << (string::npos != rabano.find(aba)) << "\n";
cout << "Using xfrm: " << aba << " in " << rabano << " == " <<
boolalpha << (string::npos != xfrm(rabano).find(xfrm(aba))) << "\n";
}
However, as you can see... This doesn't do what you want. See the comment at your question.

string parsing for C++

I have a text file that has #'s in it...It looks something like this.
#Stuff
1
2
3
#MoreStuff
a
b
c
I am trying to use std::string::find() function to get the positions of the # and then go from there, but I'm not sure how to actually code this.
This is my attempt:
int pos1=0;
while(i<string.size()){
int next=string.find('#', pos1);
i++;}
Here's one i made a while ago... (in C)
int char_pos(char c, char *str) {
char *pch=strchr(str,c);
return (pch-str)+1;
}
Port it to C++ and there you go! ;)
If : Not Found Then returns Negative.
Else : Return 'Positive', Char's 1st found position (1st match)
It's hard to tell from your question what you mean by "position", but it looks like you are trying to do something like this:
#include <fstream>
#include <iostream>
int main()
{
std::ifstream incoming{"string-parsing-for-c.txt"};
std::string const hash{"#"};
std::string line;
for (auto line_number = 0U; std::getline(incoming, line); ++line_number)
{
auto const column = line.find(hash);
if (std::string::npos != column)
{
std::cout << hash << " found on line " << line_number
<< " in column " << column << ".\n";
}
}
}
...or possibly this:
#include <fstream>
#include <iostream>
int main()
{
std::ifstream incoming{"string-parsing-for-c.txt"};
char const hash{'#'};
char byte{};
for (auto offset = 0U; incoming.read(&byte, 1); ++offset)
{
if (hash == byte)
{
std::cout << hash << " found at offset " << offset << ".\n";
}
}
}

Passing variable (array type) from function to "main" scope Type: std::tr1::match_results<std::string::const_iterator>

I would like to pass the variable from a function to the main scope which I'm calling, I'm trying to do like I use to do in C but it returns nothing.
I want to be able to output and deal with it after the return of the function
#include "StdAfx.h"
#include <regex>
#include <iostream>
#include <string>
#include <conio.h>
using namespace std;
std::tr1::match_results<std::string::const_iterator> match(std::string& regex, const std::string& ip,std::tr1::match_results<std::string::const_iterator> res)
{
const std::tr1::regex pattern(regex.c_str());
bool valid = std::tr1::regex_match(ip, res, pattern);
std::cout << ip << " \t: " << (valid ? "valid" : "invalid") << std::endl;
cout << "FIRST RES FOUND: " << res[1] << endl;
return res;
}
int main()
{
string regex = "(\\d{1,3}):(\\d{1,3}):(\\d{1,3}):(\\d{1,3})";
string ip = "49:22:33:444";
std::tr1::match_results<std::string::const_iterator> res;
match(regex,ip.c_str(), res);
cout << "Result >" << res[1] << "< " << endl;
_getch(); return 0;
}
When I compile and run, The output is: "FIRST RES FOUND: 49
Result ><"
It's probably a really simple solution but what do I have to do to set it for my main can read it correctly as in: "Result >49<"
Thanks in advance. :)
Option 1: Use references:
void match(string& regex, const string& ip, tr1::match_results<string::const_iterator> & res)
{
const tr1::regex pattern(regex.c_str());
bool valid = tr1::regex_match(ip, res, pattern);
cout << ip << " \t: " << (valid ? "valid" : "invalid") << endl;
cout << "FIRST RES FOUND: " << res[1] << endl;
}
Option 2: Return the result by value and store it:
tr1::match_results<string::const_iterator> match(string& regex, const string& ip)
{
tr1::match_results<string::const_iterator> res;
// ...
return res;
}
int main()
{
// ...
tr1::match_results<string::const_iterator> res = match(regex, ip);
}
On a separate note, there should be absolutely no need for all the c_str() calls, as <regex> has a perfectly functional std::string interface. Check the documentation for details, you just have to get a couple of typenames right.
Edit: Here are some basic examples on using std::string. There are equivalent constructions for std::wstring, char* and wchar_t*, but std::strings should be the most useful one.
Since <regex> support is still patchy, you should consider the TR1 and Boost alternatives, too; I provide all three and you can pick one:
namespace ns = std; // for <regex>
namespace ns = std::tr1; // for <tr1/regex>
namespace ns = boost; // for <boost/regex.hpp>
ns::regex r("");
ns::smatch rxres; // 's' for 'string'
std::string data = argv[1]; // the data to be matched
// Fun #1: Search once
if (!ns::regex_search(data, rxres, r))
{
std::cout << "No match." << std::endl;
return 0;
}
// Fun #2: Iterate over all matches
ns::sregex_iterator rt(data.begin(), data.end(), r), rend;
for ( ; rt != rend; ++rt)
{
// *rt is the entire match object
for (auto it = rt->begin(), end = rt->end(); it != end; ++it)
{
// *it is the current capture group; the first one is the entire match
std::cout << " Match[" << std::distance(rt->begin(), it) << "]: " << *it << ", length " << it->length() << std::endl;
}
}
Don't forget to handle exceptions of type ns::regex_error.
Pass in res by reference instead of by value. In other words, declare the parameter res as a reference instead of a value, i.e., type &res, not type res.

convert string to integer in c++

Hello
I know it was asked many times but I hadn't found answer to my specific question.
I want to convert only string that contains only decimal numbers:
For example 256 is OK but 256a is not.
Could it be done without checking the string?
Thanks
The simplest way that makes error checking optional that I can think of is this:
char *endptr;
int x = strtol(str, &endptr, 0);
int error = (*endptr != '\0');
In C++ way, use stringstream:
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
int main()
{
stringstream sstr;
int a = -1;
sstr << 256 << 'a';
sstr >> a;
if (sstr.failbit)
{
cout << "Either no character was extracted, or the character can't represent a proper value." << endl;
}
if (sstr.badbit)
{
cout << "Error on stream.\n";
}
cout << "Extracted number " << a << endl;
return 0;
}
An other way using c++ style : We check the number of digits to know if the string was valid or not :
#include <iostream>
#include <sstream>
#include <string>
#include <cmath>
int main(int argc,char* argv[]) {
std::string a("256");
std::istringstream buffer(a);
int number;
buffer >> number; // OK conversion is done !
// Let's now check if the string was valid !
// Quick way to compute number of digits
size_t num_of_digits = (size_t)floor( log10( abs( number ) ) ) + 1;
if (num_of_digits!=a.length()) {
std::cout << "Not a valid string !" << std::endl;
}
else {
std::cout << "Valid conversion to " << number << std::endl;
}
}