PDA

Prikaži potpunu verziju : Treba mi pomoć oko pisanja programa [C++]


Demosten
19.3.2012, 20:46
Treba mi da napišem program [C++] koji će izvući određene podatke iz TXT fajlova i snimiti ih u fajl, tj u tabelu u određenom sheet-u u njemu. Razlog zašto to ne radim ručno je jer toga ima izuzetno mnogo(i fajlova i podataka u njima).
Idem prvo sa jednostavnijom varijantom:
Fajl izgleda ovako:

http://usnimi.me/slike/evaluate.gif

I iz njega bi mi trebale 3 ili 4 kolone sa podacima da se snime kao iste takve kolone u exel fajlu u određenom sheet-u. Recimo kolone ADAPS, MDAPS i HWAMS.

Da kasnije ne bi bilo "što odmah nisi sve rekao" evo ostatka problema:

U glavnom folderu imam dvadesetak podfoldera(podfolder1),a svaki od tih 20 podfoldera sadrži još 6-7 podfoldera(podfolder2) u kojima se nalaze fajlovi iz kojih treba izvući podatke. Fajlovi se uvek isto zovu (evaluate.out).
Ideja mi je da napravim program (uz nadam se vašu veliku pomoć :D) koji bi se pokrenuo iz glavnog foldera(nije potrebno da bude u prozoru mislio sam da se pokreće iz command line-a, pretpostavljam da je to i jednostavnije), pročešljao podfoldere i u svakom od podfoldera1 napravio excel fajl (sa recimo imenom <evaluate - ime podfoldera1.xls>) gde bi u sheet sa imenom podfoldera2 smestio podatke izvučene iz evaluate fajla, koji se nalazio u tom podfolderu 2. Znači taj jedan excel fajl bi imao 6-7 sheet-ova.

Za početak me interesuje kako izvući te kolone sa podacima...

PS: Nisam početnik u programiranju, ali bi možda bilo dobro da me tako tretirate jer sam dobrano zarđao... Ovaj problem bih taman iskoristio da (ponovo) naučim C++.
Za početak me interesuje kako izvući te kolone sa podacima...

PS: Nisam početnik u programiranju, ali bi možda bilo dobro da me tako tretirate jer sam dobrano zarđao... Ovaj problem bih taman iskoristio da (ponovo) naučim C++.

Belphegor
19.3.2012, 21:23
Evo nesto na brzinu, mozda moze i bolje:

Recimo evaluate.txt je ovaj:

1 97 1 1 MZ 84 -99 -99 -99 -99 162 ABC
1 31 1 1 MZ 84 -99 -99 -99 -99 107 ABC
1 42 1 1 MZ 84 -99 -99 -99 -99 184 ABC
1 56 1 1 MZ 84 -99 -99 -99 -99 111 ABC
ima 12 kolona i hoces da izvuces vrednost iz 2 i 11:


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

int main()
{
try
{
std::fstream in("evaluate.txt", std::ios::in);

std::vector<std::string> vout;
std::string line;
while(std::getline(in, line))
{
std::stringstream sstr;
sstr << line;
std::string tmp, out;
for(std::size_t i = 0; i < 12; ++i)
{
if(i == 1)
{
sstr >> out;
out += ' ';
}
else if(i == 10)
{
tmp.clear();
sstr >> tmp;
out += tmp;
vout.push_back(out);
out.clear();
}
else
{
sstr >> tmp;
}
}
}

const auto& end = vout.end();
auto it = vout.begin();
for(; it != end; ++it)
{
std::cout << *it << std::endl;
}
}
catch (const std::exception& e)
{
std::cerr << e.what() << std::endl;
}

std::cin.ignore();
return 0;
}


output:

97 162
31 107
42 184
56 111

s'tim da prvo treba preskociti prvih par redova. E sad za setanje po folderima trazi po MSDN-u FindFirstFile (http://msdn.microsoft.com/en-us/library/windows/desktop/aa364418%28v=vs.85%29.aspx) i FindNextFile (http://msdn.microsoft.com/en-us/library/windows/desktop/aa364428%28v=vs.85%29.aspx)
:ciao:

Belphegor
20.3.2012, 15:00
Evo ti kompletnije resenje u attachmentu, src i test folderi, samo posaljes kao argument stazu do root foldera. Ako sam dobro razumeo strukturu kako si objasnio.

Koristio sam LibXL biblioteku (http://www.libxl.com/) za snimanje .xls dokumenata (TRIAL), nadji nesto bolje ili iplementiraj sam.

Ima na par mesta treba da se prepravi kod jer sam zbrcko na brzaka ali radi.

zokocx
20.3.2012, 18:52
Evo za sat vremena, bar sam naucio nesto novo, ovo ispalo lakse od skolskog primera.
Koristio sam free biblioteku za .xls fajlove, trebalo bi da odradjuje posao za ovakave simple stvari.
http://code.google.com/p/excellibrary/

Samo ubacis .exe i .dll u taj glavni folder pokrenes i sve ti ispise sta je uradio.
Ubacio sam neke osnovne provere, i javlja ako naleti na neki dzumbus u .OUT fajlovima.

Belphegor
20.3.2012, 19:03
using ExcelLibrary.SpreadSheet;
E kad bi bilo samo ovako jednostavno i u C++. :D

Treba mi pomoć oko pisanja programa [C++]

Mada je ocigledno da mu je za ovo bolje i brze resenje C#.

zokocx
20.3.2012, 19:16
Mogao sam i da uradim preko COM Interop ali to bi zahtevalo da ima instaliranu odogovarajucu verziju MS office excel-a i kod izgleda malo glupavije, ovako radi i bez office-a.
using Microsoft.Office.Interop.Excel;

http://msdn.microsoft.com/en-us/library/ms173186%28v=vs.80%29.aspx

Btw. nisi morao da radis da cita komandnu linuju, napisao je da moze i samo da se stavi u taj osnovni folder.

Ne znam kako se radi sa COM objektima u C++, ali sigurno je neko karabudzenje.

Belphegor
20.3.2012, 19:24
Jeste karabudzenje za C++, nailazio sam na neke primere, da se prekrstis nogom i rukom. A vidim neki predlazu csv pa da se posle importuje ali ne znam da li bi onda mogao u vise sheetova da rasporedi.

A pogledaj samo koliko kosta za ovaj LibXL:
http://www.dodaj.rs/f/3y/6G/44gdiDM5/excel.jpg

zokocx
20.3.2012, 19:29
Ufff koja cena, a za .NET ima tih free biblioteka kolko hoces cak i nije tolko tesko sa COM objektom, ali za razliko ovo treba da radi perfektno i imas podrsku dok ovo free sto sam ja upotrebio, samo sam pogledao na Issues deo na code.google i ima svasta od nemogucnosti otvaranja (u kodu) velikih fajlova do nekompatabilnosti sa razim verzijama Excela.

Todors
20.3.2012, 20:10
Mislim da bih mu ovde CSV parser savršeno završio posao.

U C# bi kod izgledao ovako nešto: http://www.switchonthecode.com/tutorials/csharp-tutorial-using-the-built-in-oledb-csv-parser ,

a za c++ srećno :D.

Belphegor
20.3.2012, 20:36
Nasao sam nesto "free" http://www.codeproject.com/Articles/42504/ExcelFormat-Library upravo prelistavam src. S'obzirom da mu treba bazicna funkcionalnost mozda ce moci nesto da iskopa.

Demosten
21.3.2012, 0:22
Hvala puno svima na pomoći:tapsh:, pre sve pre svega Zokocx:n_klanja:. Sada ću da ga skinem i probam.

Jeste da sam rekao C++, ali to je zato što sam mislio da iskoristim ovo kao priliku da se ponovo malo podučim programiranju i mislo sam da je dobra ideja da krenem od C-a. Nisam znao da li je iz nekog jezika to lakše ili teže uraditi.
Definitivno ovakvoj Zokocxooj pomoći ne smem da gledam u zube, pa makar da je pisao i u LILA-777, a pogotovo i zato što baš i nemam suviše vremena za sve.

Kada sredim ove podatke onda ću se udubiti da vidim, kako i da li se to moglo uraditi u C++ ili kom drugom jeziku...

Inače javim se uskoro za drugi deo problema.;)
Rekao sam na početku da je ovo lakši deo...:D

zokocx
21.3.2012, 1:16
Pa nije bilo nesto tesko, realno da bi morao ovo da uradim u C++ dosta bi se pomucio, jer slabije poznajem jezik i jos slabije biblioteke.
Svaka cast Balphegor-u sto je probao to da uradi u C++, jedino da prepravi da program gleda samo foldere u folderu gde se pokrene i to je to.

Belphegor
21.3.2012, 3:40
...i trebaju malo da se seckaju stringovi jer hoce da mu se generisani xls-ovi zovu kao i "podfolder1" a sheetovi "podfolder2_sheet", ali me mrzelo. To je ionako malo posla.

Demosten
22.3.2012, 12:25
Uf, konačno sam uspeo da ga nateram da radi...
Najveći problem je bio što nisam uspevao da pročitam koju grešku prijavljuje zbog teget boje slova na crnoj pozadini.
Neku grešku bi mi prijavljvao, neke excel fajlove bi napravio, kada bih probao da ih otvorim Excel bi mi javljao da nisu ispravni, da su koruptovani...
Na kraju sam otkrio tek uz pomoć screenshoot-a i photoshop-a...
Prijavljivao mi je više od jednog .out fajla u folderu.
Greška je do mene jer niste imali sve informacije. U krajnjim direktorijumima je bilo više .OUT fajlova, ne samo Evaluate.out nego i SoilWatBal.out i Overview.out, što Zokocx nije znao kada je pravio proveru da li ima više .OUT falova. A podaci u SoilWatBal(koji je inače drugi deo problema) i Overview nisu istog formata kao u Evaluate iako su isto TXT fajlovi.
Malo sam pročačkao kod i uspeo da ga nateram da proradi. A koliko vidim radi savršeno. Još jednom hvala. :)

Evo ovde je bila "greška"(boldovao sam "problem"):

foreach (string sub2Dir in DataDirStruct[sub1Dir])
{
string SheetName = Path.GetFileNameWithoutExtension(sub2Dir);
string[] inFile = Directory.GetFiles(sub2Dir, "*.OUT", SearchOption.TopDirectoryOnly);
// if there's more than one .OUT file in subdir2
if (inFile.Length > 1)
{
Console.ForegroundColor = ConsoleColor.DarkBlue;
Console.WriteLine("Subdir2: " + sub2Dir + "\ncontains more than 1 .OUT files for evaluation\nOnly sheet for first file can be created!");
Console.WriteLine("Continue? (Y/N)");
ConsoleKeyInfo cki = Console.ReadKey(false);
if (cki.Key == ConsoleKey.N)
return;
}
// just process first one .OUT file
else if(inFile.Length > 0)
{
// sheet for subdir2
worksheet = new Worksheet(SheetName);
using (StreamReader inStream = new StreamReader(inFile[0]))
{
// Move to line 4
for (int i = 0; i < 3; i++)
A ovako sam ga "ispravio". Verujem da postoji i elegantniji i bolji naćin, ali zadovoljan sam što sam i ovo uspeo sam :kreza: (boldovao sam ispravku)

foreach (string sub2Dir in DataDirStruct[sub1Dir])
{
string SheetName = Path.GetFileNameWithoutExtension(sub2Dir);
string[] inFile = Directory.GetFiles(sub2Dir, "Evaluate.OUT", SearchOption.TopDirectoryOnly);
// if there's more than one .OUT file in subdir2
if (inFile.Length > 1)
{
/* Console.ForegroundColor = ConsoleColor.DarkBlue;
Console.WriteLine("Subdir2: " + sub2Dir + "\ncontains more than 1 .OUT files for evaluation\nOnly sheet for first file can be created!");
Console.WriteLine("Continue? (Y/N)");
ConsoleKeyInfo cki = Console.ReadKey(false);
if (cki.Key == ConsoleKey.N)
return;
*/ }
// just process first one .OUT file
else if(inFile.Length > 0)
{
// sheet for subdir2
worksheet = new Worksheet(SheetName);
using (StreamReader inStream = new StreamReader(inFile[0]))
{
Samo sam * zamenio sa Evaluate i stavio u komentar IF deo koda posle...

zokocx
22.3.2012, 13:01
Stavio sam ja proveru da li ima vise .OUT fajlova, :D malo nisam pazio na boju texta
Console.ForegroundColor = ConsoleColor.DarkBlue;
Console.WriteLine("Subdir2: " + sub2Dir + "\ncontains more than 1 .OUT files for evaluation\nOnly sheet for first file can be created!");


Recimo da se bolje vidi moze da bude zuta
Console.ForegroundColor = ConsoleColor.Yellow;

Ali ovo je manje vise obavestajna poruka, program ce uzeti da obradi 1. .OUT fajl koji bude u nizu izgleda da sreca dobro sluzi, Evaluate.out je pre ova dva ostala. A to sto prijavi gresku je jer se u ostalim .OUT fajlovima u tim kolkonama ne nalazi ceo broj i tu se corruptuje .xls fajl.
Da si samo spomenuo da svi ti fajlovi se zovu Evaluate.out, uradio bi kako treba.

Evo nabrzinu ispravljeno sad gleda samo jedan jedini evaluate.out (velika/mala slova fajla nisu bitna).

Demosten
22.3.2012, 13:08
program ce uzeti da obradi 1. .OUT fajl koji bude u nizu izgleda da sreca dobro sluzi, Evaluate.out je pre ova dva ostala. A to sto prijavi gresku je jer se u ostalim .OUT fajlovima u tim kolkonama ne nalazi ceo broj i tu se corruptuje .xls fajl.
Ne samo da se tu ne nalazi ceo broj, nego nema ni kolona :D


Da si samo spomenuo da svi ti fajlovi se zovu Evaluate.out, uradio bi kako treba.
Mislio sam da jesam, sada kada sam ponovo pročitao prvi post, video sam da sam bio dosta neodređen i nedovoljno precizan...


Evo nabrzinu ispravljeno sad gleda samo jedan jedini evaluate.out (velika/mala slova fajla nisu bitna).
Hvala još jednom :)...

Belphegor
22.3.2012, 13:46
Vidim iz tvojih ranijih postova da se bavis "medicinom", nadam se samo da ti je ovaj projekat edukativnog tipa, jer ako ga budes koristio u druge svrhe jedna greska moze da kosta nekog pacijenta zivota! :a_whistli

Demosten
22.3.2012, 16:26
Vidim iz tvojih ranijih postova da se bavis "medicinom", nadam se samo da ti je ovaj projekat edukativnog tipa, jer ako ga budes koristio u druge svrhe jedna greska moze da kosta nekog pacijenta zivota! :a_whistli

Da tada je bila medicina, tačnije medicinske labaratorije, ali na svu sreću više nije...
Sada je u pitanju agronomija, tako da ako nešto omašim može samo da nam izrastu ruke na leđima od onoga što pojedemo... :p

Belphegor
22.3.2012, 16:44
Pao sam sa stoilice.. :rofl: :tapsh:

zokocx
22.3.2012, 18:49
Zato sam ja stavio tamo GPL licencu, bez garancije :kreza:, a i meni nece nist da izraste ja jedem domacu hranu :D

Demosten
24.3.2012, 13:19
Dobro, malo se zezam. ;)
Samo je reč o statistici prinosa usled klimatskih promena i predviđanju na osnovu nje...

No, ovo je drugi deo problema:
Sve je isto kao u prvom slučaju, jedino su drugačiji podaci i fajl iz kog ih treba izvući.
Fajl se zove SoilWatBal.out. Nalazi se u istoj folderskoj strukturi, u podfolderima 2.
Isto je tekstualni, samo što podaci nisu dati po kolonama... Evo kako to i izgleda:

http://usnimi.me/slike/soilwatbal.gif

Podaci koje treba izvući su (označio sam ih na slici):
- Effective irrigation
- Precipitation
- Soil Evaporation
- Transpiration
- Potential ET
Podaci se na taj način ponavljaju 99 puta. Treba ih isto izvući u kolone, kao u prethodnom slučaju, samo što sada ima 5 kolona. Isto ih rasporediti po sheet-ovima, nazvanim na isti način u excel fajlove sa imenom <SoilWatBal - ime podfoldera1.xls>

Znači sve je isto osim fajla, podataka i načina kako su dati u fajlu...

Evo SoilWatBal.out fajla i takođe delimične folderske strukture. Kažem delimične jer ima mnogo više podfoldera1 u prinosu, a takođe nisam u svim krajnjim podfolderima2 ostavio fajlove zbog ograničenja od 100KB na veličinu attacment-a:

Belphegor
24.3.2012, 13:55
Ovo ti je isto prosto, samo napravis "parser" specifican za ovaj tip dokumenta.
Nego koliko si ti spreman da od tvog dela zarade da platis lepo zokocx-u da ti odradi? Ili bi ovo trebalo da radis rucno pa zarad duzih pauza na poslu hoces da automatizujes? :D

Demosten
24.3.2012, 14:32
Recimo da je bliže ovom drugom, mada u stvari nije u pitanju ni jedno, ni drugo.
Devojka mi radi master rad na agronomiji, pa joj pokušavam "pomoći", tj, olakšati i ubrzati proces...

zokocx
24.3.2012, 14:49
Ja se bas obradovao :p, da ti ovo olaksava posao jer jbg. morao sam da se odrekenem Metallice 'certa da bi uzeo Diablo3 na vreme ,mada metallica mi je vec smor vise mi treba kinta za novu stolicu za komp :D. Nista kad dodjem u NS sto moze biti vrlo skoro i vrlo cesto, duzan si mi pivo :).

Jer da se rucno izvlace podaci u excel fajlove ili na papir mnogo duze bi trajalo nego sto sam utrosio vremena da napravim program.

Sad bas i nema vremena (a i malo sam mamuran) moram da ucim za ispit koji imam u utorak, a plus gde su ostali forumasi programeri video sam ih par tamo u temi za Programing Challenge koji znaju C# sto se ne baci na ovaj lak challenge.

Algoritam za obradu ovog novog fajla ne smem da spomenem sto je kratak, staje u jednu kracu recenicu.

Evo i kod iz poslednje vrezije, sve sto je potrebno izmeniti je ime fajla koji se cita i sve od gde pise Parsing do kraj using bloka.

Belphegor
24.3.2012, 14:57
E pa ako je za ljubav onda u redu.

Malo editujes zokocx-ov kod:

//ne valja kod!
@zokocx
Da li si uploadovao pravi src? Jer vidim da izvlacis stare kolone u ovom.

EDIT: Nece da valja imaju 'space' karakteri u imenima.

EDIT2: Moram poceti da ucim i C# :D

MG-RAY
24.3.2012, 15:20
@Demosten:

Za ovaj drugi problem, iz fajla možeš vrlo kako podatke da izvučeš pomoću regulatnih izraza... Na primer:

(?<=Effective Irrigation\s*)\d{1,5}\.\d{2,4}

var matches = Regex.Matches(sadrzajFajla, @"(?<=Effective Irrigation\s*)\d{1,5}\.\d{2,4}");

^ Ovo radi samo u .net-u i još jednom regex engineu, da napomenem. :)

Belphegor
24.3.2012, 15:29
Samo sto covek verovatno nije upoznat sa regex-om tako da mu to nije nesto od pomoci, a verujem da je kratak rok za taj master sto radi da bi stigao sve to da predje na vreme. Osim ako mu ti ne uradis za ovih 5 "atributa".

MG-RAY
24.3.2012, 15:33
Samo sto covek verovatno nije upoznat sa regex-om tako da mu to nije nesto od pomoci, a verujem da je kratak rok za taj master sto radi da bi stigao sve to da predje na vreme. Osim ako mu ti ne uradis za ovih 5 "atributa".

Nije mi problem... Počeću sada pa postavljam kada završim (da malo pustim mozak na ispašu anwyz)... :D

zokocx
24.3.2012, 16:13
Taj kod sto sam stavio je za prosli problem ono sa kolonama, evo sad se bakcem sa Regex-om ... koji normalno vise odmaze nego sto pomaze.

Mada ja sam isao na resenje ako red sadrzi ime potrebnih kolona onda regex-ujem samo decimalnu vrednost i to upise odmah u cell.

@Balp: Lakse je nauciti C# posle C++, samo moras manje da razmisljas na low LVL sistnice, dok je teze sa C# na C++ moras da pazis na neke stvari koji su u C# postale trivijalne.

MG-RAY
24.3.2012, 16:31
Done.

Program očekuje dva parametra sa cmd linije, in (root folder za pretragu) i out (folder u koji će smeštati fajlove). Pogledaj debug opcije u propertijima projekta.

Disclaimer: Neću biti odgovoran za bilo kakve dodatne udove koji izrastu u budućnosti. :D

zokocx
24.3.2012, 16:57
Nije trebalo ni da se bakces sa cmd linijom dovoljno je bilo da program ocekuje da u folderu kojem se nalazi ocekuje struktru foldera

subdir1 - subdir2_1
- subdir2_2
subdir2 - subdir2_1
- subdir2_2
.
.
.


Evo glavnog dela mog resenja (mada dodao sam i nultu N kolonu za brojanje redova)

string[] names = { "Effective Irrigation",
"Precipitation",
"Soil Evaporation",
"Transpiration",
"Potential ET" };
// Create sheet headers
worksheet.Cells[0, 0] = new Cell("N");
worksheet.Cells.ColumnWidth[0] = 1152; // * 32 = pixels
worksheet.Cells[0, 1] = new Cell(names[0]);
worksheet.Cells.ColumnWidth[1] = 3904;
worksheet.Cells[0, 2] = new Cell(names[1]);
worksheet.Cells.ColumnWidth[2] = 2784;
worksheet.Cells[0, 3] = new Cell(names[2]);
worksheet.Cells.ColumnWidth[3] = 3456;
worksheet.Cells[0, 4] = new Cell(names[3]);
worksheet.Cells.ColumnWidth[4] = 2880;
worksheet.Cells[0, 5] = new Cell(names[4]);
worksheet.Cells.ColumnWidth[5] = 2688;
// row counter (0 are headers)
int r = 1;
// Start reading data
try
{
while ((oneLine = inStream.ReadLine()) != null)
{
for (int i = 0; i < 5; i++)
{
// check lowercase name in lowercase oneLine
if (oneLine.ToLower().Contains((names[i]).ToLower()))
{
worksheet.Cells[r, 0] = new Cell((int)r);
var doubleVal = System.Text.RegularExpressions.Regex.Split(oneLine , @"[^0-9\.]+").Where(c => c != "." && c.Trim() != "").SingleOrDefault();

worksheet.Cells[r, i + 1] = new Cell(decimal.Parse(doubleVal), "#,##0.00");
if(i == 4)
r++;
break;
}
}
}
}
catch (FormatException fex)
{
WriteErorrMsg(fex.ToString() + "\n");
WriteErorrMsg("Wrong format data in line: " + r.ToString() + " of file: " + inFile[0]);
}
catch (Exception ex)
{
WriteErorrMsg(ex.ToString());
}

Demosten
25.3.2012, 23:23
Hvala puno svima na trudu i pomoći, bila je zaista velika i svesrdna. Ovome se stvarno na početku nisam nadao... :n_klanja:
Zokocx, nadam se da te nisam suviše omeo oko pripremanja ispita... Lepo se provedi u utorak.

Nista kad dodjem u NS sto moze biti vrlo skoro i vrlo cesto, duzan si mi pivo :).


To definitivno... :)

zokocx
26.3.2012, 0:09
I onako bi me ometale druge beskorisne stvari u ucenju :qliranje: a dok sam ovo radio bar sam nesto naucio novo i napravio nesto korisno.

Pozeli srecu devojci na odbrani master rada.

Za pivo ce se cujemo pa vidimo... :ciao:

Belphegor
26.3.2012, 0:24
I onako bi me ometale druge beskorisne stvari u ucenju...

Kao na primer TES V. :D

zokocx
26.3.2012, 0:39
:kreza: To mi omelo januarski ...

sad je jos gore ne znam sta da pocnem :D, moram da prestanem da prokrastiniram i bacim se na Deus Ex serijal.

Demosten
28.3.2012, 11:05
Zokoc, kako je prošao ispit?