Kysymys:
Kokonaisluku ASCII: lle C18: ssa
user17592
2013-04-13 11:50:48 UTC
view on stackexchange narkive permalink

Kirjoitan koodia PIC18F46K22: lle käyttäen C18-kääntäjää. Haluan kirjoittaa kokonaisluvun \ $ n \ $ arvon ASCII-muodossa USART: n kautta tietokoneelleni.

\ $ n<10 \ $: lle se on helppoa:

  Write1USART (n + 0x30); // 0x30 = '0'  

Tämä toimi \ $ 10 \ le {} n \ le100 \ $:

  Write1USART ((n / 10 ) + 0x30); Write1USART ((n% 10) + 0x30);  

Mutta tämä ei todennäköisesti ole nopein mahdollinen tapa.

Joten onko jossain sisäänrakennettu toiminto tai toiminto, jota voisin käyttää vain sen sijaan, että pyörittäisin omaa ?

Tarkoitatko jotain, joka voisi saavuttaa int-koko?
@Kortuk kyllä, tai vielä parempi, `allekirjoittamaton pitkä`.
Vain ehdotus: `n + 0x30`: n sijaan kommentilla, että` `0x30 = '0' ', käytä` n +' 0 ''. Sekä C että C ++ edellyttävät, että numeroilla "0" - "9" on vierekkäiset kasvavat arvot, joten "n +" 0 "toimii aina ja on selkeämpi.
Viisi vastused:
Anindo Ghosh
2013-04-13 14:19:00 UTC
view on stackexchange narkive permalink

C18-kääntäjä tukee tavallisten C-funktioiden numero-ascii-ryhmää stdlib.h : itoa () , ltoa () , ultoa () ym.

Riippuen siitä, mikä kääntäjä / stdlib.h sinulla on, asiaankuuluva funktion prototyyppi olisi:

  extern char * itoa (char * buf, int val, int base); // allekirjoitettu inteksteri char * utoa (char * buf, allekirjoittamaton val, int-pohja); // allekirjoittamaton int  

tai

  ulkoinen char * itoa (char * buf, int val); // allekirjoitettu inteksteri char * utoa (char * buf, allekirjoittamaton val); // unsigned int  

Jos etsit suhteellisen vankkaa sisäänrakennettua "standardi " C-tapaa muuttaa numerosi ASCII-merkkijonoiksi, nämä xtoa () -funktioita olisi käytettävä.

Jos toisaalta pakotat puristamaan muutaman ylimääräisen jakson tai tavua muistia lopullisesta koodista, niin useita muita vastauksia kysymykseesi ovat oikea tapa edetä.

Nämä toiminnot eivät ole vakiintuneita C. `` itoa '' saattaa olla peräisin muinaisesta Borland C: stä, mutta se ei koskaan päässyt ISO C: ksi. jos he ovat siellä, käytä niitä.
user17592
2013-04-13 11:50:48 UTC
view on stackexchange narkive permalink

Olen itse tehnyt toiminnon:

  void writeInteger (allekirjoittamaton pitkä syöttö) {unsigned long start = 1; allekirjoittamaton pitkä laskuri; kun taas (start * 10 < = input) start * = 10; for (laskuri = alku; laskuri > = 1; laskuri / = 10) Write1USART (((syöttö / laskuri)% 10) + 0x30);}  
Tästä koodista keskustellaan [täällä] (http://electronics.stackexchange.com/q/65475/17592).
abdullah kahraman
2013-04-13 12:47:00 UTC
view on stackexchange narkive permalink

Voit kokeilla toimintoa, joka muuntaa merkkijonoksi brute-force-menetelmää. Alla oleva toiminto ei käytä moduulioperaattoria eikä kertolaskua. Se palauttaa merkkijonon.

  / * * Luo funktio, joka palauttaa merkkijonon. * Se hyväksyy 'inputValue' -arvon, joka on korkeintaan 255, mutta voit tehdä siitä int- tai longint-arvon ... * ... sen jälkeen, kun olet muokannut toimintoa. * inputValue: 5 7 6 * Numerot: 1. 2. 3. * / allekirjoittamaton merkki * returnString (allekirjoittamaton char inputValue) {staattinen allekirjoittamaton char prosessoituString [4]; // Palauta 3-numeroinen merkkijono. allekirjoittamaton merkki ensinDigitCounter = 0; // Raakavoiman laskuri ensimmäiselle numerolle. allekirjoittamaton merkki secondDigitCounter = 0; // Toisen numeron raakavoimalaskuri. if (inputValue > 99) // Jos meillä on 3-numeroinen luku, {while (inputValue > 99) // Kunnes luku on 3 numeroa, eli suurempi kuin 99, {inputValue - = 100; // Vähennä 100 ja .. firstDigitCounter ++; // .. lisää ensimmäinen numero. } while (inputValue > 9) // Kunnes luku on 3 numeroa eli suurempi kuin 9, {inputValue - = 10; // Vähennä 10 ja .. secondDigitCounter ++; // .. lisää toinen numero. } // Olemme nyt jättäneet 'inputValue' yksinumeroisena. processingString [0] = firstDigitCounter + 0x30; // Ensimmäinen numero käsiteltyString [1] = secondDigitCounter + 0x30; // Toinen luku käsiteltyString [2] = inputValue + 0x30; // Kolmas numero käsiteltyString [3] = '\ 0'; // Merkkijono. } else // Jos meillä on kaksinumeroinen luku, {while (inputValue > 9) // Kunnes lukumme on 3 numeroa eli suurempi kuin 99, {inputValue - = 10; // Vähennä 10 ja .. secondDigitCounter ++; // .. lisää toinen numero. } processingString [0] = secondDigitCounter + 0x30; // Toinen luku käsiteltyString [1] = inputValue + 0x30; // Kolmas numero
processingString [2] = '\ 0'; // Merkkijono. } palautus käsiteltyString; // Palauta käsitelty merkkijono.}  

Pastebin yllä olevasta koodista.

Olen jumissa dinosauruksen kanssa, jolla on vain kokoonpanija, ja luopuin ongelmasta lähettämällä tietoja heksalla. Joten +1 menettelylle, joka ei käytä kertolaskuja tai vielä tärkeämpää jakoja. Mutta se ei skaalaa helposti 4 tai 5-numeroisille numeroille. Onko ideoita kuinka skaalata se suuremmaksi?
@BobbiBennett Käytän yleensä hexia laitteissani, jos haluan, että lähtö näyttää hyvältä, annoin tietokoneeni tehdä sen. Olen myös käyttänyt mikrotietokoneita, jotka eivät tue kertomista suoraan, jakaminen vie yli millisekunnin, siinä tapauksessa tämä on ainoa tapa.
jippie
2013-04-13 12:48:18 UTC
view on stackexchange narkive permalink

Olen aiemmin käyttänyt sprintf (); -tunnusta. Sen lisäksi, että se on kätevää muotoilun kanssa, en ole täysin varma, onko se nopea ja pienen jalanjäljen. Sen mukana tulee.

  #include <stdio.h>const uint8_t stringLength = 16; char string [stringLength] = {0}; volatile uint32_t measuring = 12345; sprintf (string, "Mitattu:% lu millisekuntia \ n ", mittaus); uint8_t charCounter = 0; while ((charCounter < stringLength) ja (string [charCounter]! = 0x00)) {serialByteOut (string [charCounter]); // Lähetä yhden merkin charCounter ++;}  

Missä mittaus on ISR: ssä päivitetty 32-bittinen kokonaisluku, jonka haluan tulostaa ja merkkijono on lähtöpuskuri. % lu tarkoittaa, että pitkä allekirjoittamaton kokonaisluku on tulostettava ja \ n on uusi rivi.

Käyttö on pääosin sama kuin printf (); Asiakirjat ovat kattavia, ja ne löytyvät helposti Internetistä useilta verkkosivustoilta: http://linux.die.net/man/3/sprintf

Olen tässä pinossa oppimiseksi, vaikka se johtuisi omista virheistäni. Miksi äänestys alaspäin?
Käytän normaalisti myös sprintf (): ää, mutta se ei suinkaan ole pieni jalanjälki. En muista todellisia lukuja, mutta huomaat merkittävän koodikoon kasvun. Mutta pii on halpaa :-)
Marquis of Lorne
2013-04-13 13:06:12 UTC
view on stackexchange narkive permalink

Voit kokeilla tätä:

  void writeInteger (allekirjoittamaton i) {if (i > 9) writeInteger (i / 10); write1USART (i% 10 + '0');}  
Tämä koodi toimii (ASCII: ssa), mutta on tarpeettoman söpö kahdessa suhteessa: (1) "| "0" "+" 0 "sijasta hämmentää suoritettavaa operaatiota (vaikka se toimii ASCII" 0 ": lla). (2) rekursiivinen puhelu ei ole ihanteellinen mikro-ohjaimille, jotka toimivat usein hyvin pienillä pinon kooilla. Soittaja saattaa olla töykeä yllätys, jos he päätyvät yhdeksän rekursiotasoa kasaamaan pinoonsa.
@microtherion ASCII määritettiin kysymyksessä, mutta '0': n käyttö ei ole 'söpö', se on hyväksytty tapa erottaa merkistöjoukot. Jos kääntäjä käytti BCD: tä, koodi toimisi myös BCD: ssä. Se on 0x30, joka toimii vain ASCII: ssa. | | +: n sijasta ilmaisee tosiasian, että asetamme vyöhykebitin, emme suorita maagista laskutoimitusta. Rekursio ei voi toistua yli kymmenen kertaa, ellei allekirjoittamattomalla intillä ole 64 bittiä, mikä vie meidät kokonaan pois mikroprosessorien alueista, ja kymmenen kertaa eivät kuluta merkittävästi enemmän muistia kuin muut täällä olevat ratkaisut.
@EJP, ei ole "0", jota vastustan, se on |. Ilmaisemaamme operaatiota on "yhdistää numero vierekkäisten merkkien alueelle", joten + on tälle täysin selvä, ja se toimii tapauksissa, joissa kyseisen alueen nollan LSB: t eivät ole 0 (esim. (numeeristen esitysten lukumäärä Unicodessa). | on vähemmän selkeä ja vähemmän yleinen.
Mitä tulee rekursioon, joka ei käytä "merkittävästi" enemmän muistia, 32-bittiselle allekirjoittamattomalle 10-kertainen rekursio käyttää todennäköisesti 60-80 tavua RAM-muistia, riippuen mikro-ohjaimen osoitekoolta. Iteratiivinen ratkaisu käyttää <20 tavua. Joidenkin MCU: iden kanssa, joissa on vain 128 tavua RAM-muistia, 40 tavun ** tuhlaaminen voi ** olla merkittävää.
@microtherion Oletan, että sen pitäisi olla joko + '0' tai | 0x30. Rekursiokustannuksia tasapainottaa jossain määrin menetelmän oma pieni koko, mutta rajat ovat rajoja ja niitä on noudatettava varmasti.


Tämä Q & A käännettiin automaattisesti englanniksi.Alkuperäinen sisältö on saatavilla stackexchange-palvelussa, jota kiitämme cc by-sa 3.0-lisenssistä, jolla sitä jaetaan.
Loading...