Locating doubles in a char array (C++/ROOT) - c++

I have parsed some XML data, and I want latitude and longitude information. The line I need to parse is this:
trkptlat="60.397015"lon="5.32299"
This is an element in a char array, how can I extract/parse the numbers as doubles? Note that the number precision varies as the data goes on, so I can't solely rely on picking out the column indexes.

You are using C-Style char arrays as strings. So, my assumptions that you still are on C. Otherwise, you would std::string. Ìn C++ there is no jsutification to use a char array instead of a std::string.
Please see the C-Style solution:
#include <cstring>
#include <cstdlib>
#include <cstdio>
int main() {
char data[] = "SomeTrashMoreTrashtrkptlat=\"60.397015\"lon=\"5.32299\"MoreTrashMoreTrash";
char firstDoubleIndicator[] = "trkptlat=\"";
char secondDoubleIndicator[] = "\"lon=\"";
double latitude = 0;
double longitude = 0;
char* startPosition = strstr(data, firstDoubleIndicator);
if (startPosition) {
latitude = std::atof(startPosition + std::strlen(firstDoubleIndicator));
}
startPosition = strstr(data, secondDoubleIndicator);
if (startPosition) {
longitude = std::atof(startPosition + std::strlen(secondDoubleIndicator));
}
std::printf("\nlatitude:\t%f\nlongitude:\t%f\n\n", latitude, longitude);
return 0;
}

This can be done in numerous ways, warning totally untested code ahead
Using a safe version of sscan with a parameter that looks something like this
"\"trkptlat=\"%d\"lon=\"%d\""
Be sure to check the return value for length and errors.
Using std::find_first_of with digits and with dots
auto start = find_first_of (haystack.begin(), haystack.end(), digits.begin(), digit.end());
auto end = find_first_of (it, haystack.end(), digitsdot.begin(), digitdot.end(),
[](char a, char b){ return a != b; });
double lat = atof(start); // somewhere there might be a version that returns how many chars read also.
// check for errors
etc.
see further http://www.cplusplus.com/reference/algorithm/find_first_of/
if your the trusting kind you can take some shortcuts that you know that
"trkptlat="
will be prepended so you can start at
auto start = haystack+preLen;

Related

Parse (replace) in C++ std::string

I have a "custom" string that has the following format. Example:
std::string MyString = "RndOrder%5d - RndCustomer%8s - RndHex%8x";
I would like to replace/parse the string:
the %5d (%NUM_d) would be replaced with a random 5-digit decimal
the %8s (%NUM_s) would be replaced with a random 8-chars
the %8x (%NUM_x) would be replaced with a random 8-digit hexadecimal
Is there any function that helps me parse those "special marks"? Not sure if I would have to parse the string char by char and check for every possible combination.
If the format can be variant (not always the fixed 3 arguments: %5d, %8s and %8x) and you want to be flexible in that manner, you should write your own implementation for that.
Assuming that count defined after % is a general digit (not only 5 or 8) you could try using the std::regex_search or std::regex_match to find the actual mnemonics you are looking for. For example your expression could look like %\d+[dsx]
Then you should parse it to find the COUNT and type and substitute with a random number acquired with the desired generator.
To parse you could try updating the above expression to %(\d+)([dsx]) and capturing groups.
A sample parse implementation for your case could look like this:
std::string text = "RndOrder%5d - RndCustomer%8s - RndHex%8x";
auto reg = std::regex("%(\\d+)([sdx])");
std::smatch match;
while (std::regex_search(text, match, reg))
{
const auto& full = match.str(); // in 1st iter contains "%5d"
const auto& count = match.str(1); // in 1st iter contains "5"
const auto& type = match.str(2); // in 1st iter contains "d"
// further processing: type conversion, number generation, string replacement
text = match.suffix().str();
}
For implementation example with search and group capturing you can also check out another question: Retrieving a regex search in C++
Ok, assuming that you're actually asking about string parsing here (and not random number/data generation)... have a look at this:
int iRandom1 = 12345; // 5-digit decimal
int iRandom3 = 0x12345678; // 8-digit hexadecimal
char cRandom2[9] = "RandomXY\0"; // Don't forget to NULL-terminate!
std::string sFormat = "RndOrder%5d - RndCustomer%8s - RndHex%8x";
char cResultBuffer[500]; // Make sure this buffer is big enough!
std::sprintf( cResultBuffer, sFormat.c_str(), iRandom1, cRandom2, iRandom3 );
std::string MyString = cResultBuffer; // MyString = "RndOrder12345 - RndCustomerRandomXY - RndHex12345678";
It's a candidate for std::snprintf (c++14), but take care to request the correct buffer size in one call, allocate a buffer and then format the string into the buffer:
#include <iostream>
#include <cstring>
#include <string>
template<class...Args>
std::string replace(const char* format, Args const&... args)
{
// determine number of characters in output
auto len = std::snprintf(nullptr, 0, format, args...);
// allocate buffer space
auto result = std::string(std::size_t(len), ' ');
// write string into buffer. Note the +1 is allowing for the implicit trailing
// zero in a std::string
std::snprintf(&result[0], len + 1, format, args...);
return result;
};
int main() {
auto s = replace("RndOrder%5d - RndCustomer%8s - RndHex%8x", 5, "foo", 257);
std::cout << s << std::endl;
}
expected output:
RndOrder 5 - RndCustomer foo - RndHex 101

How to get multiple parameters from boost::split

How can split a std::string so that both the values of structure object get filled.
q.Qcmd = "Command1"
q.timeValue = 1.0
This is the sample code.
struct QueueCommand
{
std::vector<std::string>QCmd;
std::vector<float>timeValue;
};
int _tmain(int argc, _TCHAR* argv[])
{
std::string str = "command1|1.0"
std::string str1 = "command2|2.0"
QueueCommand q;
boost::split( q,str,boost::is_any_of("|")); // need to fill Qcmd and timevalue
boost::split( q,str1,boost::is_any_of("|"));
return 0;
}
This is not a correct usage of boost::split because the first parameter has to be a container for string, and split does not know how to fill the specific structure. I give you hints on how to solve it. I have not tested the code, but you can try yourself:
First, you have to declare a vector to store the parts:
std::vector<std::string> parts;
Then, boost::split can split the command string:
boost::split( parts, str, boost::is_any_of("|"));
Reserve enough space in the corresponding QueueCommand variable:
q.QCmd.resize(parts.size() - 1);
(the last one contains the float number). Copy the strings to the structure. You have to make sure the parts array contains at least two elements:
std::copy(parts.begin(), parts.begin() + parts.size() - 1, q.QCmd.begin());
Set the float part of the struct:
q.timeValue = boost::lexical_cast<float>(parts[parts.size() - 1]);
5gon12eder suggestion in comments:
Which seems more elegant and efficient, but requires C++11 for std::move:
q.timeValue = boost::lexical_cast<float>(parts.back());
parts.pop_back();
q.QCmd = std::move(parts);

Reverse a string with pointers [duplicate]

This question already has answers here:
C++ Reverse Array
(5 answers)
Closed 7 years ago.
This is an amateur question. I searched for other posts about this topic, found lots of results, but am yet to understand the concepts behind the solution.
This is a practice problem in my C++ book. It is not assigned homework. [Instructions here][1] .
WHAT I WOULD LIKE TO DO:
string input;
getline(cin, input); //Get the user's input.
int front = 0;
int rear;
rear = input.size();
WHAT THE PROBLEM WANTS ME TO DO
string input;
getline(cin, input); //Get the user's input.
int* front = 0;
int* rear;
rear = input.size();
Error: a value of type "size_t" cannot be assigned to an entity of type int*
This makes sense to me, as you cannot assign an 'address' of an int to the value of an int.
So my questions are:
What is the correct way to go about this? Should I just forget about initializing front* or rear* to ints? Just avoid that all together? If so, what would be the syntax of that solution?
Why would this problem want me to use pointers like this? It's clear this is a horrible usage of pointers. Without pointers I could complete this problem in like 30 seconds. It's just really frustrating.
I don't really see an advantage to EVER using pointers aside from doing something like returning an array by using pointers.
Thanks guys. I know you like to help users that help themselves so I did some research about this first. I'm just really irritated with the concept of pointers right now vs. just using the actual variable itself.
Posts about this topic that I've previously read:
[Example 1][2]
[Example 2][3]
[Example 3][4]
[1]: http://i.imgur.com/wlufckg.png "Instructions"
[2]: How does reversing a string with pointers works "Post 1"
[3]: Reverse string with pointers? "Post 2"
[4]: Reverse char string with pointers "Post 3"
string.size() does not return a pointer - it returns size_t.
To revert a string try this instead:
string original = "someText"; // The original string
string reversed = original; // This to make sure that the reversed string has same size as the original string
size_t x = original.size(); // Get the size of the original string
for (size_t i = 0; i < x; i++) // Loop to copy from end of original to start of reversed
{
reversed[i]=original[x-1-i];
}
If you really (for some strange reason) needs pointers try this:
string input;
getline(cin, input); //Get the user's input.
char* front = &input[0];
char* rear = &input[input.size()-1];
but I would not use pointers into a string. No need for it.
I guest you may not quite understand the problem here. This problem want you to COPY a C string then REVERSE it by pointer operation. There is no classes in standard C. So, the C string is quite different from string class in C++. It is actually an array of char-type elements ended with character '\0'.
After understand this, you may start to understand the problem here. If you want to copy a C string, you can not just use str_a = str_b. You need constructor here. However, in pure C style, you should REQUIRE memory space for the string at first (you can use malloc here), then copy each element. For example, you want to create a function to make a copy of input string,
#include <string.h>
char *strcopy(char* str_in) {
int len = strlen(str_in);
char *str_out = (char*)malloc(len+1);
char *in = str_in;
char *out = str_out;
while(*in != '\0') { *out++ = *in++; }
return str_out;
}
As you see, we actually use char* not int* here to operate string element. You should distinguish the pointer (such as in) and the element pointed by the pointer (such as *in) at first.
I'll show you a solution in pure C style for your problem, I hope this would help you to understand it. (You should be able to compile it without modification)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* strreverse(char* in){
// length of input string
int len = strlen(in);
// allocate memory for string operation
char *out = (char*)malloc(len+1);
// initialize <front> and <end>
char *front = out, *end = out + len - 1;
char buffer;
// copy input string
for(int i = 0; i <= len; i++){ out[i] = in[i]; }
// reverse string
for(; front < end; front++, end--) {
buffer = *front;
*front = *end;
*end = buffer;
}
return out;
}
int main() {
printf("REVERSE >> %s\n", strreverse("Hello, World!"));
return 0;
}
This is not you would do by C++ in actual programming, however, I guess the problem here is trying to let you understand mechanism of pointers. In this aspect, original C style would help a lot.

How to find the length of a string in C++

I a writing a program and I need to write a function that returns the amount of characters and spaced in a string. I have a string(mystring) that the user writes, I want the function to return the exact amount of letters and spaces in string, for examples "Hello World" should return 11, since there are 10 letters and 1 space. I know string::size exists but this returns the size in bytes, which is of no use to me.
I'm not sure if you want the length of the string in characters or you just want to count the number of letters and spaces.
There is no specific function that lets you count just letters and spaces, however you can get the amount of letters and spaces (and ignore all other types of characters) quite simply:
#include <string>
#include <algorithm>
#include <cctype>
int main() {
std::string mystring = "Hello 123 World";
int l = std::count_if(mystring.begin(), mystring.end(), [](char c){ return isspace(c) || isalpha(c); });
return 0;
}
Otherwise, unless you use non-ascii strings, std::string::length should work for you.
In general, it's not so simple and you're quite right if you assumed that one byte doesn't necessarily mean one character. However, if you're just learning, you don't have to deal with unicode and the accompanying nastiness yet. For now you can assume 1 byte is 1 character, just know that it's not generally true.
Your first aim should be to figure out if the string is ascii encoded or encoded with a multi-byte format.
For ascii string::size would suffice. You could use the length property of string as well.
In the latter case you need to find the number of bytes per character.
You should take the size of your array, in bytes, using string::size and then divide this by the size in bytes of an element of that string (a char).
That would look like: int len = mystring.size() / sizeof(char);
Just make sure to include iostream, the header file that contains std::sizeof.
You can make your own function to get the length of string in C++ (For std::string)
#include <iostream>
#include <cstring>
using namespace std;
int get_len(string str){
int len = 0;
char *ptr;
while(*ptr != '\0')
{
ptr = &str[len];
len++;
}
int f_len = len - 1;
return f_len;
}
To use this function, simply use:
get_len("str");

Creating Multiple folders with mkdir() Function using loop c++

I want to create folders in a directory by naming them in a sequence like myfolder1, myfolder2. i tried doing it with mkdir() function using a for loop but it doesn't take 'integer variables' and only takes 'const char values'. what to do now? is there any other function which do that or can mkdir() do that?
I'm not aware of any library calls that take an integer like you are asking. What you need to do is embed the number into the string before passing it to mkdir(). Since you tagged this question with 'c++' I've demonstrated a C++ oriented way of accomplishing this below.
#include <sstream> // for std::ostringstream
#include <string> // for std::string
const std::string baseFolderName = "myfolder";
for (int i = 1; i < 20; ++i)
{
std::ostringstream folderName;
folderName << baseFolderName << i;
mode_t mode = 0; //TBD: whatever is appropriate
mkdir(folderName.str().c_str(), mode);
}
If you really want this, you can use itoa(...)
Lets say
i = 20;
char buffer [33];
itoa (i,buffer,10); //10 means decimal
Now buffer = "20\0"
After this conversion you can add buffer to your default string.
So, all in all, you can use:
std::string str = "string";
char buffer[33] ;
itoa(20, buffer, 10);
str.append(buffer);
mkdir(str.c_str());