1

I have this char array:

char movimiento[]="L30 G10 L50 G-45 L-10 G50"

I want to get the value of the number after the letter 'L' and store them into an integer variable to use it afterward

eg. 30, 50, -10

I've tried this as ASCII code numbers start from 0==48 but I don't know how to store the chars into an integer: concat 3, 0 and store them into an integer.

int i = 0;
while(movimiento[i] != '\0'){
    if(movimiento[i]=='L'){
        while(movimiento[i]!=' '){
        printf("%d",(movimiento[i+1]-48));
        i++;
        }
    }
    i++;
}
Gerhardh
  • 11,688
  • 4
  • 17
  • 39
  • Possible duplicate of [How do I determine the size of my array in C?](https://stackoverflow.com/questions/37538/how-do-i-determine-the-size-of-my-array-in-c) – Guillaume May 16 '19 at 04:23
  • 1
    This may be helpful: [How to convert a string to integer in C](https://stackoverflow.com/questions/7021725/how-to-convert-a-string-to-integer-in-c) – Chris Rollins May 16 '19 at 04:27
  • 1
    You are close. After you find the L, call [strtol](https://linux.die.net/man/3/strtol) – MFisherKDX May 16 '19 at 04:28
  • @MFisherKDX I have trouble understanding how to implement the method – Ahmad Abu Abdou May 16 '19 at 04:49
  • You should not use magic numbers like `48` if you can use `'0'` instead. – Gerhardh May 16 '19 at 07:24
  • Possible duplicate of [How to convert an ascii character into an int in C](https://stackoverflow.com/questions/5322056/how-to-convert-an-ascii-character-into-an-int-in-c) Hi, thats answer is what you need I guess - https://stackoverflow.com/a/5322080/4892907 You can just cast char into int to get number from ASCII table, digits are 48 >= 57 (https://simple.wikipedia.org/wiki/ASCII) so , like `char number1 = '1'` then ascii value `(int) number1` = 48 – xxxvodnikxxx May 16 '19 at 07:44

3 Answers3

3

You extract each integer following a "prefix" character, by first locating the prefix character using strchr and then calling strtol beginning with the next character after the prefix.

With your string, some prefix character taken from the command line (or using 'L' by default if no argument is given) and a pointer to the beginning of your string:

int main (int argc, char **argv) {

    char movimiento[]="L30 G10 L50 G-45 L-10 G50",  /* string */
        prefix = argc > 1 ? *argv[1] : 'L',         /* prefix (L default) */
        *p = movimiento;                            /* pointer to string */

You can then locate each occurrence of the prefix in your string with:

    while ((p = strchr (p, prefix))) {  /* while next prefix found */
        ...

Then it is just a matter of attempting the conversion to long beginning with the next character:

        errno = 0;          /* set errno zero */
        char *endptr;       /* end-pointer for strtol */
        long tmp = strtol (p + 1, &endptr, 0);  /* convert from next char */

and validating the return from strtol along with endptr to check for any error condition resulting from the conversion attempt:

        if (p == endptr)    /* no digits convertedd */
            p++;            /* advance to next and try again */

If digits were converted and errno remains unset and the value of the long returned by strtol is within the range of int, then you have a good integer value, use it any way you like:

        else {
            /* if no error and in range of int -- good value */
            if (!errno && INT_MIN <= tmp && tmp <= INT_MAX) {
                int val = (int)tmp;
                printf (n ? ", %d" : "%d", val);    /* output int */
                n++;        /* increment counter */
            }
            p = endptr;     /* advance to one-past last digit converted */
        }

(note: so long as there were digits converted, p is updated with endptr to point to the next character after the last digit converted, see man 3 strtol)

You are basically done. You can check whether at least one number was output and tidy up by outputting a newline in that case with:

    if (n) putchar ('\n');  /* if integers found tidy up with newline */
}

Putting it altogether, you would have:

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

int main (int argc, char **argv) {

    char movimiento[]="L30 G10 L50 G-45 L-10 G50",  /* string */
        prefix = argc > 1 ? *argv[1] : 'L',         /* prefix (L default) */
        *p = movimiento;                            /* pointer to string */
    int n = 0;                                      /* counter */

    while ((p = strchr (p, prefix))) {  /* while next prefix found */
        errno = 0;          /* set errno zero */
        char *endptr;       /* end-pointer for strtol */
        long tmp = strtol (p + 1, &endptr, 0);  /* convert from next char */

        if (p == endptr)    /* no digits convertedd */
            p++;            /* advance to next and try again */
        else {
            /* if no error and in range of int -- good value */
            if (!errno && INT_MIN <= tmp && tmp <= INT_MAX) {
                int val = (int)tmp;
                printf (n ? ", %d" : "%d", val);    /* output int */
                n++;        /* increment counter */
            }
            p = endptr;     /* advance to one-past last digit converted */
        }
    }
    if (n) putchar ('\n');  /* if integers found tidy up with newline */
}

Example Use/Output

$ ./bin/intafterprefix
30, 50, -10

or, using the prefix 'G':

$ ./bin/intafterprefix G
10, -45, 50

Look things over and let me know if you have any further questions.


Handle Multiple Prefixes with strpbrk

Also note if you wanted to be able to pass a string of prefixes allowing you to use "G" or "L" or "GL" as the prefix characters, you can make prefix a string and use strpbrk instead of strchr. For example using:

    char movimiento[]="L30 G10 L50 G-45 L-10 G50",  /* string */
        *prefix = argc > 1 ? argv[1] : "L",         /* prefix (L default) */
    ...
    while ((p = strpbrk (p, prefix))) { /* while next prefix found */
       ...

Example Use/Output

That would then allow you to search for any or all prefixes, e.g.

$ ./bin/intafterprefix2
30, 50, -10

$ ./bin/intafterprefix2 G
10, -45, 50

$ ./bin/intafterprefix2 GL
30, 10, 50, -45, -10, 50
David C. Rankin
  • 81,885
  • 6
  • 58
  • 85
0
#include <ctype.h>  // isalnum
#include <stdio.h>  // printf
#include <stdlib.h> // atoi
#include <string.h> // memset

int main() {
    char arr[256] = "L30 G10 L55434 G-45 L-10 G50 L3";
    char buf[256];
    memset(buf, 0, 256);

    for (size_t i = 0; i < sizeof(arr); ++i) {
        if (arr[i] == 'L') {
            size_t count = 0;
            while (isalnum(arr[i]) || arr[i] == '-') {
                ++i;
                buf[count++] = arr[i];
            }
            int number = atoi(buf);
            printf("%d\n", number);
            memset(buf, 0, 256);
        }
    }

    return 0;
}

John DeBord
  • 638
  • 1
  • 5
  • 17
0

For this you could use sscanf

char movimiento[]="L30 G10 L50 G-45 L-10 G50";

struct coords { int l; int g; } coords[3];
if ( sscanf(movimiento, "L%d G%d L%d G%d L%d G%d"
  , &coords[0].l 
  , &coords[0].g
  , &coords[1].l 
  , &coords[1].g
  , &coords[2].l 
  , &coords[2].g
  ) == 6 )
{
  for (int i = 0; i < sizeof(coords)/sizeof(coords[0]); ++i)      
  {
    printf( "%d, %d\n", coords[i].l, coords[i].g );
  }
}
AndersK
  • 35,813
  • 6
  • 60
  • 86