I am trying to get the string value from a protobuf message. My .proto schema looks like this:
syntax = "proto3";
package messages;
message Telemetry
{
optional string key1 = 1;
optional string key2 = 2;
}
The piece of code which is used to manipulate with it:
int main(int argc, char **argv)
{
GOOGLE_PROTOBUF_VERIFY_VERSION;
messages::Telemetry telemetry;
// Initialize values
telemetry.set_key1("string_1");
telemetry.set_key2("string_2");
std::cout << "key1: " << telemetry.key1() << std::endl;
std::cout << "key2: " << telemetry.key2() << std::endl;
const google::protobuf::Descriptor *desc = telemetry.GetDescriptor();
int fieldCount = desc->field_count();
for(int i = 0; i < fieldCount ; i++)
{
const google::protobuf::FieldDescriptor *field = desc->FindFieldByNumber(i + 1);
fprintf(stderr, "Name of the %i th key: %s, type: %s \n", i, field->name().c_str(), field->type_name());
}
const google::protobuf::FieldDescriptor *field = desc->FindFieldByName("key1");
const google::protobuf::Reflection *refl = telemetry.GetReflection();
std::string str;
str = refl->GetStringReference(telemetry, field, &str);
std::cout << "Value: " << str << std::endl;
}
Somehow, the output looks like:
Name of the 0 th key: key1, type: string <- OK
Name of the 1 th key: key2, type: string <- OK
key1: string_1 <- OK
key2: string_2 <- OK
Value: string_2 <- This line is expected to be 'string_1'
Then if I tried desc->FindFieldByName("key2"), the program would be crashed with (Segmentation fault (core dumped)).
Thanks in advance for any suggestion.
Related
I am new to c++ and I have to work on a project for my end-of-study internship.
The project consists in managing the data of the electronic log of the ATMs.
My problem is that I have to get the data from a file.txt(which is an electronic gab log) and store it in the table I created.
Here is an example of the file.txt (the electronic gab log) :
Every events of this file is separated by : ************************
File log.txt
File log.txt
The data I need to store in the table is : (look the image)
Table journal_contents
I have the Journal object that I created and I want to get tha data in this object and then in the database.
Here is the code I've done :
This is my header.h
//Declaration de struct
struct events {
int id_event;
std::string id_event_ligne;
float amount_withdraw;
int type_transaction;
int type_return_transaction;
int type_card_returned;
int type_card_insert;
int type_return_motif;
};
class Journal // Object journal
{
public:
Journal(){};
int getId_ligne();
private:
int id;
int id_atm;
int id_ligne;
int date_ligne;
int date_insert;
std::vector<events> trans_events;
};
This is my file.cpp
//Some random code
int Journal::getId_ligne( )
{
time_t t =time(0); // get time now
tm* now = localtime(&t);
int year= (now->tm_year + 1900);
string syear(to_string(year));
int month = (now->tm_mon + 1);
string smonth(to_string(month));
int day = now->tm_mday;
string sday(to_string(day));
int hour = now->tm_hour;
string shour(to_string(hour));
int minute = now->tm_min;
string sminute(to_string(minute));
int second = now->tm_sec;
string sseconde(to_string(second));
if(smonth.length()== 1)
{
smonth = '0' + smonth;
}
if(sday.length()== 1)
{
sday = '0' + sday;
}
if(shour.length()== 1)
{
shour = '0' + shour;
}
if(sminute.length()== 1)
{
sminute = '0' + sminute;
}
if(sseconde.length()== 1)
{
sseconde = '0' + sseconde;
}
string current_time =syear + '-' + smonth + '-' + sday + '\t' + shour + ':' + sminute + ':' + sseconde ;
string datee= syear + smonth+ sday + ".jrn" ;
const char* path = "C:\\Users\\dell\\Desktop\\Stage\\journals\\";
string str_path = string(path)+ datee;
//find filename
unsigned found = str_path.find_last_of("/\\");
string same_path = str_path.substr(found+1);
//Compare
if (datee.compare(same_path)== 0)
{
// Here I just writed 8902 as an Id to test but what I need to do is to get the id from the file.txt
string filename = string(str_path);
ifstream file1(filename);
string line;
string word;
if(file1.is_open())
{ int k=0;
while (getline(file1, line))
{
if (line.find("8902") != string::npos){
istringstream isstream;
isstream.str(line);
getline(isstream, word, ' ');
getline(isstream, word, ' ');
int id_ligne = stoi(word);
Db_response::Connection();
string insert_query = "INSERT INTO `journal_contents`(`id_ligne`) VALUES ('"+word+"')";
//int qstate = mysql_real_query(conn,insert_query.c_str(), strlen(insert_query.c_str()));
query_state=mysql_query(conn, insert_query.c_str());
if(!query_state)
{
cout << "Query Execution Problem " << mysql_errno(conn) << endl;
}
else
{
cout << endl << "success" << endl;
}
k=1;
}}
if (k==0) {
}
file1.close();
}
else
cout <<"File not found " << endl;
file1.close();
//cout << id << endl;
return id_ligne;
}
}
main.cpp
int main(int argc, const char* argv[])
{
cout << "Hello world!" << endl;
Journal current_journal;
cout << current_journal.getId_ligne() << endl;
}
I hope I have explained my problem well. I really need your help
Thanks in advance for helping me.
i'm trying to get process name from Win32_Processor soo i create function ProcessNameInfo.
my code is :
void ProcessNameInfo(string nameoption, String^ hardwareClass, String^ propertyNname)
{
ManagementObjectSearcher^ searcher = gcnew ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM " + hardwareClass);
ManagementObjectCollection^ collection = searcher->Get();
for each (ManagementObject^ object in collection)
{
String ^ s = object[propertyNname]->ToString();
CString str3(s);
const TCHAR* x = (LPCTSTR)str3;
char szString[MAX_LENGTH];
size_t nNumCharConverted;
wcstombs_s(&nNumCharConverted, szString, MAX_LENGTH,
x, MAX_LENGTH);
std::string HardwareInfo = szString;
std::transform(HardwareInfo.begin(), HardwareInfo.end(), HardwareInfo.begin(), [](char ch) {
return ch == ' ' ? '_' : ch;
});
file << "\"" << nameoption << "\": \"" << HardwareInfo << "\"," << endl;
}
}
in the main i call this function like this :
ProcessNameInfo("Processor", "Win32_Processor", "Name");
for some devices it's working but in another devices i get error Unhandled exception:
System.NullReferenceException object reference not set to an instance of an object in ProcessNameInfo(basic_string<char\,std::char_traites<char>\,std::allocator<char> >* nameoption, String hardwareClass, String propertyNname) in main() _mainCRTStartup()
I'm writing a project to simulate (an oversimplified version of) a blockchain. I've written a class called Block to manage blocks in the blockchain:
(You may notice that I am referencing some additional classes/headers which are not listed in an #include statement at the top. To my knowledge, all the dependencies are adequately taken care of by the makefile.)
#include "Block.h"
/**** constructors ****/
Block::Block()
{
prevHash = "";
merkleRoot = "";
nonce = "";
}
Block::Block(std::string str)
{
std::vector<std::string> strings;
std::string word;
int pos = str.find(" ");
while(pos != std::string::npos)
{
word = str.substr(0, pos);
strings.push_back(word);
pos = str.find(" ");
str = str.substr(pos+1);
}
if(strings.size() != 3)
{
prevHash = "";
merkleRoot = "";
nonce = "";
}
else
{
prevHash = strings.at(0);
merkleRoot = strings.at(1);
nonce = strings.at(2);
}
}
Block::Block(std::vector<Block> &blocks, std::string merkle)
{
// use prev block from Block vector to get hash of prev block
Block prevBlock = blocks.at(0);
prevHash = picosha2::hash256_hex_string(utils::hexToString(prevBlock.toString()));
merkleRoot = merkle;
nonce = mine();
}
Block::Block(std::string hash, std::string merkle, std::string n)
{
prevHash = hash;
merkleRoot = merkle;
nonce = n;
}
Block::Block(const Block &b) //copy constructor
{
prevHash = b.getPrevHash();
merkleRoot = b.getMerkleRoot();
nonce = b.mine();
}
Block::~Block() //destructor
{
}
/**** public methods ****/
bool Block::isValid()
{
std::string hash = picosha2::hash256_hex_string(utils::hexToString(this->toString()));
if(hash[0] == '0')
return true;
return false;
}
std::string Block::toString()
{
return prevHash + merkleRoot + nonce;
}
std::string Block::mine() const
{
// brute force nonces so hash begins with zero/block is valid
for(int i = 0; i < pow(2, 8); i++)
{
Block temp(this->getPrevHash(), this->getMerkleRoot(), std::to_string(i));
if(temp.isValid())
{
// convert i to hex string and return
std::stringstream stream;
stream << std::hex << std::to_string(i);
return stream.str();
}
}
std::cout << "No nonce found." << std::endl;
return "";
}
// calculate this block's hash
std::string Block::calcHash()
{
std::string hash = picosha2::hash256_hex_string(utils::hexToString(this->toString()));
return hash;
}
std::string Block::getPrevHash() const
{
return prevHash;
}
std::string Block::getMerkleRoot() const
{
return merkleRoot;
}
std::string Block::getNonce() const
{
return nonce;
}
So, the actual problem: I can't add instances of the Block class to my vector of Blocks (or an array of Blocks, for that matter; I tried that too). I can create a Block, print it out, basically anything I want. But if I add it to a vector, my computer throws a runtime error. Below is my main file and the output of a run:
#include "main.h"
// function prototype
std::string merkleRoot(std::vector<Transaction> &);
int main(int argc, char ** argv)
{
int numblocks = 0;
int numtransactions = 0;
std::vector<Block> blocks;
std::vector<Transaction> transactions;
if(argc != 3)
{
std::cout << "Usage: main [blockchain.txt] [transaction.txt]" << std::endl;
exit(1);
}
std::string blockchainFileName = argv[1];
std::string transactionFileName = argv[2];
std::cout << "blockchainFileName: " << blockchainFileName << std::endl;
std::cout << "transactionFileName: " << transactionFileName << std::endl;
std::ifstream blockchainFile(blockchainFileName);
std::ifstream transactionFile(transactionFileName);
if(!blockchainFile)
{
std::cout << "Cannot open " << blockchainFileName << std::endl;
exit(1);
}
if(!transactionFile)
{
std::cout << "Cannot open " << transactionFileName << std::endl;
exit(1);
}
/*** Read in blockchain ***/
std::string line;
int count = 0;
while(std::getline(blockchainFile, line))
{
std::vector<Block> temp;
std::cout << "line number " << ++count << std::endl;
Block newBlock(line);
std::cout << newBlock.toString() << std::endl;
blocks.push_back(newBlock);
}
}
Output:
$ ./main textfiles/blockchain_1.txt textfiles/transactions_1.txt
blockchainFileName: textfiles/blockchain_1.txt
transactionFileName: textfiles/transactions_1.txt
line number 1
026765a1c8235d4ac23d2582cda3b9f5c062f805540320173eb9e9148c0dc518704b42e4b11ca131b443c2b02a07ec0b45407f1b125027e3e68b86ace692445800000001
libc++abi.dylib: terminating with uncaught exception of type std::out_of_range: basic_string
Abort trap: 6
blockchain_1.txt file:
026765a1c8235d4ac23d2582cda3b9f5c062f805540320173eb9e9148c0dc518 704b42e4b11ca131b443c2b02a07ec0b45407f1b125027e3e68b86ace6924458 00000001
0b53181ae351f4508363cdc3e8fb3e819fb706c4ba98a3005a980a837561074a 06aa7a8cbda7ac4351c0cae116c589c2eb0ca96cb4c90844812945cb4ffe27c5 00000019
000000000000000000ad6e90c0790e83760a9d13728c23474352a2c8c7a6e0eb 2b12fcf1b09288fcaff797d71e950e71ae42b91e8bdb2304758dfcffc2b620e3 0000000f
transactions_1.txt file:
Bob Alice 5.0
Alice Bob 1.0
John Bill 2.4
Bill Alice 1.3
John Bill 2.7
Bob John 7.9
Tom Todd 4.5
Todd Bob 12.0
I've dug around for several hours now and I'm kind of out of leads. I will say that I am a little rusty with C++, particularly constructing and using my own classes. If anyone has any ideas, I'd really appreciate it! Let me know if you need any additional parts of my code.
I have a program like below:
// test.c
#include <stdio.h>
#define LOG printf
int main(int argc, char *argv[])
{
LOG("Hello, my name %s, my age %d\n", "John", 30);
LOG("I have wife and %d kids\n", 2);
return 0;
}
I want to create a log file which contains all texts like:
// message.txt
LINE: "Hello, my name %s, my age %d\n"
LINE: "I have wife and %d kids\n"
Is it possible to do it using C's preprocessor, make, or even a script?
Edited:
Let's say I have a program that prints those messages in English already, I have source code for sure, now I want to support French then:
I need to get all messages that developers put into their program and create a message.txt which contains all texts, replace each message in original program with an identify number which maps each message in message.txt. I want to do it programmatically not manually.
What you are looking for is localization, read something about it here. If you're on a posix system you can use gettext() for that, see manpage. If you're using Windows you can take a look at GetText for Windows.
Nevertheless I wrote a little C++ program that generate the files you want, see code below.
You call it via myProg filename logFunction where filename is the source file you want to input and logFunction is for example LOG.
You will get a map file called filename_map and a new source file filename_new. The new source file will contain a new macro LOG and a function readLocaleStrings() which will read all the strings at program start from the filename_map file. The new macro LOG will use the right strings automatically then.
In your example you would call it by myProg test.c LOG and would get:
test_map.txt:
7: "Hello, my name %s, my age %d\n"
8: "I have wife and %d kids\n"
and a test_new.c:
// test.c
#include <stdio.h>
#define LOG(filename,line,...) printf(localeStrings.strings[localeStrings.lastIdx++], __VA_ARGS__)
/* Beginning: Generated code for localization */
#include <stdlib.h>
#include <string.h>
typedef struct {
size_t count;
size_t lastIdx;
char ** strings;
} stringArray_t;
stringArray_t localeStrings = { 0, 0, NULL };
int readLocaleStrings (const char * const filename)
{
FILE * file = NULL;
char * line = NULL;
char * str = NULL;
size_t len = 0;
ssize_t read;
file = fopen(filename, "r");
if (file == NULL)
{
return -1;
}
localeStrings.strings = malloc (sizeof (char *));
localeStrings.count = 0;
while (-1 != (read = getline(&line, &len, file)))
{
size_t curIdx = localeStrings.count++;
localeStrings.strings = realloc(localeStrings.strings, localeStrings.count * sizeof (char *));
str = strstr(line, "\"");
localeStrings.strings[curIdx] = malloc(sizeof (char) * (size_t)(1 + read));
strcpy (localeStrings.strings[curIdx], str);
}
fclose(file);
if (line)
{
free(line);
}
return 0;
}
void freeLocaleStrings()
{
size_t idx;
for (idx = 0; idx < localeStrings.count; ++idx)
{
free(localeStrings.strings[idx]);
}
free(localeStrings.strings);
}
/* End: Generated code for localization */
int main(int argc, char *argv[])
{
readLocaleStrings("test_map.txt");
LOG("test_map.txt", "7", "John", 30);
LOG("test_map.txt", "8", 2);
freeLocaleStrings();
return 0;
}
C++ program:
The C++ program has limitation, it will just find LOG(" if you want also to find LOG with spaces anywhere like: LOG (" you have to change that code. Moreover there are cases such as multiple lines messages, messages that had been commented out etc. You have to extend the code for your requirements then. Also there is no great argument parse handling or error checking. Further for the writing of the helper code it is needed to find the main function. But for your given input file it works perfectly and should just point you in the right direction. To extend it more easy and make it more flexible using a regex library would be wise.
Code:
#include <iostream>
#include <fstream>
/* Function definition is under main function */
const char * getNextHelperFunctionLine();
std::string getExtension (const std::string filename)
{
/* get dot of e.g. foo.c */
size_t posDot = filename.rfind('.');
/* extract extension */
std::string extension;
if (std::string::npos != posDot)
{
/* extension found */
extension = filename.substr(posDot);
}
return extension;
}
std::string getFilename (const std::string filename)
{
/* get dot of e.g. foo.c */
size_t posDot = filename.rfind('.');
/* extract filename */
std::string name = filename;
if (std::string::npos != posDot)
{
name = name.substr(0, posDot);
}
return name;
}
int main (int argc, char* argv[])
{
if (argc < 3)
{
std::cerr << "Usage: "
<< " " << argv[0] << " filename logFunction"
<< std::endl;
return 0;
}
std::string infileName (argv[1]);
/* extract filename and extension */
std::string filename = getFilename(infileName);
std::string extension = getExtension(infileName);;
/* names for generated files */
std::string mapfileName = filename + "_map.txt";
std::string mappedfileName = filename + "_new" + extension;
/* open streams for input and output */
std::ifstream infile(infileName.c_str());
std::ofstream fileMap(mapfileName.c_str());
std::ofstream fileMapped(mappedfileName.c_str());
/* string for log function e.g. "LOG(" */
std::string logFun = std::string(argv[2]);
std::string logFunOpen = logFun + "(\"";
std::string lineRead;
size_t lineNr = 1;
size_t mainParanthesis = 0;
bool mainReturnFound = false;
/* Loop through whole input file */
while (std::getline(infile, lineRead))
{
/* position of log function opening e.g. "LOG(" */
size_t posLogOpen = lineRead.find(logFunOpen);
/* opening found? */
bool foundOpen = std::string::npos != posLogOpen;
if (foundOpen)
{
bool foundClose = false;
/* position of the string beginning */
size_t posLogStringBeg = posLogOpen + logFunOpen.length();
size_t posLogClose = posLogStringBeg;
/* find closing of the log function e.g. "LOG(...)" */
while (!foundClose)
{
/* search for '"' and skip these if they are in the string */
posLogClose = lineRead.find("\"", posLogClose + 1);
if (std::string::npos != posLogClose)
{
foundClose = (0 != lineRead.compare(posLogClose - 1, 1, "\\"));
}
}
/* closing found write map file and new source file */
if (foundClose)
{
size_t len = posLogClose - posLogStringBeg;
fileMap << lineNr << ": \""
<< lineRead.substr(posLogStringBeg, len) << "\""
<< std::endl;
fileMapped << lineRead.substr(0, posLogStringBeg - 1)
<< '"' << mapfileName << "\", "
<< '"' << lineNr
<< lineRead.substr(posLogClose)
<< std::endl;
}
}
/* not a log function write normal code */
else
{
if ( std::string::npos != lineRead.find("#define")
&& std::string::npos != lineRead.find(logFun))
{
/* log functions needs to be changed */
fileMapped << "#define "
<< logFun << "(filename,line,...) "
<< "printf(localeStrings.strings[localeStrings.lastIdx++], __VA_ARGS__)" << std::endl;
}
else if ( 0 == mainParanthesis
&& std::string::npos != lineRead.find(" main")
&& std::string::npos != lineRead.find("(")
&& std::string::npos != lineRead.find(")"))
{
/* found main function write all helper functions in front of it */
const char * helperLine;
while ((helperLine = getNextHelperFunctionLine()))
{
fileMapped << helperLine << std::endl;
}
/* write main function part */
fileMapped << lineRead << std::endl;
/* is there an opening parenthesis? */
if (std::string::npos != lineRead.find("{"))
{
++mainParanthesis;
fileMapped << " readLocaleStrings(\"" << mapfileName << "\");" << std::endl;
}
}
else
{
/* in main function write first part */
if (std::string::npos != lineRead.find("{"))
{
/* write opening */
fileMapped << lineRead << std::endl;
if (0 == mainParanthesis)
{
fileMapped << " readLocaleStrings(\"" << mapfileName << "\");" << std::endl;
}
++mainParanthesis;
}
/* return statement? */
else if ( 1 == mainParanthesis
&& std::string::npos != lineRead.find("return"))
{
mainReturnFound = true;
fileMapped << " freeLocaleStrings();" << std::endl;
/* write return */
fileMapped << lineRead << std::endl;
}
else if ( 1 == mainParanthesis
&& std::string::npos != lineRead.find("}"))
{
--mainParanthesis;
if (!mainReturnFound)
{
fileMapped << " freeLocaleStrings();" << std::endl;
}
/* write closing */
fileMapped << lineRead << std::endl;
}
else
{
/* write other code */
fileMapped << lineRead << std::endl;
}
}
}
++lineNr;
}
return 0;
}
const char * getNextHelperFunctionLine()
{
static size_t idx = 0;
static const char * helperFunLines[] =
{
"",
"/* Beginning: Generated code for localization */",
"#include <stdlib.h>",
"#include <string.h>",
"",
"typedef struct {",
" size_t count;",
" size_t lastIdx;",
" char ** strings;",
"} stringArray_t;",
"",
"stringArray_t localeStrings = { 0, 0, NULL };",
"",
"int readLocaleStrings (const char * const filename)",
"{",
" FILE * file = NULL;",
" char * line = NULL;",
" char * str = NULL;",
" size_t len = 0;",
" ssize_t read;",
"",
" file = fopen(filename, \"r\");",
" if (file == NULL)",
" {",
" return -1;",
" }",
"",
" localeStrings.strings = malloc (sizeof (char *));",
" localeStrings.count = 0;",
"",
" while (-1 != (read = getline(&line, &len, file)))",
" {",
" size_t curIdx = localeStrings.count++;",
" localeStrings.strings = realloc(localeStrings.strings, localeStrings.count * sizeof (char *));",
"",
" str = strstr(line, \"\\\"\");",
" localeStrings.strings[curIdx] = malloc(sizeof (char) * (size_t)(1 + read));",
" strcpy (localeStrings.strings[curIdx], str);",
" }",
"",
" fclose(file);",
" if (line)",
" {",
" free(line);",
" }",
"",
" return 0;",
"}",
"",
"void freeLocaleStrings()",
"{",
" size_t idx;",
" for (idx = 0; idx < localeStrings.count; ++idx)",
" {",
" free(localeStrings.strings[idx]);",
" }",
" free(localeStrings.strings);",
"}",
"/* End: Generated code for localization */",
""
};
if (idx < (sizeof (helperFunLines) / sizeof (helperFunLines[0])))
{
return helperFunLines[idx++];
}
else
{
return nullptr; /* use NULL if compiler doesn't support nullptr */
}
}
I have some MET data I want to validate which would look something like these:
char validBuffer[] = {"N51374114W1160437"};
char invalidBuffer[] = {"bad data\n"};
char emptyBuffer[] = {""};
I've tried a simple sscanf, but that failed:
int _tmain(int argc, _TCHAR* argv[])
{
char validBuffer[] = {"N51374114W1160437"};
char invalidBuffer[] = {"bad data\n"};
char emptyBuffer[] = {""};
char ns = ' ';
char ew = ' ';
int northing = -999;
int easting = -999;
int paramsConverted = sscanf_s(validBuffer, "%c%d%c%d", &ns, &northing, &ew, &easting);
printf("Converted \"%s\"; Found %d params [%c,%d,%c,%d]\n", validBuffer, paramsConverted, ns, northing, ew, easting);
paramsConverted = sscanf_s(invalidBuffer, "%c%d%c%d", &ns, &northing, &ew, &easting);
printf("Converted \"%s\"; Found %d params [%c,%d,%c,%d]\n", invalidBuffer, paramsConverted, ns, northing, ew, easting);
paramsConverted = sscanf_s(validBuffer, "%c%d%c%d", &ns, &northing, &ew, &easting);
printf("Converted \"%s\"; Found %d params [%c,%d,%c,%d]\n", emptyBuffer, paramsConverted, ns, northing, ew, easting);
getchar();
return 0;
}
gives me:
Converted "N51374114W1160437"; Found 2 params [N,-999,",-1024]
Converted "bad data
"; Found 1 params [b,-999,",-1024]
Converted ""; Found 2 params [N,-999,",-1024]
I'd rather not use any external libraries if at all possible, so is there a nice simple way of doing this without parsing it one character at a time?
How about using Regular expressions from TR1?
char validBuffer[] = {"N51374114W1160437"};
char invalidBuffer[] = {"bad data\n"};
char emptyBuffer[] = {""};
if(strlen(validBuffer)!=18)
{
//Error not valid buffer
}
char ns = validBuffer[0];
char ew = validBuffer[9];
int N = atoi(&validBuffer[1]);
int W = atoi(&validBuffer[10]);
if(N==0 || W==0)
//Error not valid buffer
Not simple not the best but better than nothing
You could use std::stringstream and the stream operators...
#include <string>
#include <sstream>
#include <iostream>
using namespace std;
bool parse(string & s) {
stringstream ss(s);
char n = 0, w = 0;
int x = 0, y = 0;
ss >> n;
if (! ss.good ()) return false;
ss >> x;
if (! ss.good ()) return false;
ss >> w;
if (! ss.good ()) return false;
ss >> y;
if ( ss.bad ()) return false;
cout << "Parsed {" << n << ", " << x << ", "
<< w << ", " << y << "}" << endl;
return true;
}
int main ()
{
string validBuffer = "N51374114W1160437";
string invalidBuffer = "bad data\n";
string emptyBuffer = "";
if (! parse (validBuffer))
cout << "Unable to parse: '" << validBuffer << "'" << endl;
if (! parse (invalidBuffer))
cout << "Unable to parse: '" << invalidBuffer << "'" << endl;
if (! parse (emptyBuffer))
cout << "Unable to parse: '" << emptyBuffer << "'" << endl;
return 0;
}
My output using the above:
Parsed {N, 51374114, W, 1160437}
Unable to parse: 'bad data
'
Unable to parse: ''
Consider a bit specific format parameter for sscanf():
int paramsConverted = sscanf(validBuffer, "%c%8d%c%7d", &ns, &northing, &ew, &easting);