Millä konstilla saisi kokonaisluvun pilkottua yksittäisiksi luvuiksi?
Esim.
int luku = 673; <- tuosta tulisi seuraava muuttuja: osat[0] = 6, osat[1] = 7, osat[2] = 3.
Seuraava koodi toimii positiivisilla kokonaisluvuilla ja nollalla. Jos luku onkin negatiivinen, voit muuttaa sen ensin vastaluvuksi. Ensin selvitetään luvun pituus katsomalla, mikä on suurin luvun 10 moninkerta, joka on lukua pienempi tai sen kanssa yhtä suuri. Esim. jos luku on 673, viimeinen tällainen moninkerta on 100, joten luvussa on kolme numeroa. Tämän jälkeen haetaan luvun numerot yksi kerrallaan jakamalla sitä toistuvasti 10:llä ja ottamalla talteen jakojäännökset. Tällä menetelmällä numerot tulevat käänteisessä järjestyksessä, minkä vuoksi oli hyvä tietää niiden määrä etukäteen, jotta numerot saadaan suoraan oikeaan paikkaan taulukossa.
int luku = 673; int osat[20]; int pituus = 1; int laskuri = 10; /* selvitetään numeroiden määrä */ while (laskuri <= luku) { pituus++; laskuri *= 10; } /* haetaan numerot taulukkoon */ laskuri = pituus - 1; while (laskuri >= 0) { osat[laskuri] = luku % 10; luku /= 10; laskuri--; } /* näytetään määrä ja numerot */ printf("Luvussa on %i numeroa:\n", pituus); for (laskuri = 0; laskuri < pituus; laskuri++) { printf("%i\n", osat[laskuri]); }
tai sit superkäytännöllisemmin:
int luku; char tmp[10]; luku=673; itoa(luku,tmp,10); /* kymmenjärjestelmään */ printf("%c %c %c",tmp[0],tmp[1],tmp[2]);
Myöhästyin :(.
Esitän oman ratkaisuni kuitenkin kun se tuli tehtyä ja testattua:
#include<stdio.h> #include<stdlib.h> #include<math.h> int main(int argc, char **argv) { int luku = 673; int n = log10(luku)+1; int *osat; int tmp = luku; int i; osat = malloc(n*sizeof(int)); for(i = n-1; i >= 0; i--) { osat[i] = tmp%10; tmp /= 10; } printf("%d\n", luku); for(i = 0; i < n; i++) { printf("%d\n", osat[i]); } free(osat); return 0; }
tqunnerin vinkki ei oikeen toiminut. Antin koodi taas toimi vallan mainoisti. Kiitos!
punppis kirjoitti:
tqunnerin vinkki ei oikeen toiminut.
Mikähän tqunnerin vinkissä ei toiminut? Itselläni pelitti ainakin. Itoa-funktio löytyy ainakin stdlib.h-otsikkotiedostosta.
Siinä ei varmaan toiminut se, että luvuista tuli merkkejä eikä lukuja.
Koska minulla oli tähän liittyvää koodia, tarjoan omankin version. Tämä näyttää, miten tuon väärän järjestyksen ongelman voi kiertää rekursion avulla luontevasti. On tietenkin aivan laillista pitää iteratiivisista ratkaisuista tällaisen sijasta, mutta minä puolestani tykkään tästä.
Rekursio sopii tähän käyttöön, koska int-tyyppisen muuttujan koko on rajoitteinen. Ei tarvitse huolehtia, että tulee liian monta perättäistä kutsua.
Käytän -1:stä etumerkkitietona, ja se siis löytyy negatiivisen luvun numerolistan alusta.
#include <stdio.h> #define MAX_DIGITS 20 /* 20 digits in 2^64 */ #define END_DIGITS -2 /* marks the end of the array, -1 and 0 N.A. */ int* get_digits_rec (int n, int* out) { int last_digit = n % 10; int rest = n / 10; if (rest > 0) out = get_digits_rec (rest, out); *out++ = last_digit; return out; } void get_digits (int n, int buf[MAX_DIGITS+2]) { int* out = buf; if (n < 0) { n *= -1; *out++ = -1; } out = get_digits_rec (n, out); *out = END_DIGITS; } void test_it (int n) { int i=0; int digits [MAX_DIGITS+2]; printf ("Testing with %10d: ", n); get_digits (n, digits); printf ("["); while (digits[i] != END_DIGITS) { printf ("%d", digits[i]); ++i; if (digits[i] != END_DIGITS) printf (", "); } printf ("]\n"); } int main (void) { test_it (3); test_it (33); test_it (333); test_it (123456789); test_it (-1); test_it (-12); test_it (-123); test_it (0); return 0; }
No kun nyt kerran toteutuksia laitetaan näytille, niin laitanpa minäkin printf-funktiota varten tekemäni:
#define UINTMAX_DIGITS 20 /* Etumerkitön */ char *fmtuint(uintmax_t i, char *buf_end) { *--buf_end = 0; // Tekstin lopetus; while (i) { *--buf_end = (i%10) + '0'; i /= 10; } return buf_end; } /* Etumerkillinen */ char *fmtint(intmax_t i, char *buf_end) { if (i < 0) { buf_end = fmtuint(-i, buf_end); *--buf_end = '-'; return buf_end; } return fmtuint(i, buf_end); }
char puskuri[UINTMAX_DIGITS + 2]; char *teksti; teksti = fmtint(-123456, puskuri + sizeof(puskuri)); printf("%d = %s\n", -123456, teksti);
/* Ja se int-tauluksi muuttaminen, jos pitää tuota kautta tehdä */ /* Etumerkkiä ei nyt huomioida tässä. */ int numerot[UINTMAX_DIGITS]; int i; for (i = 0; teksti[i]; ++i) { numerot[i] = teksti[i] - '0'; }
Metabolix kirjoitti:
char puskuri[UINTMAX_DIGITS + 2]; char *teksti; teksti = fmtint(-123456, puskuri + sizeof(puskuri)); printf("%d = %s\n", teksti);
Metabolixin tapa kääntää numerot oikeinpäin on myös selkeä, jos minulta kysytään.
On ehkä vähän epähienoa tästä nyt nipottaa, mutta tuossa taisi mennä parametrit ja %-liput vahingossa vähän ristiin:
printf("%d = %s\n", teksti);
Vai onko minulla näin aamusta vielä silmät ristissä?
Kopeekka kirjoitti:
On ehkä vähän epähienoa tästä nyt nipottaa, mutta tuossa taisi mennä parametrit ja %-liput vahingossa vähän ristiin.
Huppeliskeikkaa, jäi se luku printtaamatta. :) Korjasinpa.
Aihe on jo aika vanha, joten et voi enää vastata siihen.