RapidJSON Looping through a string array? - c++

I am using RapidJSON to parse JSON data except I can't work out how to loop through the members of:
{
"members":{
"0":{
"template":"this is member 1"
},
"1":{
"template":"this is member 2"
}
}
}
I tried the following
e_doc["members"][iString]["template"].GetString()
inside a loop with converting the loop index (i) to a string but it doesn't recognize it as a string.
It works as:
printf("%s", e_doc["members"]["0"]["template"].GetString());
printf("%s", e_doc["members"]["1"]["template"].GetString());

There might be a small issue as you are not iterating over an array, but over an object. However, in the end the code is similar.
const rapidjson::Value& membersObject = e_doc["members"];
for(rapidjson::Value::ConstMemberIterator it=membersObject.MemberBegin(); it != membersObject.MemberEnd(); it++) {
std::cout << it->value["template"].GetString();
}

Related

How to convert a string to array of strings made of characters in c++?

How to split a string into an array of strings for every character? Example:
INPUT:
string text = "String.";
OUTPUT:
["S" , "t" , "r" , "i" , "n" , "g" , "."]
I know that char variables exist, but in this case, I really need an array of strings because of the type of software I'm working on.
When I try to do this, the compiler returns the following error:
Severity Code Description Project File Line Suppression State
Error (active) E0413 no suitable conversion function from "std::string" to "char" exists
This is because C++ treats stringName[index] as a char, and since the array is a string array, the two are incopatible.
Here's my code:
string text = "Sample text";
string process[10000000];
for (int i = 0; i < sizeof(text); i++) {
text[i] = process[i];
}
Is there any way to do this properly?
If you are going to make string, you should look at the string constructors. There's one that is suitable for you (#2 in the list I linked to)
for (int i = 0; i < text.size(); i++) {
process[i] = string(1, text[i]); // create a string with 1 copy of text[i]
}
You should also realise that sizeof does not get you the size of a string! Use the size() or length() method for that.
You also need to get text and process the right way around, but I guess that was just a typo.
std::string is a container in the first place, thus anything that you can do to a container, you can do to an
instance of std::string. I would get use of the std::transform here:
const std::string str { "String." };
std::vector<std::string> result(str.size());
std::transform(str.cbegin(), str.cend(), result.begin(), [](auto character) {
return std::string(1, character);
});

How to get letter from String by index? C++

Can someone briefly explain how to get a character from index from String in C++.
I need to read the first 3 letters of a String and in java it would bestr.charAt(index) and I have been searching the internet for a solution for 2h now and still don't understand...
can some one please give me an example.
std::string provides operator[] to access a character by index:
https://en.cppreference.com/w/cpp/string/basic_string/operator_at
Example:
const std::string s("hello");
const char c = s[0];
// c is set to ‘h’
substr()
It returns a newly constructed string object with its value initialized to a copy of a substring of this object.
Syntax
substr(pos, pos+len)
Code
std::string str ("Test string"); //string declaration
string sub_string = str.substr(0,3);
String index starts from 0.
Best place to look would be cpluspluc.com: http://www.cplusplus.com/reference/string/string/
You may use as earlier mentioned: http://www.cplusplus.com/reference/string/string/operator[]/
std::string str ("Test string");
for (int i=0; i<str.length(); ++i)
{
std::cout << str[i];
}
Or better yet: http://www.cplusplus.com/reference/string/string/at/
std::cout << str.at(i);
which also checks for a valid position and throws an out of range exception otherwise.
Alternatively you could use http://www.cplusplus.com/reference/string/string/data/
to acces the raw data.
Or if you want to check that your string starts with a specific pattern: http://www.cplusplus.com/reference/string/string/rfind/
std::string str = "Hey Jude!";
if (str.rfind("Hey", 0) == 0) {
// match
}
Another option to obtain a single character is to use the std::string::at() member function. To obtain a substring of a certain length, use the std::string::substr member function.

Using regex_match() on iterator with string in c++

working on a c++ project, I need to iterate on a string ( or char* depending the solution you could provide me ! ). So basically I'm doing this :
void Pile::evalExpress(char* expchar){
string express = expchar
regex number {"[+-*/]"};
for(string::iterator it = express.begin(); it!=express.end(); ++it){
if(regex_match(*it,number)){
cout<<*it<<endl;
}
}
}
char expchar[]="234*+";
Pile calcTest;
calcTest.evalExpress(expchar);
the iterator works well ( I can put a cout<<*it<<'endl above the if statement and I get a correct output )
and then when I try to compile :
error: no matching function for call to 'regex_match(char&, std::__cxx11::regex&)'
if(regex_match(*it,number)){
^
I have no idea why this is happening, I tried to don't use iterator and iterate directly on the expchar[i] but I have the same error with regex_match()...
Regards
Vincent
Read the error message! It tells you that you're trying to pass a single char to regex_match, which is not possible because it requires a string (or other sequence of characters) not a single character.
You could do if (std::regex_match(it, it+1, number)) instead. That says to search the sequence of characters from it to it+1 (i.e. a sequence of length one).
You can also avoid creating a string and iterate over the char* directly
void Pile::evalExpress(const char* expchar) {
std::regex number {"[+-*/]"};
for (const char* p = expchar; *p != '\0'; ++p) {
if (regex_match(p, p+1, number)) {
cout<<*p<<endl;
}
}
}

ADO Recordset Field Value to C++ vector/array (capture pointer value)

I am trying to query an SQL Server (Express) through Visual C++ (express) and store the resulting dataset into a C++ vector (array would be great as well). To that end I researched the ADO library and found plenty of help on MSDN. In short, reference the msado15.dll library and use those features (especially the ADO Record Binding, which requires icrsint.h). In short, I have been able to query the database and display the field values with printf(); but am stumbling when I try to load the field values into a vector.
I originally tried loading values by casting everything as char* (due to despair after many type conversion errors) only to find the end result was a vector of pointers that all pointed to the same memory address. Next (and this is the code provided below) I attempted to assign the value of the memory location but am ending up with a vector of the first character of the memory location only. In short, I need help understanding how to pass the entire value stored by the Recordset Field Value (rs.symbol) pointer (at the time it is passed to the vector) instead of just the first character? In this circumstance the values returned from SQL are strings.
#include "stdafx.h"
#import "msado15.dll" no_namespace rename("EOF", "EndOfFile")
#include "iostream"
#include <icrsint.h>
#include <vector>
int j;
_COM_SMARTPTR_TYPEDEF(IADORecordBinding, __uuidof(IADORecordBinding));
inline void TESTHR(HRESULT _hr) { if FAILED(_hr) _com_issue_error(_hr); }
class CCustomRs : public CADORecordBinding {
BEGIN_ADO_BINDING(CCustomRs)
ADO_VARIABLE_LENGTH_ENTRY2(1, adVarChar, symbol, sizeof(symbol), symbolStatus, false)
END_ADO_BINDING()
public:
CHAR symbol[6];
ULONG symbolStatus;
};
int main() {
::CoInitialize(NULL);
std::vector<char> tickers;
try {
char sym;
_RecordsetPtr pRs("ADODB.Recordset");
CCustomRs rs;
IADORecordBindingPtr picRs(pRs);
pRs->Open(L"SELECT symbol From Test", L"driver={sql server};SERVER=(local);Database=Securities;Trusted_Connection=Yes;",
adOpenForwardOnly, adLockReadOnly, adCmdText);
TESTHR(picRs->BindToRecordset(&rs));
while (!pRs->EndOfFile) {
// Process data in the CCustomRs C++ instance variables.
//Try to load field value into a vector
printf("Name = %s\n",
(rs.symbolStatus == adFldOK ? rs.symbol: "<Error>"));
//This is likely where my mistake is
sym = *rs.symbol;//only seems to store the first character at the pointer's address
// Move to the next row of the Recordset. Fields in the new row will
// automatically be placed in the CCustomRs C++ instance variables.
//Try to load field value into a vector
tickers.push_back (sym); //I can redefine everything as char*, but I end up with an array of a single memory location...
pRs->MoveNext();
}
}
catch (_com_error &e) {
printf("Error:\n");
printf("Code = %08lx\n", e.Error());
printf("Meaning = %s\n", e.ErrorMessage());
printf("Source = %s\n", (LPCSTR)e.Source());
printf("Description = %s\n", (LPCSTR)e.Description());
}
::CoUninitialize();
//This is me running tests to ensure the data passes as expected, which it doesn't
std::cin.get();
std::cout << "the vector contains: " << tickers.size() << '\n';
std::cin.get();
j = 0;
while (j < tickers.size()) {
std::cout << j << ' ' << tickers.size() << ' ' << tickers[j] << '\n';
j++;
}
std::cin.get();
}
Thank you for any guidance you can provide.
A std::vector<char*> does not work because the same buffer is used for all the records. So when pRs->MoveNext() is called, the new content is loaded into the buffer, overwriting the previous content.
You need to make a copy of the content.
I would suggest using a std::vector<std::string>:
std::vector<std::string> tickers;
...
tickers.push_back(std::string(rs.symbol));
Why you did not use std::string instead of std::vector?
To add characters use one of these member functions:
basic_string& append( const CharT* s ); - for cstrings,
basic_string& append( const CharT* s,size_type count ); - otherwise.
Read more at: http://en.cppreference.com/w/cpp/string/basic_string/append.
If you want a line breaks, simply append '\n' where you want it.

Format vector string on stdout

So for this program I'm writing for class I have to format a vector string into standard output. I get how to do it with just strings with the 'printf' function but I don't understand how to do it with this.
Here's what I got:
void put(vector<string> ngram){
while(!(cin.eof())){ ///experimental. trying to read text in string then output in stdout.
printf(ngram, i);///
Okay, I can't read a lot out of your question but from what I understood, you want to print a vector of strings to the standard output!? This would work like this:
void put(std::vector<std::string> ngram){
for(int i=0; i<ngram.size(); i++)
{
//for each element in ngram do:
//here you have multiple options:
//I prefer std::cout like this:
std::cout<<ngram.at(i)<<std::endl;
//or if you want to use printf:
printf(ngram.at(i).c_str());
}
//done...
return;
}
Is that what you wanted?
If you simply want each item on a single line:
void put(const std::vector<std::string> &ngram) {
// Use an iterator to go over each item in the vector and print it.
for (std::vector<std::string>::iterator it = ngram.begin(), end = ngram.end(); it != end; ++it) {
// It is an iterator that can be used to access each string in the vector.
// The std::string c_str() method is used to get a c-style character array that printf() can use.
printf("%s\n", it->c_str());
}
}