Extract the data from array_buffer and stored in the variable - c

I am receiving data continuously using UART and stored in the buffer in the following form::
$GNRMC,114811.00,A,3558.94849,N,14008.90158,E,0.076,,141115,,,A*69
$GNVTG,,T,,M,0.076,N,0.141,K,A*38
$GNGSA,A,3,,,,,,,,,,,,,3.03,1.18,2.80*1E
$GPGSV,3,2,09,20,04,163,,22,49,280,29,24,45,048,33,25,53,183,28*75
$GNGLL,3558.94849,N,14008.90158,E,114811.00,A,A*70*
I want to extract only the $GNRMCdata and store it on some variable year, mon, day, hour, min, sec so that I can display that in 16*2LCD. The value right after $GNRMC 114811 is the time. But I am not getting the data on those variables. Where I am wrong?
void gps_getinfo(unsigned char rx2_id_buff[]);
void uart2_rx_int(void);
#define MAX_LINEBUF 70
char gps_linebuf[MAX_LINEBUF];
unsigned char time_flag;
unsigned char rx2_id_buff[70];
unsigned char rx2_id_pointer;
unsigned char year[4]={0},mon[4]={0},day[4]={0};
unsigned char hour[4]={0},min[4]={0},sec[4]={0};
#pragma interrupt uart2_rx_int (vect=0x16)
void uart2_rx_int(void)
{
unsigned char error;
error = SSR11 & 0x07;
rx2_id = SDR11;
if (error == 0) {
if(rx2_id == '$' ) rx2_id_pointer = 0;
rx2_id_buff[rx2_id_pointer] = rx2_id; //storing data in the buffer received form UART
gps_getinfo(rx2_id_buff[rx2_id_pointer]);
}
else
rx2_id_buff[rx2_id_pointer] = err | 0xF0;
rx2_id_pointer++;
if (rx2_id_pointer > 69) rx2_id_pointer = 0;
}
void gps_getinfo(unsigned char rx2_id_buff[]) {
short i,j,len;
char *ptr,*ptrTop;
unsigned char j1,j2;
unsigned char comma[20]={0};
if (rx2_id_buff != '\n') {
gps_linebuf[idx++] = rx2_id_buff;
if(idx >= MAX_LINEBUF)idx=0;
}
else {
gps_linebuf[idx++] = '\n';
gps_linebuf[idx] = '\0';
i = MAX_LINEBUF;
j = idx - 1;
while(1) {
if(gps_linebuf[j] == '$') break;
j--;
if(j < 0) j = MAX_LINEBUF - 1;
if(i-- == 0) {
gps_linebuf[0] = 0; idx=0;
return;
}
}
gps_linebuf[idx] = 0; idx=0;
ptrTop = (char *)&gps_linebuf[j];
ptr = (char *)&gps_linebuf[j];
//$GNRMC,114811.00,A,3558.94849,N,14008.90158,E,0.076,,141115,,,A*69
if(strstr(ptrTop,"GNRMC")!=0) {
len=strlen(ptr);
j=0;
for(i=0; i<len; ++i,ptr++) {
if(*ptr == ',') {
comma[j++] = i+1;
}
}
ptr = ptrTop;
j1=comma[0];
j2=comma[1] - comma[0];
time_flag = 0;
if(j2>=4) {
strncpy((char *)hour,ptr+j1 ,2);
strncpy((char *)min, ptr+j1+2,2);
strncpy((char *)sec, ptr+j1+4,2);
time_flag |=0x01;
}
j1=comma[1];
j2=comma[2] - comma[1];
if(j2>=1) {
if(*(ptr + j1) == 'A') {
time_flag |=0x04;
}
}
j1=comma[8];
j2=comma[9] - comma[8];
if(j2>=4) {
strncpy((char *)day, ptr+j1 ,2);
strncpy((char *)mon, ptr+j1+2,2);
strncpy((char *)year, ptr+j1+4,2);
time_flag |=0x02;
year = atoi((char *)year);
mon = atoi((char *)mon);
day = atoi((char *)day);
hour = atoi((char *)hour);
min = atoi((char *)min);
sec = atoi((char *)sec);
}
}
}
}

There are a few errors in your code. I have tested it, and with some smaller changes it works as expected.
Add the correct header files:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
Please change
if (rx2_id_buff != '\n') {
gps_linebuf[idx++] = rx2_id_buff;
to
if (rx2_id_buff[0] != '\n') {
gps_linebuf[idx++] = rx2_id_buff[0];
The integer output variables need to have different names than the corresponding string variables:
int i_year,i_mon,i_day;
int i_hour,i_min,i_sec;
i_year = atoi((char *)year);
i_mon = atoi((char *)mon);
i_day = atoi((char *)day);
i_hour = atoi((char *)hour);
i_min = atoi((char *)min);
i_sec = atoi((char *)sec);

Related

pass multiple values from a function defined in one file to another file using c

I have a task get multiple values from one function defined in one.c file to other function defined in two.c file.
Please find below code snippet from both the files and kindly help to access the values from one.c file into two.c file.
file one.c:
void GetABFWversion(uint8_t* fwcommand, uint8_t* fwaction, uint16_t* fwvalue)
{
uint16_t FW_slot=SdusAutoDetectSlotForNewFirmware();
char MyCopy[10];
strcpy (MyCopy, BrakeBoardInfo.firmwareVersion);
char MyCopy1[10];
for (int k=0; k<9; k++)
{
int l=1;
MyCopy1[k] = MyCopy[k+l];
}
char FWversion_AB[10] = {0};
int z = 0;
for(int x=6;x<10;x++)
{
FWversion_AB[z] = MyCopy1[x];
z++;
}
char res=0;
uint16_t val = atoi(FWversion_AB);
//res = proto485OnlyWrite(0x09,0x02,0x00,val);
printf("\n");
printf("FW version is sent to Arduino!!! ");
RESULT = 1;
*fwcommand = 0x02;
*fwaction = 0x00;
*fwvalue = val;
}
file two.c:
int16_t driver485Read (uint8_t *buffer, const uint16_t length)
{
char head[20];
const char *format="KL%02x:";
int16_t wait_loop_cnt=0;
static uint32_t totalBytes = 0;
static uint32_t respNo = 0;
GPIO_ClearValue(PMAP_GPIO_PORT_DIR_RS485, PMAP_GPIO_PIN_DIR_RS485);
UartRxFlush(UARW_UART_INDEX_RS485); /
respNo++;
int counter = 0;
do
{
OSTimeDly(2);
int8_t newBytesRcv = UartReceive(UARW_UART_INDEX_RS485,
(uint8_t*)&(buffer[counter]), length-counter);
totalBytes += newBytesRcv;
counter = totalBytes;
}
while (/*wait_loop_cnt++<= MAX_WAIT_LOOP &&*/ counter < length);
totalBytes = 0;
uint8_t i = 0;
format="OK%02x:";
printf("Byte received........");
int FWmsg[9] = {0x09,0x30,0x30,0x32,0x32,0x31,0x31,0x31,0x31};
int arduinodata[9] = {0x09,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30};
for (i=0; i<9;i++)
{
printf("%d ",buffer[i]);
arduinodata[i] = buffer[i];
}
if(compareArray(FWmsg,arduinodata,7)==0)
{
printf("Arrays have same elements.\n");
printArray(FWmsg,9);
char res = 0;
uint8_t fwc, fwa;
uint16_t fwv;
GetABFWversion(&fwc, &fwa, &fwv);
res = proto485OnlyWrite(0x09,fwc,fwa,fwv);
printf("\n");
printf("FW version is sent to Arduino!!! ");
}
else
{
printf("Arrays have different elements.\n");
}
/* 1st byte is the slave address byte which value should be >= RS485_ADDRESS_SLAVE_FIRST &&
<= RS485_ADDRESS_SLAVE_LAST and is already checked in dePadLeft() */
for(int i = 1; i < length && buffer[i] >= RS485_PAYLOAD_VALID_MIN && buffer[i] <= RS485_PAYLOAD_VALID_MAX; i++);
counter = i; // to be OK, i = length = RS485_MSG_LENGTH if response (after eventual dePad..) is OK
printf("driver485Read %d\n",counter);
#ifdef RS485_DEBUG
static uint32_t i = 0;
i++;
#endif
return counter;
GPIO_SetValue(PMAP_GPIO_PORT_DIR_RS485, PMAP_GPIO_PIN_DIR_RS485);
}
file three.c:
uint8_t proto485OnlyWrite(uint8_t address, uint8_t command, uint8_t action, uint16_t value)
{
uint8_t res=ERROR_FOUND;
OSSemPend(pbSemaphore, 0, &res);
if (res == OS_ERR_NONE)
{
rs485_message_t rs485Msg;
if (command ==CMD_POWER_PUMP_PB)
{
printf("CMD_POWER_PUMP_PB");
}
proto485ComposeMsg(&rs485Msg, address, command, action, value);
res = (RS485_MSG_LENGTH == driver485Write((uint8_t *)&rs485Msg, sizeof(rs485Msg))) ?
NO_ERROR:
ERROR_FOUND;
OSSemPost(pbSemaphore);
}
return res;
}
I want to get the values of "fwcommand", "fwaction" and "fwvalue" defined in file one.c into file two.c at the place where I am passing the same to "res = proto485OnlyWrite(0x09,fwc,fwa,fwv);" in the place of "fwc", "fwa" and "fwv" respectively.
Thank you....

Creating list of ip addresses over a specific range in C

I am writing a tool to scan all the nodes on a network but I have ran in to a problem. I'm writing the tool in C but I'm new to the language so I'm not sure how the iterate through the address range.
The user will give the argument 192.168.*.* and it will create every IP address in that range, e.g. 192.168.1.1, 192.168.1.2, 192.168.1.3 and then eventually 192.168.2.1, 192.168.2.2, 192.168.2.3 etc.
My previous code was:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void scanner(int s)
{
char addr[20];
for (int i = 0; i < 255; ++i)
{
sprintf(addr, "192.168.%d.%d", s, i);
printf("%s\n", addr);
}
}
int main()
{
for (int i = 0; i < 255; ++i)
{
scanner(i);
}
return 0;
}
But I don't know how to run this from the user input.
You can take the inputs from the user using the scanf function. I have updated your code to use the same -
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int addr_byte_0;
int addr_byte_1;
void scanner(int s)
{
char addr[200];
int i;
for (i = 0; i < 255; ++i)
{
sprintf(addr, "%d.%d.%d.%d", addr_byte_0, addr_byte_1, s, i);
printf("%s\n", addr);
}
}
int main()
{
int i;
//printf("Enter the first byte of the address: ");
scanf ("%d", &addr_byte_0);
//printf("Enter the second byte of the address: ");
scanf ("%d", &addr_byte_1);
for (i = 0; i < 255; ++i)
{
scanner(i);
}
return 0;
}
Also, as per C standards you cannot declare a variable inside the for loop. Hence I have moved the declaration out of the for loop. Hope this helps!
Inspired by (e.g. python-) generators, my solution doesn't perform dynamic memory allocation and and has constant memory consumption. I don't like that I currently rely on a do while loop. Also the explicit check for ig->num_wildcards == 0 is ugly. Anyways:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define IP_OCTETS 4
#define MAX_UCHAR 255
typedef struct {
int wildcard_pos[IP_OCTETS];
int num_wildcards;
int counter[IP_OCTETS];
int octet[IP_OCTETS];
} ip_generator;
char* mystrsep(char** stringp, const char* delim)
{
char* start = *stringp;
char* p;
p = (start != NULL) ? strpbrk(start, delim) : NULL;
if (p == NULL)
{
*stringp = NULL;
}
else
{
*p = '\0';
*stringp = p + 1;
}
return start;
}
void init_ip_gen(ip_generator *ig, char* ip_mask)
{
char *token, *string;
char* ip_mask_ptr = ip_mask;
const char delimiters[] = ".";
int i = 0;
while ((token = mystrsep(&ip_mask_ptr, delimiters)) != NULL)
{
ig->wildcard_pos[i] = -1;
if (strcmp(token, "*") == 0)
{
ig->wildcard_pos[ig->num_wildcards] = i;
ig->counter[ig->num_wildcards] = 1;
ig->num_wildcards++;
}
else
{
ig->octet[i] = atoi(token);
}
i++;
}
}
int ig_next(ip_generator *ig)
{
int i;
int carry = 1;
if (ig->num_wildcards == 0)
{
return 0;
}
for (i = ig->num_wildcards - 1; i >= 0; i--)
{
if (carry == 1)
{
if (ig->counter[i] == MAX_UCHAR)
{
ig->counter[i] = 1;
}
else
{
ig->counter[i]++;
carry = 0;
}
}
if (carry == 0)
{
break;
}
if (i == 0 && carry == 1)
{
return 0;
}
}
return 1;
}
void generate_ip(ip_generator *ig, char *ip)
{
int i;
int j = 0;
int oct[IP_OCTETS];
for (i = 0; i < IP_OCTETS; i++)
{
if (i == ig->wildcard_pos[j])
{
oct[i] = ig->counter[j];
j++;
}
else
{
oct[i] = ig->octet[i];
}
}
sprintf(ip, "%d.%d.%d.%d", oct[0], oct[1], oct[2], oct[3]);
}
int main()
{
char ip_mask[] = "192.*.10.*";
//char ip_mask[] = "192.1.10.123";
ip_generator ig;
memset(&ig, 0, sizeof(ig));
init_ip_gen(&ig, ip_mask);
char ip[32];
memset(ip, 0, sizeof(ip));
do
{
generate_ip(&ig, ip);
printf("%s\n", ip);
} while (ig_next(&ig));
return 0;
}

Inserting a value into an array and arranging array according to value c

char num = '5';
strcpy(array, "2,3,7,9")
Hi guys, any ideas if want to insert 5 into the array according to the value which will result in, how would i go about doing this?
array = "2,3,5,7,9"
#include <stdio.h>
#include <string.h>
void insert_string(char *target, const char *to_insert, int index) {
int count = 0;
int i;
int move_dst;
int insert_comma = 0;
int to_len = strlen(to_insert);
if (index < 0) index = 0;
if (index <= 0) {
i = 0;
} else {
for (i = 0; target[i] != '\0'; i++) {
if (target[i] == ',') {
count++;
if (count >= index) {
i++;
break;
}
}
}
}
/* i is where to insert the string */
if (target[i] == '\0') {
/* the insertion target was end of the string */
target[i] = ',';
target[++i] = '\0';
}
move_dst = i + to_len;
if (target[i] != '\0') {
/* the sequence continues after insertion point */
move_dst++;
insert_comma = 1;
}
memmove(&target[move_dst], &target[i], strlen(&target[i]) + 1); /* copy includes termination '\0' */
memcpy(&target[i], to_insert, to_len);
if (insert_comma) target[i + to_len] = ',';
}
int main(void) {
char array[1024];
char num = '5';
char num_string[2] = {num, '\0'};
int c = 2;
strcpy(array, "2,3,7,9");
puts(array);
insert_string(array, num_string, c);
puts(array);
return 0;
}

C histogram of words printing problems

I have this code, what i want it to do is print the string that represents the word, and print the number of times it occurred in the file, instead it outprints something liek this: (a load of blank space) and then this number -1076720020, which i have no idea where it came from, how would i go about fixing this?
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
struct podatki {
char beseda[1000];
int frekvenca;
};
void zamenjaj(char *str1, char *str2) {
char *beseda2 = (char *)malloc((strlen(str1) + 1) * sizeof(char));
strcpy(beseda2, str1);
strcpy(str1, str2);
strcpy(str2, beseda2);
free(beseda2);
}
int posodobi(struct podatki s[], const char unit[], int count) {
int i =0;
for (i = 0; i < count; i++) {
if (strcmp(s[i].beseda, unit) == 0) {
s[i].frekvenca++;
return count;
}
}
strcpy(s[count].beseda, unit);
s[count].frekvenca++;
return (count + 1);
}
int main() {
int stBes;
scanf("%d", &stBes);
//zacetne deklaracije
struct podatki s[1000];
char string[1000], unit[2000], c;
int i = 0;
int frekvenca = 0;
int j = 0;
int count = 0;
int num = 0;
//branje
for (i = 0; i < 1000; i++) {
s[i].frekvenca = 0;
}
i = 0;
do {
fflush(stdin);
c = getchar();
string[i++] = c;
} while (c != '\n');
//pretvori v majhne crke
char *p;
for (p = string; *p != '\0'; ++p) {
*p = tolower(*p);
}
string[i - 1] = '\0';
for (i = 0; i < strlen(string); i++) {
while (i < strlen(string) && string[i] != ' ' && !ispunct(string[i])) {
unit[j++] = string[i++];
}
if (j != 0) {
unit[j] = '\0';
count = posodobi(s, unit, count);
j = 0;
}
}
int a;
for (i = 0; i < count; ++i) {
for (j = i + 1; j < count; ++j) {
if (s[i].frekvenca < s[j].frekvenca) {
a = s[i].frekvenca;
s[i].frekvenca = s[j].frekvenca;
s[j].frekvenca = a;
zamenjaj(s[i].beseda, s[j].beseda);
}
}
}
for (i = 0; i < count; i++) {
for (j = 1; j < count; j++) {
if (s[i].frekvenca == s[j].frekvenca){
if (strcmp(s[i].beseda, s[j].beseda) < 0) {
a = s[i].frekvenca;
s[i].frekvenca = s[j].frekvenca;
s[j].frekvenca = a;
zamenjaj(s[i].beseda, s[j].beseda);
}
}
}
}
//printanje
for (i = 0; i < stBes; i++) {
printf("%s\t %d\n", s[i].beseda, s[i].beseda);
if (s[i].frekvenca > 1) {
num++;
}
}
return 0;
}
The problem is that you convert the string to lower case before nul terminating it.
Here
i = 0;
do {
fflush(stdin);
c = getchar();
string[i++] = c;
} while (c != '\n');
/* Goes here <---------------------+ */
/* | */
//pretvori v majhne crke | */
char *p; /* | */
for (p = string; *p != '\0'; ++p) {/* | */
*p = tolower(*p);/* | */
} /* | */
/* | */
string[i - 1] = '\0'; /* ---------------------+ */
You should also remove the fflush(stdin) and instead use getchar() to fetch the white space characters ignored by the previous scanf(), and please use scanf() correctly and check it's returned value.

Showing an array of Doubles

I want to write a function to transform an array of n doubles to an string, a show function, something like:
struct vec { uint64_t n; double *x; };
char *show(struct vec *v) {...}
Notice that I don't want to print them, only do a serialization into a string.
How can I do this in C?
You can do something like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#define MAX_DOUBLE_LENGTH 15
typedef struct
{
size_t n;
double* x;
} DoubleArray;
int ShowArray(const DoubleArray* const doubleArrayPtr, char** const resultStringPtr)
{
int errorCode = 0;
char* tempStr = NULL;
char str[MAX_DOUBLE_LENGTH + 2]; /* 1 for trailing space and 1 for null-terminator */
size_t N = 0;
size_t i = 0;
if (doubleArrayPtr == NULL || resultStringPtr == NULL)
{
errorCode = 1;
}
else
{
if (doubleArrayPtr->n != 0)
{
/*
calculating max string length from:
str = <double01> <space> <double02> <space> <double03> <null-terminator>
ex.: str = '3.25 4.75 0.01 5.678\0'
*/
N = doubleArrayPtr->n * MAX_DOUBLE_LENGTH + doubleArrayPtr->n;
tempStr = malloc(N * sizeof(*tempStr));
if (tempStr == NULL)
{
errorCode = 1;
}
else
{
memset(tempStr, 0, N * sizeof(*tempStr));
for(i = 0; i < doubleArrayPtr->n; i++)
{
sprintf(str, "%.6f ", doubleArrayPtr->x[i]);
strcat(tempStr, str);
}
tempStr[strlen(tempStr) - 1] = '\0';
/* string formed -- allocating buffer for result */
(*resultStringPtr) = malloc((strlen(tempStr) + 1) * sizeof(**resultStringPtr));
if ((*resultStringPtr) == NULL)
{
errorCode = 1;
}
else
{
/* exporting result */
memcpy((*resultStringPtr), tempStr, strlen(tempStr) * sizeof(*tempStr));
(*resultStringPtr)[strlen(tempStr)] = '\0';
}
}
free(tempStr);
tempStr = NULL;
}
}
return errorCode;
}
int main(void)
{
/* test code part */
DoubleArray d;
char* s = NULL;
size_t i = 0;
srand(time(NULL));
d.n = rand() % 21;
d.x = malloc(d.n * sizeof(*d.x));
for(i = 0; i < d.n; i++)
{
d.x[i] = (rand() % 99999) / 100.0;
printf("[%d] = %f\n", i, d.x[i]);
}
ShowArray(&d, &s);
printf("str = '%s'\n", s);
free(d.x);
free(s);
return 0;
}

Resources