I am makinga code to send a query for my SQLlite database, but I just can't find a way to add a variable to the Char * variable that is being used as the query. the query and the variable that I want to add are declared like this:
String p = "10004F1F7";
char *sql = "SELECT * from TABELTAGGEGEVENS WHERE ID =" + p;
the error i get is this: error: invalid user-defined conversion from 'Arp::BasicString' to 'char*' [-fpermissive]
many thanks.
This doesn't work because in C++ the '+' operator on char pointers doesn't concatenate the strings.
One solution would be to make the literal value a String as well:
String p = "10004F1F7";
String query = "SELECT * from TABELTAGGEGEVENS WHERE ID =";
You can then concatenate like this: + operator: p + operator
I don't know the particular library you appear to be working with (Arp::BasicString), so I don't know how you'd convert that into a char *.
With std::string you can simply call c_str on the result.
Another and probably better solution is to use formatters.
For reference see:
https://www.thecodingdelight.com/string-cplusplus/
How to concatenate two strings in C++?
https://learn.microsoft.com/en-gb/cpp/text/string-and-i-o-formatting-modern-cpp?view=vs-2019
String p = "10004F1F7";
char *sql = "SELECT * from TABELTAGGEGEVENS WHERE ID =" + p;
You can handle the Arp::BasicString almost like an std::string.
Looking through the headers you will find a Method named "CStr()".
Like that you should be able to do something like this:
String P = "10004F1F7";
String Query = "SELECT * from TABELTAGGEGEVENS WHERE ID =" + p;
char *sql = Query.CStr()
The only hit on Google for Arp::BasicString was used in the SDK for a software company, PLCnext. A little bit of riffling through I found a header file BasicString.hxx and inside a prototype for BasicString class template. There the baseString data structure is private.
I had to come up with this (rather low-level) workaround, compiling with PLCnext software succeeded and passed tests when adjusted for std::string):
String p = "10004F1F7";
const char* CMD_SEQUENCE = "SELECT * from TABELTAGGEGEVENS WHERE ID =";
const int CMD_LENGTH = 41;
// allocate and assign memory for the static characters in the command
char *sql = (char *)malloc(CMD_LENGTH * sizeof(char));
memcpy(sql, CMD_SEQUENCE, CMD_LENGTH);
// iterate through all chars in String p
// resizing the memory buffer as needed and adding ith char to the end
for (int i=0; i<p.Size();i++){
sql = (char*)realloc(sql, (CMD_LENGTH + i) * sizeof(char));
// destination is the ith memory cell past the cmd sequence
int destIdx = CMD_LENGTH + i;
// copy 1 char at a time; ith char in p
memcpy( &sql[destIdx], &p.At(i), sizeof(char) );
}
Related
I have two prefilled arrays as follows:
char *query1;
char *query2;
and one array that is filled by the user.
char *username;
what i want to do is combine these into one for example
char *SQLquery;
i have try'd working with strlen and strcat in this way:
if (query==3) {
char *query1 = "SELECT * FROM Users WHERE UserName='";
char *username = "DEFSER"; //prefilled this for test purpuse
char *query2 = "'";
SQLquery = new char[strlen(query1)+strlen(username)+strlen(query2)+1];
*SQLquery = '/0';
strcat(SQLquery,query1);
strcat(SQLquery,username);
strcat(SQLquery,query2);
strcpy(laArray[0][2],SQLquery);
}
there is no compiler error however when i print my laArray[0][2] or my SQLquery it returns 0.
did i do something wrong?
If you plan to use C, use the following
const char query1[] = "SELECT * FROM Users WHERE UserName='";
char *username = "DEFSER";
SQLquery = malloc(strlen(query1) + strlen(username) + strlen(query2) + 1 + 1);
sprintf("%s%s'", query1, username);
laArray[0][2] = SQLquery; /* Based on comments, I believe this is what you want to do */
...
/* Do whatever you want to do with laArray */
...
laArray[0][2] = NULL;
free(SQLquery);
SQLquery = NULL;
If you plan to use C++, use the std::string like following
std::string SQLquery = "SELECT * FROM Users WHERE UserName='";
std::string username = "DEFSER";
SQLquery += username;
SQLquery += '\'';
laArray[0][2] = SQLquery; /* if laArray is 2D array of string, const_cast<char *>(SQLquery.c_str()) if it contains pointers */
/* Do whatever you want to do with laArray */
...
I understand BLUEPIXY has already spotted the real issue, but just to add another option, you could use sprintf_s(...) to do your string concatenation and potentially provide some more control over formatting (should that be required).
For the suggestions of using std::string (if in C++): you'll need to use the c_str() method to access the char* from std::string if you need to convert back to a old-style C char string.
Good luck.
It is impossible to use direct '+' concatenation in C. In C++ you could overload an operator, but it would be much smarter to use std::string, which already overloads the operator+ and then extract c_str() out of it to get const char *.
I'm making a lexical analyzer and this is a function out of the whole thing. This function takes as argument a char, c, and appends this char to the end of an already defined char* array (yytext). It then increments the length of the text (yylen).
I keep getting segfaults on the shown line when it enters this function. What am I doing wrong here? Thanks.
BTW: can't use the strncpy/strcat, etc. (although if you want you can show me that implementation too)
This is my code:
extern char *yytext;
extern int *yylen;
void consume(char c){
int s = *yylen + 1; //gets yylen (length of yytext) and adds 1
//now seg faults here
char* newArray = new char[s];
for (int i = 0;i < s - 1;i++){
newArray[i] = yytext[i]; //copy all chars from existing yytext into newArray
}
newArray[s-1] = c; //append c to the end of newArray
for (int i = 0;i < s;i++){ //copy all chars + c back to yytext
yytext[i] = newArray[i];
}
yylen++;
}
You have
extern int *yylen;
but try to use it like so:
int s = (int)yylen + 1;
If the variable is an int *, use it like an int * and dereference to get the int. If it is supposed to be an int, then declare it as such.
That can t work:
int s = (int)yylen + 1; //gets yylen (length of yytext) and adds 1
char newArray[s];
use malloc or a big enought buffer
char * newarray=(char*)(malloc(s));
Every C-style string should be null-terminated. From your description it seems you need to append the character at c. So, you need 2 extra locations ( one is for appending the character and other for null-terminator ).
Next, yylen is of type int *. You need to dereference it to get the length (assuming it is pointing to valid memory location ). So, try -
int s = *yylen + 2;
I don't see the need of temporary array but there might be a reason why you are doing it. Now,
yytext[i] = newArray[i]; //seg faults here
you have to check if yytext is pointing to a valid write memory location. If yes, then is it long enough to fill the appending character plus null terminator.
But I would recommend using std::string than working with character arrays. Using it would be a one liner to solve the problem.
So, thanks for all the help guys, I am just have one last problem, I am putting the website source in a char var, and then reading the product title (I have gotten that), however it only works if I take part of the source, or only the html from one of the featured products on neweggs page. I think the program is crashing, because it doesnt know which title to pick when I need to get all three titles and put them into an array. Any ideas? Thanks. Here is the parser code:
http://paste2.org/p/809045
Any solution is greatly appreciated.
/**
* num_to_next -
* takes in a pointer to a string and then counts how many
* characters are until the next occurance of the specified character
* #ptr: the pointer to a string in which to search
* #c: char delimiter to search until
**/
int num_to_next(char *ptr, char c)
{
unsigned int i = 0;
for (i = 0; i < strlen(ptr); i++) {
if (ptr[i] == c) {
return i;
}
}
return -1;
}
/**
* space_to_underscore -
* this should help to alleviate some problems when dealing with
* filepaths that have spaces in them (basically just changes all
* spaces in a string to underscores)
* #string: the string to convert, yo
**/
int space_to_underscore(char *string)
{
for (unsigned int i = 0; i < strlen(string); i++) {
if (string[i] == ' ') {
string[i] = '_';
}
}
return 0;
}
char *file_name = (char *)malloc(sizeof(char *)); // allocate memory for where the app name will be stored
memset(file_name, 0, sizeof(file_name)); // zero the memory
char td_one[] = "<ul class="featureCells"><li id="ItemCell" class="cell">";
char *pstr = strstr(buffer, td_one) + strlen(td_one) + 6; // buffer is the source
char *poop = pstr + num_to_next(pstr, '>') + 1;
int blah = num_to_next(poop, '<');
strncpy(file_name, poop, blah);
// null terminate the string //
file_name[blah] = '\0';
space_to_underscore(file_name);
MessageBox(NULL, file_name, "Product Name", MB_OK);
free(file_name);
I'm not sure if these are your only problems, but...
First, you can't do char* filename = (char*)malloc(sizeof(char*)) (well, you can, but that's not what you actually want from your app).
What you want to have is char* filename = (char*)malloc(SIZE_OF_YOUR_STRING * sizeof(char));, so you can't allocate just an abstract buffer for your string and you have to know the expected size of it. Actually, here you don't have to write sizeof(char) because it always equals 1, but this sometimes this way of writing the code can help you(or somebody else) to understand that this block would store a string as array of chars).
Another example on the same problem: char* filename = (char*)malloc(65); - is ok and will allocate a block of memory to store 65 char symbols.
If we go further (where you're doing the memset), char* is a plain pointer and sizeof(filename) in your case would return the size of your pointer, but not your string. What you should write here is strlen(filename).
When I convert char* to an string it gives an bad memory allocation error in 'new.cpp' . I used following method to convert char* called 'strData' and 'strOrg' to string.
const char* strData = dt.data();
int length2 = dt.length();
string s1(strData);
First time it work without any problem. But in the second convertion it gives above error. When I swap the two conversion in the order, it give the error always in the second conversion regardless of the char* I am converting. Whole code is shown in the following.
mysqlpp::Query query = conn.query("SELECT data,origin from image where id =2");
mysqlpp::UseQueryResult res = query.use();
mysqlpp::Row eee= res.fetch_row();
mysqlpp::Row::reference dt = eee.at(0);
mysqlpp::Row::reference org = eee.at(1);
const char* strData = dt.data();
int length2 = dt.length();
string s1(strData);
istringstream is1(s1);
char * imgData = new char;
is1.read(reinterpret_cast<char *> (imgData), length2);
delete [] strData;
const char* strOrg = org.data();
int length3 = org.length();
string s2(strOrg);
istringstream is2(s2);
char * imgOrg = new char;
is2.read(reinterpret_cast<char *> (imgOrg), length3);
delete [] strOrg;
This where the error comes from
void *__CRTDECL operator new(size_t size) _THROW1(_STD bad_alloc)
{
void *p;
while ((p = malloc(size)) == 0)
if (_callnewh(size) == 0)
{ // report no memory
static const std::bad_alloc nomem;
_RAISE(nomem);
}
return (p);
}
How can I solve this?
Instead of
char * imgData = new char;
is1.read(reinterpret_cast<char *> (imgData), length2);
try
char * imgData = new char[length2];
is1.read(reinterpret_cast<char *> (imgData), length2);
When you read data from an istringstream using read, the buffer you provide must have enough space to hold the results!
If you call new char; you get space for one char. Use new char[n]; to get space for n.
delete [] strData;
This is bad. The line above it probably is also but I know this one is.
You're deleting dt.data(). If I recall correctly this is guaranteed to be the internal buffer of the string.
This may or may not be your underlying problem, like I said, I suspect the line above it is bad also since you pass in a pointer to a single character to what would seem to expect a buffer of some length.
I believe the problem (or at least part of the problem) lies with your allocation:
char * imgData = new char;
This only allocates 1 char, and then istream.read will assume that imgData is a buffer of chars (notice plural) and place whatever it reads into the single char you allocated, and then beyond that into the memory used by who knows what.
The result is typically called "undefined behaviour" - sometimes you'll get away with it as in the first instance, other times you won't, as in the second conversion.
i have code like this
string xml_path(conf("CONFIG"));
xml_path+=FILE_NAME;
Where,
conf function returns char * and FILE name is const char *
I want to combine it to one line like
xml_path(conf("CONFIG")).append(FILE_NAME)
how do i do it?
any suggestions ??
Question asked for one line:
string xml_path = string(conf("CONFIG")) + string(FILE_NAME);
(I assume xml_path is the name of the variable, and not some sort of call in a library I don't know about).
Alternatively, if you want to format variable of different type, use a ostringstream.
eg.
std::ostringstream oss;
int a = 2;
char *s = "sometext";
oss<<s<<a<<endl;
cout<<oss.str(); // will output "sometext2"
const char * f = "foo";
char * b = "bar";
string s = string( f ) + b;
Note that you cannot use append(-0 because neither of the strings invvolved is a std:;string. If you really want to append, it will have to be two-stage process:
string s ( f );
s.append( b );
string xml_path(conf("CONFIG"));
xml_path += string(FILE_NAME);
should do the trick.