Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: C++: Tiedoston haku/luku ei toimi?

Sivun loppuun

Oskuz [25.08.2013 16:29:06]

#

Siis ohjelma sanoo suoritettaessa tuon "tiedoston avaus ei onnistu",
Debuggeri taas ei sano mitään. Käyttis on windows ja kehitys ympäristö on Dev-c++, että pitääkö tiedosto lisätä erikseen jostain asetuksista vai onko tuo koodi vain päin mäntyä:

int main() {
	std::ifstream inputData;
inputData.open("new 1.txt");
int i=0;
int j=0;
char lista [i] [j];
if (!inputData.good()){
	std::cout << "tiedoston avaus ei onnistu" << std::endl;
	return 1; }
while (inputData.good())
{
while ((inputData.good())&&(inputData.get()))
{
	inputData >> lista [i] [j];
	j++;
} i++;
}


 for ( int a=0; a<j; a++ ) {
    	std::cout << lista [a] << std::endl; //tulostetaan arvot


    inputData.close(); }

   std::cout << "siinäpä se" << std::endl; }

Teuro [25.08.2013 18:36:00]

#

Tiedoston tulee olla ajokansiossa, jotta kyseinen tiedosto voidaan lukea. Mulla ainakin toimi ihan käännös g++ main.cpp -o oskuz ja ajettaessa oskuz tulee

lainaus:

`■(
siinõpõ se

Jos haluat tiedoston kaikki rivit tietorakenteeseen, niin alla oleva koodi lukee tiedostoa rivi kerrallaan.

#include <iostream>
#include <fstream>
#include <vector>

int main() {
    std::ifstream inputData;
	inputData.open("new 1.txt");

	std::string rivi;
	std::vector <std::string> rivit;

	if (!inputData){
		std::cout << "tiedoston avaus ei onnistu" << std::endl;
		return 1;
	}

	while (std::getline(inputData, rivi)) {
		rivit.push_back(rivi);
	}

    inputData.close();

    for (unsigned int i = 0; i < rivit.size(); ++i) {
		std::cout << rivit[i] << std::endl;
    }

    std::cout << "siinäpä se" << std::endl;
}

Metabolix [26.08.2013 21:59:56]

#

Eräs koodin keskeinen ongelma on tässä määrittelyssä:

char lista [i] [j];

En tiedä, mitä kuvittelet tuossa tekeväsi. Rivi on C++:n standardin vastainen; muuttujia ei voi käyttää taulukon koon määrittämiseen. Jotkin kääntäjät kuitenkin hyväksyvät rivin, mutta koska i = j = 0, tuloksena on 0-alkioinen taulukko. Taulukon koko ei enää myöhemmin muutu. En osaa suoralta kädeltä sanoa, mihin luettavat merkit tarkalleen tuossa tilanteessa päätyvät, mutta ainakin ne sotkevat vääriä alueita muistista ja kaatavat ohjelman.

Toinen ongelma on tässä silmukassa:

while ((inputData.good())&&(inputData.get()))

Kutsut jo while-rivillä get-funktiota eli heität siinä yhden merkin hukkaan, jolloin taulukkoosi päätyy vain puolet merkeistä. Voisit käyttää sen sijaan peek-funktiota, joka vain kurkistaa seuraavan merkin mutta jättää sen myöhemmin luettavaksi.

Lisäksi ilmeisesti luulet, että silmukka päättyisi aina rivin loppuessa, vaikka näin ei missään nimessä ole: rivin loppua merkitsee rivinvaihtomerkki '\n' (tavu 10 eli 0x0a), joten silmukka vain jatkuu, kunnes tiedosto loppuu. Vaikka loisit ison taulukon ja lukisit siihen kaikki merkit, ne menisivät taulukossa yhdelle riville.

Taulukossa jokaisen tekstirivin loppuun pitäisi laittaa 0-tavu, jotta tekstiä pystyisi käsittelemään. Ylipäänsä tuollaisen tietorakenteen käsittely on hyvin hankalaa. Teuro tarjosi onneksi jo paremman.

Oskuz [27.08.2013 16:57:53]

#

Kiitos nyt aluksi Teurolle, alkohan se toimimaan vaikkakin syistä joita Metabolix esitti ei se kyllä toiminut. Että seuraavaksi aletaankin tutkimaan tuota vector kirjastoa.

Teuro [28.08.2013 05:39:17]

#

Juu siis kun käännetään ohjelma seuraavasti:
g++ osku.cpp -Wall -Wextra -pedantic -o osku

lainaus:

C:\Users\teurokoski\Documents\Oskuz>g++ osku.cpp -Wall -Wextra -pedantic -o osku

osku.cpp: In function 'int main()':
osku.cpp:2: error: 'ifstream' is not a member of 'std'
– –
osku.cpp:6: warning: ISO C++ forbids variable length array 'lista'
osku.cpp:6: warning: ISO C++ forbids variable length array 'lista'
osku.cpp:8: error: 'cout' is not a member of 'std'
– –

Tässä nähdään, että koodista puuttuu otsikot fstream ja iostream. Lisätään kyseiset kirjastot, sekä yriteään kääntää uudestaan.

lainaus:

C:\Users\teurokoski\Documents\Oskuz>g++ osku.cpp -Wall -Wextra -pedantic -o osku

osku.cpp: In function 'int main()':
osku.cpp:9: warning: ISO C++ forbids variable length array 'lista'
osku.cpp:9: warning: ISO C++ forbids variable length array 'lista'

Tässä nähdään, että muuttujat eivät voi olla taulukon kokona. Lisätään kokeeksi sana const molempien muuttujien eteen. Tällöihän koko on vakio.

lainaus:

C:\Users\teurokoski\Documents\Oskuz>g++ osku.cpp -Wall -Wextra -pedantic -o osku

osku.cpp: In function 'int main()':
osku.cpp:9: warning: ISO C++ forbids zero-size array 'lista'
osku.cpp:9: warning: ISO C++ forbids zero-size array 'lista'
osku.cpp:18: error: increment of read-only variable 'j'
osku.cpp:19: error: increment of read-only variable 'i'

Voihan räkä nollan pituista taulukkoa ei voi tehdä, sekä muuttujia pitäisi voida vielä muuttaakin silmukoissa. Tämän tehtävän voisi ratkaista taulukoillakin, mutta se vaatisi ohjelmoijalta hyvää muistinhallintaa. Parempi ohjelmoida c++:a ihan noilla valmiilla listoilla ja taulukoilla.

Ylipäätään kannattaa joskus kääntää ohjelmat ihan "käsin" komentoriviltä, niin saa paremman käsityksen miten kääntäjä toimii. Kehitysympäristöksi kannattaa harkita Code::Blocks nimistä vekotinta. Dev-Cpp on bugisempi ja sen kehitys oli pitkään telakalla. Nykyään sitäkin kai taas kehitetään.

feenix [28.08.2013 22:28:13]

#

Ja Visual Studiotakin saa ihan ilmaiseksi Expressinä, silläkin tulisi heti kirjoittaessa jo valitusta kaikista noista. Ei tarvitse edes yrittää kääntää, Intellisense huomaa kaikki noista ongelmista. Ja toki kaikki kääntäjän ilmoitukset näkyvät tulosteena kun kääntää. Aloittelijallekin erittäin mukavaa kun näkee koko ajan missä on virhe.

Oskuz [29.08.2013 10:27:49]

#

Juu, mie vaihoinkin jo lennosta tuohon Expressiin..
Löysi heti koodista kaikkea korjailtavaa.

Voiko muuten tiedostoon vertailla, eli tarkistaa löytyykö joku sana tiedostosta, lataamatta sen sisältöä johonkin muutujaan?

Teuro [29.08.2013 14:48:56]

#

Lukemalla datan muuttujaan ja hakemalla sanaa luetusta datasta. Vaikkapa näin:

#include <iostream>
#include <fstream>

int main() {
    std::ifstream sisaan;
	sisaan.open("new 1.txt");

	std::string hakusana = "juttu";
	std::string teksti;
	std::string sana;
	std::vector <std::string> rivit;

	if (!sisaan){
		std::cout << "tiedoston avaus ei onnistu" << std::endl;
		return 1;
	}

	while (sisaan >> sana) {
		teksti += sana;
	}

	std::size_t kohta = teksti.find(hakusana);

	if (kohta != std::string::npos) {
		std::cout << "Ensimmäinen '" << hakusana << "' löytyi kohdasta " << kohta << std::endl;
	}

    sisaan.close();

    std::cout << "siinäpä se" << std::endl;
}

Oskuz [29.08.2013 16:02:41]

#

Kiitos taas vinkistä Teuro, pitää kokeila tuota kun pääsee koneelle.

Grez [29.08.2013 16:58:03]

#

Oskuz kirjoitti:

Voiko muuten tiedostoon vertailla, eli tarkistaa löytyykö joku sana tiedostosta, lataamatta sen sisältöä johonkin muutujaan?

Ei voi.

Tai tietysti voi ilman että omassa koodissa lataa käyttämällä ulkoista ohjelmaa (joka lataa tiedoston sisältöä)

Oskuz [02.09.2013 17:53:39]

#

Vielä tuli tämmönen ongelma (ei liity ylempiin).

while (luku==0) {           //tätä riviä valittaa.
		 if (luku%2==0) { luku= luku/2;}
		 else { luku=luku-1; maara++;}}

sannoo tämmöstä tuosta silmukasta:

lainaus:

1>numeron tuhoaja.cpp(13): error C2059: syntax error : 'while'
1>numeron tuhoaja.cpp(13): error C2143: syntax error : missing ';' before '{'

Että ite en keksinyt miksise tuota valittaa.

Teuro [02.09.2013 18:15:17]

#

Näytäs pari riviä ennen tuota while riviä. Ilmeisesti siellä on jokin syntaksivirhe, koska tuossa osassa eri näytä olevan virhettä. Yleisin lienee puuttuva ;-merkki rivin lopusta.

Oskuz [02.09.2013 18:32:57]

#

juu, virhe löyty, siellä oli vähän ylimäärästä tavaraa :)


Sivun alkuun

Vastaus

Aihe on lukittu, joten siihen ei voi vastata.

Tietoa sivustosta