[C] jak převést číslo uložené v poli na integer

C++, C#, Visual Basic, Delphi, Perl a ostatní

Moderátor: Moderátoři Živě.cz

Odeslat příspěvekod H4CK1 15. 10. 2011 19:29

Zdravím. Chtěl bych se zeptat, jak mám převést číslo, které mám uložené v poli, na celé číslo?
Myslím to takhle:
Na vstupu je číslo 199992, které mám uložené v poli:
pole[0]=1, pole[1]=9, pole[2]=9, pole[3]=9, pole[4]=9, pole[5]=2
A potřebuju z toho získat celé číslo 199992, které bych mohl následně dělit, sčítat, odčítat..
Zkoušel jsem to takhle, ale to my háže blbosti:
Kód: Vybrat vše
        cislo = 0;
        nas = 1;
        i = 0;
        while (pocetprv > i)
        {
        cislo = str[i] * nas + cislo;
        nas = nas * 10;
        i = i + 1;
        }
        printf("cislo je %d \n",cislo);


Díky za odpovědi :)
Desktop: i5 2400, GTX960, 8GB RAM, SSD Intel 330
Notebook: Acer Nitro 5, i5 7300HQ, GTX1050Ti
Smartphone: Samsung Galaxy A5 2016
H4CK1
Junior

Odeslat příspěvekod soban 15. 10. 2011 19:54

Záleží zda v tom poli je číslo (int), nebo znak (char)

Pokud je tam int stačí přičítat a násobit, pokud je tam znak tak podle znakové sady to musíš převést na číslo a pak zase násobit a sčítat.
/----------------------------------------\
| Petr Šobáň |
| Olomouc |
\----------------------------------------/
soban
Pokročilý

Odeslat příspěvekod H4CK1 15. 10. 2011 20:02

Co jedna položka v poli, to číslo 0-9. Přesně tak bych to chtěl udělat, násobením a přičítáním. Co je tedy v tom mém zdrojovém kódu špatně a jak to má být? Díky za rychlou reakci.
Desktop: i5 2400, GTX960, 8GB RAM, SSD Intel 330
Notebook: Acer Nitro 5, i5 7300HQ, GTX1050Ti
Smartphone: Samsung Galaxy A5 2016
H4CK1
Junior

Odeslat příspěvekod soban 15. 10. 2011 20:16

Tak třeba takto:

Kód: Vybrat vše

#include <stdio.h>


void main(void)
{

int pole[6];
int i,nas,cislo,delka;

nas=1;
cislo=0;

pole[0]=1;
pole[1]=9;
pole[2]=9;
pole[3]=9;
pole[4]=9;
pole[5]=2;


delka=sizeof(pole)/sizeof(int);

for (i = 1; i < delka; i++) nas *= 10;

for (i = 0; i < delka; i++)
{
   cislo += pole[i]*nas;
   nas /= 10;
}

printf("Zobrazím číslo: %d \n", cislo );

}



Chybička - opravena měl jsem v for omylem "<=" místo "<" -> chybný: for (i = 0; i <= delka; i++)
Naposledy upravil soban dne 16. 10. 2011 00:04, celkově upraveno 1
/----------------------------------------\
| Petr Šobáň |
| Olomouc |
\----------------------------------------/
soban
Pokročilý

Odeslat příspěvekod H4CK1 15. 10. 2011 21:04

Tak změna :D v poli mám ascii kódy čísel a ne rovnou čísla jak jsem si myslel. Jak je převést na čísla a dát tak dokupy jedno celé číslo? Už mě z toho hrabe, máme to jako úkol do školy a nesmíme použít funkci atoi :(. Jak na to?
Desktop: i5 2400, GTX960, 8GB RAM, SSD Intel 330
Notebook: Acer Nitro 5, i5 7300HQ, GTX1050Ti
Smartphone: Samsung Galaxy A5 2016
H4CK1
Junior

Odeslat příspěvekod Wikan 15. 10. 2011 21:37

ascii - 48
Wikan
Moderátor
Uživatelský avatar

Odeslat příspěvekod H4CK1 15. 10. 2011 22:52

Ježiš já sem v*l, dělám to dneska celej den a konečně mě to došlo. Moc díky za pomoc :)
Desktop: i5 2400, GTX960, 8GB RAM, SSD Intel 330
Notebook: Acer Nitro 5, i5 7300HQ, GTX1050Ti
Smartphone: Samsung Galaxy A5 2016
H4CK1
Junior

Odeslat příspěvekod soban 16. 10. 2011 00:02

Jako kdybych se na to neptal :-)

Kód: Vybrat vše
#include <stdio.h>


void main(void)
{

char pole[6];
int i,nas,cislo,delka;

nas=1;
cislo=0;

pole[0]='1';
pole[1]='9';
pole[2]='9';
pole[3]='9';
pole[4]='9';
pole[5]='2';


delka=sizeof(pole)/sizeof(char);


for (i = 1; i < delka; i++) nas *= 10;

for (i = 0; i < delka; i++)
{
        cislo += ((int)pole[i]-(int)'0')*nas;
        nas /= 10;
}

printf("Zobrazím číslo: %d \n", cislo );

}
/----------------------------------------\
| Petr Šobáň |
| Olomouc |
\----------------------------------------/
soban
Pokročilý

Odeslat příspěvekod Fuller009 17. 10. 2011 13:56

Myslím že by se sobanův výpočet dal zjednodušit cca takto:
Kód: Vybrat vše
#include <stdio.h>

void main(void)
{
char pole[6];
int cislo,delka;

cislo=0;

pole[0]='1';
pole[1]='9';
pole[2]='9';
pole[3]='9';
pole[4]='9';
pole[5]='2';

delka=sizeof(pole)/sizeof(char);

for (int i = 0; i < delka; ++i)
{
        //cislo +=cislo * 10 + ((int)pole[i]-(int)'0');
        //Samozřejmně že bez plus. to plus je za násobením. sem lama
        cislo =cislo * 10 + ((int)pole[i]-(int)'0');

}

printf("Zobrazím číslo: %d \n", cislo );
}


V podstatě jde jen o odstranění toho zbytečnýho foru na začátku a toho zbytečného dělení ve druhém foru. Po odstranění těchto 2 "neduhů" by měl být program efektivnější.
Naposledy upravil Fuller009 dne 18. 10. 2011 12:09, celkově upraveno 1
Fuller009
Junior

Odeslat příspěvekod soban 17. 10. 2011 15:41

Jasně....

To je tak když jsem to psal v rychlosti. No víc hlav víc ví......

PS ten for je správně ?
Kód: Vybrat vše
for (int i = 0; i < delka; ++i)
nemá tam být "i++" :-)
/----------------------------------------\
| Petr Šobáň |
| Olomouc |
\----------------------------------------/
soban
Pokročilý

Odeslat příspěvekod Wikan 17. 10. 2011 15:54

i++ a ++i znamená trochu něco jiného (post increment a pre increment), ale tady je to jedno.
Wikan
Moderátor
Uživatelský avatar

Odeslat příspěvekod pucmeloudek 17. 10. 2011 16:31

soban píše:PS ten for je správně ?

Hlavicka foru je spravne, ale ocividne psana od nekoho, kdo se chce odlisovat za kazdou cenu. Zatim jsem nevidel nikoho, kdo by psal inkrementaci do foru takle.
Co ale neni spravne, je += v tele toho foru.
pucmeloudek
Junior

Odeslat příspěvekod Nargon 17. 10. 2011 17:01

To ja uz jsem videl inkrement ve for cyklu psany takhle ++i. Je to o kousicek rychlejsi nez varianta i++, ale temer kazdy programator to pise jako i++, protoze se mu to lip pise. Alespon me teda jo.

A k tomu vykonu, je to fakt jen o zdibicek rychlejsi. A v tom cyklu to mozna optimalizace u prekladu prelozi na stejny kod, takze to ani nepujde poznat.
Desktop: Ryzen 7 1800X (3.95GHz, 1.35V), Asus Crosshair VI Hero, 16GB DDR4 Ram (3200MHz), 128GB SSD + 3TB HDD, Nvidia GTX 1080
Notebook: Asus UL50VT 15.6" (SU7300@1.7GHz, 4GB ram, 500GB HDD, Intel GMA 4500MHD + nVidia G210M, dlouha vydrz cca 7+ hod)
Nargon
Moderátor

Odeslat příspěvekod fotoba 17. 10. 2011 17:05

ak su to znaky
tak staci za posledny pridat znak 0= koniec retazca

string[n+1]=0;

a potom len

sscanf(string, "%d",&cislo);
fotoba
Junior

Odeslat příspěvekod soban 17. 10. 2011 18:58

No jo ale jak tam tu nulu přidat ?

Předpokládám že pole znaků je z jiné části programu. Takže by se muselo to pole překopírovat.

Jinak proč by se nemohlo += používat v for ?

Jinak i++ nebo ++i jsem skoušel a fakt to vygeneruje stejnej kod.



Kód: Vybrat vše
   .file   "pokus.c"
   .section   .rodata
.LC0:
   .string   "Zobraz\303\255m \304\215\303\255slo: %d \n"
   .text
   .globl   main
   .type   main, @function
main:
.LFB0:
   .cfi_startproc
   pushq   %rbp
   .cfi_def_cfa_offset 16
   .cfi_offset 6, -16
   movq   %rsp, %rbp
   .cfi_def_cfa_register 6
   subq   $32, %rsp
   movl   $0, -4(%rbp)
   movb   $49, -32(%rbp)
   movb   $57, -31(%rbp)
   movb   $57, -30(%rbp)
   movb   $57, -29(%rbp)
   movb   $57, -28(%rbp)
   movb   $50, -27(%rbp)
   movl   $6, -12(%rbp)
   movl   $0, -8(%rbp)
   jmp   .L2
.L3:
   movl   -4(%rbp), %edx
   movl   %edx, %eax
   sall   $2, %eax
   addl   %edx, %eax
   addl   %eax, %eax
   movl   %eax, %edx
   movl   -8(%rbp), %eax
   cltq
   movzbl   -32(%rbp,%rax), %eax
   movsbl   %al, %eax
   subl   $48, %eax
   addl   %edx, %eax
   addl   %eax, -4(%rbp)
   addl   $1, -8(%rbp)
.L2:
   movl   -8(%rbp), %eax
   cmpl   -12(%rbp), %eax
   jl   .L3
   movl   $.LC0, %eax
   movl   -4(%rbp), %edx
   movl   %edx, %esi
   movq   %rax, %rdi
   movl   $0, %eax
   call   printf
   leave
   .cfi_def_cfa 7, 8
   ret
   .cfi_endproc
.LFE0:
   .size   main, .-main
   .ident   "GCC: (GNU) 4.6.1 20110908 (Red Hat 4.6.1-9)"
   .section   .note.GNU-stack,"",@progbits
/----------------------------------------\
| Petr Šobáň |
| Olomouc |
\----------------------------------------/
soban
Pokročilý

Odeslat příspěvekod pucmeloudek 17. 10. 2011 20:52

Jinak proč by se nemohlo += používat v for ?

obecne samozrejme muze. v kodu od Fullera ale zpusobuje nesmyslny vysledek...

Jinac to, ze i++ v 3. casti foru je pomalejsi nez ++i je samozrejme donebe volajici pitomost, vysledek toho tretiho vyrazu se nijak nezpracovava, takze je jedno, jestli je to 9 nebo 10. To by musel bejt HODNE blaznivej prekladac, kterej by to prelozil jinak. ostatne obecne neni duvod ani tento zapis prekladat jinak:
Kód: Vybrat vše
for (int i = 0; i < delka; cislo =cislo * 10 + ((int)pole[i]-(int)'0'), i++)
        ;

To, ze nektere prekladaze zejmena v debug verzi trochu jinak preskladaj skoky a pouziti registru je vec jina; pokud clovek ale ty cykly takrikajic rozvine a diva se jen na vykonne instrukce, dostane opet nemlich to samy.
pucmeloudek
Junior

Odeslat příspěvekod Fuller009 18. 10. 2011 09:36

pucmeloudek píše:Co ale neni spravne, je += v tele toho foru.

Ano ano... v rychlém přepisování jsem, zapoměl toto plus umazat. nemá tam být a je to hrubá chyba... Hrozně se stydim :-[ :'(

k Rozdílu ++i a i++. Jejch použití je o zvyku, jednoduše jsem zvyklý to používat v tomto případě takto a zvyk je železná košile. Téměř jakýkoliv překladač to přeloží na stejný kód, tudíž v rychlosti rozdíl nebude... byl by jen v případě hooodně tupého překladače.
Fuller009
Junior

Odeslat příspěvekod soban 18. 10. 2011 10:12

Tak to tam oprav s nějakou poznámkou že jsi tam takovou chybičku měl. (Třeba ten řádek zakomentuj a přepiš znovu správně)

Jinak k ++i to vidím prvně (možná někdy dávno se to v nějaké učebnici C našlo) ovšem co jsem viděl psané tak vždy i++ .

Fakt to vidím na - "Musím se odlišovat, však to překladač přebere......"

A to int v for taky není moc košér... prostě mě se tam nelíbí...."for ( int i = 0; i < delka; ++i)"
/----------------------------------------\
| Petr Šobáň |
| Olomouc |
\----------------------------------------/
soban
Pokročilý

Odeslat příspěvekod cejdap 18. 10. 2011 10:25

K ++i a i++ je to i intu asi jedno. Prekladac to asi prelozi stejne. Otazka je jestli se da na to spolehat. U nas na skole je celkem bezne psat ++i, protoze kdyz clovek bude iterovat neco jineho nez je int treba iterator, tak pak je lepsi psat ++i. No a na to si clovek tak nejak navykne, ze to tak pise i u intu. Takze to neni tak, ze by clovek chtel vynikat. Spis si myslim, ze tomu trochu lip rozumi, nez ten kdo vsude pise tupe i++,proteze se jazyk jmenuje c++ a ne ++c :-)
cejdap
Junior
Uživatelský avatar

Odeslat příspěvekod pucmeloudek 18. 10. 2011 11:49

K tomy intu - naopak, takle je to pekny. Krasne omezis platnost promenne jen na ten cyklus...
pucmeloudek
Junior

Odeslat příspěvekod Fuller009 18. 10. 2011 12:20

soban píše:Fakt to vidím na - "Musím se odlišovat, však to překladač přebere......"

Že ty neznáš rozdíl významu ++i a i++ ještě neznamená, že to je něco co se nepoužívá... ++i se dá využít na spoustě místech k podstatnému zjednodušení výpočtů.
Překladač si to přebere tak, že i++ interpretuje právě jako ++i, protože nebereš v úvahu návratovou hodnotu tohoto výrazu.

soban píše:A to int v for taky není moc košér... prostě mě se tam nelíbí...."for ( int i = 0; i < delka; ++i)"

Tak tady se dost pleteš. nevím jak ty, ale já nežiju v c ANSI(nebo dokonce starší) kde nešli deklarovat proměnné mimo začátek funkce. V normě c99 je toto povolený, a dokonce doporučený zápis. Např kvůli
pucmeloudek píše:Krasne omezis platnost promenne jen na ten cyklus...
Fuller009
Junior

Odeslat příspěvekod soban 18. 10. 2011 14:10

Ale zde se nebavíme o C++ a pod..... pokud vidím dobře je v názvu pouze C.

Jinak já jsem se s ++i nesetkal ovšem netvrdím že to nemůže být výhodné použít v nějakých případech tak stejně použití int v for ovšem tam je to zase trošku diskutabilní pokud v programu používáme často for zda není lepší proměnnou definovat na začátku.
/----------------------------------------\
| Petr Šobáň |
| Olomouc |
\----------------------------------------/
soban
Pokročilý

Odeslat příspěvekod pucmeloudek 18. 10. 2011 20:58

sobane, tady se vsichni bavi o C, ne o C++. Samozrejme ze lze deklarovat promennou v cyklu i v obycejnem C (teda ne az tak obycnejnem, C99, popr. nejake proprietarni rozsireni predchoziho C90 nebo C89).
jinac lepsi neni deklarovat ji zvlast v zadnem pripade. Ani kdyz mas cykly 2 za sebou. Proste ta spolecna deklarace umozni tu promennou pouzivat i jinde a tim si koledujes o zbytecny problem z nepozornosti. Slusny prekladac stejne interne ty 2 promenne slouci na jedno pametove misto, takze ani na zasobniku nic neusetris. Dalsim duvodem pro definici primo ve foru je, ze vidis typ promenne primo v miste pouziti a nemusis ho hodinu hledat nekde na zacatku funkce...
pucmeloudek
Junior

Odeslat příspěvekod Fuller009 19. 10. 2011 08:23

soban píše:Ale zde se nebavíme o C++ a pod......

Kdybych se bavil o c++ psal bych o normách C99 a ANSI C? zmínil bych normu C++98 nebo která byla ta na které jsem se c++ učil(nevím jestli se už domluvili na novější verzi normy, ale 5 let zpět to bylo v plánu). Ale pokud mě paměť neklame tak v tomto případě C99 a C++98 mají stejné "znění".

soban píše:Jinak já jsem se s ++i nesetkal..

A víš aspoň ten rozdíl mezi těmi zápisy? ;-)


pucmeloudek píše: Slusny prekladac stejne interne ty 2 promenne slouci na jedno pametove misto


I kdyby nesloučil, tak tu paměť pro tu proměnou má alokovanou jen na běh cyklu a po konci cyklu by ji měl uvolnit. Jinak s tebou samozřejmně souhlasím.

Řekl bych že už jsme ale dost OT. Vše důležité k dotazu bylo už dávno řečeno.
Fuller009
Junior

Odeslat příspěvekod soban 19. 10. 2011 12:39

Jasně každý má nějaký spůsob psaní a pokud z nějakých důvodů nemusím ten zdroják optimalizovat (malá ram, rychlost atd...) tak většinou stačí jak to zoptimalizuje překladač. (a text mám zoptimalizovaný pro sebe abych se v tom sám vyznal....)
/----------------------------------------\
| Petr Šobáň |
| Olomouc |
\----------------------------------------/
soban
Pokročilý

Odeslat příspěvekod pucmeloudek 19. 10. 2011 22:02

Fuller009 píše:paměť pro tu proměnou má alokovanou jen na běh cyklu a po konci cyklu by ji měl uvolnit


je to samozrejme ouplne OT, ale tak pro uplnost - nemyslim, ze by to delal. proste na vstupu do funkce pripravi v zasobniku misto tak, aby ho bylo pro cely beh funkce dost, a na zaver ho zas vrati. aspon na x86 jsem nikdy zadnou obdobnou cilenou manipulaci s esp mimo prolog/epilog nevidel... ono by to stalo nejaky cas a to usporeny misto za to vesmes nestoji...
pucmeloudek
Junior

Odeslat příspěvekod Fuller009 20. 10. 2011 08:23

V optimalizacích překladačů se opravdu moc už nevyznám.. přecejen člověk zapomíná. Ale z logického hlediska To místo jistě neuvolní, jen si ho při překladu označí jako volné a případně ho využije později jinou proměnnou(jo v podstatě je interně sloučí jak si napsal dřív). Otázka uvolňování jak sjem ji napsal já vychází spíš z normy céčka - jak by se "mělo" chovat.

soban píše:Jasně každý má nějaký spůsob psaní a pokud z nějakých důvodů nemusím ten zdroják optimalizovat (malá ram, rychlost atd...) tak většinou stačí jak to zoptimalizuje překladač. (a text mám zoptimalizovaný pro sebe abych se v tom sám vyznal....)


Nepřipadá ti to v přímém rozporu s tvrzením

soban píše:Fakt to vidím na - "Musím se odlišovat, však to překladač přebere......"

Nebo jsi to bral podle tvrzení podle sebe soudím tebe?
Fuller009
Junior

Odeslat příspěvekod soban 20. 10. 2011 09:46

Ale to se nevylučuje.

Já to píšu nějak, a myslel jsem že prostě se chce za každou cenu odlišovat, ovšem vysvětlil že tak píše pořád......

Každý má na to nějaký názor. Svůj jsem vyjádřil, ovšem zakazovat takto psát for mu asi těžko můžu - to je jeho věc jak si to napíše pokud se v tom vyzná a je to pro něj čitelné.

Svoje názory jsme si řekly a víc to fakt nemá cenu rozmazávat - co člověk to jiný názor - překladač to přeloží stejně tak vlastně není co řešit.

Víc to fakt nemá cenu zde rozebírat pokud nepřijde někdo s něčím jiným jak převést char na číslo int.
/----------------------------------------\
| Petr Šobáň |
| Olomouc |
\----------------------------------------/
soban
Pokročilý


Kdo je online

Uživatelé procházející toto fórum: Žádní registrovaní uživatelé a 0 návštevníků