» »

[C++] Delo s *.txt datotekami

[C++] Delo s *.txt datotekami

Poldy ::

V file.txt imam razporejene številke:
2 4 7
3 5 4
1 8 9

Te številke bi rad prekopiral v dvodimenzionalni integer - int tabela[3][3]... če se ne motim je 2 - 0,1,2.

Kako se txt odpre sem že našel:

int main()

{

int tabela[3][3];

fstream file_op("c:\\file.txt",ios::in);



Sedaj pa kako naprej? Gotovo while kaj?
Upam na čimprejšne odgovore. Hvala

Backup22 ::

Torej, potreboval boš dve while ali for zanki. Prva se bo pomikala po vrstici (denso), druga pa dol (dol).
Psevdo:
for(od 1 do koca dat) // gre po "stolpcih"
for(od prvega znaka do presledka) // gre po vrsticah
branje iz *-txt in kopiranje v matriko (v i-to vrstico)


Upam, da sem pomagal kaj;)
//

Zgodovina sprememb…

  • spremenilo: Backup22 ()

Trololololo1 ::

Kaj pa če so številke večmestne? Tudi to je pametno upoštevat. Se pravi npr:

1 34 324
12 454 64
4 4 6

V datoteki boš bral od začetka in dokler bo znak, ki ga bereš številka if(isdigit(znak)), boš bral naprej, ker boš vedel da je to vse skupaj ena številka in, ko prideš do presledka boš z neko funkcijo moral spremeniti vse te števke v eno cifro. Priporočam, da si shraniš te števke v eno polje, ker boš tako lažje pretvoril v celo število.

Upam da sem kaj pomagal:)

Jean-Paul ::

Glede na to, kar imaš do sedaj, lahko storiš tako:
for(size_t i = 0; i < 3; ++i)
  for(size_t j = 0; j < 3; ++j)
    file_op >> tabela[i][j];
Drugače pa svetujem uporabo STL-ja in njegovih dobrot tudi namesto klasičnih C-jevskih polj.

Poldy ::

Aha, hvala za pomoč. res je, da sem čisto pozabil, da so številke lahko tudi večmestne. Kaj pa lahko naredim v tem primeru?

iggy ::

Hm ubistvu nebi smev biti problem samo pogledaš če je vmes presledek oz. se mi zdi da bi ti kakšna funkcija znala vzeti ven tudi več mestno številko.
Hey, you're fat!

bozjak ::

lahko pa tudi poenostaviš in breš s c-jevskimi funkcijami:


#include <stdio.h>

...

int tab[3][3];

FILE * fp;

fp = fopen ("krneki.txt", "r");

fscanf(fp, "%d %d %d\n", &tab[0][0], &tab[0][1], &tab[0][2]);
fscanf(fp, "%d %d %d\n", &tab[0][0], &tab[0][1], &tab[0][2]);
fscanf(fp, "%d %d %d\n", &tab[0][0], &tab[0][1], &tab[0][2]);

fclose(fp);

...

http://upor.blogec.si
http://bozjak.deviantart.com

Poldy ::

To kar je predlagal bozjak deluje odlično...

Danes sem izvedel, da bodo števila ločena z vejicami:( :

3,34,23
34,3,26
65,43,2

Tu pa se zatakne... ali je možno kako popraviti kodo?

iggy ::

Razbiješ to prve vejice, do druge ......
Hey, you're fat!

BlueRunner ::

Skrajno potratna varianta v C++.... (skupaj z pretvorbo v C-jevska polja). Odsvetujem za kakršno koli resno uporabo.

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

using namespace std;


const string separatorTokens(" ,");	// Tukaj našteješ vse tiste znake, ki lahko razmejujejo števila


int main(int argc, char**argv) {
	if (argc != 2) {
		cout << "Uporaba: " << argv[0] << " <ime datoteke>" << endl;
	} else {
		// Tole je branje v C++
		ifstream ins(argv[1]);
		string s;
		vector<vector<int>> lines;
		vector<int>::size_type maxLineElements = 0;

		while (getline(ins, s)) {
			if (s.length() > 0) {
				vector<int> line;
				string::size_type startPos = 0;
				string::size_type nextPos = s.find_first_of(separatorTokens, startPos);
				while (nextPos != string::npos) {
					if (nextPos != startPos) line.push_back(atoi(s.substr(startPos, nextPos - startPos).c_str()));
					startPos = nextPos + 1;
					nextPos = s.find_first_of(separatorTokens, startPos);
				}
				if (startPos < s.length()) line.push_back(atoi(s.substr(startPos, nextPos).c_str()));
				lines.push_back(line);
				maxLineElements = max<vector<int>::size_type>(maxLineElements, line.size());
			}
		}
		// Tukaj je branje v vektor vektorjev tipa int zaključeno

		// Pretvorba iz C++ vektorja vektorjev v C polje polij
		int **finalArray;

		finalArray = (int**)malloc(sizeof(int*) * lines.size());
		for (vector<vector<int>>::size_type ii = 0; ii < lines.size(); ii++) {
			finalArray[ii] = (int*)malloc(sizeof(int) * maxLineElements);
			for (vector<int>::size_type jj = 0; jj < maxLineElements; jj++) {
				finalArray[ii][jj] = jj < lines[ii].size() ? lines[ii][jj] : 0;
			}
		}

		// Testni izpis
		for (vector<vector<int>>::size_type ii = 0; ii < lines.size(); ii++) {
			for (vector<int>::size_type jj = 0; jj < maxLineElements; jj++) {
				cout << (jj > 0 ? " " : "") << finalArray[ii][jj];
			}
			cout << endl;
		}


		// Sproščanje pomnilnika
		for (vector<vector<int>>::size_type ii = 0; ii < lines.size(); ii++) {
			free(finalArray[ii]);
		}
		free(finalArray);

	}

	return 0;
}

Jean-Paul ::

Če imaš vejice, lahko v bozjakovi kodi samo zamenjaš %d %d %d z %d,%d,%d.

P.S.
Si popravil hrošča v bozjakovi kodi?

Zgodovina sprememb…

bozjak ::

uuuf BlueRunner-jeva koda ti pokaze da se da v c++ naredit znanost iz cist vsake malenkosti...
http://upor.blogec.si
http://bozjak.deviantart.com

BlueRunner ::

Znanost? Vedno! Lahko bi vse skupaj zaprl v predlogo (template), ki bi se tako obnašala ne glede na tip podatka: nizi, decimalna števila. Tako, da bi lahko naredil še večjo znanost. :D

Je pa v 16 vrsticah napisan splošen (čeprav tudi zelo potraten) način kako v pomnilnik prebrati poljubno število vrstic z poljubnim številom števil in (skoraj) poljubnimi ločili med števili. Zakaj? Ker slučajno nisem imel kaj drugega za početi, pa sem namesto runde Minesweeperja porabil nekaj minut za malo čečkanja po kodi.

Poldy ::

Hvala vsem. Zaradi enostavnosti se bom verjetno odločil za bozjakov pristop, v bluerunnerjevi kodi se izgubim že kmalu na začetku :D

Na začetku vsake "tabele" bom imel vedno podano, kakšna (XY) bo ta "matrika". Tako da bom uporabil bozjakovo branje, s tem da bom vse skupaj dal v zanke - kolikokrat se ponovijo bom pa prebral na začetku, kot sem že omenil...

Da je vse skupaj v poljih mi pa odgovarja za kasnejšo uporabo - preračunavanje. Vendar to niso matrike, bolj podobno koordinatam.

Ali je uporaba polj mar že zastarela?

Zgodovina sprememb…

  • spremenil: Poldy ()

Jean-Paul ::

Vendar to niso matrike, bolj podobno koordinatam.
Zakaj ne bi bile matrike? Poglej, tvoje koordinate so vektorji (sklepam da 3D), ki jih lahko "zložiš" v matriko.
Ali je uporaba polj mar že zastarela?
Glede na to, da si v naslovu teme navedel jezik C++ in da si se lotil odpiranja datotek v C++ načinu (ftsream) in ne v C načinu (FILE in fopen), smo ti nekateri predlagali, kako tvoj problem rešiti v C++ načinu, kjer lahko namesto klasičnih C-jevskih polj uporabiš npr. razred std::vector, ki omogoča varno dinamično zaseganje/spreminjanje velikosti polj. Ne gre za to, da bi bila polja kakorkoli zastarela - za tvoj primer so po vsej verjetnosti čisto primerna. Glede na napisano sklepam, da boš ti uporabljal statično določene velikosti polj, s čimer se znebiš vseh težav, ki so povezane z dinamično alokacijo (in kazalci, ki delajo v C-ju začetnikom pogosto težave), seveda na račun manjše splošnosti.

BlueRunner ::

Če se "odpoveš" C++ in se odločiš za C, kar je v tvojem primeru tudi smiselno, potem lahko dobiš tudi nekaj takšnega:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>


#define LINE_BUFFER_SIZE 1024

const char *delimiters = ", \n";

int main(int argc, char* argv[])
{
	FILE *f;
	char *stringBuffer;
	char *token;
	int rows, cols;
	int row, col;
	int **tabela;

	if (argc != 2) {
		printf("Uporaba: %s <ime datoteke>\n", argv[0]);
	} else {
		stringBuffer = (char*)malloc(LINE_BUFFER_SIZE * sizeof(char));
		f = fopen(argv[1], "rt");
		if (!feof(f)) {
			/* Preberem število vrstic in stolpcev iz prve vrstice */
			fgets(stringBuffer, LINE_BUFFER_SIZE, f);
			rows = atoi(strtok(stringBuffer, delimiters));
			cols = atoi(strtok(NULL, delimiters));
			/* Pripravim polje vrstic */
			tabela = (int**)malloc(rows * sizeof(int*));
			/* Če še ni konec datoteke... */
			if (!feof(f)) {
				row = 0;
				do {
					fgets(stringBuffer, LINE_BUFFER_SIZE, f);
					/* Če to ni prazna vrstica (konec datoteke ima pogosto to lepo lastnost...) */
					token = strtok(stringBuffer, delimiters);
					tabela[row] = (int*)malloc(cols * sizeof(int));
					/* Preberem vse elemente v vrstici */
					col = 0;
					while (token != NULL) {
						tabela[row][col++] = atoi(token);
						token = strtok(NULL, delimiters);
					}
					row++;
				} while (!feof(f) && (row < rows));
			}
		}
		/* Pospravim kazalce */
		fclose(f);
		free(stringBuffer);

		/* Testni izpis */
		for (row = 0; row < rows; row++) {
			for (col = 0; col < cols; col++) printf("%s%d", col > 0 ? " " : "", tabela[row][col]);
			printf("\n");
		}

		/* Sproščanje pomnilnika */
		for (row = 0; row < rows; row++) free(tabela[row]);
		free(tabela);
	}

	return 0;
}


Koda sicer ni "lepa", vendar pa za večino primerov zadošča. Seveda ti tabelo prebranih števil postavi dinamično, glede na podatke v prvi vrstici (vrstic,stolpcev). Aha, pa še nekaj: koda ne preverja izjem, kar boš moral narediti sam.

kihc ::

Morda ti tole kaj pomaga:

/* branje stevil iz datoteke */

#include <iostream>
#include <fstream>

using namespace std;
int main() 
{
    ifstream fin ("vhod.txt");
    int a, b, c;
    while(!fin.eof())
    {
    fin >> a >> b >> c;
    cout << a << " " << b << " " << c << endl;
    }
    cin.ignore().get();
    return 0;
}
x

Poldy ::

Program sem že spesnil in deluje odlično, hvala vsem. Na temu računalniku ga nimam, drugače bi ga prilepil...

Me pa samo še zanima, s čim je omejeno polje - tab[i][j] - kakšni sta lahko max. vrednosti za i in j?

Gundolf ::

Velikost polje je omejena le s tvojim pomnilnikom. V primeru ko pa polje definiraš znotraj funkcije, si pa omejen še malo bolj, z velikostjo sklada, ki pa je odvisna od OSa/prevjanika, je pa vedno manjša od velikosti celotnega pomnilnika.

Tr0n ::

Regex matching nübz, regex.


Vredno ogleda ...

TemaSporočilaOglediZadnje sporočilo
TemaSporočilaOglediZadnje sporočilo
»

C - shranjevanje rezultatov iz baze v array

Oddelek: Programiranje
71144 (843) Randomness
»

Pomoč pri programiranju z javo

Oddelek: Programiranje
203343 (2270) milc
»

[Java] Quicksort

Oddelek: Programiranje
6670 (506) MrBrdo
»

Java Objekti

Oddelek: Programiranje
102110 (1804) Mavrik
»

[c++] tabela? vecih dinamicnih struktur(classou)

Oddelek: Programiranje
71808 (1674) elKaktus

Več podobnih tem