Conversão de uma string para um array de int
Quando temos um número numa string, por vezes, pode ser prático passar os dígitos desse número para um array de int. A maneira mais prática de o fazer é, sem dúvida, uma cópia "directa" da string para o array.
while (*src) *dst++ = *src++ - '0';
Mas esta solução prática pressupoe duas coisas que podem não ser verdade em alguns casos.
- src é composto unicamente por digitos (e o
\0
) - dst tem espaço suficiente para todos os dígitos de src.
A função que se segue evita os erros quando os pressupostos não são verdade, fiz uma função que passa os dígitos duma string para um array de int.
- A função atoarr() copia os digitos duma string para um array de int.
atoarr(array, 10, "1415926535"); /* array[0] = 1; array[1] = 4; ... array[9] = 5; */
- Os caracteres que não sejam dígitos são ignorados.
atoarr(array, 2, " 3\n"); /* array[0] = 0; array[1] = 3; */
- Se houver vários grupos de dígitos, só o primeiro grupo é considerado.
atoarr(array, 4, "abc123def456ghi"); /* array[0] = 0; array[1] = 1; array[2] = 2; array[3] = 3; */
- O tamanho do array de destino também é tido em conta e nunca será escrito nada fora do array.
- Se a string tiver poucos dígitos para o array, os elementos extra são preenchidos com 0.
atoarr(array, 4, "42"); /* array[0]=0; array[1]=0; array[2]=4; array[3]=2; */
- Se a string tiver muitos dígitos só os dígitos menos significativos é que são copiados para o array.
atoarr(array, 2, "8542"); /* array[0]=4; array[1]=2; */
Ficheiro: atoarr.h
#ifndef ATOARR_H_INCLUDED
#define ATOARR_H_INCLUDED
/* atoarr: 'converts' a string into an array of int
* the function ignores all characters that are not digits
* but only considers the first group of digits for the conversion
*
* Parameters:
* int *arr ==> the destination array
* int elems ==> number of elements in the destination array
* const char *src ==> the source string
* All consecutive digits in `src` are put into arr
* Return value:
* ATOARR_OK (0)
* all ok
* some characters in `src` may not be digits or whitespace
* ATOARR_SMALL (1)
* arr is too small for all digits in src
* the least significant digits are copied
* ATOARR_NODIGITS (2)
* no digits in src
* the destination array is filled with 0's
* ATOARR_NULL (-1)
* `src` or `arr` are NULL
* ATOARR_NOELEMS (-2)
* elems < 1
*/
enum ATOARR_CODES {
ATOARR_NOELEMS = -2, /* elems < 1 */
ATOARR_NULL, /* src or arr is NULL*/
ATOARR_OK, /* all ok */
ATOARR_SMALL, /* arr is too small */
ATOARR_NODIGITS /* no digits in src */
};
int atoarr(int *arr, int elems, const char *src);
#endif
Ficheiro: atoarr.c
#include <ctype.h>
#include "atoarr.h"
int atoarr(int *arr, int elems, const char *src) {
int ndx = 0; /* for indexing src first, then arr */
int ndigits; /* number of consecutive digits in src */
int first_unused_digit; /* position of first unused digit in src */
/* a digit becomes 'used' after it's been converted and copied to arr */
int small_arr_adjustment = 0; /* needed for when arr is not large enough for all digits in src */
int opt_tmp; /* optimize subtraction away from the loop */
int retval = ATOARR_OK; /* value to return to caller */
/* validate inputs */
if (!src || !arr) { return ATOARR_NULL; }
if (elems < 1) { return ATOARR_NOELEMS; }
/* skip initial non digits */
while (src[ndx] && !isdigit((unsigned char)src[ndx])) { ndx++; }
first_unused_digit = ndx;
/* count consecutive digits */
ndigits = 0;
while (isdigit((unsigned char)src[ndx])) { ndigits++; ndx++; }
/* if there are special circunstances, set retval */
if (ndigits > elems) { retval = ATOARR_SMALL; }
if (ndigits == 0) { retval = ATOARR_NODIGITS; }
/* fill the first 'unused' elements with 0 */
ndx = 0; /* re-use ndx */
opt_tmp = elems - ndigits; /* help the compiler optimize the subtraction away :) */
while (ndx < opt_tmp) { /* while (ndx < elems - ndigits) { */
arr[ndx] = 0;
ndx++;
}
/* adjust index if arr is too small */
if (elems < ndigits) { small_arr_adjustment = ndigits - elems; }
/* convert and copy digits */
while (ndx < elems) {
arr[ndx] = src[first_unused_digit + small_arr_adjustment] - '0';
first_unused_digit++;
ndx++;
}
return retval;
}
Exemplo de uso
#include <stdio.h>
#include "atoarr.h"
int main(void) {
const char *num;
int array[20];
int k, arr_size;
int val;
num = " 1234567890123456789 ";
arr_size = 20;
val = atoarr(array, arr_size, num);
printf("[%s] ==> ", num);
if (val >= ATOARR_OK) for (k=0; k<arr_size; k++) printf("%d ", array[k]);
printf("(return value: %d)\n", val);
num = " 1234567890123456789 ";
arr_size = 12;
val = atoarr(array, arr_size, num);
printf("[%s] ==> ", num);
if (val >= ATOARR_OK) for (k=0; k<arr_size; k++) printf("%d ", array[k]);
printf("(return value: %d)\n", val);
num = "42";
arr_size = 6;
val = atoarr(array, arr_size, num);
printf("[%s] ==> ", num);
if (val >= ATOARR_OK) for (k=0; k<arr_size; k++) printf("%d ", array[k]);
printf("(return value: %d)\n", val);
num = "0";
arr_size = 6;
val = atoarr(array, arr_size, num);
printf("[%s] ==> ", num);
if (val >= ATOARR_OK) for (k=0; k<arr_size; k++) printf("%d ", array[k]);
printf("(return value: %d)\n", val);
num = "";
arr_size = 6;
val = atoarr(array, arr_size, num);
printf("[%s] ==> ", num);
if (val >= ATOARR_OK) for (k=0; k<arr_size; k++) printf("%d ", array[k]);
printf("(return value: %d)\n", val);
num = "2008-December-10";
arr_size = 6;
val = atoarr(array, arr_size, num);
printf("[%s] ==> ", num);
if (val >= ATOARR_OK) for (k=0; k<arr_size; k++) printf("%d ", array[k]);
printf("(return value: %d)\n", val);
num = "pmg";
arr_size = 6;
val = atoarr(array, arr_size, num);
printf("[%s] ==> ", num);
if (val >= ATOARR_OK) for (k=0; k<arr_size; k++) printf("%d ", array[k]);
printf("(return value: %d)\n", val);
num = "60 something";
arr_size = 6;
val = atoarr(array, arr_size, num);
printf("[%s] ==> ", num);
if (val >= ATOARR_OK) for (k=0; k<arr_size; k++) printf("%d ", array[k]);
printf("(return value: %d)\n", val);
num = "RS232-C";
arr_size = 6;
val = atoarr(array, arr_size, num);
printf("[%s] ==> ", num);
if (val >= ATOARR_OK) for (k=0; k<arr_size; k++) printf("%d ", array[k]);
printf("(return value: %d)\n", val);
num = NULL;
arr_size = 6;
val = atoarr(array, arr_size, num);
printf("[NULL] ==> ");
if (val >= ATOARR_OK) for (k=0; k<arr_size; k++) printf("%d ", array[k]);
printf("(return value: %d)\n", val);
num = "2008";
arr_size = 1;
val = atoarr(NULL, arr_size, num);
printf("[%s] ==> ", num);
if (val >= ATOARR_OK) for (k=0; k<arr_size; k++) printf("%d ", array[k]);
printf("(return value: %d)\n", val);
num = "2008";
arr_size = 0;
val = atoarr(array, arr_size, num);
printf("[%s] ==> ", num);
if (val >= ATOARR_OK) for (k=0; k<arr_size; k++) printf("%d ", array[k]);
printf("(return value: %d)\n", val);
num = "2008";
arr_size = 1;
val = atoarr(array, arr_size, num);
printf("[%s] ==> ", num);
if (val >= ATOARR_OK) for (k=0; k<arr_size; k++) printf("%d ", array[k]);
printf("(return value: %d)\n", val);
return 0;
}
Resultado do teste
[ 1234567890123456789 ] ==> 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 (return value: 0)
[ 1234567890123456789 ] ==> 8 9 0 1 2 3 4 5 6 7 8 9 (return value: 1)
[42] ==> 0 0 0 0 4 2 (return value: 0)
[0] ==> 0 0 0 0 0 0 (return value: 0)
[] ==> 0 0 0 0 0 0 (return value: 2)
[2008-December-10] ==> 0 0 2 0 0 8 (return value: 0)
[pmg] ==> 0 0 0 0 0 0 (return value: 2)
[60 something] ==> 0 0 0 0 6 0 (return value: 0)
[RS232-C] ==> 0 0 0 2 3 2 (return value: 0)
[NULL] ==> (return value: -1)
[2008] ==> (return value: -1)
[2008] ==> (return value: -2)
[2008] ==> 8 (return value: 1)