Hei osaatteko sanoa mistä tässsä nyt on kyse kun alla olevalla koodilla koetan tulostaa silmukassa kaikki ascii merkit (siis standardi osan merkit 0 - 127), mutta viimeinen merkki jää puuttumaan.
char i; for(i = 0; i < 127; i++) { printf("ASCII merkki %c\n",i ); }
Jos muutan tuon silmukan ehdon tälläiseksi, i <= 127, jää silmukka ikuisesti pyörimään. Sitä en oikein ymmärrä, arvoalue 127 pitäisi riittää char tyypille, eikö niin?
Jos muutan i:n tyypiksi int ja pidän ehdon (i <= 127), saan kaikki merkit tulostumaan (siis ne jotka merkein voidaan esittää).
Pelkkä char on etumerkillinen ja voi siten sisältää arvot luvusta -128 lukuun 127. Ongelma on siinä, että i:tä kasvatetaan vielä kerran tuon 127:n jälkeen, jotta ehto "i <= 127" muuttuisi epätodeksi ja suoritus päättyisi. Nythän arvoksi ei kuitenkaan tule 128 vaan -128, josta i kasvaa 127:een yhä uudelleen ja uudelleen. Voit käyttää tuossa esim. tyyppi unsigned char, joka kattaa arvot 0-255 tai sitten jo kokeilemaasi intiä.
Edit: Jos aivan tarkkoja ollaan niin ASCII:ssa ainoastaan merkit 32-126 ovat tulostettavia. Loput ovat ns. ohjausmerkkejä.
Ok, kiitos.
Suosittelen int-tyypin käyttöä silmukassa ja erillistä muunnosta char-tyyppiseksi tulostusvaiheessa. (Tosin printf:lle char-muuttujakin välitetään inttinä, joten muunnoksella ei tuossa tapauksessa olisi merkitystä.) Monet standardikirjaston funktiot (mm. fgets) käyttävät int-tyyppiä myös siksi, että sillä saadaan ilmaistua char-lukualueen ulkopuolella oleva virhekoodi EOF. Tällaiselle on joskus tarvetta omissakin ohjelmissa.
Hyvä muistutus tuo unsigned char juttu on asia joka pitää itse muistaa eräistä asioista ei osaa olla varuillaan.ps. ei muuten näytä olevan kaikilla kääntäjillä pelkkä char etumerkkillinen olen ihan varma että perus chariin sain joskus 255 luvunkin talteen standardia tai sitten ei samapa se mutta menikö niin että jos haluan etumerkillisen varmasti laitan signed enkä unsigned...
Otetaan nyt vielä se standardikin mukaan (lihavointi oma):
lainaus:
The implementation shall define char to have the same range, representation, and behavior as either signed char or unsigned char.
Monissa kääntäjissä tuon voi valita jollain lipulla (GCC: -funsigned-char). Borlandilla se ainakin joskus oli oletuksena unsigned.
Jos char-muuttujaan on tarkoitus säilöä merkkejä, kannattaa minusta pitää se pelkkänä charina, koska eihän merkin lukuarvolla pitäisi olla paljonkaan väliä ohjelmassa. Jos taas on tarkoitus käyttää sitä 8-bittisenä lukuna, on ehkä järkevintä määritellä typedefillä sille tarkoitusta kuvaava nimi (kuten tiny_int).
Metabolix kirjoitti:
Otetaan nyt vielä se standardikin mukaan (lihavointi oma):
Jos taas on tarkoitus käyttää sitä 8-bittisenä lukuna, on ehkä järkevintä määritellä typedefillä sille tarkoitusta kuvaava nimi (kuten tiny_int).
Mikäli muuttujan koolla on merkitystä, on suositeltavampaa käyttää standardissa (C99) tätä varten määriteltyjä tyyppejä, jotka on esitelty stdint.h:ssa. 8-bittinen etumerkitön luku on uint8_t, etumerkillinen int8_t jne.
Schedler kirjoitti:
8-bittinen etumerkitön luku on uint8_t, etumerkillinen int8_t jne.
Pilkunviilausta \o/
Ihan hyvä huomautus. Jos kuitenkin tarkoituksena on saada vain pieni luku, int_fast8_t tai int_least8_t ovat turvallisimmat vaihtoehdot sen mukaan, onko nopeus vai koko tärkeämpi. Nämä on varmasti määritelty, kun taas uint8_t ei ole pakollinen, jos järjestelmä ei tue etumerkitöntä, tasan 8-bittistä muuttujaa.
Jos on kyse jostain täsmällisestä binaariformaatista (esim. tiedostojärjestelmästä), uint8_t on teoriassa oikea tyyppi, mutta tällaisissa ollaan joka tapauksessa jo C:n standardin ulkopuolella, kun joudutaan huomioimaan BE/LE-asioita ja tietueiden täytetavuja.
Aihe on jo aika vanha, joten et voi enää vastata siihen.