I am having issues getting a function to run and having the results of a MySQL query to be saved as a variable that other functions can use and call upon. I know the results get read from the table as a string. I was able to do this fine when getting the results and converting it to a float and then passing the results to a pointer. But I can not seem to figure out how to get the results as a string, and compare it with another string to see if they match or do not. No matter what I have tried to do, I can not seem to get a value to be saved as a string to a variable outside the function.
Here is the code of how I got it to work as a float:
(Outside the main function)
float temperature_reading;
float *p_temperature_reading= &temperature_reading;
float humidity_reading;
float *p_humidity_reading= &humidity_reading;
The function I have working with the float, that I can save to a global variable
void MIA_get_current_temperature()
{
const char *query = "SELECT Temperature, Humidity FROM `temperature` WHERE Type='Current_Temperature'";
if (mysql_query(conn, query) != 0)
{
fprintf(stderr, "%s\n", mysql_error(conn));
exit(-1);
} else {
MYSQL_RES *query_results = mysql_store_result(conn);
if (query_results)
{ // make sure there *are* results..
MYSQL_ROW row;
while((row = mysql_fetch_row(query_results)) !=0)
{
float f = row[0] ? atof(row[0]) : 0.0f;
float h = row[1] ? atof(row[1]) : 0.0f;
*p_temperature_reading = f;
*p_humidity_reading = h;
printf("The Temp & Hum from DB is: %.1f & %.1f\n", *p_temperature_reading,*p_humidity_reading);
}
/* Free results when done */
mysql_free_result(query_results);
}
}
}
This is the function I can not get to work:
(Outside main Function)
char ac_mode[256];
char *p_ac_mode = &ac_mode[256];
Function:
void MIA_get_desired_temperature()
{
const char *query = "SELECT Mode, Desired_Temperature, Threshold FROM `ac_mode` WHERE Status='ON'";
if (mysql_query(conn, query) != 0)
{
fprintf(stderr, "%s\n", mysql_error(conn));
exit(-1);
} else {
MYSQL_RES *query_results = mysql_store_result(conn);
if (query_results)
{ // make sure there *are* results..
MYSQL_ROW row;
while((row = mysql_fetch_row(query_results)) !=0)
{
char *ac = row[0] ? row[0] : "NULL";
float desired_temperature = row[1] ? atof(row[1]) : 0.0f;
int threshold = row[2] ? atof(row[2]) : 0.0f;
*p_ac_mode = *ac;
*p_desired_temperature = desired_temperature;
*p_threshold=threshold;
}
/* Free results when done */
mysql_free_result(query_results);
}
}
}
char *ac is where I want the string to be stored.
This line:
char *p_ac_mode = &ac_mode[256];
..is incorrect. You're probably trying to declare a pointer to the array (or maybe to its contents)... what you're actually doing is declaring a char * that points at the first byte after the array ac_mode. The [256] here isn't indicating that ac_mode has 256 elements, it's indexing the array to get element 256 (which would be the 257th char in the array if it were big enough -- but it's not, so it's outside the array). You're then taking the address of that out-of-bounds char and assign it to p_ac_mode, so that p_ac_mode to points to it.
To point p_ac_mode at the array contents, you'd just use char *p_ac_mode = ac_mode; (which makes it a char * pointing at the first char in the array). To get a pointer to the array itself, you'd use char (*p_ac_mode)[256] = &ac_mode;, which makes it a pointer to a 256-element array of char. In any case there's no need for p_ac_mode at all, because you can access the array through ac_mode directly in all the same places, and the bare array name ac_mode will usually decay to a pointer to its first char anyway.
With this line:
*p_ac_mode = *ac;
..you're copying the first char from string ac to the first char after ac_mode (because that's what p_ac_mode points to, as explained above). I suspect you're actually trying to assign the whole ac string's contents to ac_mode via p_ac_mode -- but that won't work for a few reasons.
An array is actually a block of memory holding a series of values of the same type. Although in many situations the array name will decay to a pointer (the address of the array's first element), the array itself is the block of memory and not the pointer. You can't just assign a pointer (new address) to the array, and array contents aren't automatically copied this way either. The contents need to be copied over element by element, or using a function that copies the contents.
What you need to do is copy the contents of the string from your query results into the ac_mode array with strcpy() or similar. Just changing this line:
*p_ac_mode = *ac;
to this:
strcpy(ac_mode, ac);
...would do that.
You need to use strcpy in your MIA_get_desired_temperature function. Also, you don't need the pointer p_ac_mode. Just copy into ac_mode directly.
strcpy(ac_mode, ac);
Related
I am trying to understand how the concepts of parameter passing by Value Result and parameter passing by Name would apply to the following program:
// GLOBAL variables
int num[10] = {0,0,0,0,0,0,0,0,0,0}; // Subscripts start at 0 as in C++
int index = 1;
void somefun(int alpha, int beta)
{
alpha = 7;
num[index] = 33;
index = index - 6;
num[alpha] = 44;
beta = 55;
}
void main()
{
somefun( index, num[index + 4] ); // Function Call
}
This program is pseudo-code, not specific to any language, and the array subscripts start at 0.
If someone could help me understand how this program would work with parameter passing by Value Result and parameter passing by Name, I would greatly appreciate it. Thank you.
Unfortunately, I was not able to try anything on my own thus far.
The main problem I'm having is to read out values in binary in C. Python and C# had some really quick/easy functions to do this, I found topic about how to do it in C++, I found topic about how to convert int to binary in C, but not how to convert uint32_t to binary in C.
What I am trying to do is to read bit by bit the 32 bits of the DR_REG_RNG_BASE address of an ESP32 (this is the address where the random values of the Random Hardware Generator of the ESP are stored).
So for the moment I was doing that:
#define DR_REG_RNG_BASE 0x3ff75144
void printBitByBit( ){
// READ_PERI_REG is the ESP32 function to read DR_REG_RNG_BASE
uint32_t rndval = READ_PERI_REG(DR_REG_RNG_BASE);
int i;
for (i = 1; i <= 32; i++){
int mask = 1 << i;
int masked_n = rndval & mask;
int thebit = masked_n >> i;
Serial.printf("%i", thebit);
}
Serial.println("\n");
}
At first I thought it was working well. But in fact it takes me out of binary representations that are totally false. Any ideas?
Your shown code has a number of errors/issues.
First, bit positions for a uint32_t (32-bit unsigned integer) are zero-based – so, they run from 0 thru 31, not from 1 thru 32, as your code assumes. Thus, in your code, you are (effectively) ignoring the lowest bit (bit #0); further, when you do the 1 << i on the last loop (when i == 32), your mask will (most likely) have a value of zero (although that shift is, technically, undefined behaviour for a signed integer, as your code uses), so you'll also drop the highest bit.
Second, your code prints (from left-to-right) the lowest bit first, but you want (presumably) to print the highest bit first, as is normal. So, you should run the loop with the i index starting at 31 and decrement it to zero.
Also, your code mixes and mingles unsigned and signed integer types. This sort of thing is best avoided – so it's better to use uint32_t for the intermediate values used in the loop.
Lastly (as mentioned by Eric in the comments), there is a far simpler way to extract "bit n" from an unsigned integer: just use value >> n & 1.
I don't have access to an Arduino platform but, to demonstrate the points made in the above discussion, here is a standard, console-mode C++ program that compares the output of your code to versions with the aforementioned corrections applied:
#include <iostream>
#include <cstdint>
#include <inttypes.h>
int main()
{
uint32_t test = 0x84FF0048uL;
int i;
// Your code ...
for (i = 1; i <= 32; i++) {
int mask = 1 << i;
int masked_n = test & mask;
int thebit = masked_n >> i;
printf("%i", thebit);
}
printf("\n");
// Corrected limits/order/types ...
for (i = 31; i >= 0; --i) {
uint32_t mask = (uint32_t)(1) << i;
uint32_t masked_n = test & mask;
uint32_t thebit = masked_n >> i;
printf("%"PRIu32, thebit);
}
printf("\n");
// Better ...
for (i = 31; i >= 0; --i) {
printf("%"PRIu32, test >> i & 1);
}
printf("\n");
return 0;
}
The three lines of output (first one wrong, as you know; last two correct) are:
001001000000000111111110010000-10
10000100111111110000000001001000
10000100111111110000000001001000
Notes:
(1) On the use of the funny-looking "%"PRu32 format specifier for printing the uint32_t types, see: printf format specifiers for uint32_t and size_t.
(2) The cast on the (uint32_t)(1) constant will ensure that the bit-shift is safe, even when int and unsigned are 16-bit types; without that, you would get undefined behaviour in such a case.
When you printing out a binary string representation of a number, you print the Most Signification Bit (MSB) first, whether the number is a uint32_t or uint16_t, so you will need to have a mask for detecting whether the MSB is a 1 or 0, so you need a mask of 0x80000000, and shift-down on each iteration.
#define DR_REG_RNG_BASE 0x3ff75144
void printBitByBit( ){
// READ_PERI_REG is the ESP32 function to read DR_REG_RNG_BASE
uint32_t rndval = READ_PERI_REG(DR_REG_RNG_BASE);
Serial.println(rndval, HEX); //print out the value in hex for verification purpose
uint32_t mask = 0x80000000;
for (int i=1; i<32; i++) {
Serial.println((rndval & mask) ? "1" : "0");
mask = (uint32_t) mask >> 1;
}
Serial.println("\n");
}
For Arduino, there are actually a couple of built-in functions that can print out the binary string representation of a number. Serial.print(x, BIN) allows you to specify the number base on the 2nd function argument.
Another function that can achieve the same result is itoa(x, str, base) which is not part of standard ANSI C or C++, but available in Arduino to allow you to convert the number x to a str with number base specified.
char str[33];
itoa(rndval, str, 2);
Serial.println(str);
However, both functions does not pad with leading zero, see the result here:
36E68B6D // rndval in HEX
00110110111001101000101101101101 // print by our function
110110111001101000101101101101 // print by Serial.print(rndval, BIN)
110110111001101000101101101101 // print by itoa(rndval, str, 2)
BTW, Arduino is c++, so don't use c tag for your post. I changed it for you.
I am using I2C_master library for AVR, Communication works fine, but I have little problem, how can I get data.
I am using this function
uint16_t i2c_2byte_readReg(uint8_t devaddr, uint16_t regaddr, uint8_t* data, uint16_t length){
devaddr += 1;
if (i2c_start(devaddr<<1|0)) return 1;
i2c_write(regaddr >> 8);
i2c_write(regaddr & 0xFF);
if (i2c_start(devaddr<<1| 1)) return 1;
for (uint16_t i = 0; i < (length-1); i++)
{
data[i] = i2c_read_ack();
}
data[(length-1)] = i2c_read_nack();
i2c_stop();
return 0;}
And now I need to use received data, and send it by UART to PC
uint8_t* DevId;
i2c_2byte_readReg(address,REVISION_CODE_DEVID,DevId,2);
deviceH=*DevId++;
deviceL=*DevId;
UART_send(deviceH);
UART_send(deviceL);
I think that I am lost with pointers. Could you help me, how can I get received data for future use? (UART works fine for me in this case, but it sends only 0x00 with this code)
The function i2c_2byte_readReg takes as a third argument a pointer to the buffer where the data will be written. Note that it must have size bigger than the forth argument called length. Your DevId pointer doesn't point to any buffer so when calling the function you've got an access violation.
To get the data you should define an array before calling the function:
const size_t size = 8;
uint8_t data[size];
Then you can call the function passing the address of the buffer as an argument (the name of the array is converted into its address):
const uin16_t length = 2;
i2c_2byte_readReg(address, REVISION_CODE_DEVID, data, length);
Assuming that the function works well those two bytes will be saved into data buffer. Remember that size must be bigger or equal to length argument.
Then you can send the data over UART:
UART_send(data[0]);
UART_send(data[1]);
I am programming a display and I am able to display characters on the display by using this function:
void printChar(char *tekst, uint16_t xPos, uint16_t yPos)
{
//calculate the position the first byte should be placed on
uint16_t startPos = yPos * width_disp_byte + (xPos/8);
int i;
//put all 16 bytes on the right place on the display based on the users' input
for(i=0;i<16;i++)
{
test_image[startPos]=convertChar(*tekst,i);
startPos += width_disp_byte;
}
}
Basically I get a character and find its location in an array that I build. Than I take 16 bytes of data and put this in the display.
The next step is to display integer variables on the display. I have written a code that looks like this:
void printVariable(uint16_t integer, uint16_t xPos, uint16_t yPos)
{
uint16_t value;
uint16_t remainder;
char printValue;
//max value is 9999 that can be displayed, caused by the '4' in the for loop
for(int i = 0; i < 4;i++)
{
value = integer;
//int_power calculates the divisor. going from 3 to 0. cq 1000,100,10,1.
value /= int_power(10,(3-i));
//remove highest number from integer value (for 312, remove the 3 by substracting 300)
integer -= (value) * (int_power(10,(3-i)));
// add '0' to value to get the correct ASCII value.
value += '0';
// convert uint16_t value into char
printValue = value;
printChar(printValue,xPos,yPos);
xPos += 8;
}
}
I take a variable, lets say 3164. The first step is to divide this by 1000. The answer will be 3, since it's an integer. I display this character using the printChar function.
the next step removes 3000 from 3164 and divides the value by 100, resulting in 1. Again this value is printed using the printf function. Then 100 is removed from from 164 and then gets divided by 10 etc etc.
This code is quite limited in its use, but it fits perfectly in what I want to achieve. There is no need to print variables within a string.
The problem here is that the printChar function does not work like I have written in the code. Normally I would use the printChar function like this:
printChar("F",0,0);
This would print the character F in the topleft corner. If I want to use the printChar function like this, it doesn't work:
printChar(printValue,xPos,yPos);
The warning message says:
incompatible integer to pointer conversion passing 'char' to parameter of type 'char *'; take the address with &
If I take the address with & I don't get the correct value displayed on my display.
How can I fix this?
You only want to print ONE character, so you do not need a pointer as parameter. Your function would work like this:
void printChar(char tekst, uint16_t xPos, uint16_t yPos){
...
//depending on the Parameters of your convertChar- function either
... = convertChar(tekst,i); // if you can modify this function too
... = convertChar(&tekst,i); // if the function is to use as it is
}
The difference is in char tekst instead of char * text
UPDATE: I solved my problem (scroll down).
I'm writing a small C program and I want to do the following:
The program is connected to a mysql database (that works perfectly) and I want to do something with the data from the database. I get about 20-25 rows per query and I created my own struct, which should contain the information from each row of the query.
So my struct looks like this:
typedef struct {
int timestamp;
double rate;
char* market;
char* currency;
} Rate;
I want to pass an empty array to a function, the function should calculate the size for the array based on the returned number of rows of the query. E.g. there are 20 rows which are returned from a single SQL query, so the array should contain 20 objectes of my Rate struct.
I want something like this:
int main(int argc, char **argv)
{
Rate *rates = ?; // don't know how to initialize it
(void) do_something_with_rates(&rates);
// the size here should be ~20
printf("size of rates: %d", sizeof(rates)/sizeof(Rate));
}
How does the function do_something_with_rates(Rate **rates) have to look like?
EDIT: I did it as Alex said, I made my function return the size of the array as size_t and passed my array to the function as Rate **rates.
In the function you can access and change the values like (*rates)[i].timestamp = 123 for example.
In C, memory is either dynamically or statically allocated.
Something like int fifty_numbers[50] is statically allocated. The size is 50 integers no matter what, so the compiler knows how big the array is in bytes. sizeof(fifty_numbers) will give you 200 bytes here.
Dynamic allocation: int *bunch_of_numbers = malloc(sizeof(int) * varying_size). As you can see, varying_size is not constant, so the compiler can't figure out how big the array is without executing the program. sizeof(bunch_of_numbers) gives you 4 bytes on a 32 bit system, or 8 bytes on a 64 bit system. The only one that know how big the array is would be the programmer. In your case, it's whoever wrote do_something_with_rates(), but you're discarding that information by either not returning it, or taking a size parameter.
It's not clear how do_something_with_rates() was declared exactly, but something like: void do_something_with_rates(Rate **rates) won't work as the function has no idea how big rates is. I recommend something like: void do_something_with_rates(size_t array_size, Rate **rates). At any rate, going by your requirements, it's still a ways away from working. Possible solutions are below:
You need to either return the new array's size:
size_t do_something_with_rates(size_t old_array_size, Rate **rates) {
Rate **new_rates;
*new_rates = malloc(sizeof(Rate) * n); // allocate n Rate objects
// carry out your operation on new_rates
// modifying rates
free(*rates); // releasing the memory taken up by the old array
*rates = *new_rates // make it point to the new array
return n; // returning the new size so that the caller knows
}
int main() {
Rate *rates = malloc(sizeof(Rate) * 20);
size_t new_size = do_something_with_rates(20, &rates);
// now new_size holds the size of the new array, which may or may not be 20
return 0;
}
Or pass in a size parameter for the function to set:
void do_something_with_rates(size_t old_array_size, size_t *new_array_size, Rate **rates) {
Rate **new_rates;
*new_rates = malloc(sizeof(Rate) * n); // allocate n Rate objects
*new_array_size = n; // setting the new size so that the caller knows
// carry out your operation on new_rates
// modifying rates
free(*rates); // releasing the memory taken up by the old array
*rates = *new_rates // make it point to the new array
}
int main() {
Rate *rates = malloc(sizeof(Rate) * 20);
size_t new_size;
do_something_with_rates(20, &new_size, &rates);
// now new_size holds the size of the new array, which may or may not be 20
return 0;
}
Why do I need to pass the old size as a parameter?
void do_something_with_rates(Rate **rates) {
// You don't know what n is. How would you
// know how many rate objects the caller wants
// you to process for any given call to this?
for (size_t i = 0; i < n; ++i)
// carry out your operation on new_rates
}
Everything changes when you have a size parameter:
void do_something_with_rates(size_t size, Rate **rates) {
for (size_t i = 0; i < size; ++i) // Now you know when to stop
// carry out your operation on new_rates
}
This is a very fundamental flaw with your program.
I want to also want the function to change the contents of the array:
size_t do_something_with_rates(size_t old_array_size, Rate **rates) {
Rate **new_rates;
*new_rates = malloc(sizeof(Rate) * n); // allocate n Rate objects
// carry out some operation on new_rates
Rate *array = *new_rates;
for (size_t i = 0; i < n; ++i) {
array[i]->timestamp = time();
// you can see the pattern
}
return n; // returning the new size so that the caller knows
}
sizeof produces a value (or code to produce a value) of the size of a type or the type of an expression at compile time. The size of an expression can therefore not change during the execution of the program. If you want that feature, use a variable, terminal value or a different programming language. Your choice. Whatever. C's better than Java.
char foo[42];
foo has either static storage duration (which is only partially related to the static keyword) or automatic storage duration.
Objects with static storage duration exist from the start of the program to the termination. Those global variables are technically called variables declared at file scope that have static storage duration and internal linkage.
Objects with automatic storage duration exist from the beginning of their initialisation to the return of the function. These are usually on the stack, though they could just as easily be on the graph. They're variables declared at block scope that have automatic storage duration and internal linkage.
In either case, todays compilers will encode 42 into the machine code. I suppose it'd be possible to modify the machine code, though that several thousands of lines you put into that task would be much better invested into storing the size externally (see other answer/s), and this isn't really a C question. If you really want to look into this, the only examples I can think of that change their own machine code are viruses... How are you going to avoid that antivirus heuristic?
Another option is to encode size information into a struct, use a flexible array member and then you can carry both the array and the size around as one allocation. Sorry, this is as close as you'll get to what you want. e.g.
struct T_vector {
size_t size;
T value[];
};
struct T_vector *T_make(struct T_vector **v) {
size_t index = *v ? (*v)->size++ : 0, size = index + 1;
if ((index & size) == 0) {
void *temp = realloc(*v, size * sizeof *(*v)->value);
if (!temp) {
return NULL;
}
*v = temp;
// (*v)->size = size;
*v = 42; // keep reading for a free cookie
}
return (*v)->value + index;
}
#define T_size(v) ((v) == NULL ? 0 : (v)->size)
int main(void) {
struct T_vector *v = NULL; T_size(v) == 0;
{ T *x = T_make(&v); x->value[0]; T_size(v) == 1;
x->y = y->x; }
{ T *y = T_make(&v); x->value[1]; T_size(v) == 2;
y->x = x->y; }
free(v);
}
Disclaimer: I only wrote this as an example; I don't intend to test or maintain it unless the intent of the example suffers drastically. If you want something I've thoroughly tested, use my push_back.
This may seem innocent, yet even with that disclaimer and this upcoming warning I'll likely see a comment along the lines of: Each successive call to make_T may render previously returned pointers invalid... True, and I can't think of much more I could do about that. I would advise calling make_T, modifying the value pointed at by the return value and discarding that pointer, as I've done above (rather explicitly).
Some compilers might even allow you to #define sizeof(x) T_size(x)... I'm joking; don't do this. Do it, mate; it's awesome!
Technically we aren't changing the size of an array here; we're allocating ahead of time and where necessary, reallocating and copying to a larger array. It might seem appealing to abstract allocation away this way in C at times... enjoy :)