Float array to bytes converts as null - c

I am trying to continuously send array of 6 floats over MQTT protocol. I was sending them as ASCII characters using sprintf function. I decided to send them as raw bytes. I put these floats into a union to represent them as unsigned char. The problem is when any of these floats is integer value, their byte representation becomes null after the position of integer.
union {
float array[6];
unsigned char bytes[6 * sizeof(float)];
} floatAsBytes;
If all of floatAsBytes.array consist float values, there is no problem at all.
If I say floatAsBytes.array[0] = 0, floatAsBytes.bytes becomes null.
If I say floatAsBytes.array[3] = 4, I can see first 8 bytes however this time last 16 bytes becomes null.
Minimal example of my client side C-code
#define QOS 0
#define TIMEOUT 1000L
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <limits.h>
#include "MQTTClient.h"
union bitFloat{
float f[6];
unsigned char s[6*sizeof(float)];
};
void publish(MQTTClient client, char* topic, char* payload) {
MQTTClient_message pubmsg = MQTTClient_message_initializer;
pubmsg.payload = payload;
pubmsg.payloadlen = strlen(pubmsg.payload);
pubmsg.qos = QOS;
pubmsg.retained = 0;
MQTTClient_deliveryToken token;
MQTTClient_publishMessage(client, topic, &pubmsg, &token);
MQTTClient_waitForCompletion(client, token, TIMEOUT);
}
int main(){
MQTTClient client;
MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
MQTTClient_message pubmsg = MQTTClient_message_initializer;
MQTTClient_deliveryToken token;
int rc;
MQTTClient_create(&client, "MQTTADDRESS:MQTTPORT", "TestClient",
MQTTCLIENT_PERSISTENCE_NONE, NULL);
conn_opts.keepAliveInterval = 20;
conn_opts.cleansession = 1;
if ((rc = MQTTClient_connect(client, &conn_opts)) != MQTTCLIENT_SUCCESS)
{
printf("Failed to connect, return code %d\n", rc);
exit(-1);
}
int i;
while(1){
union bitFloat payload;
payload.f[0] = 4.53; payload.f[1] = 2.39; payload.f[2] = 28.96; payload.f[3] = -1.83; payload.f[4] = -27.0; payload.f[5] = 9.32;
publish(client, "MyTestTopic", payload.s);
sleep(1);
}
return 0;
}
Python script to receive messages and display them
# !/usr/bin/env python
import struct
import numpy as np
import paho.mqtt.client as mqtt
def on_message(client, userdata, message):
test1 = struct.unpack('<f', message.payload[0:4])[0]
test2 = struct.unpack('<f', message.payload[4:8])[0]
test3 = struct.unpack('<f', message.payload[8:12])[0]
test4 = struct.unpack('<f', message.payload[12:16])[0]
test5 = struct.unpack('<f', message.payload[16:20])[0]
test6 = struct.unpack('<f', message.payload[20:24])[0]
print(test1, test2, test3, test4, test5, test6)
client = mqtt.Client()
client.on_message = on_message
client.connect("MQTTADDRESS", MQTTPORT)
client.subscribe("MyTestTopic")
client.loop_forever()

This line
pubmsg.payloadlen = strlen(pubmsg.payload);
is wrong. You are using strlen on something that isn't a string. Due to use of strlen the length will be wrong as strlen only count til it sees a byte that are zero.
Example:
Consider payload.f[0] = 1;. The binary representation of 1.0 is 3f800000
On little endian systems this will be saved as 00 00 80 3f so using strlen will result in 0.
On big endian systems this will be saved as 3f 80 00 00 so using strlen will result in 2.
In other words - strlen is the wrong function.
You probably need
pubmsg.payloadlen = 6 * sizeof(float);

The code works as expected.
Here is a Minimal Complete Verifiable Example. I am guessing that you are doing something right this. When you provide your own code, it may show that I have misunderstood your question:
#include <stdio.h>
int main()
{
union {
float array[6];
unsigned char bytes[6 * sizeof(float)];
} floatAsBytes;
// load up array with some date
for(int i = 0; i < 6; i++) {
floatAsBytes.array[i] = 1.99 + i;
}
puts("\nfirst run:");
floatAsBytes.array[0] = 0;
// dump array
for(int i = 0; i< 6; i++) {
printf("float #%d: %f\n", i, floatAsBytes.array[i]);
}
// dump bytes
for(int i = 0; i < sizeof(float)*6; i++) {
if(i % sizeof(float) == 0)
printf("\n");
printf(" %2x",floatAsBytes.bytes[i]);
}
// second example
puts("\nSecond run:");
floatAsBytes.array[3] = 4;
// dump array
for(int i = 0; i< 6; i++) {
printf("float #%d: %f\n", i, floatAsBytes.array[i]);
}
// dump bytes
for(int i = 0; i < sizeof(float)*6; i++) {
if(i % sizeof(float) == 0)
printf("\n");
printf(" %2x",floatAsBytes.bytes[i]);
}
return 0;
}
Here is the output:
first run:
float #0: 0.000000
float #1: 2.990000
float #2: 3.990000
float #3: 4.990000
float #4: 5.990000
float #5: 6.990000
0 0 0 0
29 5c 3f 40
29 5c 7f 40
14 ae 9f 40
14 ae bf 40
14 ae df 40
Second run:
float #0: 0.000000
float #1: 2.990000
float #2: 3.990000
float #3: 4.000000
float #4: 5.990000
float #5: 6.990000
0 0 0 0
29 5c 3f 40
29 5c 7f 40
0 0 80 40
14 ae bf 40
14 ae df 40
Process finished with exit code 0
I am not seeing the behavior that you are describing. The code works as expected.

Related

Calculate maximum path cost for a matrix in C

I am learning c and encountered maximum cost path question in which
Rules:
matrix is n x n size
Starting from the cell (bottommost leftmost cell), you want to go to the topmost
rightmost cell in a sequence of steps. In each step, you can go either right or up from
your current location.
I tried to solve using dynamic programming and this is the function I have written
computecost(int *utr,int n)//utr is the input matrix
{
int *str;
int i,j;
str=(int *)malloc(n*n*sizeof(int));
for(j=0;j<n;j++)//intialization of bottom row
{
str[n*(n-1)+j]=utr[n*(n-1)+j];
}
for(i=n-2;i>=0;i--)
{
for(j=0;j<n;j++)
{
str[n*i+j]=utr[n*i+j]+max(str[n*(i+1)+j],str[n*(i+1)+(j+1)]);
}
}
printf("%d",str[n*0+0]);
return 0;
}
and this is the input
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
scanf("%d",&str[n*i+j]);
}
}
but
for the matrix 5 x5
1 4 8 2 9
32 67 18 42 1
4 86 12 7 1
8 4 12 17 44
1 43 11 45 2
the desired output is 272 but I am getting 211.
the output matrix for my case
1 43 11 45 2
51 47 57 62 46
55 143 74 69 47
175 210 92 111 52
211 214 119 113 64
Can anyone help me?
You don't need dynamic programming for this since there are no overlapping sub-problems. Just use a simple recursion.
const int n = 5;
int mat[n][n] = {
{1,4,8,2,9},
{32,67,18,42,1},
{4,86,12,7,1},
{8,4,12,17,44},
{1,43,11,45,2}
}; // input matrix
int f(int x, int y, int sum){
if(x == 0 && y == 4)
return sum;
int p = 0, q = 0;
if(x - 1 >= 0)
p = f(x-1, y, sum + mat[x-1][y]);
if(y + 1 <= 4)
q = f(x, y+1, sum+mat[x][y+1]);
return max(p,q);
}
int main(){
int maxSum = f(4,0, mat[4][0]);
printf("%d\n", maxSum);
}
You were not very far to succeed.
In practice, you did not initialize correctly the bottom row.
Moreover, there was a little mistake in the iteration calculation.
This is the corrected code.
As said in a comment, it could be further simplified, by avoiding the use of a new array, simply updating the input array.
#include <stdio.h>
#include <stdlib.h>
int max (int a, int b) {
return (a > b) ? a : b;
}
int computecost(int *utr,int n) { //utr is the input matrix
int *str;
str = malloc (n*n*sizeof(int));
str[n*n - 1] = utr[n*n - 1];
for (int j = n-2; j >= 0; j--) { //intialization of bottom row {
str[n*(n-1)+j] = utr[n*(n-1)+j] + str[n*(n-1)+j+1]; // corrected
}
for (int i=n-2; i>=0; i--) {
str[n*i+n-1] = utr[n*i+n-1] + str[n*(i+1)+n-1];
for(int j = n-2; j >= 0; j--) {
str[n*i+j] = utr[n*i+j] + max(str[n*(i+1)+j],str[n*i + j+1]); // corrected
}
}
int cost = str[0];
free (str);
return cost;
}
int main() {
int A[25] = {
1,43,11,45,2,
8,4,12,17,44,
4,86,12,7,1,
32,67,18,42,1,
1,4,8,2,9
};
int ans = computecost (A, 5);
printf ("%d\n", ans);
return 0;
}

How to copy the semester[20] string under the structure, and count and print it in my output

I don't want to hard code fall19 and spring19 into the output. I want whatever the user input into the array semester[20] under the structure be counted and inputted into the printf. (The inputs are in a text file named enrollment.txt)
Here is the text file for enrollment.txt
10 c1 fall19 80
10 c2 fall19 85
10 c3 fall19 95
40 c2 fall19 65
2 c1 fall19 70
40 c4 fall19 95
40 c5 fall19 85
2 c2 fall19 50
4 c4 spring19 95
4 c5 spring19 89
13 c1 spring19 99
13 c2 spring19 75
#include <stdio.h>
#include <stdlib.h>
#include<string.h>
struct Enrollment {
int stud_id;
char course_id[5];
char semester[20];
float score;
}; // end struct Enrollment
struct Enrollment enroll[50];
int count1 = 0;
int count2 = 0;
for (int i = 0; i < 15; i++) {
if (strcmp(enroll[i].semester, "fall19") == 0) {
count1++;
} else if (strcmp(enroll[i].semester, "spring19") == 0) {
count2++;
}
}
printf("\n%s %d", "fall19", count1);
printf("\n%s %d", "spring19", count2);
printf("\n------------------");
printf("\n==================");
printf("\n------------------");
}
}
}
return 0;
}
Example output:
fall19 8
spring19 4
summer19 0
In your code, i do not see your function, i think you forget main, right ? if it's typo, you can see my idea below:
Firstly, you have to store data from enrollment.txt into array enroll[50];.
For this task, you can get line by line of text file using fgets or getline function. For exmaple:
FILE *fp = fopen("enrollment.txt", "r");
if(!fp) {//handle error};
char line[256];
int i = 0;
while(line, sizeof(line), fp) {
// using sscanf to read data from line to array
}
fclos(fp);
For reading the data from line, you can use sscanf:
int err = sscanf("%d %s %s %f\n", &enroll[i].stud_id, enroll[i].course_id, enroll[i].semester, &enroll[i].score);
if(err != 4) {//handle the error}
i++;
Then you can use for loop from 0 to i to increase count1 and count2 as your code.

How to output integers inside a for-loop as hex values to file

Im trying to create a .pam image with some c-code but the fwrite function only writes the ASCII counterpart to the file, not the hex values.
The head of the file needs to be ASCII and the actual image data needs to be just the hex values for rgb and alpha.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
FILE *out;
out = fopen("C:/Users/entin/Desktop/write.pam", "wb+");
if (out == NULL) {
printf("Unable to access file.\n");
} else {
//everything concerning the head
//buffer the head to not get an overflow
unsigned char headbuf[100];
sprintf(headbuf, "P7\nWIDTH 255\nHEIGHT 255\nDEPTH 4\nMAXVAL 255\nTUPLTYPE RGB_ALPHA\nENDHDR\n");
//reduce head to nessesary length so it dosent output useless NULL's
int len = strlen(headbuf);
unsigned char head[len];
sprintf(head, "P7\nWIDTH 255\nHEIGHT 255\nDEPTH 4\nMAXVAL 255\nTUPLTYPE RGB_ALPHA\nENDHDR\n");
//write head to file
fwrite(head, sizeof (head), 1, out);
//initiating pixel values
unsigned char buf[8];
int r = 0; //AA
int g = 0; //BB
int b = 0; //CC
int a = 255; //DD
//for now just change the red and green values
for (r = 0; r <= 255; r++) {
for (g = 0; g <= 255; g++) {
//coppy pixel data to buffer
sprintf(buf, "%02X%02X%02X%02X", r, g, b, a);
//write buffer to head
fwrite(buf, sizeof (buf), 1, out);
}
}
}
fclose(out);
printf("fin");
getchar();
return (EXIT_SUCCESS);
}
It outputs the head as I want it but the pixel values are also written in their ASCII values
It outputs ENDHDR\nAABBCCDD
as.
45 4E 44 48 44 52 0A 41 41 42 42 43 43 44 44
it should output it like this:
45 4E 44 48 44 52 0A AA BB CC DD
I fixed my code and just wrote the values as their ASCII counterpart.
Here is the fixed code
#include <stdio.h>
#include <stdlib.h>
int main() {
FILE *out;
out = fopen("C:/Users/entin/Desktop/write.pam", "wb+");
if (out == NULL) {
printf("Unable to access file.\n");
} else {
//head
fprintf(out, "P7\nWIDTH 255\nHEIGHT 255\nDEPTH 4\nMAXVAL 255\nTUPLTYPE RGB_ALPHA\nENDHDR\n");
//initiating pixel values
int r = 0; //red
int g = 0; //green
int b = 255; //blue
int a = 255; //alpha
//for now just change the red and green values
for (r = 0; r <= 255; r++) {
for (g = 0; g <= 255; g++) {
//call the numbers as theirr ASCII counterpart and print them
fprintf(out, "%c%c%c%c", r, g, b, a);
}
}
}
fclose(out);
printf("fin");
getchar();
return (EXIT_SUCCESS);
}
Here is the first result

How to print unsigned char data?

Im learning C so i have a little problem.
How to print: unsigned char *tlv_buffer = NULL;
In main function:
unsigned char *tlv_buffer = NULL;
int size = 1;
int len = 0;
int result;
tlv_buffer = BKS_MALLOC(size);
result = append_bertlv_data(&tlv_buffer, &size, &len, 0xDF04, 2,
"\x34\x56");
result = append_bertlv_data(&tlv_buffer, &size, &len, 0xDF81, 3, "ref");
BKS_TRACE("-------- success : %d --------- \n", result);
BKS_TRACE("======== %u =======", &tlv_buffer);
(I cannot see what happens in append_bertlv_data)
It should print df 04 02 34 56 df 81 03 72 65 66 ,
but it does not show like that.
My result is 3204447612
You can use the following:
for (int i = 0 ; i < strlen(tlv_buffer); i++)
printf("%02x ",*(tlv_buffer + i));
It will print each byte in hex.
edit:
use a space to separate and if you want the specific length bytes then specify the length instead of size. best is to use strlen.

Strange output formed by testing a combinations of sums or products in c

I have a problem with a simple code. i want to have all products and sums of a specific number for EX 4 -> 0+4 1+3 2+2 3+1 4+0. for the sum so I made this code to do it:
#include <stdio.h>
#include <stdlib.h>
typedef struct{
unsigned int x;
unsigned int y;
}str;
const int MAX = 200000;
int main(int argc,char *argv[]){
int s=atoi(argv[1]);
if(s<0 || s>MAX){
printf("errore nummero incompatibile!\n");
exit(-1);
}
str sum;
int n=MAX;
for (sum.x=0;sum.x<n;sum.x++){
for (sum.y=0;sum.y<n;sum.y++){
if(strcmp(argv[2],"+")==0){
if(sum.x+sum.y==s){
printf("%d + %d = %d\n",sum.x,sum.y,s);
}
}else{
if(sum.x*sum.y==s){
printf("%d * %d = %d\n",sum.x,sum.y,s);
}
}
}
}
exit(-1);
}
the argv[1] is the number to testand the argv[2] is the mode (Sum or product)
here is the product output of 44 *:
1 * 44 = 44
2 * 22 = 44
4 * 11 = 44
11 * 4 = 44
22 * 2 = 44
44 * 1 = 44
25266 * 169990 = 44
33998 * 126330 = 44
42110 * 101994 = 44
50532 * 84995 = 44
50997 * 84220 = 44
63165 * 67996 = 44
67996 * 63165 = 44
84220 * 50997 = 44
84995 * 50532 = 44
101994 * 42110 = 44
126330 * 33998 = 44
167378 * 179622 = 44
169990 * 25266 = 44
179622 * 167378 = 44`
it gives the correct output but then it starts giving more numbers. these are the same each time i run it. what is this and how can i stop this?
You're iterating through every number until MAX, causing you overflows along the way (See vitaut's answer for the explaination of your issue and how to prevent overflow in your case, he explained that very well.). That's not necessary. When you try to find each combinaisons of multiplication of 2 integer, you just have to iterate until said number, or MAX if the number is too large.
Try to change
int n=MAX;
by :
int n = s;
if (s > MAX)
int n=MAX;
This is caused by integer overflow:
25266 * 169990 == 4294967340
4294967340 is too large to be represented as unsigned int which is 32-bit on your platform. So the most significant bits that don't fit get discarded, effectively giving you the result modulo 2 to the power of 32:
4294967340 mod 2**32 == 44
You can detect overflow in sum.x + sum.y by checking if sum.x > UINT_MAX - sum.y and either leave the inner loop or do something else. Similar check can be done for multiplication.

Resources