Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: MS Visual C++ skippaa komentoja

filthy [12.11.2010 15:30:27]

#

#include "stdafx.h"
#include <iostream>
using namespace std;
void main()
{int x = 2;
cin>>x;
while(x == 2)
{cout<<"olooooo";
cin>>x;
}
}

Koodipätkä hyppää while-cinin yli ja menee ikuiseen silmukkaan, jos antaa ensimmäisessä cinissä kirjaimen. Kääntäjää en voi vaihtaa. Apua..

Teuro [12.11.2010 16:14:00]

#

Lue std::fail() (tai good()) ja toimi paluuarvon mukaisesti. Eli virheelinen syöte heittää virheen virtaan, josta sen voi lukea noilla funktioilla. std::clear() puhdistaa virheliput virrasta.

eq [12.11.2010 19:10:28]

#

OT: Miksi ihmeessä muotoilet koodin noin?

C++-kielessä ennalta määritelty ohjelman aloituspiste, main-funktio palauttaa aina kokonaisluvun. Jos käyttämäsi ohjelmointikieli on muuten C++:n kanssa yhteensopiva, lue eteenpäin.

(Edelleen C++:ssa:) Idiomaattinen tapa lukea syöte ja tarkastaa lukuoperaation onnistuminen (ts. että syöte oli oikein muotoiltu) on käyttää IO-virtojen ylikuormitettua operator void*-funktiota - eli evaluoida lukuoperaatio boolean-kontekstissa. Esimerkiksi:

type x;
while (std::cin >> x && x == jotain) {
   tee_jotain();
}

Jos et halua silmukan loppuvan mihin tahansa lukuvirheeseen (esim. vääräntyyppinen syöte), ei lukuoperaation onnistumista pidä tietenkään laittaa silmukan suoritusehdoksi.

Sampe [15.11.2010 20:26:08]

#

Ongelmasi ymmärtämiseksi on hyvä tietää pääasiat cin:n toiminnasta. Cin siis yrittää lukea syötevirrasta mahdollisimman monta merkkiä, jotka se voi tulkita muuttujan arvoksi. Kun ensimmäinen kelpaamaton merkki tulee vastaan, cin lopettaa lukemisen ja loput merkit jäävät syötevirtaan.

Kun cin yrittää lukea kirjainmerkkiä virrasta, se ei osaa tulkita sitä int-tyyppiseksi arvoksi. Tällöin lukuoperaatio epäonnistuu, mutta merkki jää yhä syötevirtaan. Tällöin samaa virheellistä merkkiä yritetään lukea seuraavallakin kierroksella.

Helppo tapa välttää oikeastaan kaikki ongelmat syöteen luvun kanssa:

#include <iostream>
#include <string>

using namespace std;

int main()
{
   string rivi;

   // Luetaan kaikki syöte mitä käyttäjä antaa
   getline(cin, rivi);

   // Tutkitaan onnistuiko luku
   if(!cin)
   {
      cout << "Lukeminen epäonnistui!" << endl;
      return 0;
   }

   // TODO: pilko rivi-muuttuja ja hae siitä
   // varsinainen syöte.
}

Uskaltaisin sanoa, että tämä tapa toimii kaikissa tapauksissa ja hyvin pienin muutoksin sama toimii myös tiedostojen kanssa. Haittapuolena on se, että joutuu käsittelemään merkkijonoja. Eli jos tarkoituksena on ainoastaan lukea yksittäsiä numeroita ym. yksinkertaista, pääsee eq:n esittämällä tavalla pienemmällä vaivalla.

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta