Send arguments to a function with argv and argc - function

Can someone help me to understand how i need to send the parameters to the function "lora_rf_config" ? Thank you so much !
I try with:
char cfgred[7][10]={'lora_rf_config','915000000','10','0','1','8','14'};
lora_rf_config(7,&cfgred);
The function that im trying to use is:
static void lora_rf_config(int argc, char *argv[])
{
if (argc == 1) {
e_printf("OK%d,%d,%d,%d,%d,%d\r\n", g_lora_config.lorap2p_param.Frequency,
g_lora_config.lorap2p_param.Spreadfact,
g_lora_config.lorap2p_param.Bandwidth,
g_lora_config.lorap2p_param.Codingrate,
g_lora_config.lorap2p_param.Preamlen,
g_lora_config.lorap2p_param.Powerdbm );
return;
} else {
if (argc != 7) {
out_error(RAK_ARG_ERR);
return;
}
if (!(CHECK_P2P_FREQ(atoi(argv[1])) &&
CHECK_P2P_SF(atoi(argv[2])) &&
CHECK_P2P_BDW(atoi(argv[3])) &&
CHECK_P2P_CR(atoi(argv[4])) &&
CHECK_P2P_PREMLEN(atoi(argv[5])) &&
CHECK_P2P_PWR(atoi(argv[6])))) {
out_error(RAK_ARG_ERR);
return;
}
if (read_partition(PARTITION_0, (char *)&g_lora_config, sizeof(g_lora_config)) < 0) {
out_error(RAK_RD_CFG_ERR);
return;
}
g_lora_config.lorap2p_param.Frequency = atoi(argv[1]);
g_lora_config.lorap2p_param.Spreadfact = atoi(argv[2]);
g_lora_config.lorap2p_param.Bandwidth = atoi(argv[3]);
g_lora_config.lorap2p_param.Codingrate = atoi(argv[4]);
g_lora_config.lorap2p_param.Preamlen = atoi(argv[5]);
g_lora_config.lorap2p_param.Powerdbm = atoi(argv[6]);
write_partition(PARTITION_0, (char *)&g_lora_config, sizeof(g_lora_config));
e_printf("OK\r\n");
}
return;
}
The error that i got is:
..\..\..\src\application\RAK811\app.c(107): error: #26: too many characters in character constant
char cfgred[7][10]={'lora_rf_config','915000000','10','0','1','8','14'};
I dont have experience with this kind of arguments.
Thank you for your time.

lora_rf_config expects same arguments than main function: array of pointers to strings, and its length.
Strings in C are pointers to char, where the char buffer they point to has terminating NUL character (if NUL char is missing, then it's not a string, just a character array). In other words, there is no string type in C, but stringiness is determined by the actual data in the char array or buffer. Using "" string literal creates a string, IOW it adds that terminating NUL char in addition to what you write.
// cfgred is array([) of 7 pointers(*) to char.
// Note: string literals are read-only, so you must not modify these
// strings. If you want a modifiable string, this would be a bit more complex,
// but I think this is out of the scope of your question.
char *cfgred[7] = { "lora_rf_config" , "915000000", "10","0", "1", "8", "14"};
// you can get the number of elements in array by dividing its sizeof size (bytes)
// with the size of it's elements in bytes. Just make sure cfgred here is array...
// in the function it is pointer already (arrays get converted to pointers, so
// you can't do this inside the function, you have to do it where you still have
// the original array
int cfgred_len = sizeof cfgred / sizeof(cfgred[0]);
// when you pass array to function, it is automatically converted to pointer,
// so you must not use & when passing an array like this, otherwise types don't
// match
lora_rf_config(cfgred_len, cfgred);
As a side note, always turn on compiler warnings... They help you a lot, fix them. For gcc and clagn, use -Wall -Wextra, for Visual Studio use /W3 or prefereably /W4. And then fix any warnings you get, because they are probably something that doesn't do what you expect.

Your initialization is not done correctly, try changing
char cfgred[7][10]={'lora_rf_config','915000000','10','0','1','8','14'};
into
char cfgred[7][16]={"lora_rf_config","915000000","10","0","1","8","14"};

Related

C++ If ("Char" == "value") { do [duplicate]

I have a character array and I'm trying to figure out if it matches a string literal, for example:
char value[] = "yes";
if(value == "yes") {
// code block
} else {
// code block
}
This resulted in the following error: comparison with string literal results in unspecified behavior. I also tried something like:
char value[] = "yes";
if(strcmp(value, "yes")) {
// code block
} else {
// code block
}
This didn't yield any compiler errors but it is not behaving as expected.
Check the documentation for strcmp. Hint: it doesn't return a boolean value.
ETA: == doesn't work in general because cstr1 == cstr2 compares pointers, so that comparison will only be true if cstr1 and cstr2 point to the same memory location, even if they happen to both refer to strings that are lexicographically equal. What you tried (comparing a cstring to a literal, e.g. cstr == "yes") especially won't work, because the standard doesn't require it to. In a reasonable implementation I doubt it would explode, but cstr == "yes" is unlikely to ever succeed, because cstr is unlikely to refer to the address that the string constant "yes" lives in.
std::strcmp returns 0 if strings are equal.
strcmp returns a tri-state value to indicate what the relative order of the two strings are. When making a call like strcmp(a, b), the function returns
a value < 0 when a < b
0 when a == b
a value > 0 when a > b
As the question is tagged with c++, in addition to David Seilers excellent explanation on why strcmp() did not work in your case, I want to point out, that strcmp() does not work on character arrays in general, only on null-terminated character arrays (Source).
In your case, you are assigning a string literal to a character array, which will result in a null-terminated character array automatically, so no problem here. But, if you slice your character array out of e. g. a buffer, it may not be null-terminated. In such cases, it is dangerous to use strcmp() as it will traverse the memory until it finds a null byte ('\0') to form a string.
Another solution to your problem would be (using C++ std::string):
char value[] = "yes";
if (std::string{value} == "yes")) {
// code block
} else {
// code block
}
This will also only work for null-terminated character arrays. If your character array is not null-terminated, tell the std::string constructor how long your character array is:
char value[3] = "yes";
if (std::string{value, 3} == "yes")) {
// code block
} else {
// code block
}

Pass a char array variable

I am trying to pass a char array variable as the 'msg' in the PubNub.publish(channel, msg) command. The 'msg' parameter in the command needs to be in JSON array format but my 'input' variable is a char array. The code is firmware for a Particle Photon
This works:
char msg[64] = "{\"Device\":\"on\"}";
PubNub.publish(channel, msg);
But this doesn't work
char msg[64] = "{\"DeviceID\": input}"; //'input' is my char variable for storing serial data
PubNub.publish(channel, msg);
#craig Conover Below is the code for "input" variable and there is data in it. It publishes correctly to particle.io but not to PubNub :
if(Serial1.available()){
Particle.publish("Tagged", "Tag Detected");
count = 0;
while(Serial1.available() && count < 12) // Read 12 characters and store them in input array
{
input[count] = Serial1.read();
count++;
delay(5);
}
Particle.publish("tagnumber", input, PRIVATE);
char msg[64] = "{\"DeviceID\": input}"; //'input' is my char variable for storing serial data
PubNub.publish(channel, msg);

Trying to copy char pointer to "QUERY_STRING" to a char[] variable, getting wrong result

I am working with FastCgi, trying to generate a dynamic html webpage.
I am able to get the QUERY_STRING easily enough, but I am having trouble trying to copy it into a char array.
If there is even a shorter way of just getting the value from QUERY_STRING, please advise because I am a little over my head.
char *queryString = getenv(ENV_VARS[7]);
char newDeviceName[64];
strncpy( newDeviceName, *queryString, sizeof(*queryString) -1);
printf("------- %c ------------", newDeviceName);
This compiles with only warnings, but once i try to load the webpage, the characters are some weird Chinese looking characters. -> �ፙ�
Thank you in advance.
EDIT: More of my code
const char *ENV_VARS[] = {
"DOCUMENT_ROOT",
"HTTP_COOKIE",
"HTTP_HOST",
"HTTP_REFERER",
"HTTP_USER_AGENT",
"HTTPS",
"PATH",
"QUERY_STRING",
"REMOTE_ADDR",
"REMOTE_HOST",
"REMOTE_PORT",
"REMOTE_USER",
"REQUEST_METHOD",
"REQUEST_URI",
"SCRIPT_FILENAME",
"SCRIPT_NAME",
"SERVER_ADMIN",
"SERVER_NAME",
"SERVER_PORT",
"SERVER_SOFTWARE"
};
int main(void)
{
char deviceName[]=ADAPTERNAME;
time_t t;
/* Intializes random number generator */
srand((unsigned) time(&t));
while (FCGI_Accept() >= 0) {
printf("Content-type: text/html \r\n\r\n");
printf("");
printf("<html>\n");
printf("<script src=\"/js/scripts.js\"></script>");
/* CODE CODE CODE */
printf("<p> hi </p>");
printf("<p> hi </p>");
char *queryString = getenv(ENV_VARS[7]);
char newDeviceName[64];
if (queryString == NULL)
printf("<p> +++++ERROR++++++ </p>");
else {
strcpy( newDeviceName, queryString);
newDeviceName[sizeof(newDeviceName) - 1] = 0;
printf("<p> ------- %s ------------ </p> ", newDeviceName);
}
SOLVED: Amateur mistake, for some reason none of my new edits went into effect until after i restart my lighttpd server.
Your program has undefined behavior. Read those warnings issued by the compiler. They're important.
Don't dereference the pointer when you're passing the string to strncpy(). When you do that, you're now passing a single char. That's converted to a pointer when it's given to strncpy() (which is where you probably get your warning, i.e. passing a char to a function that expects a char*).
You also can't get the size of an array that has decayed to a pointer using sizeof. You're just getting the size of the pointer (which is probably either 8 or 4 bytes depending on your system). Since you don't know the length of the string anyway, it might even be better to just use strcpy() instead of strncpy().
Here's what your code probably should look like:
char *queryString = getenv(ENV_VARS[7]);
char newDeviceName[64];
strcpy( newDeviceName, queryString);
printf("------- %s ------------", newDeviceName); /* use %s to print strings */
The length on your strncpy is wrong [too short], the second argument is wrong, and the format string is incorrect.
Try this:
strncpy( newDeviceName, queryString, sizeof(newDeviceName) - 1);
newDeviceName[sizeof(newDeviceName) - 1] = 0;
printf("------- %s ------------", newDeviceName);
In the call to strncpy, it expects a char * for the second argument, but you pass it a char.
Also, the size is not correct. *queryString is a char and has size 1. Using sizeof(queryString) is not correct either because it will return the size of a pointer. What you actually want is the size of the detination buffer.
In the printf call the %c format specifier expects a char but you pass it a char *. You should instead use %s which expects a char * pointing to a null terminated string.
So what you want to do is this:
strncpy( newDeviceName, queryString, sizeof(newDeviceName) -1);
newDeviceName[sizeof(newDeviceName) - 1] = 0;
printf("------- %s ------------", newDeviceName);
What you want is
strncpy(newDeviceName, queryString, sizeof(newDeviceName)-1);
newDeviceName[63] = '\0'; // Guarantee NUL terminator
printf("----- %s -----", newDeviceName);
So multiple problems:
*queryString just gets you the first character, which strncpy tries to treat as a pointer.
sizeof(*queryString) is the size of a char (i.e. 1)
%c prints a single character, not the string

mysql_real_escape_string including slashes in output (C, not PHP)

I've seen this question several times relating to PHP (here is an example). The answer was generally 'stop using magic quotes'. I am having this problem in C however. When I insert binary data into a BLOB in my MySQL database, having run it through mysql_real_escape_string(), some 5c ('\') characters appear in the blob. This disrupts the data and makes it unusable. How can I prevent / fix this?
#define CHUNK_SZ (1024*256)
void insertdb(int16_t *data, size_t size, size_t nmemb)
{
static int16_t *buf;
static unsigned long index;
static short initialized;
unsigned long i;
struct tm *info;
time_t rawtime;
char dbuf[12];
char tbuf[12];
char *chunk;
if(initialized==0){
buf = (int16_t *) malloc(CHUNK_SZ);
initialized = 1;
}
if(index + (nmemb*size) + 1 >= CHUNK_SZ || do_exit == 1){
time(&rawtime);
info = localtime(&rawtime);
snprintf(dbuf, 16, "%d-%02d-%02d", 1900+info->tm_year, 1+info->tm_mon, info->tm_mday);
snprintf(tbuf, 16, "%02d:%02d:%02d", info->tm_hour, info->tm_min, info->tm_sec);
chunk = (char *) malloc(index*2+1);
mysql_real_escape_string(con, chunk, (char *) buf, index);
char *st = "INSERT INTO %s (date, time, tag, data) VALUES ('%s', '%s', %d, '%s')";
int len = strlen(st)+strlen(db_mon_table)+strlen(dbuf)+strlen(tbuf)+sizeof(tag)+index*2+1;
char *query = (char *) malloc(len);
int qlen = snprintf(query, len, st, our_table, dbuf, tbuf, tag, chunk);
if(mysql_real_query(con, query, qlen)){
fprintf(stderr, "%s\n", mysql_error(con));
mysql_close(con);
exit(1);
}
free(chunk);
index = 0;
} else {
memcpy((void *) buf+index, (void *) data, nmemb*size);
index += (nmemb*size);
}
return;
}
EDIT: Please look here. They use the same function to escape binary data (from an image), insert it, and afterward get the same image from the database. That my binary data is somehow different from an image's binary data makes no sense to me.
If you're inserting into a BLOB column, then instead of escaping the data via mysql_real_escape_string(), you should probably express it as a HEX string. You will have to figure out how to encode your int16_t data into the needed byte sequence, as at minimum you have a byte-order question to sort out (but if you're in control of both encoding and decoding then you just need to make them match).
Alternatively, if the data are genuinely textual, rather than binary, then the type of the column should probably be Text rather than BLOB. In that case, you should continue to use an ordinary SQL string and mysql_real_escape_string().

C MySQL Types Error

I'm trying to store results taken from a MySQL query into an array of structs. I can't seem to get the types to work though, and I've found the MySQL documentation difficult to sort through.
My struct is:
struct login_session
{
char* user[10];
time_t time;
int length;
};
And the loop where I'm trying to get the data is:
while ( (row = mysql_fetch_row(res)) != NULL ) {
strcpy(records[cnt].user, &row[0]);
cnt++;
}
No matter what I try though I constantly get the error:
test.c:45: warning: passing argument 1 of ‘strcpy’ from incompatible pointer type
/usr/include/string.h:128: note: expected ‘char * __restrict__’ but argument is of type ‘char **’
test.c:45: warning: passing argument 2 of ‘strcpy’ from incompatible pointer type
/usr/include/string.h:128: note: expected ‘const char * __restrict__’ but argument is of type ‘MYSQL_ROW’
Any pointers?
Multiple problems, all related to pointers and arrays, I recommend you do some reading.
First, char * user[10] is defining an array of 10 char * values, not an array of char, which is was I suspect you want. The warning even says as much, strcpy() expects a char *, the user field on its own is seen as a char **.
Second, you're one & away from what you want in the second argument.
Copied from mysql.h header:
typedef char **MYSQL_ROW; /* return data as array of strings */
A MYSQL_ROW is an array of char arrays. Using [] does a dereference, so you dereference down to a char * which is what strcpy() takes, but then you take the address of it using &.
Your code should look more like this:
struct login_session
{
char user[10];
time_t time;
int length;
};
while ( (row = mysql_fetch_row(res)) != NULL ) {
strcpy(records[cnt].user, row[0]);
cnt++;
}
I don't know what guarantees you have about the data coming from mysql, but if you can't be absolutely sure that the rows are <= 10 characters long and null ('\0') terminated, you should use strncpy() to avoid any possibility of overflowing the user array.