» »

[c++]malo pozabljene osnove ali drugačen način v linux?

[c++]malo pozabljene osnove ali drugačen način v linux?

'FireSTORM' ::

torej mam en program z zagonskim parametrom
da vpišem v konzolo
ime_programa parameter
in potem program ta parameter preveri prvi del programa če je pravi ali ne
in nekak mi ne dela...
no pa naj kar koda pove svoje:

int main(int argc, char *argv[])
{
  if ( argv[1] == NULL )
  {
    tralala;
  }
  if ( argv[1] == "-h" )
  {
    hopsasa;
  }


in zdaj nevem če ne primerjam tega dobro ker sem že pozabil malo na te osnove(MFC je pustil svoje sledi)
ali se pa to v linux enostavno postori malenkost drugače?
Those penguins.... They sure aint normal....

Monster ::

rajsi primerjaj z kakim string compare ... ala strcmp( ... ) == 0 > potem je enak :)
Ka zaboga...

'FireSTORM' ::

seveda!

najlepša ti dala ;)
Those penguins.... They sure aint normal....

fiction ::

Namesto if ( argv[1] == NULL )
raje poglej argc. Ponavadi je le-ta 1 (ker imamo v argv[0] ime), ce je
2 pa tudi argv[1] ni NULL.

Aja za parsanje command line parametrov obstaja veliko boljsi nacin kot rocno preverjanje argv.
man 3 getopt

'FireSTORM' ::

raje poglej argc. Ponavadi je le-ta 1 (ker imamo v argv[0] ime), ce je
2 pa tudi argv[1] ni NULL.


tega dela nisem ravno najbolje razumel
če je argc 2, torej če argc 2 ni NULL oziroma argv[2] ni NULL potem 100% tudi argv[1] ni NULL, sem te razumel prav?
če sem te mi je to čist logično, ne moreš met pod dva nekaj pod ena pa nič

bom pa prečekiral še optget ;)
Those penguins.... They sure aint normal....

Gwanaroth ::

Če je argc 1, potem je v argv[0] ime programa. Če je argc 2, potem je v argv[1] prvi parameter.
Lights often keep secret hypnosis..

Quikee ::

argv[1] == NULL

Na to se sploh ne moreš nanašat. Če jaz ne podam parametra je argv array velik le en element. S tem ukazom pa bi gledal izven array, kjer so podatki nedoločeni in ne nujno, da so enaki NULL (0). V ekstremnem primeru se ti bi lahko tudi zgodilo, da bi ti program crknil (seg fault).

argc ti pa ravno pove velikost argv array-a.

'FireSTORM' ::

seg fault sem dobival to je res
ampak ne zaradi tega
to je pa bil drug problem ki sem ga pa rešil...
za enkrat še pa nisem mel tega problema pri tem if stavku
bom pa spremenil da slučajno nebi prišlo do tega problema

in tudi if stavke bom pustil ker mam klobaso if stavkov in bom zamenjal z switch kar bi bilo bolj pametno...ali pač?
Those penguins.... They sure aint normal....

Zgodovina sprememb…

BigWhale ::

Ali preverjaj argc ali pa delaj z getopt.... tole nekaj vmes je toplovodarjenje za brez veze.

Gundolf ::

> in tudi if stavke bom pustil ker mam klobaso if stavkov in bom zamenjal z switch kar bi bilo bolj pametno...ali pač?
Tko bom reku, to je C++, če imaš klobaso kakršnihkoli stavkov, potem delaš nekaj narobe. Klobase if-ov in predolgi switch-i - to se da rešit objektno, s callbacki, pa še kako. Ampak to magari pusti tako kot maš ali spremeni tako, kot se boš bolje znašel. Bolj pomembno je, da poslušaš nasvete, ki si jih dobil, saj to, da nisi dobil segfaulta lahko pripišeš le svoji prekomerni sreči (če ga nisi dobil, še ne spremeni dejstva, da delaš nekaj narobe).

BigWhale ::

Seveda je potrebno poudariti, da kar vseh if stavkov ne mores nadomestiti s switchi.

switch() zna delati z int tipom spremenljivk.

'FireSTORM' ::

ok sem to zdaj malo spremenil
bom pa še podal eno vprašanje kar tukaj čeprav nima dosti veze z tem zgoraj kar je
ampak se mi ne da odpirat nove teme

torej, mam en class ustvarjen
in v tem classu je ena public char* funkicja
ki jo kličem iz main, ta funkcija pa mi vrne en string velikosti 8 znakov tipa private char str[7]
nikoli več, nikoli manj...vsaj tak bi moralo biti
ok manj res ni nikoli
torej mam v main:

classname variable;
cout << variable.funkcija() << endl;


vse lepo in prav ampak včasih(zelo pogosto) pripiše kar nek char
ali je to ?, % karkoli, glavno neki znakec mi pripiše zraven
tudi če v main deklariram še en char variable ime npr. var2
in potem kličem funkcijo tako

var2 = variable.funkcija();
ali:
strcpy(var2,variable.funkcija());

je popolnoma enako

kako lahko rešim tole zadevico?

edit: pozabil omenit, v funkciji se pa spremenljivka tipa private char str[7] lepo postavi na osem znakov, torej "12345678"
le ko jo kličem iz main se tist znakec prikrade zraven in vedno samo en in nič več
Those penguins.... They sure aint normal....

Zgodovina sprememb…

Gundolf ::

Prvič, spremenljivka tipa char[7] sprejme točno 7 znakcov in ne 8.
Drugič, če delaš s C-jevskim tipom stringa, se pravi z arreyem znakov, potem ga moraš vedno končati z 0. Zadnji znak mora biti char(0) oz. '\0'. Torej, če hočeš, da ti funkcija vrne nek tekst, dolg 8 znakov, mora ta tekst biti pospravljen v array dolg 9 znakov ali več, kjer je deveti znak '\0'.

Zdej, kako ti pa tale tvoja funkcija dejansko vrača tvoj tekst je pa spet druga zgodba, ker po temle: "var2 = variable.funkcija();" sklepam, da imaš tudi to narobe.

'FireSTORM' ::

saj pravim da sem sprobaval več variant kako bi rešil, nobena iz moje glave ni bila uspešna

a se ne šteje 0 1 2 3 ... 7 torej to je 8 + 1 za \0 in bi blo char[7] čisto dovolj za 8 znakcev, če odmislim \0
vsaj tak so nam povedali v srednji šoli v drugem letniku...
Those penguins.... They sure aint normal....

Zgodovina sprememb…

Quikee ::

a se ne šteje 0 1 2 3 ... 7 torej to je 8 + 1 za \0 in bi blo char[7] čisto dovolj za 8 znakcev, če odmislim \0
vsaj tak so nam povedali v srednji šoli v drugem letniku...


Ne.
Kot je rekel gundolf. char str[8]; bo nardil polje 8 znakov, kjer bo str[0] prvi in str[7] zadnji znak, pri tem pa \0 (oz. 0, NULL) ne bo vštet zraven.
Najboljše,da narediš polje devetih znakov in vse vrednosti polja postaviš na 0 (z memset), saj vrednosti elementov polja, ko polje deklariraš niso nujno 0.

BlueRunner ::

tip[velikost] v C in C++ vedno deklarira polje velikost "velikost" elementov, z prvim indeksom 0 in zadnjim indeksom velikost-1. Velikokrat, kar nikakor ne velja samo za polja tipa char, pa se na uporabi vrednost 0 (pri številih) ali pa vrednost NULL (pri kazalcih), s katero se označi konec niza, katerega dolžina znotraj polja vnaprej ni znana. Ker se to vrednost zapiše znotraj samega polja, to pomeni, da imamo za niz tako na voljo en znak manj, kot pa je definirana velikost polja. Kar začetnike v tem C-ju velikokrat zmede, je obstoj celega kupa str* funkcij, ki dajo občutek, da je "string" nek dejansko definiran tip. V resnici pa so to samo pomožne funkcije za polja tipa char, v katerih se nahajajo nizi, ki se zaključujejo z vrednostjo 0 (oziroma znakom '\0').

Druga, pogosta napaka, ki jo začetniki naredijo, pa je napačno vračanje polja iz fukncije. Tukaj se lahko zelo hitro pripeti cel kup napak, zaradi nerazumevanja dejanskega delovanja kopice, sklada in prenosa parametrov. Tako lahko metoda vedno vrne char* (kar lahko zapišeš tudi kot char[]), vendar pa mora takšno polje tudi nekje obstajati. Če ga vračaš iz sklada metode, potem bo pri naslednjem klicu katere koli druge metode, ki uporablja parametere, ali pa lokalne spremenljivke, vsebina takšnega polja uničena. Natančno tako, kot se to zgodi tebi. Ker tako ugotoviš, da ne moreš vračati lokalne spremenljivke, si pač izbereš možnost, da boš polje naredil z "malloc" na kopici, namesto na skladu kot lokalno spremenljivko. Seveda pa je zabave konec tisti trenutek, ko ugotoviš, da delaš vedno nova in nova polja na kopici, nikoli pa jih ne sprostiš z "free". Če bo tvoj program deloval dovolj časa, boš zagledal "Out of memory", oziroma bo OOM na Linuxu ubil tvoj proces. Če pa tvoj program ne bo deloval dovolj dolgo, pa bo še vedno "nehigienično" napisan. Če si nenatančen pri takšnih "malenkostih", potem boš nenatančen tudi pri zadevah, ki bodo daleč od malenkostnih.

Sedaj imaš za vračanje polja iz funkcije še dve poti: v C-ju imaš (statično) rezerviran en sam globalen blok pomnilnika na kopici, ki ga "recikliraš". Pri zaporednih klicih funkcije prepišeš star rezultat, kar včasih je problem, včasih pa ni. Veliko str* funkcij iz standardne C knjižnice počne ravno to. Potem imaš pa čisti C++ način: uporabiš razred string, ki te reši vsega poslovodsta okoli pomnilnika, hkrati pa čisto pravilno deluje z cout objektom.

To je pa tudi vse, kar je... poglej si kaj je (sistemski) sklad in kako deluje. Pri golem C-ju je še posebej pomembno, da razumeš kako se prenašajo parametri med metodami in kako so shranjene lokalne spremenljivke. Ko boš znal to, boš tudi razumel kakšna je razlika med "char* foo" in "char[100] foo". Še posebej glede tega, kje se nahajajo elementi tako deklariranih polj. Ravno tako pa ne bo odveč, če si pogledaš še kakšno knjigo o C++, kjer boš ugotovil zakaj so objekti "dobra stvar" in na koliko različnih načinov lahko uporabiš že obstoječe.

'FireSTORM' ::

saj je že ime topica povedalo da sem pozabil te osnove
zato ker sem zadnje čase programiral večino z MFC, kjer sem uporabljal po večini(tričetrt) spremenljivke tipa CString in mi je to malce ušlo iz spomina in je te zadeve trebalo malo obnoviti ko sem začel programirat v Linux okolju, oz. se tega začel učit

ampak sem zadevo rešil

in vem kaj je sklad oz. kako "zgleda" saj so me profesorji "mučili" štiri leta pri treh različnih predmetih z skladom

in jih redno sproščam ko jih enkrat več ne rabim, oz. ko za potek programa postanejo neuporabne

čeprav sem še lajk v programiranju nisem pa totalen lajk :P
Those penguins.... They sure aint normal....

Zgodovina sprememb…

BlueRunner ::

IMO si zagrešil tri napake, ki so tako osnovne osnove, da dvomim, da si C ali C++ kdaj zares uporabljal. Zaradi tega sem odgovoril, kot pač odgovorim začetniku, ki še ni naredil domače naloge (knjige in Google).

'FireSTORM' ::

in te tri so? :P

ne nisem naredil domače naloge...
zato sem pa naredil srednjo rač. šolo, pa še študiram računalništvo in nisem naredil "domače naloge"...:\

no da se neboma samo kregala
mi povej še eno stvar

ko poženem ./configure iz konzole mi lepo zaključi configure...
ustvari make file-e
in potem ko poženem še make, dobim pa en error
ki ga odpravim tako da v src/Makefile dodam k
CXXLINK = $(LIBTOOL)...
če dodaten parameter
kaj in kje moram spremenit da bo ta parameter že dodan v Makefile ko bo ga ustvarila "configure" skripta?

edit: nevermind...rešil
moral editirat src/Makefile.in
Those penguins.... They sure aint normal....

Zgodovina sprememb…

BlueRunner ::

Nimam se želje kregati, samo na kratko sem želel pojasniti zakaj je bil odgovor takšen, kot je pač bil. Tudi ne kot opravičilo, temveč samo pojasnilo. Tri osnovne osnove, ki so mi padle v oči, pa so bile:
- argv[1] == NULL, brez preverjanja velikosti polja (argc)
- argv[1] == "-h"
- "čudni znaki" na koncu izpisanega niza (nizi terminirani z '\0')

To ne pomeni, da ne znaš napisati programa v kakšnem drugem programskem jeziku. To samo pomeni, da jaz osebno (še vedno) dvomim, da si kadarkoli prej karkoli napisal v C/C++. Vsekakor pa menim, da mora vsak, ki želi resno programirati, spoznati tudi C (po želji pa še C++), saj je potrebno za njegovo optimalno uporabo vedeti veliko zadev, ki so drugje morda samo omenjene, kot zanimivost, ali pa teorija. Morda ne zato, da ga bo vsak dan uporabljal, temveč predvsem zato, ker se pri njemu hočeš nočeš naučiš večine zakonitosti delovanja današnjih računalnikov.

Če bi pa trdil karkoli več od tega, pa bi lakho že sprožil kakšno sveto vojno :D

'FireSTORM' ::

ok, pač tvoje mišlenje, če prav je napačno ga sprejmem kot argument na moje programiranje:D
je res da sem še n00b pri programiranju v c++ ampak se trudim ;)
Those penguins.... They sure aint normal....

CCfly ::

- Za razčlenjevanje parametrov v ukazni vrstici ti toplo priporočam TCLAP in čim manj izumljanja tople vode.
- Kar se tiče build sistema sem pred nekaj časa preklopil iz GNU autotools na cmake.
"My goodness, we forgot generics!" -- Danny Kalev

'FireSTORM' ::

ok...
zdaj pa me medeš :P

katero je boljše? getopt ali tclap?
Those penguins.... They sure aint normal....

CCfly ::

Kar se mene tiče TCLAP.
"My goodness, we forgot generics!" -- Danny Kalev

'FireSTORM' ::

še eno vprašanje da spet ne odpiram nove teme

zdaj se pa gre za system();
kako vem ko se ukaz izvrši normalno brez napak?
vrne system() kako vrednost?
ok vidim output v konzoli če je bla napaka ali ne, samo kako naj programu dopovem da se je zgodila napaka pri izvržbi nekega ukaza?

ok rešil
RTFM:D
Those penguins.... They sure aint normal....

Zgodovina sprememb…



Vredno ogleda ...

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

[c] Enaki datoteki

Oddelek: Programiranje
7936 (796) Spura
»

C strukture, kazalci naloga pomoc

Oddelek: Programiranje
51385 (1280) DavidJ
»

[C/C++] in folder list

Oddelek: Programiranje
5787 (730) shock
»

C - pomoč

Oddelek: Programiranje
111390 (1130) Thagirion
»

[C++][Naloga] Tekstovne datoteke, realna števila

Oddelek: Programiranje
253870 (3486) Gundolf

Več podobnih tem