Reputation: 33
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++;
}
Upvotes: 1
Views: 835
Reputation: 36092
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 );
}
}
Upvotes: 0
Reputation: 84642
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
Upvotes: 3
Reputation: 705
#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;
}
Upvotes: 0