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++;
}
6
  • Possible duplicate of How do I determine the size of my array in C? Commented May 16, 2019 at 4:23
  • 1
    This may be helpful: How to convert a string to integer in C Commented May 16, 2019 at 4:27
  • 1
    You are close. After you find the L, call strtol Commented May 16, 2019 at 4:28
  • @MFisherKDX I have trouble understanding how to implement the method Commented May 16, 2019 at 4:49
  • You should not use magic numbers like 48 if you can use '0' instead. Commented May 16, 2019 at 7:24

3 Answers 3

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
Sign up to request clarification or add additional context in comments.

Comments

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;
}

Comments

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 );
  }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.