I am attempting to make a test program to see if an idea I had for getting and storing data from an SQLite3 database in a struct would work but I am running into some major problems with the code. While debugging I keep running into the error in the title. Here is the full text of the error window:
Debug Assertion Failed!
File: include\xstring
Line: 929
Expression: invalid null pointer
For information on how your program can cause an assertion
failure, see the Visual C++ documentation on asserts.
And here is the code, I will indicate which line the problem is with an arrow (<--; extra help see case 2 of the switch):
#include <iostream>
#include "data_placeholder.h"
#include "sqlite3.h"
#include <vector>
#include <conio.h>
#include <string>
#include <sstream>
using namespace std;
void openDB(sqlite3* dBase, int iID, string table, string operation, sqlite3_stmt* statement, vector<mission>& mission_1);
void createStatement(int iID, string table, string operation, sqlite3_stmt* statement, sqlite3* dBase, vector<mission>& mission_1);
void getMResults(string sqlStr, sqlite3_stmt* statement, sqlite3* dBase, vector<mission>& mission_1);
void returnMResult(vector<mission> mResults, vector<mission>& mission_1);
int main()
{
//Define Variables
vector<mission> mission_1;
sqlite3 *dBase;
sqlite3_stmt *statement;
int pInput;
mission_1.push_back(mission());
cout << "Input a number between 1 and 3" << endl;
cout << ">";
cin >> pInput;
cout << endl;
cout << endl;
openDB(dBase, pInput, "Mission_Data", "select from", statement, mission_1);
cout << mission_1.at(0).mName << ", " << mission_1.at(0).mDesc << ", " << mission_1.at(0).mCBELevel << ", " << mission_1.at(0).mSCReq << ", " << mission_1.at(0).mMWReq << ", " << mission_1.at(0).mTLimit << ", " << mission_1.at(0).mDifficulty << ", " << mission_1.at(0).mSector << ", " << mission_1.at(0).mSystem << ", " << mission_1.at(0).mTName << ", " << mission_1.at(0).mTSClass << ", " << mission_1.at(0).mBounty << ", " << mission_1.at(0).mXarn << ", " << mission_1.at(0).mRubies << ", " << mission_1.at(0).mDiamonds << ", " << mission_1.at(0).mDraconic << ", " << mission_1.at(0).mLithium << ", " << mission_1.at(0).mPlatinum << ", " << mission_1.at(0).mUranium << ", " << mission_1.at(0).mPlutonium << ", " << mission_1.at(0).mNWaste << ", " << mission_1.at(0).mCEXP << ", " << mission_1.at(0).mItem << ", " << mission_1.at(0).mType << ", " << endl;
_getch();
}
void openDB(sqlite3* dBase, int iID, string table, string operation, sqlite3_stmt* statement, vector<mission>& mission_1)
{
sqlite3_open("scDatabase.sqlite",&dBase);
createStatement(iID, table, operation, statement, dBase, mission_1);
}
void createStatement(int iID, string table, string operation, sqlite3_stmt* statement, sqlite3* dBase, vector<mission>& mission_1)
{
stringstream ss;
ss << iID;
string sID(ss.str());
string sqlStr = "Select * From " + table + " Where ID = " + sID;
getMResults(sqlStr, statement, dBase, mission_1);
}
void getMResults(string sqlStr, sqlite3_stmt* statement, sqlite3* dBase, vector<mission>& mission_1)
{
vector<mission> mResults;
mResults.push_back(mission());
if (sqlite3_prepare_v2(dBase, sqlStr.c_str(), sqlStr.size(), &statement, 0) == SQLITE_OK)
{
int cols;
int i;
cols = sqlite3_column_count(statement);
for (i =01; i <= cols; i++)
{
switch(i)
{
case 2:
mResults.at(0).mName = string((char*)sqlite3_column_text(statement,i)); //<-- Here is the line the assert fail happens
break;
/*
case 3:
mResults.at(0).mDesc = string(reinterpret_cast<const char*>(sqlite3_column_text(statement,i)));
break;
case 4:
mResults.at(0).mCBELevel = sqlite3_column_int(statement,i);
break;
case 5:
mResults.at(0).mSCReq = string(reinterpret_cast<const char*>(sqlite3_column_text(statement,i)));
break;
case 6:
mResults.at(0).mMWReq = string(reinterpret_cast<const char*>(sqlite3_column_text(statement,i)));
break;
case 7:
mResults.at(0).mTLimit = sqlite3_column_int(statement,i);
break;
case 8:
mResults.at(0).mDifficulty = string(reinterpret_cast<const char*>(sqlite3_column_text(statement,i)));
break;
case 9:
mResults.at(0).mSector = string(reinterpret_cast<const char*>(sqlite3_column_text(statement,i)));
break;
case 10:
mResults.at(0).mSystem = string(reinterpret_cast<const char*>(sqlite3_column_text(statement,i)));
break;
case 11:
mResults.at(0).mTName = string(reinterpret_cast<const char*>(sqlite3_column_text(statement,i)));
break;
case 12:
mResults.at(0).mTSClass = string(reinterpret_cast<const char*>(sqlite3_column_text(statement,i)));
break;
case 13:
mResults.at(0).mBounty = sqlite3_column_int(statement,i);
break;
case 14:
mResults.at(0).mXarn = sqlite3_column_int(statement,i);
break;
case 15:
mResults.at(0).mRubies = sqlite3_column_int(statement,i);
break;
case 16:
mResults.at(0).mDiamonds = sqlite3_column_int(statement,i);
break;
case 17:
mResults.at(0).mDraconic = sqlite3_column_int(statement,i);
break;
case 18:
mResults.at(0).mLithium = sqlite3_column_int(statement,i);
break;
case 19:
mResults.at(0).mPlatinum = sqlite3_column_int(statement,i);
break;
case 20:
mResults.at(0).mNWaste = sqlite3_column_int(statement,i);
break;
case 21:
mResults.at(0).mCEXP = sqlite3_column_int(statement,i);
break;
case 22:
mResults.at(0).mItem = sqlite3_column_int(statement,i);
break;
case 23:
mResults.at(0).mType = string(reinterpret_cast<const char*>(sqlite3_column_text(statement,i)));
break;
*/
default:
break;
}
}
}
else
{
cout << "something is wrong" << endl;
}
returnMResult(mResults, mission_1);
}
void returnMResult(vector<mission>mResults, vector<mission>& mission_1)
{
mission_1.at(0) = mResults.at(0);
}
The error occurs instantly when the code hits this line on the first iteration through the for loop. There are no compiler errors and I have also tried collapsing the first three functions into one function in case the database and statement pointers were not being passed correctly; same problem.
Edit 2: I have whittled down where the problem is. It has to do with my vector of structs. I took the database query out of the link where I set to mResults.at(0).mName and then added a cast for the const unsigned char to string but the assert failure still happens.
Edit 3: After looking at some code I had done earlier in the the year I have figure out what was going on, at least for the SQLite query. You have to called step in order for the query to actually be carried out. Since I had not done so the pointer was always returning as invalid since there was no row loaded and thus no columns to query. Nothing wrong with my vector.
problematic line:
sqlite3_column_text(statement,i)
will return undefined value, because when i is equal to size, it will go out of bounds.
sqlite3_column_text function iCol parameter is C-style index, that starts with zero, while you try to get column index sql-style starting 1. Fix the loop to be:
for (i = 0; i < cols; i++)
I figured out the problem. I looked back at some code I had made around June that I had working and started comparing it to the code I posted above. In the places where there were differences I copied the code over to the new test and I finally got it to work.
The problem was that I was not calling sqlite3_step so the database was not being queried. This lead to no row being loaded and so no columns to query, thus an invalid pointer returned by the sqlite3_column_text. However Iuri also had a point in that I was iterating through in a way that, if the error I was getting was fixed, would have started going out of bounds, I had not been able to get the code to go that far yet so a bit of preemptive debugging.
I also added checks in for some basic defensive coding so that the test application fails save if there is either not a row loaded or an invalid pointer so that the runtime does not kick the program out.
Related
I want to write a C++ program that converts MIDI note number to name and octave using the switch statements ?
I am having a few errors in my code the code should print out a Note name and octave number (eg. input -> 24 ; output -> C1).
https://www.inspiredacoustics.com/en/MIDI_note_numbers_and_center_frequencies
int main() {
int mi;
cout <<"MIDI value: " << std::endl;
cin >> mi;
int oct_v;
oct_v = (mi/12) - 1;
string notes;
notes = "C C# D D# E F F# G G# A A# B";
string nt;
nt = notes.substr((mi % 12) * 2 , (mi % 12) * 2 +2);
cout <<"Note name " << nt << oct_v;
return 0;
}
The code is not perfect and I am having doubts about what should I put into switch statements.
First some hints:
"I want to write a C++ script"
The term script is typically used for interpreted languages like shell scripts. As c++ is a compiled language we don't name them script. It is a c++ program or c++ source code.
" what should I put into switch statements."
You don't use any switch statement! You pick some substring from a string. That has nothing to do with a switch statement!
What is wrong with your code:
Your calculation for picking the sub string is quite fine, but you assume that your notes inside your string are always have a length of 2 but you use 2 chars for e.g. "C " or 3 chars for "A# ". You simply should write your string with 2 letters per note as:
std::string notes = "C C#D D#E F F#G G#A A#B";
The second parameter of substr is the length and not the end position.
In addition: You should not use using namespace std;
Here are some alternative solutions also with switch statement.
int main() {
int mi;
std::cout <<"MIDI value: " << std::endl;
std::cin >> mi;
unsigned int oct_v = mi/12 -1;
// variant with array
std::string notes[]={"C","C#","D","D#","E","F","F#","G","G#","A","A#","B"};
std::string nt = notes[mi%12];
// variant with substring ( from your code, but fixed )
std::string notes2= "C C#D D#E F F#G G#A A#B";
std::string nt2 = notes2.substr((mi % 12) * 2 , 2);
std::string nt3;
// with switch
switch ( mi%12 )
{
case 0: nt3 = "C"; break;
case 1: nt3 = "C#"; break;
case 2: nt3 = "D"; break;
case 3: nt3 = "D#"; break;
case 4: nt3 = "E"; break;
case 5: nt3 = "F"; break;
case 6: nt3 = "F#"; break;
case 7: nt3 = "G"; break;
case 8: nt3 = "G#"; break;
case 9: nt3 = "A"; break;
case 10: nt3 = "A#"; break;
case 11: nt3 = "B"; break;
}
std::cout <<"Note name " << nt << ":" << oct_v << std::endl;
std::cout <<"Note name2 " << nt2 << ":" << oct_v << std::endl;
std::cout <<"Note name3 " << nt3 << ":" << oct_v << std::endl;
return 0;
}
I think you'd better use a table of char arrays to store the notes. I propose the following code :
#include <iostream>
#include <string>
const char notes[12][4]={"C","C#","D","D#","E","F","F#","G","G#","A","A#","B"};
void midiToNote(int midi, int& octave,std::string& note)
{
octave = ( (midi-12)/12 );
note = std::string(notes[midi%12]);
}
int main()
{
int midi;
int oct;
std::string name;
midi = 29;
midiToNote(midi,oct,name);
std::cout << midi <<" is " <<name << oct<< std::endl;
midi = 51;
midiToNote(midi,oct,name);
std::cout << midi <<" is "<< name << oct << std::endl;
return 0;
}
Hope this helps.
The function prints the addresses of each memory location of the dynamic array. Is this the right way?
int main()
{
char str[] = "This is a test";
printAddresses(str, strlen(str));
}
template <class type>
void printAddresses(type *item, int n)
{
cout << "Printing Addresses..." << endl;
for (int i = 0; i < n; i++)
{
cout << "Index " << i << ": " << ((&item) + i) << endl;
}
}
I've also heard that I should use:
cout << "Index " << i << ": " << (void*) &item[i] << endl;
but that gives me different memory address. I'm not sure which one is right.
The correct address is the one you obtain when printing (void*)&item[i].
item is already a pointer; so is &item[i]. You are interested in printing the value of this pointer, you need to cast it to void* before calling << on it.
When you print ((&item) + i) you are making an extra level of indirection (&item is a pointer-to-pointer), so you print the address of item-the-pointer, not the address of what item is pointing to.
Note:: Starting with C++11 you can use std::addressof function in place of operator & for better readability and to avoid potential issues when T provides an overload for operator &:
cout << "Index " << i << ": " << std::addressof(item[i]) << endl;
Run this:
#include <iostream>
#include <cstring>
using namespace std;
template <class type>
void printAddresses(type *item, int n)
{
cout << "Printing Addresses..." << endl;
for (int i = 0; i < n; i++)
{
cout << "Index " << i << ": " << ((&item) + i) << endl;
cout << "Index2 " << i << ": " << (void*) &item[i] << endl;
}
}
int main()
{
char str[] = "This is a test";
printAddresses(str, strlen(str));
}
which in my machine prints:
gsamaras#gsamaras-A15:~$ g++ -Wall main.cpp
gsamaras#gsamaras-A15:~$ ./a.out
Printing Addresses...
Index 0: 0x7ffd5c9ead58
Index2 0: 0x7ffd5c9ead90
Index 1: 0x7ffd5c9ead60
Index2 1: 0x7ffd5c9ead91
Index 2: 0x7ffd5c9ead68
Index2 2: 0x7ffd5c9ead92
Index 3: 0x7ffd5c9ead70
Index2 3: 0x7ffd5c9ead93
Index 4: 0x7ffd5c9ead78
Index2 4: 0x7ffd5c9ead94
Index 5: 0x7ffd5c9ead80
Index2 5: 0x7ffd5c9ead95
Index 6: 0x7ffd5c9ead88
Index2 6: 0x7ffd5c9ead96
Index 7: 0x7ffd5c9ead90
Index2 7: 0x7ffd5c9ead97
Index 8: 0x7ffd5c9ead98
Index2 8: 0x7ffd5c9ead98
Index 9: 0x7ffd5c9eada0
Index2 9: 0x7ffd5c9ead99
Index 10: 0x7ffd5c9eada8
Index2 10: 0x7ffd5c9ead9a
Index 11: 0x7ffd5c9eadb0
Index2 11: 0x7ffd5c9ead9b
Index 12: 0x7ffd5c9eadb8
Index2 12: 0x7ffd5c9ead9c
Index 13: 0x7ffd5c9eadc0
Index2 13: 0x7ffd5c9ead9d
Now think what sequence you expect to see for stored chars? You expect every character to be adjacent to the previous one (of course) and every one to take 1 memory cell. That should tell you that:
(void*) &item[i]
is the right thing to do.
Also notice that zmbq's comment, about using a debugger to find out makes sense too.
Finally, I would advice you to read: Printing array element memory adresses C and C++, why different output?
A possible way could be to use the C-style printf with %p. So include <cstdio> then try for example:
const char *sp = "abcde" + 2; // some computation giving a string address
printf("sp=%p ('%s')\n", sp, sp);
Alternatively, cast to (void*) and use usual
std::cout << "sp at " << (void*)sp << std::endl;
The reason you get a different memory address is because your code is wrong.
void printAddresses(type *item, int n)
item is a pointer parameter to your printAddresses template function. So, in the following expression:
cout << "Index " << i << ": " << ((&item) + i) << endl;
Therefore:
&item
becomes the address of the parameter to your template function, and not the address of the array.
This is why:
(&item)+i
is wrong, and is utterly meaningless. The address of the parameter to your template function is not really very useful, here.
(void*) &item[i]
Is the correct answer.
I need to write a program which programmatically changes the Landscape mode to Portrait of a touchscreen in Windows 7. The resolution is 1920 x 1080 and I thought I could switch the 1920 with the 1080 and use ChangeDisplaySettings or ChangeDisplaySettingsEx to make the change. but it doesn't work.
Windows CE has some sort of rotate feature, so I tried that. as in:
devmode.dmFields = DM_DISPLAYORIENTATION;
devmode.dmDisplayOrientation = DMDO_90;
ChangeDisplaySettingsEx(NULL,&devmode,NULL,CDS_RESET,NULL);
But that didn't work on a normal test desktop PC.
I can do this through Control Panel, Display, Screen Resolution, choose Portrait, so should I not be able to do via Windows API?
How can I make this change in code?
EDIT
I tried this code, but I get DISP_CHANGE_BADMODE returned by ChangeDisplaySettings.
#include <Windows.h>
#include <iostream>
int main() {
DEVMODE dm;
// initialize the DEVMODE structure
ZeroMemory(&dm, sizeof(dm));
dm.dmSize = sizeof(dm);
if (0 != EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dm))
{
std::cout << "Orientation\n";
switch(dm.dmDisplayOrientation) {
case DMDO_DEFAULT: std::cout << "DMDO_DEFAULT\n"; break;
case DMDO_90: std::cout << "DMDO_90\n"; break;
case DMDO_180: std::cout << "DMDO_180\n"; break;
case DMDO_270: std::cout << "DMDO_270\n"; break;
}
std::cout << "Panning height: " << dm.dmPanningHeight << '\n'
<< "Panning width: " << dm.dmPanningWidth << '\n';
std::cout << "Colour resolution: " << dm.dmBitsPerPel << " bits per pixel\n";
std::cout << "Height in pixels: " << dm.dmPelsHeight << '\n';
std::cout << "Width in pixels: " << dm.dmPelsWidth << '\n';
if(dm.dmPelsHeight > dm.dmPelsWidth) {
std::cout << "Screen should be rotated 90 degrees\n";
std::cout << "Do you want to rotate display 90 degrees? (y or n)\n";
char ch;
std::cin >> ch;
if(ch == 'y') {
// swap height and width
DWORD tmp = dm.dmPelsHeight;
dm.dmPelsHeight = dm.dmPelsWidth;
dm.dmPelsWidth = tmp;
dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
// determine new orientation
switch (dm.dmDisplayOrientation)
{
case DMDO_DEFAULT:
dm.dmDisplayOrientation = DMDO_270;
break;
case DMDO_270:
dm.dmDisplayOrientation = DMDO_180;
break;
case DMDO_180:
dm.dmDisplayOrientation = DMDO_90;
break;
case DMDO_90:
dm.dmDisplayOrientation = DMDO_DEFAULT;
break;
default:
// unknown orientation value
// add exception handling here
break;
}
LONG ret = ChangeDisplaySettings(&dm, CDS_TEST); //0);
std::cout << "ChangeDisplaySettings returned " << ret << '\n';
switch(ret) {
case DISP_CHANGE_SUCCESSFUL: std::cout << "display successfully changed\n"; break;
case DISP_CHANGE_BADDUALVIEW: std::cout << "The settings change was unsuccessful because the system is DualView capable\n"; break;
case DISP_CHANGE_BADFLAGS: std::cout << "An invalid set of flags was passed in.\n"; break;
case DISP_CHANGE_BADMODE: std::cout << "The graphics mode is not supported.\n"; break;
case DISP_CHANGE_BADPARAM: std::cout << "An invalid parameter was passed in. This can include an invalid flag or combination of flags.\n"; break;
case DISP_CHANGE_FAILED: std::cout << "The display driver failed the specified graphics mode.\n"; break;
case DISP_CHANGE_NOTUPDATED: std::cout << "Unable to write settings to the registry.\n"; break;
case DISP_CHANGE_RESTART: std::cout << "The computer must be restarted for the graphics mode to work.\n"; break;
}
}
}
else
std::cout << "Screen orientation is just fine\n";
}
}
I saw an article on the web indicating that possibly it couldn't be done. But this code works.
#include <Windows.h>
#include <iostream>
int main(int argc, char* argv[]) {
DEVMODE dm;
// initialize the DEVMODE structure
ZeroMemory(&dm, sizeof(dm));
dm.dmSize = sizeof(dm);
// only change first/default display (index=0)
if (0 != EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dm))
{
std::cout << "Current orientation\n";
switch(dm.dmDisplayOrientation) {
case DMDO_DEFAULT: std::cout << "DMDO_DEFAULT\n"; break;
case DMDO_90: std::cout << "DMDO_90\n"; break;
case DMDO_180: std::cout << "DMDO_180\n"; break;
case DMDO_270: std::cout << "DMDO_270\n"; break;
}
std::cout << "Panning height: " << dm.dmPanningHeight << '\n'
<< "Panning width: " << dm.dmPanningWidth << '\n';
std::cout << "Colour resolution: " << dm.dmBitsPerPel << " bits per pixel\n";
std::cout << "Height in pixels: " << dm.dmPelsHeight << '\n';
std::cout << "Width in pixels: " << dm.dmPelsWidth << '\n';
if(argc != 2) {
std::cout << "Usage: rotate_screen <angle>. Angle values: 0, 90, 180, 270. Angles are rotation clockwise. Use 0 to revert back\n";
exit(0);
}
// parse parameter
int rotate = atoi(argv[1]); // should do something better and safer here
if(rotate != 0 && rotate != 90 && rotate != 180 && rotate != 270) {
std::cout << "incorrect rotation selected\n";
}
else {
// swap height and width
DWORD tmp = dm.dmPelsHeight;
dm.dmPelsHeight = dm.dmPelsWidth;
dm.dmPelsWidth = tmp;
// select fields which have changed
dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYORIENTATION;
// set angle
switch(rotate) {
case 0: dm.dmDisplayOrientation = DMDO_DEFAULT; break;
case 90: dm.dmDisplayOrientation = DMDO_90; break;
case 180: dm.dmDisplayOrientation = DMDO_180; break;
case 270: dm.dmDisplayOrientation = DMDO_270; break;
default:
std::cout << "Something went wrong, aborting\n";
exit(0);
}
LONG ret = ChangeDisplaySettingsEx(NULL, &dm, NULL, 0, NULL); //CDS_RESET, NULL); //0);
std::cout << "ChangeDisplaySettingsEx returned " << ret << '\n';
switch(ret) {
case DISP_CHANGE_SUCCESSFUL: std::cout << "display successfully changed\n"; break;
case DISP_CHANGE_BADDUALVIEW:
std::cout << "The settings change was unsuccessful because the system is DualView capable\n";
break;
case DISP_CHANGE_BADFLAGS: std::cout << "An invalid set of flags was passed in.\n"; break;
case DISP_CHANGE_BADMODE: std::cout << "The graphics mode is not supported.\n"; break;
case DISP_CHANGE_BADPARAM: std::cout << "An invalid parameter was passed in. This can include an invalid flag or combination of flags.\n"; break;
case DISP_CHANGE_FAILED: std::cout << "The display driver failed the specified graphics mode.\n"; break;
case DISP_CHANGE_NOTUPDATED: std::cout << "Unable to write settings to the registry.\n"; break;
case DISP_CHANGE_RESTART: std::cout << "The computer must be restarted for the graphics mode to work.\n"; break;
}
}
} // enum worked
}
I have started working with C++ libcql library for Cassandra.. I am trying to retrieve data from Cassandra using C++ with libcql library..
Whenever I go on the command line using cqlsh and do select like this -
select records from profile_user where user_id = '1';
I always get the below output on the cql command line and in which records column is actually a map in which key is e1 and value is HELLO. In the same way key is e2 and value is HELLO again.. When I created the table in CQL, I created records as the map as I was using collection feature of CQL..
records
--------------------------------
{'e1': 'HELLO', 'e2': 'HELLO'}
Now Coming to C++ world-
Now I am trying to retrieve the same thing from the C++ libcql library... I will be running the same above select query in C++ and I want to return a map which will have e1, e2 as the key and HELLO as there value inside that map... It is possible to do it in C++?
/**
* This method will retrieve the data from Cassandra..
* And then call print_rows method to print it out on the console
*/
void get_attributes(string id){
try{
// some code
//Connection open
connection_open();
execute_query("USE testks;");
//this will give me the result back of the select query
cql_result_t& result = execute_query("select * from profile_user where key ='"+id+"';");
// and this is printing it out on the console
print_rows(result);
// some code
} catch (int e){
// some code here
}
}
Below is the method which will print out the results on the console after running my C++ program -
/**
* This method prints out the result on the console.. *
*
*/
void print_rows(cql::cql_result_t& result) {
while (result.next()) {
for (size_t i = 0; i < result.column_count(); ++i) {
cql::cql_byte_t* data = NULL;
cql::cql_int_t size = 0;
result.get_data(i, &data, size);
std::cout.write(reinterpret_cast<char*>(data), size);
std::cout << " | ";
}
std::cout << std::endl;
}
}
The result that I see on the console after running my above C++ program is something like this -
e1HELLOe2HELLO |
But what I am looking for is - Store the result in a Map in C++, in such a way such that key should be e1 and e2 in the Map.. And the value for them should be HELLO in the same Map... And then iterate the Map and print out the result in C++? Is this possible to do with the current code I have?
If yes, can anyone provide a simple example on this? Thanks...
It is basically a C++ question I guess.. Just retrieve the data and put it into the Map... But the problem I am facing is my background is totally in Java so having little bit hard time to figure out how to do that...
I don't know libcql and I failed to locate any documentation. Looking at the header for cql_result_t indicates that there are functions to determine how many columns there are and how to access them. From the looks of it, you merely copied the demo example which doesn't seem to be a particular good demo. I would start off with refining the print_result() function to look something like the below and see what I'd get. My guess is that you get a "map" type from your query and you'll need to see how to extract and use the corresponding representation by digging through their headers (unless there is somewhere some documentation). The code below mere extracts a few types and mostly prints that it needs to deal with processing the respective type (assuming it actually compiles):
void print_result(cql::cql_result_t& result)
{
std::size_t const columns(result.column_count());
while (result.next()) {
for (std::size_t column(0); column != columns; ++column) {
cql::cql_column_type_enum type;
if (result.column_type(column, type)) {
switch (type) {
case cql::CQL_COLUMN_TYPE_CUSTOM:
std::cout << "todo: process custom type\n";
break;
case cql::CQL_COLUMN_TYPE_ASCII:
std::cout << "todo: process ascii type\n";
break;
case cql::CQL_COLUMN_TYPE_BIGINT:
std::cout << "todo: process bigint type\n";
break;
case cql::CQL_COLUMN_TYPE_BLOB:
std::cout << "todo: process blob type\n";
break;
case cql::CQL_COLUMN_TYPE_BOOLEAN:
std::cout << "todo: process boolean type\n";
break;
case cql::CQL_COLUMN_TYPE_COUNTER:
std::cout << "todo: process counter type\n";
break;
case cql::CQL_COLUMN_TYPE_DECIMAL:
std::cout << "todo: process decimal type\n";
break;
case cql::CQL_COLUMN_TYPE_DOUBLE: {
double value;
if (result.get_double(column, value)) {
std::cout << "column=" << column << " "
<< "double=" << value << "\n";
}
else {
std::cout << "failed to extract double for column "
<< column << "\n";
}
break;
case cql::CQL_COLUMN_TYPE_FLOAT: {
float value;
if (result.get_float(column, value)) {
std::cout << "column=" << column << " "
<< "float=" << value << "\n";
}
else {
std::cout << "failed to extract float for column "
<< column << "\n";
}
break;
case cql::CQL_COLUMN_TYPE_INT: {
int value;
if (result.get_int(column, value)) {
std::cout << "column=" << column << " "
<< "int=" << value << "\n";
}
else {
std::cout << "failed to extract int for column "
<< column << "\n";
}
break;
case cql::CQL_COLUMN_TYPE_TEXT: {
std::string value;
if (result.get_string(column, value)) {
std::cout << "column=" << column << " "
<< "text='" << value << "'\n";
}
else {
std::cout << "failed to extract text for column "
<< column << "\n";
}
break;
case cql::CQL_COLUMN_TYPE_TIMESTAMP:
std::cout << "todo: process timestamp type\n";
break;
case cql::CQL_COLUMN_TYPE_UUID:
std::cout << "todo: process uiid type\n";
break;
case cql::CQL_COLUMN_TYPE_VARCHAR:
std::cout << "todo: process varchar type\n";
break;
case cql::CQL_COLUMN_TYPE_VARINT:
std::cout << "todo: process varint type\n";
break;
case cql::CQL_COLUMN_TYPE_TIMEUUID:
std::cout << "todo: process timeuuid type\n";
break;
case cql::CQL_COLUMN_TYPE_INET:
std::cout << "todo: process inet type\n";
break;
case cql::CQL_COLUMN_TYPE_LIST:
std::cout << "todo: process list type\n";
break;
case cql::CQL_COLUMN_TYPE_MAP:
std::cout << "todo: process map type\n";
break;
case cql::CQL_COLUMN_TYPE_SET:
std::cout << "todo: process set type\n";
break;
}
}
}
}
}
cql_result_t has a method get_map. Use get_map instead of get_data:
cql::cql_result_t *r;
cql::cql_map_t *props = 0;
if (!r->get_map("records", &props)) {
delete props;
// throw an error
}
std::auto_ptr<cql::cql_map_t> p(props);
std::map<std::string, std::string> m;
for (std::size_t i = 0; i < p->size(); ++i) {
std::string key;
if (!p->get_key_string(i, key))
// throw an error
std::string value;
if (!p->get_value_string(i, value))
// throw an error
m.insert(std::make_pair(key, value));
}
Attempting to use MsiEnumRelatedProducts with various input is constantly returning only ERROR_INVALID_PARAMETERS for me. The documentation doesn't give any details on what the source of the invalid parameter could be but I've tried many different options. Currently I have this code below to demonstrate the problem. Replace the with a valid upgrade guid.
int _tmain(int argc, _TCHAR* argv[])
{
const wchar_t* upgrade = L"812D9038-YOUR-GUID-B2EB-64F4E0B3FB3D";
wchar_t product[39];
DWORD index = 0;
switch (MsiEnumRelatedProducts(upgrade, 0, index++, product)) {
case ERROR_SUCCESS:
wcout << L"ERROR_SUCCESS" << endl;
break;
case ERROR_NO_MORE_ITEMS:
wcout << L"ERROR_NO_MORE_ITEMS" << endl;
break;
case ERROR_BAD_CONFIGURATION:
wcout << L"ERROR_BAD_CONFIGURATION" << endl;
break;
case ERROR_INVALID_PARAMETER:
wcout << L"ERROR_INVALID_PARAMETER" << endl;
break;
case ERROR_NOT_ENOUGH_MEMORY:
wcout << L"ERROR_NOT_ENOUGH_MEMORY" << endl;
break;
default:
wcout << L"DEFAULT" << endl;
break;
}
}
Try enclosing your upgrade code in curly brackets so it looks like {GUID}.