topgun
Tengo un número entero como 1191223 y quiero iterar sobre los dígitos. No estoy seguro de cómo hacer esto en C, ¿hay alguna manera fácil de hacerlo?
Gracias.
BRPocock
¿Hacia adelante o hacia atrás?
Suponiendo un entero positivo:
unsigned int n = 1191223;
while (n != 0) {
doSomething (n % 10);
n /= 10;
}
…funcionará de menor a mayor, o…
EDITAR Había olvidado todo sobre esta solución que no funcionaba que tenía aquí. Tenga en cuenta que Very Smart People™ parece usar la iteración de menor a mayor de manera constante (tanto el kernel de Linux como el de GLibC). printf
por ejemplo, solo iterar hacia atrás) pero aquí hay una forma pésima de hacerlo si realmente no quieres usar snprintf
por alguna razón…
int left_to_right (unsigned int n) {
unsigned int digit = 0;
if (0 == n) {
doSomething (0);
} else {
digit = pow(10, 1.0+ floor(log10(n)));
while (digit /= 10) {
doSomething ( (n / digit) % 10 );
}
}
}
Supongo que es muy tonto suponer que tienes log10
y pow
pero no snprintf
por lo que un plan alternativo sería
int left_to_right_fixed_max (unsigned int n) {
unsigned int digit = 1000000000; /* make this very big */
unsigned int n10 = 10 * n;
if (0 == n) {
doSomething (0);
} else {
while (digit > n10) { digit /= 10; }
while (digit /= 10) {
doSomething ( (n / digit) % 10 );
}
}
}
… o, si realmente no tienes hardware para multiplicar/dividir, puedes recurrir al uso de una tabla de potencias de diez.
int left_to_right (unsigned int n) {
static const unsigned int digit [] =
{ 1,
10,
100,
1000,
10000,
100000,
1000000,
10000000,
100000000,
1000000000 /* make this very big */
};
static const unsigned char max_place = 10;
/* length of the above array */
unsigned char decimal;
unsigned char place;
unsigned char significant = 0; /* boolean */
if (0 == n) {
doSomething (0);
} else {
place = max_place;
while (place--) {
decimal = 0;
while (n >= digit[place]) {
decimal++;
n -= digit[place];
}
if (decimal | significant) {
doSomething (decimal);
significant |= decimal;
}
}
}
}
…que he adaptado de http://www.piclist.com/techref/language/ccpp/convertbase.htm en una versión algo más de propósito general.
-
su primera versión es de atrás hacia adelante, cómo obtiene los dígitos de adelante hacia arriba como 1234> 1 2 3 y luego 4 en lugar de 4 3 2 y 1 … gracias
– topgun
29 de diciembre de 2011 a las 21:34
-
la iteración funciona bien para adelante, pero se salta los ceros, ¿alguna idea de por qué está haciendo eso?
– topgun
29 de diciembre de 2011 a las 22:09
-
Wow, estoy seguro de que cometí un estúpido descuido. Le echaré un vistazo esta noche. 🙁 ¡Tontamente solo lo intenté con “1191123!”
– BRPocock
30 de diciembre de 2011 a las 0:29
-
Solo por curiosidad, ¿resolviste esto con 0? He repetido esto muchas veces, no estoy seguro de qué está causando que 0 sea eliminado.
– topgun
30 de diciembre de 2011 a las 15:15
moooeeeeep
En lo siguiente, supongo que te refieres a dígitos decimales (base 10). Probablemente puedas adaptar las soluciones a otros sistemas numéricos sustituyendo el 10
s.
Tenga en cuenta que la operación de módulo es algo complicado con respecto a los operandos negativos. Por lo tanto, he elegido que el tipo de datos sea un entero sin signo.
Si desea procesar primero el dígito menos significativo, puede probar el siguiente enfoque no probado:
uint32_t n = 1191223;
do {
uint32_t digit = n%10;
// do something with digit
}
while (n/=10);
Si prefiere recorrer los dígitos a partir del dígito más significativo, puede intentar adaptar el siguiente código no probado:
uint32_t n = 1191223;
#define MAX_DIGITS 10 // log10((double)UINT32_MAX)+1
uint32_t div = pow(10, MAX_DIGITS);
// skip the leading zero digits
while ( div && !(n/div) ) div/=10;
if ( !div ) div = 10; // allow n being zero
do {
uint32_t digit = (n/div)%10;
// do something with digit
}
while (div/=10);
Desea iterar sobre dígitos de base 10, pero un número entero no tiene concepto de notación árabe y dígitos. Conviértalo en una cadena primero:
int i = 1191223;
char buffer[16];
char *j;
snprintf(buffer, 16, "%i", i);
for ( j = buffer; *j; ++j ) { /* digit is in *j - '0' */ }
-
thiton Solo tengo curiosidad, ¿qué quiere decir aquí con *j – ‘0’, evita el primer 0? Estaba probando esto con un dígito de 0191223 y la longitud no llega a ser la correcta, ¿alguna sugerencia?
– topgun
29 de diciembre de 2011 a las 19:58
-
@kforkarim probablemente ese sea el
char2int
conversión:uint32_t digit = *j-'0';
. Asegúrese de manejar el'-'
la cadena puede contener.– mooooooooooooooooooooooo
29 de diciembre de 2011 a las 20:06
Puedes usar sprintf()
para convertirlo en un char
matriz, y luego iterar a través de eso, así (no probado, solo para comenzar):
int a = 1191223;
char arr[16];
int rc = sprintf(arr, "%d", a);
if (rc < 0) {
// error
}
for (int i = 0; i < rc; i++) {
printf("digit %d = %d\n", i, arr[i]);
}
void access_digits(int n)
{
int digit;
if (n < 0) n = -n;
do {
digit = n % 10;
/* Here you can do whatever you
want to do with the digit */
} while ((n/=10) > 0);
}
Algo como esto:
char data[128];
int digits = 1191223;
sprintf(data, "%d", digits);
int length = strlen(data);
for(int i = 0; i < length; i++) {
// iterate through each character representing a digit
}
Note que si usa un número octal como 0100
también tienes que cambiar el sprintf(data, "%d", digits);
a sprintf(data, "%o", digits);
.
Para mis propósitos, el siguiente código corto funcionó.
Tener una variable entera el_enteroy una variable entera suma_de_digitos inicializado (línea 1) Podrías hacer lo siguiente:
1) Convierta la variable entera en una variable de tipo cadena con el uso de la std::a_cadena(int) función.
2) Iterar los caracteres de la cadena resultante. for(char& c: str::to_string(the_integer))
3) Para volver a convertir los caracteres en números enteros, utilice c-‘0’ . Para esta solución, eche un vistazo a la discusión en (Convertir char a int en C y C++).
4) .. y sumándoles los dígitos: suma_de_digitos += c-‘0’
*) luego puede imprimir sus variables: líneas 3 y 4.
int the_integer = 123456789; int sum_of_digits;
for (char& c: std::to_string(the_integer)) {sum_of_digits += c-'0';}
std::cout << "Integer: " << the_integer << std::endl;
std::cout << "Sum of Digits << sum_of_digits << std::endl;
Tenga en cuenta que std::a_cadena() tiene algunas notas, consulte las referencias de C++ para ver si el código sigue siendo relevante para sus propósitos.
-
Describa lo que está haciendo su código en su respuesta.
– CtrlS
20 de marzo de 2019 a las 17:29