2

I need some help in Identifying the string. I have incoming string like this *H1999999#it can vary from *H1000000#~*H1999999# sometimes it is *H1FINE# or *H1MED# or any other text in between.Now what I have already done is I have parsed the numeric string and copied the integer value to a buffer. Here is the code for that.

        char H1subbuff[10];

        char *ptr;

        if ((strncmp(rec,"*H1", 3) == 0) && (rec[9] == '#'))    
         {
            memcpy(H1subbuff, &rec[3], 6 );
            H1subbuff[6] = '\0';

            H1Val = strtol(H1subbuff, &ptr, 10);

            //Display H1VAL
       }

Now my query is how can check if the String consist of Number or Alphabet. How can I check H1subbuff data, so that I can compare. I need to do the same above process of parsing *H1FINE# string.

Note :- The above two string doesn't have same string length.

MICRO
  • 253
  • 2
  • 9
  • `strcmp(end, "#") == 0` -> `rec[9] == '#'`, this has nothing to do with your problem but you would avoid to define `end` and use `memcpy`. Also, `memcpy()` for a single character is completely unecessary, in fact I wouldn't use it at all in your code, since there are too few characters to copy you can copy one by one. – Iharob Al Asimi Aug 04 '16 at 11:41
  • And now to the issue, what do you think `ptr` is for? The second parameter to `strtol()`. Did you read the documentation? – Iharob Al Asimi Aug 04 '16 at 11:43
  • @iharob You are right. For single character `memcpy()` should not be used. I did mistake using `memcpy()` for single characters. – MICRO Aug 04 '16 at 15:40

3 Answers3

3

You can use this to determine whether it's numeric or not

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void
check_string(const char *string)
{
    char *endptr;
    long int value;
    if (strstr(string, "*H1") == NULL)
        return; // This string is not valid
    // Move after the '*H1'
    string += 3;
    if (strchr(string, '#') == NULL)
        return; // Missing the '#'
    // Now we can try to determine whether the content
    // between '*H1' and '#' is a number, or text
    value = strtol(string, &endptr, 10);
    // This simply compares pointer values, if `endptr'
    // has the same value as `string`, then `strtol()' didn't
    // find any numeric character, i.e. the first one
    // in the data pointed to by `string' was non-numeric
    if (endptr == string)
        fprintf(stdout, "It's NOT a number\n");
    else if (*endptr == '#')
        fprintf(stdout, "It's a number: %ld\n", value);
    else
        fprintf(stdout, "It's almost a number\n");
}

First we perform some integrity check, once we know that it's a candidate we can try to determine whether or not the delimited portion is a number or not.

Note the "It's almost a number" part, it means that not all the characters delimited by *H1 and # are numeric, but the few first were and then a non numeric character occurred.

Also, if it was allowed to have a '#' embedded into the delimited portion, escaping it for example, this code would not work.

Iharob Al Asimi
  • 52,653
  • 6
  • 59
  • 97
  • Thanks! I really understood what is happening. But I have few questions. What is stored in `endptr` ? There is no predefined string, it is an incoming string, so comparing `endptr` with `string` would not be possible, I guess. All I need to check if the Portion between `*H1` and `#` is numeric or Alphabet, if it is a numeric I can use `strtol()' to copy the int value into an buffer. How can I copy the alphabet or text into an buffer? – MICRO Aug 04 '16 at 15:39
  • 1
    @AnujMattoo Please read the [documentation](http://man7.org/linux/man-pages/man3/strtol.3.html). – Iharob Al Asimi Aug 04 '16 at 16:40
  • I am confused now! Really didn't understand what is happening. – MICRO Aug 04 '16 at 17:50
  • Yes I read the documentation. I am really thankful to you. I will try the code, if any issue occurs will comment again! Thanks! – MICRO Aug 04 '16 at 19:32
  • I tried the code, it is wokring fine. But I shows some unexpected values. For example the incoming string is sometimes *H1-01234# in that case, it doesn't print Alphabet values. – MICRO Aug 05 '16 at 15:46
  • There are no alphabet characters, all numbers. It's the negative `-1234`, please [READ THIS, ALL OF IT AND IF YOU DON'T UNDERSTAND READ IT AGAIN](http://man7.org/linux/man-pages/man3/strtol.3.html) – Iharob Al Asimi Aug 05 '16 at 20:26
2

like this:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdbool.h>

bool validate_data(const char rec[], int *number, char text[]){
    *number = -1;//if invalid
    *text = 0;   //if invalid

    if(strncmp(rec, "*H1", 3) != 0) return false;//invalid header

    bool not_digit = false;
    int i, j = 0;
    for(i = 3; rec[i] && rec[i] != '#'; ++i){
        text[j++] = rec[i];
        if(!isdigit(rec[i]))
            not_digit = true;
    }
    text[j] = 0;

    if(rec[i] != '#'){
        *text = 0;
        return false;//invalid footer
    }
    if(not_digit == false){
        if(j != 6){
            *text = 0;//valid as text?
            return false;//invalid number format
        }
        *number = atoi(text);
    }
    return true;
}


int main(void){
    const char *test_data[] = {
        "*H1000000#","*H1999999#", "*H1123456#", "*H1FINE#", "*H1MED#",
        "*h123#", "**H1666666#", "*H2888888#", "*H1777#", "*H1555555"
    };
    int number_of_data = sizeof(test_data)/sizeof(*test_data);
    char H1subbuff[10];
    int H1Val;

    for(int i = 0; i < number_of_data; ++i){
        printf("%s :\n", test_data[i]);
        if(validate_data(test_data[i], &H1Val, H1subbuff)){
            if(H1Val >= 0)
                printf("value is %d(%s)\n", H1Val, H1subbuff);
            else
                printf("text is %s\n", H1subbuff);
        } else {
            printf("invalid format\n");
        }
        puts("");
    }
    return 0;
}
BLUEPIXY
  • 39,699
  • 7
  • 33
  • 70
  • I can't predefine values in `*test_Data` in my code. The String is incoming which needs to be checked (Numeric/Alphabet) and parse and store it in buffer. Then display it's content. The code you posted is using predefined set of Strings which defeats the purpose. I will be having around 10,000 different numeric values or characters. Can't define like this. Is there any way around? I am storing my incoming string in an `unsigned char rec[12];` – MICRO Aug 04 '16 at 19:30
  • @AnujMattoo part of `main` is just a demo. you call `if(validate_data(rec, &H1Val, H1subbuff)){` then print `H1Val`, `H1subbuff` like demo. – BLUEPIXY Aug 04 '16 at 19:37
  • Hey, Thanks man! Code working fine. It solved my problem. But I couldn't understand the `bool validate_data' routine. Can you please explain me, how did you achieve this piece of Amazing code? – MICRO Aug 04 '16 at 20:50
  • @AnujMattoo Where you can't understand the part? – BLUEPIXY Aug 04 '16 at 20:55
  • One more issue, the code only reads first four alphabet of string. For example `*H1FINEdine#` it only prints `FINE`. How to print `FINEdine` ?? – MICRO Aug 05 '16 at 21:07
  • @EmbeddedGeek It does not reproduce. see [DEMO](http://ideone.com/6pemqG) – BLUEPIXY Aug 05 '16 at 21:42
  • I tried this code, it worked well. Issues on my side. It is reading whole character now. How can I handle negative values using this code? For example, `*H1-123456#` it consider it as text and display. What I need is it reads the `-` negative sign and copies all the numeric after that and print `value is " -123456"`. Is it possible? Can I have a check for negative values? Have a look what is happening right now. [link] (http://ideone.com/mSco0X) – MICRO Aug 06 '16 at 03:56
  • Change for the negative is easy. do it yourself. – BLUEPIXY Aug 06 '16 at 09:15
1

If you have only two input strings as said in the question you can directly compare them and do the action accordingly.

And if not this case then you can use the ASCII values to compare the characters in the string .

Nutan
  • 778
  • 1
  • 8
  • 18
  • No there are not two strings only. It can vary from `*H1000000#` to `*H1999999#` also it can have any text or characters in between. Comparing won't work, as there are not any predefined comparable string other than `*H1` and `#` – MICRO Aug 04 '16 at 15:45