GPS MODULE DATA - solution? - c

Here are the datas that we receive from GNSS module:
#include <stdio.h>
#include <stdlib.h>
//$GPGLL,,,,,,V,N*64
//$GaabL,,,,,,V,N*5D
char Received[] = { "Odetnij to jak mozesz$GaabL,,,,,,V,N*5D" };
int main(void)
{
int i = 0;
int b;
int c;
int super_atoi;
int wynik;
int xor = 0;
while (Received[i] != '$')
{
printf("%c", Received[i]);
i++;
}
i++;
printf("%c\n ");
while (Received[i] != '*')
{
printf("%c", Received[i]);
xor ^= Received[i];
i++;
}
printf("\n XOR = %d", xor);
printf("\n XOR w hex = %#02x ", xor);
printf("\n XOR w dec = %d ", xor);
if (Received[i] == '*')
{
i++;
b = Received[i];
printf("\n 1 znak w kodzie za * = %c", b);
i++;
c = Received[i];
printf("\n 2 znak w kodzie za * = %c", c);
}
char a[3] = { b, c };
super_atoi = atoi(a);
super_atoi = strtol(a, NULL, 16);
printf("\n ATOI = %s ", a, super_atoi);
if (xor == super_atoi)
{
printf("%c\n ");
printf("\n WORKING!");
}
else
{
printf("%c\n ");
printf("\n not working");
}
return 0;
}
To count the sumcheck of each we've got to xor char's between "$" and "*". My program for that is:
DEMO
Basically we check each char if its "$" then xor elements till we receive *.
However i've small problem... I need to check every single line of data - NEO-7 transmit pack of [280]+ chars each certain period of time, which include 11"$: and 11 *. There are two ways of checking everything that i can think of:
Checking every single byte (char), start counting when "$" appears, finishes when * appears, compare the results with 2 elements after "*".
(More suitable for my program) Receive array[35] from GPS module, create seperate array in which i will include what's left from previous sumcheck, put next pack of data that arrives from GPS, repeat. Could you please tell me what's better? also How to create these solutions?

Related

How do I make printf from right to left

I've written this code for converting Decimal numbers to binary but it prints the number vice versa how can I make this work?
Can I use getch command to make it happen we are currently learning getch.
#include <stdio.h>
int main() {
int n;
scanf("%d", &n);
for(;n>0;n=n/2){
int d = n%2;
printf("%d", d);
}
return 0;
}
You can get tricky with this by using a recursive function:
#include <stdio.h>
void print_binary(int n)
{
if (n != 0) {
print_binary(n/2);
printf("%d ", n%2);
}
}
int main() {
int n;
scanf("%d", &n);
print_binary(n);
return 0;
}
By printing after the recursive call returns, the digits print in the reverse order.
Each time print_binary is called, it calls itself with an argument of n/2, then prints the least significant bit. However, each recursive call does the same thing.
Here's what the call stack looks like with n equal to 11 (binary 1011):
main
scanf
print_binary(11)
print_binary(5)
print_binary(2)
print_binary(1)
print_binary(0)
printf("%d ", 1);
printf("%d ", 0);
printf("%d ", 1);
printf("%d ", 1);
You can see that this results in the most significant bit being printed first.
Here is another way, working from most significant bit, with "zero supression". No reversal is needed.
#include <stdio.h>
int main(void) {
int n = 0; // the value
int hadone = 0; // 0 suppression control
int bits = 8 * sizeof n; // assume 8 bits for example
unsigned mask = 1u << (bits-1); // set msb of mask
scanf("%d", &n);
while(mask) {
if(n & mask) { // is it a 1 bit?
putchar('1');
hadone = 1; // cancel 0 suppression
}
else if(hadone || mask == 1) { // ensure a lone `0` goes out
putchar('0');
}
mask >>= 1; // next bit
}
putchar('\n');
return 0;
}
Program session:
42
101010
You can store digits into an array , and reverse it , to get the correct number .
Here's a non-recursive solution:
#include <stdio.h>
int main() {
int n;
char buf[100];
char *bp;
printf("Enter number: ");
fflush(stdout);
scanf("%d", &n);
bp = buf;
// store into array instead of printing [chars will be reversed]
// NOTE: we use "bp == buf" to force output if entered number is zero
for (; n>0 || bp == buf; n=n/2){
int d = n%2;
bp += sprintf(bp, "%d", d);
}
// print array in reverse order
for (bp -= 1; bp >= buf; --bp)
fputc(*bp,stdout);
printf("\n");
return 0;
}

How to extract multi-digit numbers from a string?

Firstly, I know similar questions have been asked before but I believe my case is different.
My input string is:
(5,7) (1,6) (2,4) (10,14) (8,9)
I wrote the following code for extraction into an array.
main(){
char s[100];
int i=0,x,n=0;
int a[20];
printf("Enter the sets:");
gets(s);
x=strlen(s);
while(i<x){
if((s[i]=='(' && s[i+2]==',') || (s[i]==',' && s[i+2]==')'))
{
a[n]=s[i+1]-'0';
n++;
}
i++;
}
for(i=0;i<n;i++){
printf("%d\n",a[i]);
}
}
The output I get is:
5 7 1 6 2 4 8 9
I understand why my code will skip numbers having 2 or more digits.
Please suggest some minor changes to the present code to fix this limitation.
P.S.- I'm looking for a solution which doesn't depend on length of the number.
Since you only care about the numbers and not any of the delimiters, you can use strtok, which allows for a set of delimiters.
Use the following in place of you existing while loop:
char *p = strtok(s, "(), ");
while (p) {
a[n++] = atoi(p);
p = strtok(NULL, "(), ");
}
Output:
5
7
1
6
2
4
10
14
8
9
If on the other hand you are particular about the format, you can do the following:
char *start = s, *p1 = NULL, *p2 = NULL, *p3 = NULL;
if (start) p1 = strchr(start, '(');
if (p1) p2 = strchr(p1+1, ',');
if (p2) p3 = strchr(p2+1, ')');
while (p1 && p2 && p3) {
a[n++] = atoi(p1+1);
a[n++] = atoi(p2+1);
start = p3+1;
if (start) p1 = strchr(start, '(');
if (p1) p2 = strchr(p1+1, ',');
if (p2) p3 = strchr(p2+1, ')');
}
I have used a different approach to the problem, but I have solved it and it works. Consider trying this. Btw I have used char *s as a string literal but you can keep it like yours.
main(){
char *s="(5,7) (1,6) (2,4) (10,14) (8,9)";
int i=0,x,n=0;
char a[20];
x=strlen(s);
while(i<x){
if (isdigit(s[i])) {
a[n]=s[i];
if (s[i+1]==',' || s[i+1]==')') {
a[n+1]=' ';
n++;
}
n++;
}
i++;
}
printf("%s\n", a);
}
output:
tenshi#mashiro:~/projects/test$ ./test
5 7 1 6 2 4 10 14 8 9
#include <stdio.h>
int main(void) {
// your code goes here
char s[100];
int i=0,x,n=0;
int a[20];
printf("Enter the sets:");
gets(s);
x=strlen(s);
while(i<x-1){
if(isdigit(s[i]))
{
if(isdigit(s[i+1]))
{
a[n]=(s[i]-'0')*10 +(s[i+1]-'0');
i++;
}
else
{
a[n]=s[i]-'0';
}
n++;
}
i++;
}
printf("\n");
for(i=0;i<n;i++){
printf("%d\n",a[i]);
}
return 0;
}
What about the above code, unfortunately C doesn't have simple string functions like split with Regex(it has split function but i didn't understand well). Alternatively, here is ideone for it https://ideone.com/eRKTbD
If the input is in the exact format as in the question, then you can add two loops inside the main while loop to read one set at a time.
while (i < x)
{
if (s[i] == '(')
{
// temporary var to store number
int num = 0;
// read first number
while (s[++i] != ',')
num = num*10 + s[i]-'0';
a[n++] = num;
num = 0;
// read second number
while (s[++i] != ')')
num = num*10 + s[i]-'0';
a[n++] = num;
}
i++;
}
If you always have the same format (a,b)(c,d)...(y,z) and the same number of values then this solution works :
char * arr = "(5,7)(1,6)(2,4)(10,14)(8,9)";
int a,b,c,d,e,f,g,h,i,j;
sscanf(arr,"(%d,%d)(%d,%d)(%d,%d)(%d,%d)(%d,%d)",&a,&b,&c,&d,&e,&f,&g,&h,&i,&j);
printf("%d %d %d %d %d %d %d %d %d %d\n", a, b, c, d, e, f, g, h, i, j);

My comparison of two strings for a hangman game doesn't work properly

I've been working on a hangman game for a class course and I'm almost done. However, I've stumbled upon a problem that I can't seem to fix.
First, the computer choose a random word from a text file, takes the lenght of that word and with that length creates a masked copy of the original word. Then the game start. The player types in letters and if the word is completed before he/she fails six times, he wins. Otherwise, he/she loose. I think the problem with my code is when I create my mask of the word chosen by the computer, but I'm not sure.
If I run the program it looks something like this:
Chosen word: strand (first control of word chosen by computer)
Chosen word: strand (second control to see if the same word is copied from the function to the string in the main)
Chosen word: monster (this is printed by the free() function. for some reason it's one word higher)
Chosen word: strand (third control is done before the lenght of the word is copied, in order to see if it's the right word being copied, which it is)
Wordlenght: 6 (control to see if the lenght matches the word, which it does)
Mask: _ _ _ _ _ _ N (ignore the spaces between the underscores, they are only there to make it easier to see. this is where i think the problem is, because of the extra character added in the end, the "N" in this case. the number of underscores match the number of letters which is good)
Mask: _ _ _ _ _ _ N (printed by the second free() function)
Then the actual game starts. Everything else works fine (if the player aborts or looses and if the player wants or doesn't want to play again). I checked if the actual strcmp() in the int resultat (char* word, char* mask, int count) function worked, and it did. So the fault has be with the strings being compared. I think it's when I get the lenght of the chosen word with strlen(). When I get the length, I subtract with one because otherwise I would get a lenght which is too long(for example, paper would give a lenght of 6, but when I subtract with one I get 5).
If someone could help me or maybe give me some hints I would be very grateful!
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<string.h>
#include<time.h>
#define MAX_WORD_LEN 20
char* datorns_val();
int ordlengd(char* word);
char* datorns_val_mask(char* word, int len);
int spel(char* word, char* mask, int len, int count, int result);
int resultat (char* word, char* mask, int count);
char get_user_choice();
void hangman(int count, int result);
const int MAX_GUESS = 6;
const char ABORT_CH = '0';
const int LOOSE = 0;
const int WIN = 1;
const int ABORTED = 2;
/************************************************************
*
* MAIN
*
*
************************************************************/
int main ()
{
char word[MAX_WORD_LEN];
char mask[MAX_WORD_LEN];
int ch;
int len;
int result;
int count;
/* -------------------- Programstart -----------------*/
srand(time(NULL));
while (true)
{
result = 5;
count = 0;
strcpy(word,datorns_val());
printf("Valt ord 2: %s", word);
free(datorns_val());
len = ordlengd(word);
strcpy(mask,datorns_val_mask(word,len));
printf("\nMask 2: %s <-----", mask);
free(datorns_val_mask(word,len));
printf( "\nV\x84lkommen till HANGMAN 2014!\n");
printf( "Du har %d gissningar p\x86 dig (avbryt med 0)\n", MAX_GUESS );
printf( "Datorn har nu valt ett ord p\x86 %d bokst\x84ver\n", len );
/* GAME MAIN LOOP */
while (count < 6)
{
count=spel(word,mask,len,count,result);
result=resultat(word,mask,count);
hangman(count,result);
}
/* END MAIN GAME LOOP */
if( result == WIN )
{
printf("\nGrattis du vann!\n");
}
else if( result == LOOSE )
{
printf("\nTyv\x84rr du f\x94rlorade! Ordet var: %s\n", word);
}
else
{
printf("Avbrutet\n");
}
printf("Vill du spela igen? (j/n)");
ch = get_user_choice();
if (ch == 'n' || ch == 'N')
{
break;
}
}
}
/***********************************************************
*
* --------- Funktionsdefinitioner ----------------
*
***********************************************************/
char get_user_choice()
{
char tkn;
scanf(" %c", &tkn);
return tkn;
}
char* datorns_val()
{
char ordlista[20];
char* valt_ord = malloc(20);
int random;
int raknare = 0;
random = rand()%4+1;
FILE *ptr_file;
ptr_file =fopen("hangman.dat","r");
if (!ptr_file)
{
printf("Filen kunde inte öppnas!");
}
while (fgets(ordlista,20, ptr_file)!= NULL)
{
if (raknare == random)
{
strcpy(valt_ord, ordlista);
break;
}
raknare=raknare+1;
}
printf("Valt ord 1: %s",valt_ord);
fclose(ptr_file);
return valt_ord;
}
int ordlengd(char* word)
{
printf("Valt ord 3: %s", word);
int ordlengd;
ordlengd=strlen(word)-1;
printf("Ordlengd 1: %i", ordlengd);
return ordlengd;
}
char* datorns_val_mask(char* word, int len)
{
int j;
char* gissning = malloc(20);
for (j=0; j<len; j++)
{
gissning[j]='_';
}
printf("\nMask 1: %s <----", gissning);
return gissning;
}
int spel(char* word, char* mask, int len, int count, int result)
{
int j;
char bokstav;
int ratt = 0;
printf("\nSkriv en bokstav: ");
scanf(" %c", &bokstav);
for(j=0; j<len; j++)
{
if(bokstav==word[j])
{
mask[j]=bokstav;
ratt = 1;
}
else if(bokstav=='0')
{
count = 7;
return count;
}
}
if (ratt == 0)
{
printf("\nBokstaven finns inte i ordet!\n");
count=count+1;
}
printf("Antal fel: %i\n\n", count);
ratt = 0;
for (j=0; j<len; j++)
{
printf("%c", mask[j]);
printf(" ");
}
return count;
}
void hangman(int count, int result)
{
const char* str[20];
int j;
str[0]="\n_______ \n";
str[1]=" | \n";
str[2]=" O \n";
str[3]="//|\\\\\n";
str[4]=" | \n";
str[5]="// \\\\\n";
if(result != ABORTED)
{
for (j=0; j<count; j++)
{
printf("%s", str[j]);
}
}
}
int resultat (char* word, char* mask, int count)
{
char* a = "Hej";
char* b = "Hej";
if (count == 6)
{
return LOOSE;
}
else if (count < 6 && strcmp(mask,word) == 0)
{
return WIN;
}
else if (count == 7)
{
return ABORTED;
}
}
There are some things around the code:
1) The first free() call in pointless:
free(datorns_val());
This reserves memory for a string and deletes it without making any use of it. So get rid of it.
2) Using fgets() to read strings from a file stores also the '\n' character at the end of the line into your string, so you must get rid of it. As a hint, I have used this sentence:
while(fscanf(ptr_file,"%s", ordlista) >0)
that does not store '\n' characters.
3) In ordlengd(char* word) function, you had problem with an extra character (the above mentioned '\n') so the length is the same as the one returned by strlen(), not the
strlen(word) - 1
you had written.
4) You have think about another condition to end the while loop of the main function. I would suggest to add
else return 5;
at the end of resultat() function and the check this value en the while loop of the main function
while (count < 6 && result == 5)
Hope it helps

Scanf for digits

I am pretty new in C and I have a question about scanf just for digits. What I need to do is scanf in input just 3 digits, antoher characters or symbols should be evaluate as trash. Or maybe I need use isdigit() but I am not sure how it works. I have just that, but I know that it doesn't work:
scanf("%d, %d, %d", &z, &x, &y);
You could read a string, use a scan set to filter it and convert it to an integer.
See scanf: http://www.cplusplus.com/reference/clibrary/cstdio/sscanf/
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char num1[256], num2[256], num3[256];
scanf("%s %s %s", num1, num2, num3);
sscanf(num1, num2, num3, "%[0-9]d %[0-9]d %[0-9]d", num1, num2, num3);
int n1 = atoi(num1), n2 = atoi(num2), n3 = atoi(num3); // convert the strings to int
printf("\n%d %d %d\n", n1, n2, n3);
return 0;
}
Sample Input & Output:
2332jbjjjh 7ssd 100
2332 7 100
A little more complicated solution, but prevents overflow of array and works for any kind of input. get_numbers_from_input function takes array where read numbers will be put and maximum count of numbers in array and returns count of numbers read from standard input. function reads characters from standard input until enter is pressed.
#include <stdio.h>
//return number readed from standard input
//numbers are populated into numbers array
int get_numbers_from_input(int numbers[], int maxNumbers) {
int count = -1;
char c = 0;
char digitFound = 0;
while ((c = getc(stdin)) != '\n') {
if (c >= '0' && c <= '9') {
if (!digitFound) {
if (count == maxNumbers) {
break; //prevent overflow!
}
numbers[++count] = (c - '0');
digitFound = 1;
}
else {
numbers[count] = numbers[count] * 10 + (c - '0');
}
}
else if (digitFound) {
digitFound = 0;
}
}
return count + 1; //because count starts from -1
}
int main(int argc, char* argv[])
{
int numbers[100]; //max 100 numbers!
int numbersCount = get_numbers_from_input(numbers, 100);
//output all numbers from input
for (int c = 0; c < numbersCount; ++c) {
printf("%d ", numbers[c]);
}
return 0;
}
Try this.
If the first char is not a digit.
Use "%*[^0-9]" to skip chars which is not digits.
' * ' is an optional starting asterisk indicates that the data is to be read from the stream but ignored (i.e. it is not stored in the location pointed by an argument), and ' ^ ' means any number of characters none of them specified as characters between the brackets.
#include <stdio.h>
int main()
{
int x,y,z;
if(!scanf("%d",&x)==1) scanf("%*[^0-9] %d",&x);
if(!scanf("%d",&y)==1) scanf("%*[^0-9] %d",&y);
if(!scanf("%d",&z)==1) scanf("%*[^0-9] %d",&z);
printf("%d %d %d\n",x,y,z);
return 0;
}
Input & Output
fehwih 2738 #$!(#)12[3]
2738 12 3
Reference from: http://www.cplusplus.com/reference/cstdio/scanf/

Performing arithmetic on Characters in C

I am trying to write a program that adds, subtracts, multiplies, and divides a string of characters. Where I'm at now with the program is figuring out how to split the input string into two strings, and then perform the appropriate +-/*.
The input should look like this abc+aaa
and the output for that should be abc + aaa = bcd
How do I convert character strings into integer strings?
#include <stdio.h>
#include <math.h>
#include <string.h>
int main() {
printf("This is a pseudo arithmetic program");
char input[10];
input[10] = '\0';
char first [9];
first[9] = '\0';
char last [9];
last[9] = '\0';
int i = 0;
int b;
int e;
while (input[0] != '0') {
if (input[0] == 0){
return -1;
}
printf("\nEnter a math problem in SOS format using only lowercase letters up to 9 characters");
printf("\nEx: abc+abc... type '0' to quit \n");
scanf("%s", input);
int x = 0;
x = strlen(input);
if (strchr(input, '+')){
for (i = 0; i <= x; i++) {
if (i == '+')
strncpy(first, &input[0], i-1);
i = 0;
}
for (i = x; i >= input[0]; i--) {
if (i == '+')
strncpy(last, &input[i], x);
i = 0;
}
printf("%s", first);
printf(" + ");
printf("%s", last);
printf(" = %d", first + last);
}
There seems to be multiple problems with your code:
There is a array out of bounds happening for almost all the arrays:
char input[10];
input[10] = '\0';
In this if you want to initialize the last character with '\0' then it should be
input [9] = '\0'
Arrays indexes always start from 0.
It is not clear what is the use of below lines:
while (input[0] != '0') { if (input[0] == 0){ return -1; }
When taking input for a string, why are prompting users to enter a 0 to end it?
strrchr returns the pointer from where the searched character begins. So, you can that itself to determine where the '+' symbol is and two split the strings instead of your while loop. See strrchr man page
Also, your idea of adding characters is not clear. From your example, it appears you are considering a = 1, b = 2 etc. In such a case, if your code is case insensitive, then you can convert all your input to upper case and then do (input[0] - 'A')+1 to convert your letters like a, b, c to 1, 2, 3 etc.
Hope these pointers help. Suggest you check your problem statement again and refactor your code accordingly.

Resources