How can I split a 9 character array with 3-2-2-2 cadence and convert it to 4 different int variables?
example:
char s[9] = {'9', '8', '7', '6', '5', '4', '3', '2', '1'}
a=987;
b=65;
c=43;
d=21;
How can I split a 9 character array with 3-2-2-2 cadence and convert it to 4 different int variables?
example:
char s[9] = {'9', '8', '7', '6', '5', '4', '3', '2', '1'}
a=987;
b=65;
c=43;
d=21;
You can use sscanf()
with caution for this job:
#include <stdio.h>
int main() {
char s[9] = { '9', '8', '7', '6', '5', '4', '3', '2', '1' };
int a, b, c, d;
{ // check that the input data starts with 9 digits
int n = 0;
sscanf(s, "%9*[0-9]%n", &n);
if (n != 9)
return 1;
}
// parse the input data into 4 integers composed of 3, 2, 2 and 2 digits
if (sscanf(s, "%3d%2d%2d%2d", &a, &b, &c, &d) == 4) {
printf("%d, %d, %d, %d\n", a, b, c, d);
}
return 0;
}
Output: 987, 65, 43, 21
The conversion specifiers in scanf()
support a numeric argument specifying the maximum number of characters to consume from the source: %3d
means convert a decimal integer number consuming at most 3 characters. 4 consecutive conversions, each with a specified length of 3 or 2 characters implement your goal precisely. Note however that initial white space consumed before each of the conversions is not counted so you must ensure that the input string starts with 9 digits for the above code to work, which can be performed with another sscanf()
unless the input is known to have the proper contents.
Alternately, if you know the input contains only digits, you can parse them on the fly with a simple function:
#include <stdio.h>
int get_int(char **pp, int n) {
int num = 0;
while (n --> 0) {
num = num * 10 + (*(*pp)++ - '0');
}
return num;
}
int main() {
char s[9] = { '9', '8', '7', '6', '5', '4', '3', '2', '1' };
char *p = s;
int a = get_int(&p, 3);
int b = get_int(&p, 2);
int c = get_int(&p, 2);
int d = get_int(&p, 2);
printf("%d, %d, %d, %d\n", a, b, c, d);
return 0;
}
You can use sscanf
to parse even a character array that does not have a string terminator, such as yours, as long as you give maximum field widths in all your conversion specifiers, such that sscanf
does not attempt to consume data past the end of the array. For example:
char s[9] = {'9', '8', '7', '6', '5', '4', '3', '2', '1'}
int a, b, c, d;
sscanf(s, "%3d%2d%2d%2d", &a, &b, &c, &d);
Do note that the field widths are not sufficient by themselves to ensure that the array bounds are not overrun, because %d
directives cause (s
)scanf
to consume leading whitespace, too. If the character data (not a string because it is not terminated) comes from an external source, then you really ought to verify its contents before parsing.
Here's one way:
#include <assert.h>
#include <stdio.h>
static int char_to_digit(char const ch) {
assert(ch >= '0' && ch <= '9');
return ch - '0';
}
static int arr_to_int(char const* arr, int const sz) {
int res = 0;
for (int i = 0; i < sz; ++i)
res = res * 10 + char_to_digit(arr[i]);
return res;
}
int main() {
char const s[9] = {'9', '8', '7', '6', '5', '4', '3', '2', '1'};
int const a = arr_to_int(s, 3);
int const b = arr_to_int(s + 3, 2);
int const c = arr_to_int(s + 5, 2);
int const d = arr_to_int(s + 7, 2);
printf("%d, %d, %d, %d\n", a, b, c, d);
}
The job is split between two small functions with descriptive names.