In my code, I want to update the contents of global array data via a function. When I call the function, however, the contents of data do not change, despite the function calling strcpy() to effect that change -- afterward, data still contains "prg". How can I use strcpy() or something similar to write a new value to data?
char data[255] = "prg";
void process_tuple(Tuple *t)
{
//Get key
int key = t->key;
//Get integer value, if present
int value = t->value->int32;
//Get string value, if present
char string_value[32];
strcpy(string_value, t->value->cstring);
strcpy(data, "prg1212");
//Decide what to do
switch(key) {
case key_0:
break;
};
}
static WeatherAppDataPoint s_data_points[] =
{
{
.city = data,
.description = "surfboard :)",
.icon = WEATHER_APP_ICON_GENERIC_WEATHER,
.current = 110,
.high = 120,
.low = 100,
},
};
You are mistaking, the program as written will change data to prg1212 if the function is executed. You are either not calling it (bad event hookup, etc), the code as written isn't accurate (partial code that hides the real problem) or evaluating the wrong pointer during debugging (or at the wrong time).
I have figured out the problem with help from #Blidny and #MikeofSST
It turns out that my code above contained in a file app_data.c wasn't running code outside if the functions created in app_data.h. I moved my code up into the void where my temperature values were formatted and written, and strcpy() worked like a charm.
Related
I want to parse output from a commandline tool using the fsm programming model. What is the simplest implementation of a fsm that is possible for this task?
Basically, the core idea of a finite state machine is that the machine is in a "state" and, for every state, the behaviour of the machine is different from other states.
A simple way to do this is to have an integer variable (or an enum) which stores the status, and a switch() statement which implements, for every case, the required logic.
Suppose you have a file of the followin kind:
something
begin
something
something2
end
something
and you duty is to print the part between begin/end. You read the file line by line, and switch state basing on the content of the line:
// pseudo-C code
enum state {nothing, inblock};
enum state status;
string line;
status = nothing;
while (!eof(file)) {
readline(line);
switch(status) {
case nothing:
if (line == "begin") status=inblock;
break;
case inblock:
if (line == "end")
status=nothing;
else print(line);
break;
}
}
In this example, only the core idea is shown: a "status" of the machine and a mean to change status (the "line" read from file). In real life examples probably there are more variables to keep more informations for every state and, perhaps, the "status" of the machine can be stored in a function pointer, to avoid the burden and rigidity of the switch() statement but, even so, the programming paradigm is clean and powerful.
The fsm model works in C by assigning function pointers to certain functions that have to process certain data. One good use for fsms is for parsing commandline arguments, for parsing captured output.... The function pointer is assigned to a preset starting function. The start function assigns the function pointer, which must be passed along, to the appropriate next function. And that decides the next function and so on.
Here is a very simple implementation of a fsm:
struct _fsm
{
void (*ptr_to_fsm)(struct _fsm fsm);
char *data;
}
struct _fsm fsm;
fsm->ptr_to_fsm = start; // There is a function called start.
while (fsm->ptr_to_fsm != NULL)
{
fsm->ptr_to_fsm(&fsm);
}
void start (struct _fsm fsm)
{
if (fsm->data == NULL)
{
fsm->ptr_to_fsm = stop; // There is a function called stop.
}
/* Check more more conditions, and branch out on other functions based on the results. */
return;
}
void stop (struct _fsm fsm)
{
fsm->ptr_to_fsm = NULL; /* The while loop will terminate. */
/* And you're done (unless you have to do free`ing. */
}
I am using the jansson library for a C project.
I have some problem understanding how to use the decref. Shall it be used after each new json_t parameter or not? As I understand jansson will borrow references to make this simpler.
If I run this program and check the values of a_id and a_test they are the same. I expected error or null for a_test.
I tried the same idea but then I added decref for json_acc and json_param but it crashed before I could even read the 1:th value. I was assuming a crash but not until a_test.
This is part of a bigger project but I try to add an example to show the essentials.
API side:
json_t* parObj;
void loadFile(char* path)
{
json_error_t error;
parObj = json_load_file(path, 0, &error);
}
int getAccountId(char* id)
{
json_t* json_acc = json_object_get(parObj, "accounts");
json_t* json_param = json_object_get(json_acc, id);
return json_integer_value(json_param);
}
void cleanJson()
{
json_decref(parObj);
}
Caller side:
loadFile("/home/jacob/accountDump.json");
int a_id = getAccountId("10");
cleanJson();
int a_test = getAccountId("10");
I did misunderstood how it is supposed to work, I assumed that decref would also set the memory to zero.
The API will remove the references and make it a free memory but as long as no one writes there or memset it to zero and the pointer is not set to null I can still read the values from that pointer.
This is a mplab harmony code, I am trying to received a data at client, I want to control the LEDs from server socket, text "START" will turn the LEDs ON and "STOP" will turn the LEDs OFF, when I debug the code, it shows that Appbuffer[80] has all null variable, ACK[] = last variable is null \0, same in AOK[].I want to know that is it a right way to compare the string as I have written in the code here. Because when I debug the code, it escape this line and jump to server task init(). Please help me.
case APP_TCPIP_WAIT_FOR_RESPONSE:
{
char Appbuffer[80];
static const char ACK[]="START";
static const char AOK[]="STOP";
memset(Appbuffer, 0, sizeof(Appbuffer));
if (!TCPIP_TCP_IsConnected(appData.clientSocket))
{
SYS_CONSOLE_MESSAGE("\r\nConnection Closed\r\n");
appData.clientState = APP_TCPIP_WAITING_FOR_COMMAND;
break;
}
if (TCPIP_TCP_GetIsReady(appData.clientSocket))
{
TCPIP_TCP_ArrayGet(appData.clientSocket, (uint8_t*)Appbuffer, sizeof(Appbuffer) - 1);
SYS_CONSOLE_PRINT("%s", Appbuffer);
if(!strcmp(Appbuffer, ACK)) //// breakpoint
{
BSP_LEDStateSet(BSP_LED_1,BSP_LED_STATE_ON);
BSP_LEDStateSet(BSP_LED_2,BSP_LED_STATE_ON);
BSP_LEDStateSet(BSP_LED_3,BSP_LED_STATE_ON);
}
else if(!strcmp(Appbuffer, AOK)) // breakpoint
{
BSP_LEDStateSet(BSP_LED_1,BSP_LED_STATE_OFF);
appData.serverState = APP_TCPIP_CLOSING_CONNECTION;
SYS_CONSOLE_MESSAGE("Connection was closed\r\n");
}
}
}
AppBuffer has all null because of the call to function memset.
I didn't see in the code you posted, that AppBuffer is assigned a value.
Hence AppBuffer is essentially a zero-length string and therefore when you compare it with AOK, the result is false.
The program below uses a keypad and arduino to test whether an input is equal to the password. Whenever '#' is pressed the input is checked and then the variable storing the input resets to an empty string (char input[257] = ""). The program then loops back to the beginning of the void loop() code block. I am having a problem when my program loops back to the beginning of the "void loop()" code block. When i reset input to an empty string, input is reset to an empty string as it should. However, when the program loops the value of input is changed to what it was before. So if i originally entered "123abc" and hit '#' the program would tell me that the input was incorrect and then the program would reset the variable to an empty string, but when the program loops the variable storing the empty string is changed back to "123abc". What's happening? Why doesn't the variable remain an empty string?
#include <Keypad.h>
const byte ROWS = 4; //four rows
const byte COLS = 4; //three columns
char keys[ROWS][COLS] = {
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'*','0','#','D'}
};
byte rowPins[ROWS] = {5, 4, 3, 2}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {9, 8, 7, 6}; //connect to the column pinouts of the keypad
char password[9] = "3994A", input[257]="";
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
int x;
void setup(){
Serial.begin(9600);
}
void loop(){
x = 0;
Serial.println(input);
while (1)
{
char key = keypad.getKey();
if (key)
{
if (key == '#')
{
break;
}
input[x] = key;
x+=1;
}
}
if (strcmp(password,input) == 0)
{Serial.println("Access Granted");
}
else
{Serial.println("Access Denied");
}
char input[257] = "";
Serial.println(input);
}
Not the same variable. You've got one input in your top block and another in your loop function.
This line
char input[257] = "";
makes a new local variable called input, but you dont want that. You already made a global one here:
char password[9] = "3994A", input[257]="";
Change
char input[257] = "";
to
memset(input,0,257);
So you dont lose the new variable off the stack and instead use the global one you declared earlier.
The second char input[257] = ""; declares a new variable named input. It does not change the contents of the existing variable named input. Use memset() instead.
I agree with the error in declaring again the input variable
char input[257] = "";
but i would not solve it with memset() but doing
input[0]='\0';
because this is faster and doesn't require to include the memset() function on the code. we are talking about a microcontroller, cpu and memory is precious and it is a good habit to write fast and light code.
Here, how could I achieve this:
Go to the official Arduino Website Download Keypad.h http://playground.arduino.cc/Code/Keypad#Download (ctrl+f and type: download) Download the library to put on C:\Program Files (x86)\Arduino\libraries Close your current Arduino screen then re-open the screen. Rewrite your code and put the code first. I okey with this method.
#include <Keypad.h>
I'm making a domino game and when the user adds a domino to the left, the domino is added but when the function exits the domino added is GONE.
FYI:
fitxesJoc (Link List) contains the dominoes of
the game and is a pointer passed to the function (so that it lasts all the game)
opcionesCorrectas (Domino) contains the correct choices of domino
inferior (int) contains the smaller number of the domino
superior (int) contains the bigger number of the domino
pos (int) the position of the domino
opcionFitxa (int) contains the choice of the player
ultimaFitxa->seg is the 'next' node
tNode* ultimaFitxa = (tNode *)malloc(sizeof(tNode));
ultimaFitxa->info.inferior = opcionesCorrectas[opcionFitxa - 1].inferior;
ultimaFitxa->info.superior = opcionesCorrectas[opcionFitxa - 1].superior;
ultimaFitxa->info.pos = opcionesCorrectas[opcionFitxa - 1].pos;
ultimaFitxa->seg = fitxesJoc;
fitxesJoc = ultimaFitxa;
Header of the function
unsigned int demanar_fitxa_tirar(tJugador *jugador, tNode* fitxesJoc, tPartida *partida, tPila* fitxesBarrejades, bool primerCop)
Call of the function
resultado = demanar_fitxa_tirar(&Jugadors[jugadorActual], fitxesJoc, partida, fitxesBarrejades, true);
This way I add the domino, in the top of the other dominoes.
Your problem is that the last line of demanar_fitxa_tirar:
fitxesJoc = ultimaFitxa;
is assigning to a local variable, which has no effect on the calling code. You need to pass a pointer to the calling code's fitxesJoc, like this:
unsigned int demanar_fitxa_tirar(..., tNode** fitxesJoc, ...) // Note extra *
{
// ...
*fitxesJoc = ultimaFitxa; // Note extra *
}
void mainProgram()
{
tNode* fitxesJoc;
// ...
resultado = demanar_fitxa_tirar(..., &fitxesJoc, ...); // Note extra &
// ...
}
From your code, it's not clear where your function starts and ends and what it takes as parameters but I guess your problem is with the fitxesJoc variable which is probably passed as an argument to the function. C copies arguments when calling functions (call-by-value). You could pass the address to fitxesJoc variable using a pointer instead and rewrite it as something like this:
// fitxesJoc would be a `tNode**` rather than `tNode*`.
tNode* ultimaFitxa = (tNode *)malloc(sizeof(tNode));
ultimaFitxa->info.inferior = opcionesCorrectas[opcionFitxa - 1].inferior;
ultimaFitxa->info.superior = opcionesCorrectas[opcionFitxa - 1].superior;
ultimaFitxa->info.pos = opcionesCorrectas[opcionFitxa - 1].pos;
ultimaFitxa->seg = *fitxesJoc;
*fitxesJoc = ultimaFitxa;
I don't think you've provided enough code, but I suspect the problem is in:
fitxesJoc = ultimaFitxa;
(Linked-list now equals the new Node).
The problem is that parameters are passed by value.
If you want to change the value of the parameter, you'll need to pass by pointer,
and use the pointer to change the value.
*pfitxesJoc = ultimaFitxa;
Please provide more code, including the function header and the function call, for a better answer.
It looks like you're not actually adding the new domino to the linked list. But, it's hard to tell because you need to post more code, and because your code isn't in English.