Afişează mesaje
Pagini: [1] 2
1  infoarena - concursuri, probleme, evaluator, articole / Arhiva de probleme / Răspuns: 474 Teams : Martie 18, 2013, 13:23:49
Am inteles.

Cred ca evaluarea tine cont de timpul de citire/scriere, asa ca un cod simplu, cum ar fi cel de mai jos, n-ar trebui sa afecteze evaluarea. Incadrarea in limitele impuse trebuie sa vina din algoritm.
Cod:
  // citire
  ifstream is( "teams.in" );
  is >> N >> A >> B;
  for ( i = 0; i < N; ++i )
  {
    is >> x;
    if ( x < B )
      ++c[ v[j++] = x ]; // aici lucrurile sunt amestecate putin: nu este numai citire; este implementata si o parte din algoritm
  }

  // algoritm
  // ...

  // scriere
  ofstream( "teams.out" ) << s / 2;
Desigur, se poate recurge la “parsare”, si am pus ghilimele pentru ca nu e o parsare adevarata, dar asta ar insemna ca a fost folosita o smecherie: nu a fost modificat algoritmul propriu-zis. Daca "parsarea" e folosita doar pentru a micsora timpul de executie, nu pentru a te incadra in timpul impus, atunci cred ca metoda poate fi acceptata.

Cred ca am inteles si care sunt standardele impuse pentru astfel de probleme: foarte relaxate. Intr-un mediu real ar trebui, de exemplu sa verifici limitele, sa folosesti alocare dinamica, tabele de asociere, etc. “Parsarea”, asa cum am vazut-o eu in codul din arhiva, e o smecherie: presupune ca datele de intrare sunt formate din cifre si spatii, lucru care in realitate este de neacceptat: in fisierul de intrare poate fi orice, nu ce ne imaginam noi ca ar trebui sa fie. Si ca sa vezi cat de reala e problema, cineva a postat mai sus un set de date de intrare presupus corect, dar care este in afara limitelor date de probleme: este inclusa si valoarea zero, desi valoarea minima este 1. Rezultatul obtinut de cel ce a postat setul a fost confirmat si de o alta persoana, desi setul este gresit.


Succes si mult sport.
2  infoarena - concursuri, probleme, evaluator, articole / Arhiva de probleme / Răspuns: 474 Teams : Martie 05, 2013, 23:42:14
Poate cineva să-mi arate o citire completă cu parsare ? Cry (de la declararea fișierelor)

Ai mutat intrebarea. Incerc sa-ti raspund la intrebarea originala. Nu cunosc problema.

Parsarea unui fisier presupune utilizarea unui scanner (sau analizor lexical); scannerul sparge streamul de intrare in lexeme (token-uri sau cuvinte). De exemplu, sirul " 1234 test" poate fi vazut, din punct de vedere al lexemelor, astfel: "numar identificator".

Urmatorul exemplu foloseste un scanner ce intoarce doua tipuri de lexeme: intreg si caracter. Apoi scannerul este folosit pentru a afisa doar numerle.

Cod:
#include <fstream>
#include <string>
#include <iostream>

using namespace std;

// doua tipuri de lexeme (token): intreg si caracter plus sfarsit de stream
enum lexeme_kind { lexeme_eof, lexeme_char, lexeme_int };

// lexema contine tipul si valoarea
struct lexeme
{
  lexeme_kind k;
  union
  {
    int i;
    char c;
  } v;
  lexeme( int ai ) { k = lexeme_int; v.i = ai; }
  lexeme( char ac ) { k = lexeme_char; v.c = ac; }
  lexeme() { k = lexeme_eof; }
};

//
lexeme last_lexeme;

// "scanner" (citeste urmatoarea lexema din stream)
lexeme get_lexeme( istream& is )
{
  char c;
  
  // ignora whitespace
  ws( is );

  //
  is.get( c );
  if ( ! is )
    return last_lexeme = lexeme(); // eof sau error

  // daca este numar (ignoram numerele ce incep cu '+' sau '-')
  if ( isdigit( c ) )
  {
    string s;
    s += c;
    while ( is.get( c ) && isdigit( c ) )
      s += c;
    is.putback( c );
    return last_lexeme = lexeme( atoi( s.c_str() ) );
  }

  // nu e numar
  return last_lexeme = lexeme( c );
}

int main()
{
  //
  ifstream is( "test.txt" );
  if ( ! is )
    return -1;

  // citeste lexemele si afiseaza doar numerele
  while ( get_lexeme( is ).k != lexeme_eof )
    switch ( last_lexeme.k )
    {
    case lexeme_int: cout << last_lexeme.v.i << endl; break;
    case lexeme_char: break;
    default: return -2; // lexema necunoscuta
    }

  return 0;
}

P.S. Am citit enuntul. Sunt nedumerit. Cum s-a ajuns la probleme legate de parsare?!
3  infoarena - concursuri, probleme, evaluator, articole / Informatica / Răspuns: Lucrul cu fisiere : Martie 05, 2013, 17:32:35
Corect: sare peste "whitespaces" (blanc, tab, CR, NL). Se poate rescrie asa:

Cod:
while ( is.get( c ) )
{
  // ...

sau asa (mai complicat):

Cod:
is >> noskipws;
while ( is >> c )
{
  // ...

Codul in care folosesc break mi s-a parut mai usor de inteles decat varianta originala si este mai usor de inteles si decat codul de mai jos (care respecta teorema programarii structurate):

Cod:
is >> noskipws;
while ( is >> c && c != '\n' )
{
  // ...

sau

Cod:
while ( is.get( c ) && c != '\n' )
{
  // ...



4  infoarena - concursuri, probleme, evaluator, articole / Informatica / Răspuns: Lucrul cu fisiere : Martie 05, 2013, 14:15:57
Scuzati-mi insistenta si poate greutatea cu care am inteles.
N-ai pentru ce-ti cere scuze. Nimeni nu s-a nascut invatat iar fara efort ma indoiesc ca poti realiza ceva.

Textul problemei este interpretabil. De exemplu, daca numarul randului ar fi fost specificat, atunci ar fi trebuit sa numeri caracterele "new-line" (sau altul care desemneaza sfarsitul de linie, in functie de formatul fisierului). Cum randul nu este specificat, poate ca vrea o functie care sa ia ca argument numarul randului.

Poti anticipa gradul de complexitate al exercitiului in functie de cunostintele predate pana acum. Daca ultima lectie se refera la codurile ASCII, atunci poate ca profesorul se asteapta sa folosesti comparatii in loc de "toupper". Si tot asa.

O ultima observatie legata de codul postat de Razvan. Daca ati invata despre "break", poate fi rescris asa:
Cod:
  char c;
  bool is_even = false;
  while ( is >> c ) // cat timp pot citi din fisierul de intrare
  {
    if ( c == '\n' )
      break; // iesi din bucla
    // ...
  }
Adica, nu e nevoie de niciun "get".

Spor la invatat.
5  infoarena - concursuri, probleme, evaluator, articole / Informatica / Răspuns: Lucrul cu fisiere : Martie 04, 2013, 18:23:35
Din textul problemei: "se citeste un text". Nu spune cate caractere. Secventa:
Cod:
for(i=0;i<256;i++)
    f1>>sir[i];
citeste primele 256 de caractere sau pana la sfarsitul fisierului daca sunt mai putin de 256.

Ceva nu-ti este clar, dar nu am inteles ce anume.
6  infoarena - concursuri, probleme, evaluator, articole / Informatica / Răspuns: Lucrul cu fisiere : Martie 04, 2013, 17:48:41
- "a[256];" Nu ai nevoie de niciun vector. Citesti caracterul, il convertesti, daca-i cazul si il afisezi.
- "fstream f1("exemplu.txt",ios::in);" De ce nu ai folosit "ifstream is("exemplu.txt");"? In mod traditional un stream de intrare se noteaza cu "is".
- "f1>>sir" Citeste din f1 pana la primul blanc (exclusiv)
- "a=(int)sir;" Ce ai vrut sa faci aici?

O rezolvare posibila:
Cod:
#include <fstream>
#include <iostream>

using namespace std;

int main()
{
  ifstream is( "exemplu.txt" );
  if ( ! is )
    return -1; // eroare la deschidere (fisierul nu a fost gasit, de exemplu)

  char c;
  bool is_even = false;
  while ( is >> c ) // cat timp pot citi din fisierul de intrare
  {
    if ( is_even )
      cout << char( toupper( c ) );
    is_even = ! is_even;
  }

  return 0;
}
7  infoarena - concursuri, probleme, evaluator, articole / Informatica / Răspuns: citire si scriere caractere cu diacritice : Martie 02, 2013, 00:28:47
Citeste/scrie in mod binar.

De exemplu:
Cod:
  ifstream is( "in.txt", ios_base::binary );
  if ( ! is )
    return -1;

  ofstream os( "out.txt", ios_base::binary );
  if ( ! os )
    return -2;

  char c;
  while ( is.get( c ) && os.put( c ) )
    ;

Daca cu ce ai citit vrei sa mai faci si altceva, lucrurile se complica.

Succes.
8  infoarena - concursuri, probleme, evaluator, articole / Informatica / Răspuns: citire din fisier : Martie 01, 2013, 16:14:34
Cod:
  int c;
  while ( (c = fgetc( f )) != EOF )
  {
    // ...
  }
9  infoarena - concursuri, probleme, evaluator, articole / Informatica / Răspuns: Robot : Martie 01, 2013, 13:05:40
In cazul asta, felicitari. Implementarea pare a fi foarte simpla. Ce faci acolo semana cu “breadth-frist search”. O sa revad enuntul, daca gasesc timp.

Cel mai simplu ar fi sa intrerupi executia, daca depasesti limitele, si sa afisezi un mesaj de eroare; sau poti folosi coada standard <queue> (mai lenta).

...

Am gasit ceva timp si am implementat cum m-am priceput. Nu am participat la vreun concurs, asa ca nu prea stiu care sunt cerintele. Se pare ca este incurajata folosirea variabilelor globale si a numelor criptice. Copiaza codul pe calculatorul tau si vezi ce iese.

Cod:
#include <time.h>
#include <fstream>
#include <iostream>
using namespace std;

// i este indexul randului; intodeauna
// j este indexul coloanei; intodeauna

// energia maxima
#define EMAX 30000

// numarul maxim de randuri
#define RMAX 200

// numarul maxim de coloane
#define CMAX 200

// energia intiala
int p;

// numarul de randuri
int n;

// numarul de coloane
int m;

// tabla de joc
int c[RMAX][CMAX];

// celulele vizitate
char v[RMAX][CMAX];

// starea robotului
struct t_state
{
  int r; // rand
  int c; // coloana
  int ec; // energie celula
  int er; // energie robot
  void set( int ar, int ac, int aec, int aer ) { r = ar; c = ac; ec = aec; er = aer; }
};

// coada de stari intermediare
t_state q[RMAX*CMAX]; // datele
int dq; // indexul de extrage (deque)
int eq; // indexul de inserare (enque)

// solutii
int s[CMAX];
int ns; // numar solutii

//
int global_bytes_count()
{
  return sizeof( p ) + sizeof( n ) + sizeof( m ) +
    sizeof( c ) +
    sizeof( v ) +
    sizeof( q ) + sizeof( dq ) + sizeof( eq ) +
    sizeof( s ) + sizeof( ns );
}

//
bool read()
{
  ifstream is( "robot.in" );
  if ( ! is )
    return false;

  if ( ! ( is >> p >> n >> m ) )
    return false;

  for ( int i = 0; i < n; ++i )
    for ( int j = 0; j < m; ++j )
      if ( ! ( is >> c[i][j] ) )
        return false;

  return true;
}

//
bool write()
{
  ofstream os( "robot.out" );
  if ( ! os )
    return false;

  if ( ns < 1 )
  {
    if ( ! ( os << -1 ) )
      return false;
  }
  else
  {
    for ( int i = 0; i < ns; ++i )
      if ( ! (os << s[i] << ' ' ) )
        return false;
  }

  return true;
}

// find_path implementeaza algoritmul "breadth-first search"
// cu o definitie alternativa a adiacentei data de consumul de energie:
// daca consumul este prea mare, celula nu este adiacenta
// (vezi Introduction to Algorithms, Cormen et alii)
bool find_path( int j )
{
  // reseteaza celulele vizitate
  memset( v, 0, sizeof(v) );

  // reseteaza coada
  dq = eq = 0;

  // adauga pozitia initiala
  q[eq++].set( 0, j, c[0][j], p );

  // marcheaza pozitia initiala
  v[0][j] = 1;
 
  // cat timp coada nu e goala
  while ( eq - dq > 0 )
  {
    // extrage din coada
    int tq = dq++;

    // daca am ajuns la ultimul rand
    if ( q[tq].r >= n - 1 )
      return true;

    // examineaza celulele adiacente
    int i = q[tq].r + 1; // randul adiacent
    int pc = ( q[tq].c <= 0 ) ? 0 : -1; // prima coloana relativ la pozitia curenta
    int uc = ( q[tq].c <= m - 2 ) ? 1 : 0; // ultima coloana relativ la pozitia curenta
    for ( int k = pc; k <= uc; ++k ) // coloanele adiacente relativ la coloana curenta
    {
      // coloana adiacenta
      int j = q[tq].c + k;
     
      // care ar fi energia robotului daca s-ar muta pe celula adiacenta
      int er = q[tq].er - abs( c[i][j] - q[tq].ec );
      if ( er <= 0 )
        continue; // toata energia ar fi consumata: celula nu e "adiacenta"

      // celula adiacenta
     
      // daca celula nu este vizitata
      if ( ! v[i][j] )
      {
        // insereaza in coada
        q[eq++].set( i, j, c[i][j], er );
        // marcheaza
        v[i][j] = 1;
      }
    }
  }

  // nu a fost gasit niciun drum
  return false;
}

//
void run()
{
  // initializeaza numarul de solutii
  ns = 0;

  // cauta drumul pentru fiecare coloana
  for ( int j = 0; j < m; ++j )
    if ( find_path( j ) )
      s[ns++] = j + 1;
}

//
void print_gmem_info()
{
#ifndef NDEBUG
  cout << "Memorie globala consumata: " << double( global_bytes_count() ) / 1024 / 1024 << " MB" << endl;
#endif
}

// numarul de executii pentru benchmark
#define XMAX 100000

// afiseaza durata total a executiilor
#define BENCHMARK

int main()
{
  print_gmem_info();

  if ( ! read() )
  {
    cerr << "Eroare la citire";
    return -1;
  }

#ifdef BENCHMARK
  clock_t t0 = clock();
  for ( int k = 0; k < XMAX; ++k )
#endif

    run();

#ifdef BENCHMARK
  clock_t d = clock() - t0;
  cout << "Durata pentru " << XMAX << " executii: " << double(d)/CLOCKS_PER_SEC << "s" << endl;
#endif

  if ( ! write() )
  {
    cerr << "Eroare la scriere";
    return -2;
  }

  return 0;
}
10  infoarena - concursuri, probleme, evaluator, articole / Informatica / Răspuns: Răspuns: Robot : Martie 01, 2013, 00:04:38
Felicitari pentru participarea la olimpiada.

- [...puţină memorie şi are un timp de execuţie cât mai mic.] Inainte de orice, trebuie sa te preocupe corectitudinea rezultatului.
- [...E ceva greşit dacă îi zic "coadă" ?] Nu; e foarte bine, doar ca nu am vazut-o. Nu-mi aduc aminte de algoritm; au trecut ceva ani de cand am terminat scoala.
- [Pe viitor o să folosesc comentarii.] Comentariile te ajuta.
- [...am făcut o greşeală gravă.] N-as zice.
- [...nu credeam că e o greşeală gravă] N-ai putea compila codul pe compilatoare mai noi.
- M-am uitat inca o data la programel si nu am inteles ce urmaresti, asa ca l-am compilat. Pentru setul de mai jos am obtinut: 1 2 3 4. Este corect?
100 4 4
 10  80  60  90
100 100 100  50
200 100 100  60
300 500 200 100

11  infoarena - concursuri, probleme, evaluator, articole / Informatica / Răspuns: Robot : Februarie 28, 2013, 01:02:35
- Cerinta nu pomeneste nimica de optimal (si cred ca nu aveti cunostinele necesare).
- Nu am inteles la ce foloseste "coada" (si nici de ce ii zici "coada").
- Ce faci daca drumul pe care esti consuma toata energia dar exista altul bun (cu acelasi punct de pornire)?
- Foloseste comentarii.
- bool p[dim] = {false}; initializeaza primul element, nu tot vectorul. Asta a fost intentia?
- main fara int in fata violeaza standardul curent.
12  infoarena - concursuri, probleme, evaluator, articole / Informatica / Răspuns: Divide et Impera : Februarie 27, 2013, 13:33:26
Cine naiba scrie manualele astea? Sunt de o absurditate strigatoare la cer.
Nu stiu... Pare a fi cea mai simpla problema ce ilustreaza algoritmul, dar cred ca nu se poate rezolva fara a sti cate ceva despre <string>. Pe de alta parte, sper ca la momentul angajarii, elevul de acum sa stie ca nu asa se inverseaza un sir; sa stie ca exista metode mult mai putin costisitoare.
13  infoarena - concursuri, probleme, evaluator, articole / Informatica / Răspuns: Divide et Impera : Februarie 26, 2013, 22:21:20
Am vorbit despre această idee de rezolvare la ora de info,am convenit că nu implică "Divide et Impera".
Asa e. M-am uitat intr-o carte de algoritmi si nu este conform definitiei. Implementarea de mai jos este conform definitiei (desi absurd de costisitoare).
Cod:
#include <string>
// ...
string reverse( string s )
{
  if ( s.size() < 2 )
    return s; // am ajuns la baza
  // subproblema "stanga"
  string l = reverse( s.substr( s.size() / 2, s.size() - 1 ) );
  // subproblema "dreapta"
  string r = reverse( s.substr( 0, s.size() / 2 ) );
  // combinarea celor doua solutii
  string c = l + r;
  return c;
}

Definitia zice cam asa:
- problema trebuie rezolvata recursiv
- la fiecare nivel se parcurg urmatorii pasi:
  o "Divide" problema curenta se divide in cel putin doua subprobleme.
  o "Impera" subproblemele sunt rezolvate recursiv.
  o Rezultatele subproblemelor sunt combinate rezultand solutia problemei curente.
14  infoarena - concursuri, probleme, evaluator, articole / Informatica / Răspuns: Divide et Impera : Februarie 26, 2013, 18:31:00
Cod:
void reverse( char* s , int i, int j )
{
  if ( i < j )
  {
    std::swap( s[i], s[j] );
    reverse( s, i+1, j-1 );
  }
}

Cred ca o astfel de cerinta are doar scop educativ. In lumea reala poate ca ar arata asa:

Cod:
void reverse( char* s )
{
  if ( ! s )
    return;
  char* e = s;
  while ( *e )
    ++e;
  for ( --e; s < e; ++s, --e )
  {
    char t = *s;
    *s = *e;
    *e = t;
  }
}

Succes.
15  infoarena - concursuri, probleme, evaluator, articole / Informatica / Răspuns: Calcularea functiei phi(N) folosind Ciurul lui Eratostene : Februarie 25, 2013, 18:06:53
Pe multe procesoare moderne varianta de mai jos este mai rapida decat varianta originala.

Cod:
    // N divizibil cu 4, de exemplu
    for ( int i = 1; i <= N; i+=4 )
    {
      phi[i] = i - 1;
      phi[i+1] = i;
      phi[i+2] = i + 1;
      phi[i+3] = i + 2;
    }

    // sau

    for ( int i = 0; i < N; i+=4 )
    {
      phi[i+1] = i;
      phi[i+2] = i + 1;
      phi[i+3] = i + 2;
      phi[i+4] = i + 3;
    }
16  infoarena - concursuri, probleme, evaluator, articole / Informatica / Răspuns: fisiere : Februarie 17, 2013, 20:06:27
dar la multe probleme imi iese din timp cu ifstream Sad
Un exemplu ar fi util. Poate nu este folosit cum trebuie.
17  infoarena - concursuri, probleme, evaluator, articole / Informatica / Răspuns: Memorie/complexitate : Februarie 17, 2013, 20:04:29
si pentru complexitate ?
eu programez in pascal:d

Nu am folosit Pascal de foarte mult timp. Pot spune ca nu mai stiu nimica. In general, din punctul de vedere al complexitatii algoritmului, ar trebui sa le vezi la fel. In realitate alocarea pe heap necesita un timp mai mare (ce nu poate fi controlat de client). Imagineaza-ti ca ai un raft de cutii inchise si-ti trebuie o cutie goala; stii ca exista, dar nu stii unde: poate-i prima, poate-i ultima.
18  infoarena - concursuri, probleme, evaluator, articole / Informatica / Răspuns: fisiere : Februarie 17, 2013, 19:46:47
Nici cu freopen nu trebuie sa inchizi nimic.
Primul rezultat intors de Google: http://www.cplusplus.com/reference/cstdio/freopen/
19  infoarena - concursuri, probleme, evaluator, articole / Informatica / Răspuns: Răspuns: Memorie/complexitate : Februarie 17, 2013, 19:45:03
Daca vei scrie codul conform standardelor acceptate in programare uneori vei fi ineficient.

Nu am participat la vreun concurs, asa ca nu-mi pot da cu parerea, dar: daca concursul este despre algoritmi si este analizata altceva in afara complexitatii algoritmului, atunci ceva nu-i in regula. Una e sa folosesti un ciclu pentru a calcula suma primelor 100 de numere si alta e sa folosesti formula lui Gauss. In primul caz poti folosi orice artificiu de programare, ca nu vei ajunge la performantele formulei. Nu pot fi de acord cu: "scrie-l oricum, numai sa fie rapid". Aplicatiile reale sunt mari si astfel de "solutii" duc la cod greu de intretinut/inteles si in final la aplicatii ratate. Viteza nu trebuie sa vina din artificii de programare, ci din algoritm. Artificiile de programare adauga un plus de viteza si ininteligibilitate, de cele mai multe ori.

Ce ma nemultumeste total este tendinta profeorilor de a lucra cu mijloace invechite. Angajatorii nu asta asteapta. Doar un exemplu: iostream.h in loc de iostream, asa cum prevede standardul curent.
20  infoarena - concursuri, probleme, evaluator, articole / Informatica / Răspuns: fisiere : Februarie 17, 2013, 16:50:50
...(fscanf sau cu freopen)...

fscanf si freopen fac lucruri diferite.

Daca programezi in c++ foloseste streamurile din biblioteca standard (ifstream, ofstream). Unul din avantaje este ca se inchid automat la iesirea din blocul de executie.


Succes.
21  infoarena - concursuri, probleme, evaluator, articole / Informatica / Răspuns: Memorie/complexitate : Februarie 17, 2013, 16:44:27
Memoria e impartita in mai multe zone. De interes, in general, este stiva (stack) si free-store (heap).

Stiva este bucata de memorie in care alocarea se face pe principiul LIFO (last-in-first-out). Poti privi stiva ca un teanc de cutii inalt cat o camera (dimensiunea maxima); cand ai nevoie de o variabila locala (automata) iei ultima cutie, o stivuiesti alaturi si tot asa cu urmatoarele variabile. La iesirea din blocul de executie cutiile sunt puse, automat, inapoi in stiva initiala in ordine inverse (daca ai lua prima cutie, stiva s-ar darma). Alocarea variabilelor din stiva este foarte rapida (trebuie doar sa iei cutia urmatoare; nu cauti).
int fun()
{
  int i; // i este alocata
  for ( int j = 0 /* j este alocata */; j < 10; ++j )
  {
    //…
  } // j este dealocata
  // ...
} // i este dealocata


Memoria dinamica (heap sau free store) este zona de memorie din care alocare/dealocarea se face prin intermediul unui manager (new/delete). Este ca un raft in care ai cutii goale. Cand ai nevoie de o variabila, o ceri managerului (new) iar managerul cauta o cutie goala de dimensiunea ceruta. Cautarea ia mai mult timp decat in cazul stivei, dar heap-ul este mult mai mare decat stiva. Existenta variabilei nu se incheie in mod automat: daca nu mai ai nevoie de ea, trebuie s-o pui inapoi in heap (delete).

Variabilele globale nu sunt alocate pe stiva sau heap; este folosita o zona de memorie dedicata. In c++ utilizarea variabilelor globale este descurajata.

In privinta vitezei, cred ca ar trebui sa te preocupe corectitudinea implementarii, iar daca viteza este alta decat cea asteptata, abia atunci sa-ti pui problema optimizarilor.


Succes.
22  infoarena - concursuri, probleme, evaluator, articole / Informatica / Răspuns: problema .campion : Februarie 15, 2013, 21:16:00
Incearca sa declari vectorii mari in afara mainului (pe heap ai mai mult decat pe stiva)

Inainte de a muta declaratia variabilelor, estimeaza spatiul necesar: probabil ca 50000 este mai mult decat ai nevoie.

Variabilele globale (cele declarate in afara functiei main) sunt alocate intr-un alt segment de memorie, nu pe heap.

//...
int g_i; // variabila globala
//...
int main()
{
  int i; // variabila locala
  int* pi = new int; // pi este locala dar indica catre o zona de memorie alocata din heap
  *pi = 10; // memoria de pe heap va contine 10
  delete pi; // elibereaza memoria alocata
  return 0;
}
23  infoarena - concursuri, probleme, evaluator, articole / Informatica / Răspuns: problema .campion : Februarie 15, 2013, 20:17:37
Nu am studiat problema pe care incearca s-o rezolve aplicatia. Am cateva observatii legate de implementare:
 - De ce vectorii s si sum trebuie sa fie atat de mari? Stiva, probabil ca nu este foarte multumita. Nu programez sub Linux, dar probabil ca mesajul de eroare inseamna ca ai depasit dimensiunea maxima a stivei.
 - De ce fstream si nu ifstream si ofstream?
 - Deschiderea cu succes a unui fisier trebuie confirmata:
       std::ifstream is( "tren1.in" );
         if ( ! is )
           return -1; // eroare la deschidere

 - Este indicat ca variabilele locale sa fie declarate pe masura ce sunt folosite. De exemplu, nu are rost sa declari i la inceputul functiei daca este folosit doar in for. Mai corect ar fi: for ( int i = 0; i < n; ++ i )
 - Functia main trebuie sa intoarca o valoare.


Succes.
24  infoarena - concursuri, probleme, evaluator, articole / Informatica / Răspuns: Librarie <vector> : Februarie 15, 2013, 16:16:51
Exemplul 2 emuleaza exemplul 1, ca sa scoata in evidenta diferentele intre cele doua abordari.

s este lungimea curenta a vectorului, chiar daca prin declaratia v[VMAX] se aloca 10 elemente. Folosirea oricarui index in afara domeniului [0, s-1] este eronata.

Lungimea fizica a vectorului v[VMAX] este VMAX (chiar daca s capata valoarea VMAX + 10, de exemplu). Lungimea vectorului std::vector< int > v poate fi ajustata dinamic: poate fi zero, 10 sau cat decizi in momentul in care-l folosesti, spre deosebire de abordarea statica in care lungimea nu poate depasi VMAX.
25  infoarena - concursuri, probleme, evaluator, articole / Informatica / Răspuns: Librarie <vector> : Februarie 15, 2013, 14:45:38
De ce e eroare logica v[1] = 1? int v[10] ar insemna ca indexul maxim e 9, ok.

VMAX (10) este dimensiunea vectorului static (indexul-fizic corect este de la 0 la 9). Din tot vectorul, exemplul foloseste doar primele s elemente. La acel moment s este 1, deci domeniul valid de indecsi-logici este de la 0 la 0 (de la 1 pina la 9 sunt valori ce nu sunt intializate sau nu mai sunt valide in acel punct). Programul nu o sa "crape" (in jargon) dar e posibil sa se comporte anormal, si se poate termina anormal din cauze indirecte. Nu o sa crape in mod direct pentru ca locatia in care scrii este valida (asa cum ai observat, lungimea-fizica a vectorului este 10 iar indexul 1 este in domeniu).

Daca indexul este in afara domeniului-fizic (0-9) atunci scrierea poate avea loc intr-o locatie care nu-i pe placul compilatorului si aplicatia poate crapa fara vreun avertisment.

In aplicatiile comerciale vectorii statici sunt rar utilizati. De cele mai multe ori dimensiunile depind de datele introduse de utilizator, asadar ai nevoie de un vector cu lungime ajustabila dinamic.

Pagini: [1] 2
Powered by SMF 1.1.19 | SMF © 2006-2013, Simple Machines