I am currently dealing with a problem that especially has something to do with the first and second ASCII characters, the NULL Character and SOH Character.
The goal of this code is to send some characters and save them in a Tag, which contains 32 Bits/4 Bytes Blocks where Data can be saved in.
I know that there are better ways to achieve this. My Code functions nearly properly except in one single case:
When the Character equals the first ASCII character NULL. Which means when I view the value of the character: c_Char="", when this get sent to the Tag, it doesnt count as an ascii character and gets skipped.
Which means when I check which Characters are sent, the Buffer does not return the character with the 0 decimal value since it was not saved and got skipped.
Is there any If-Condition that I can use to make my program count the NULL ascii character?
This is part of the main Code:
// Splitting the 32 bits from B0 to 4 Bytes
Daten_EEPROM_Byte_VERTEILER(B0);
// Converting The four 32 Bits/4 Bytes Variables into 4 different decimal numbers
Data_Converting_binary_decimal(cFirst_Byte,&i_Char1);
Data_Converting_binary_decimal(cSecond_Byte,&i_Char2);
Data_Converting_binary_decimal(cThird_Byte,&i_Char3);
Data_Converting_binary_decimal(cFourth_Byte,&i_Char4);
//Converting the 4 decimal numbers into 4 ascii Chars.
Fmt(c_Char1,"%c<%i", i_Char1);
Fmt(c_Char2,"%c<%i",i_Char2);
Fmt(c_Char3,"%c<%i",i_Char3);
Fmt(c_Char4,"%c<%i",i_Char4);
//Converting Ascii characters into hexadecimal numbers.
DATEN_Umwandlungsfunktion_Char_hex (c_Char1, x_char1, &iSeriennummer);
DATEN_Umwandlungsfunktion_Char_hex (c_Char2, x_char2, &iSeriennummer);
DATEN_Umwandlungsfunktion_Char_hex (c_Char3, x_char3, &iSeriennummer);
DATEN_Umwandlungsfunktion_Char_hex (c_Char4, x_char4, &iSeriennummer);
//Putting the 4 hex numbers into the one variable:
Fmt(x_Result_B0,"%s<%s%s%s%s",x_char1,x_char2,x_char3,x_char4);
//Showing the 4 hex numbers in a panel:
SetCtrlAttribute(sPanels.P_Hauptmenue, P_MAIN_WB0, ATTR_CTRL_VAL, x_Result_B0);
memset(x_char1,0,sizeof(x_char1));
memset(x_char2,0,sizeof(x_char2));
memset(x_char3,0,sizeof(x_char3));
memset(x_char4,0,sizeof(x_char4));
//Sending the 4 characters into a MSP430 Port to save them in a tag through an antenna
Fmt(Result_Block0,"%s<%s%s%s%s",c_Char1,c_Char2,c_Char3,c_Char4);
Fmt(cCommand,"%s<%s%s%s%s",WRITE_BLOCK,"0_",Result_Block0,ENDE);
// Write and Read Data in and from Block 0
iResult = Befehl_Senden(cCommand,cAnswer);
Fmt(cCommand,"%s<%s%s%s",READ_BLOCK,"0",ENDE);
iResult = Befehl_Senden(cCommand,cAnswer);
CopyBytes(cRead_Block_0,0,cAnswer,23,8);
SetCtrlAttribute(sPanels.P_Hauptmenue, P_MAIN_BR0, ATTR_CTRL_VAL, cRead_Block_0);
These are the following functions that are used to convert the variables:
char *decimal_to_binary(int n)
{
int c, d, t;
char *p;
t = 0;
p = (char*)malloc(32+1);
if (p == NULL)
exit(EXIT_FAILURE);
for (c = 31 ; c >= 0 ; c--)
{
d = n >> c;
if (d & 1)
*(p+t) = 1 + '0';
else
*(p+t) = 0 + '0';
t++;
}
*(p+t) = '\0';
return p;
}
void Daten_HILFSFUNKTION_binary_decimal (char *cEingang, int *iAusgang)
{
int multiplier = 0;
int i;
int sum = 0;
int length;
char cMonth[10] = {0};
int iMonth;
length = StringLength (cEingang);
for (i=length-1; i>=0; i--)
{
CopyBytes (cMonth, 0, cEingang, i, 1);
Fmt (&iMonth, "%x<%s", cMonth);
sum = sum +(iMonth*pow(2, multiplier));
multiplier = multiplier + 1;
}
Fmt (iAusgang, "%i<%i", sum);
}
void Daten_EEPROM_Byte_VERTEILER(char *B)
{
CopyBytes(cFirst_Byte, 0,B,0,8);
CopyBytes(cSecond_Byte, 0,B,8,8);
CopyBytes(cThird_Byte, 0,B,16,8);
CopyBytes(cFourth_Byte, 0,B,24,8);
}
char *Daten_EEPROM_HILFSFUNKTION(char *Char_in_Bits, char *c_8Bits)
{
int Decimal = 0;
char c_Character[5] = {0};
CopyString(Char_in_Bits, 0,c_8Bits,0,8);
Daten_HILFSFUNKTION_binary_decimal (Char_in_Bits, &Decimal);
int B_1_dec = Decimal;
Fmt(c_Character,"%c<%i",B_1_dec);
memset(Char_in_Bits,0,sizeof(Char_in_Bits));
return c_Character;
}
void DATEN_alle_Char_uerbergabe_Funktion (char *Byte_Block,char *c_Char1, char *c_Char2, char *c_Char3,char * c_Char4)
{
DATEN_erster_Char_uebergabe_Funktion(Byte_Block, c_Char1);
DATEN_zweiter_Char_uebergabe_Funktion(Byte_Block, c_Char2);
DATEN_dritter_Char_uebergabe_Funktion(Byte_Block, c_Char3);
DATEN_vierter_Char_uebergabe_Funktion(Byte_Block, c_Char4);
}
char DATEN_erster_Char_uebergabe_Funktion (char *Byte_Block,char *c_Char1)
{
return* c_Char1 = *Daten_EEPROM_HILFSFUNKTION(Byte_Block, cFirst_Byte);
}
char DATEN_zweiter_Char_uebergabe_Funktion(char *Byte_Block,char *c_Char2)
{
return *c_Char2 = *Daten_EEPROM_HILFSFUNKTION(Byte_Block, cSecond_Byte);
}
char DATEN_dritter_Char_uebergabe_Funktion(char *Byte_Block,char *c_Char3)
{
return *c_Char3 = *Daten_EEPROM_HILFSFUNKTION(Byte_Block, cThird_Byte);
}
char DATEN_vierter_Char_uebergabe_Funktion(char *Byte_Block,char *c_Char4)
{
return *c_Char4 = *Daten_EEPROM_HILFSFUNKTION(Byte_Block, cSecond_Byte);
}
void char_Umwandeln (char *cEingang,char *cAusgang)
{
int ilaenge;
int idez_Wert;
int iPos;
char cZwischenspeicher [5] = {0};
ilaenge = StringLength(cEingang);
for (iPos = 0; iPos <=ilaenge - 1; iPos++)
{
idez_Wert = 0;
//CopyBytes (cZwishcenspeicher, 0, cEingang, ilaenge-iPos,1);
CopyBytes (cZwischenspeicher,0,cEingang,iPos,1);
Scan (cZwischenspeicher,"%s>%i[r256]",&idez_Wert);
if (idez_Wert == 0)
{
CopyBytes (cAusgang, 0,"00",0,2);
}
else if (idez_Wert <16)
{
Fmt(cAusgang,"%s<%s%s%i[r16]",cAusgang,"0",idez_Wert);
}
else
{
Fmt(cAusgang,"%s<%s%i[r16]",cAusgang,idez_Wert);
}
}
StringUpperCase(cAusgang);
}
void DATEN_Umwandlungsfunktion_Char_hex (char *Char, char *hex_Char, int *dec_Nummer)
{
char_Umwandeln (Char,hex_Char);
Scan(&hex_Char,"%s>%x",&dec_Nummer);
}
If anyone has already had this problem and knows a solution for this issue, I would be so thankful. Thanks a lot in advance.
So I have this text file (cartCoords.txt):
a = 2b, 1d; milk cheese eggs
b = 2a, 1e, 2c;
c = 2b, 1f;
d = 1a, 1g;
e = 1h, 1b;
f = 1i, 1c;
g = 1j, 1d;
h = 1k, 1e;
i = 1l, 1f;
j = 1m, 1g;
k = 1n, 1h;
l = 1o, 1i;
m = 2n, 1j;
n = 2m, 1k, 2o;
o = S, 2n, 1l;
These represent my version of a map layout. Point "a" is 2 units away from "b" and 1 unit away from "d" and at point a, we have the items "milk", "cheese", and "eggs".
I've constructed a struct:
struct stopPoints {
char **items;
char connectingPoints[10];
int weights[10];
int startBool;
};
So each "stop point" (a,b,c...etc) contains a list of items (milk, cheese, etc), a list of connected points (the b and d in 2b and 1d), the "weight" of each corresponding connecting point (the 2 and 1 in 2b and 1d), and a boolean value representing if it's a start point or not (indicated by an "S).
I've been able to store each connecting point and it's weight into each point's struct, but I'm having trouble storing each individual string of items into an array. What I want to do is for each struct to have an array that stores each item in each index, like this:
["milk", "cheese", "eggs"]
How would I go about doing this?
Below is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 10
struct stopPoints {
char **theItem;
char connectingPoints[10];
int weights[10];
int startBool;
};
struct stopPoints makeStruct(char* str)
{
char items[10];
int i,j=0,k=0, l=0, semiCheck =0, a;
struct stopPoints point;
for(i=4; i<strlen(str); i++)
{
//check if its a starting point
if(i==4 && str[i] == 'S')
{
point.startBool = 1;
i+=3;
}
else if(i==4)
{
point.startBool = 0;
}
//if there's no semicolon present, proceed with the code
if (semiCheck == 0) {
//checks if its a number
if(str[i] < 58 && str[i] > 47){
point.weights[j] = str[i];
j++;
}
//checks if its a letter
else if(str[i] < 122 && str[i] > 96){
point.connectingPoints[k] = str[i];
k++;
}
else if (str[i] == 59){
semiCheck = 1;
i++;
}
}
else if(semiCheck==1){
for (a=1; a<(strlen(str)-i); a++){
if (str[i+a] != 32){
items[a-1] = str[i+a];
}
}
}
}
return point;
}
int main(){
int selections[100];
int numOfItems,x,y,j,z,temp;
int i = 0;
struct stopPoints store[26];
FILE *fp;
char str[60];
/* opening file for reading */
fp = fopen("cartCoords.txt" , "r");
if(fp == NULL) {
perror("Error opening file");
return(-1);
}
while( fgets (str, 600, fp)!= NULL ) {
/* writing content to stdout */
//printf("test1");
store[i] = makeStruct(str);
i++;
printf("store[%d] connecting points = %c and %c and %c\n", i-1, store[i-1].connectingPoints[0], store[i-1].connectingPoints[1], store[i-1].connectingPoints[2]);
}
fclose(fp);
return 0;
}
The output of this program is:
store[0] connecting points = b and d and
store[1] connecting points = a and e and c
store[2] connecting points = b and f and
store[3] connecting points = a and g and
store[4] connecting points = h and b and
store[5] connecting points = i and c and
store[6] connecting points = j and d and
store[7] connecting points = k and e and
store[8] connecting points = l and f and
store[9] connecting points = m and g and
store[10] connecting points = n and h and
store[11] connecting points = o and i and
store[12] connecting points = n and j and
store[13] connecting points = m and k and o
store[14] connecting points = n and l and
So I've been able to properly store the letters and numbers. I just don't know how to take a complete string and store it into an array. My approach was to have my loop check for a semicolon (using its ascii value) and once a semicolon is detected, it would start gathering each separate string. The only problem is is that I have no idea how to implement that.
I have a function that I am trying to convert from PHP. I am executing the function like this example:
latlong_hex("1234.5678N");
and I need the result to be processed but I am running into problems with the string to double conversion and the calculations. After the conversion, I am losing all numbers after the decimal. The HEX function at the bottom is working fine.
int latlong_hex(char* gps_coord)
{
int gps_result;
char direction[2] = {0};
char gps_latlong[10] = {0};
double latdeg;
double tempDec;
char* tempGPS;
strncpy(gps_latlong, gps_coord, 9);
strncpy(direction, gps_coord+9, 1);
tempDec = strtod(gps_latlong, NULL);
free(gps_latlong);
tempDec = tempDec / 100;
if(direction == 'W' || direction == 'S')latdeg = round((floor(tempDec)+((tempDec - floor(tempDec))/60),7))*-1;
else latdeg = round((floor(tempDec) + ((tempDec - floor(tempDec))/60),7));
if(latdeg > 0){
gps_result = latdeg / 0.0000001;
}
else{
gps_result = (4294967295 + (latdeg/0.0000001)) ;
}
dec_hex(gps_result);
return 1;
}
This:
free(gps_latlong);
is instant undefined behavior, since gps_latlong is not a heap-allocated object. Remove that line.
Also, you should call strtod() directly on gps_coord, the local copying serves no purpose.
I've done a C program that writes an integer array into the Arduino:
// ...
FILE* file;
file = fopen("/dev/ttyuSB0","w");
for (int i = 0; i < 3; i++) {
fprintf(file, "%d ", rgb[i]);
}
fclose(file);
// ...
How can I do from my arduino code (.ino) to catch the three integers from the file?
while (Serial.available() > 0) {
// What can I do here ???
}
You need to read the data and put it into a buffer. After you encounter a ' ' character you terminate the string inside the buffer and convert it into an int.
When you do this three times you have read all three ints.
const uint8_t buff_len = 7; // buffer size
char buff[buff_len]; // buffer
uint8_t buff_i = 0; // buffer index
int arr[3] = {0,0,0}; // number array
uint8_t arr_i = 0; // number array index
void loop() {
while (Serial.available() > 0) {
char c = Serial.read();
if (buff_i < buff_len-1) { // check if buffer is full
if (c == ' ') { // check if got number terminator
buff[buff_i++] = 0; // terminate the string
buff_i = 0; // reset the buffer index
arr[arr_i++] = atoi(buff); // convert the string to int
if (arr_i == 3) { // if got all three numbers
arr_i = 0; // reset the number array index
// do something with the three integers
}
}
else if (c == '-' || ('0' <= c && c <= '9')) // if negative sign or valid digit
buff[buff_i++] = c; // put the char into the buffer
}
}
// maybe do some other stuff
}
Or if you don't mind blocking code[1] you can use builtin ParseInt.
void loop() {
while (Serial.available() > 0) {
arr[0] = Serial.parseInt();
arr[1] = Serial.parseInt();
arr[2] = Serial.parseInt();
Serial.read(); // read off the last space
// do something with the three integers
}
// maybe do some other stuff, but might be blocked by serial read
}
[1] If your computer has a hiccup and doesn't send all the data at once, your Arduino code will just wait for data and won't be doing anything else. Read more here.
I am trying to convert from a popen pass, to a float as the final result. I have tried converting to a char, and then into a float in every possible way I can find, however the output I have seen using printf seems to be wrong every time. I have tried using a tostring function, as well as using a %s like in the printf function that returns the correct function, however it all seems to give me the wrong output as soon as I try to convert the output. Should I be trying a different conversion method?
Here is the code.
FILE * uname;
char os[80];
int lastchar;
char n;
uname = popen("sudo python ./return63.py", "r");
lastchar = fread(os, 1, 80, uname);
os[lastchar] = "\0";
n = toString(("%s", os));
printf("THE DIRECT OUTPUT FROM PY IS %s", os);
printf("THE DIRECT OUTPUT For n IS %c", n);
float ia = n - 0;
long p = ia - 0;
float dd = p - 0;
printf("Your OS is %f", dd);
Output from the PY is 'THE DIRECT OUTPUT FROM PY IS 63.0' , which is the correct value,
output from the n is 'THE DIRECT OUTPUT For n IS �'
output from the dd is 'Your OS is Your OS is 236.000000'
The function tostring was pulled from an answered question about how to get the output from another answered question. I have tried with and without this code.
int toString(char a[]) {
int c, sign, offset, n;
if (a[0] == '-') { // Handle negative integers
sign = -1;
}
if (sign == -1) { // Set starting position to convert
offset = 1;
}
else {
offset = 0;
}
n = 0;
for (c = offset; a[c] != '\0'; c++) {
n = n * 10 + a[c] - '0';
}
if (sign == -1) {
n = -n;
}
return n;
}
toString returns an int, so store an int and output an int.
int n = toString(os); // Also removed the obfuscating '("%s", ..)'
printf("THE DIRECT OUTPUT For n IS %d", n);
Also your toString function has undefined behavior because sign might be read without being initialized.
if (a[0] == '-') { // Handle negative integers
sign = -1;
offset = 1;
}
else {
sign = 1;
offset = 0;
}
You have a potential os buffer overflow and you are not doing the null termination of os correctly:
lastchar = fread(os, 1, sizeof(os) - 1, uname); // Only read one byte less
os[lastchar] = '\0'; // changed from string "\0" to char '\0'
And finally you are not checking the input string for digits, you are accepting every input (also the '.' in "63.0"). You might want to stop at the first non-digit character:
for (c = offset; !isdigit((unsigned char)a[c]); c++) {