[ ___ @ 11.05.2011. 17:18 ] @
Zadatak glasi ovako:
* U datoteci pesme.txt nalaze se informacije o gledanosti pesama na Youtube-u u sledecem formatu: izvodjac - naslov, brojGledanja
* Napisati program koji ucitava informacije o pesmama i vrsi sortiranje pesama u zavisnosti od argumenata komandne linije:
* (a) nema opcija, sortiranje po broju gledanja.
* (b) -i, sortiranje po imenu izvodaca
* (c) -n, sortiranje po naslovu pesme
* Ne praviti nikakve pretpostavke o maksimalnoj duzini imena izvodjaca, naslova pesme, kao i ukupnom broju pesama.

Da li mi neko može dati savet kako da dinamički alociram ove niske, ime izvođača i naziv pesme? Postaviću dole kod, ali on funkcioniše samo ako se navedu ograničenja u dužini ta dva podatka :(

Code:

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

// broj elemenata koje rezervisemo unapred
#define KORAK 10

// struktura Pesme
typedef struct {
    char* izvodjac;
    char* naslov;
    int brGledanja;
} Pesme;

// pomocni karakter, globalna promenljiva u kojoj se cuva opcija koju je korisnik naveo
char kriterijum;

// samo prototip funkcije, telo se nalazi ispod glavne
int uporedi(const void*, const void*);

int main(int argc, char** argv) {
    // brojaci        
    int i, j;
    // pomocna promenljiva za iscitavanje niski iz datoteke
    char s[50];
    
    // ucitavanje podataka iz datoteke, i smestanje u niz struktura Pesme
    FILE* ulaz;
    if((ulaz = fopen("pesme.txt", "r")) == NULL) {
        printf("Greska pri ucitavanju datoteke.\n");    
        exit(1);
    }

    // rezervisemo mesta za jednu strukturu Pesme
    Pesme* pesme = (Pesme*) malloc(sizeof(Pesme));
    if(pesme == NULL) {
        printf("Greska pri alokaciji.\n");
        exit(1);
    }
    
    // broj (unetih) elemenata u nizu struktura
    int n = 0; 
    // broj alociranih struktura u memoriji
    int alocirano = 1; 
    

    while(1) {
        // ako je broj alociranih jednak broju unetih struktura, alociramo jos prostora
        if(alocirano == n) {
            alocirano+=KORAK;
            pesme = (Pesme*)realloc(pesme, sizeof(Pesme)*alocirano);

            // i naravno, obavezna provera da li je alokacija memorije uspesno izvrsena
            if(pesme == NULL) {
            printf("Greska pri alokaciji.\n");
            exit(1);
            }
            
        }
        
        // ako procitamo prazan red, dosli smo do kraja datoteke, i naslino izlazimo iz petlje
        if(fgets(s,50,ulaz) == NULL) break;

        // sada u niski s cuvamo liniju iz datoteke, a ona je formata " ime_autora ili/i_prezime_odnosno_pseudonim_autora - naziv_pesme, 123456789 " 

        // ime autora citamo do prve povlake, s tim sto se vratimo jedan karakter unazad, i tu nalepimo nulu (da ne bismo cuvali belinu)
        // koristimo dva brojaca, i i j, sa i se krecemo po liniji iz datoteke, a sa j po odredjenom podatku strukture
        for(i=0,j=0;s[i]!='-';i++,j++) 
            pesme[n].izvodjac[j] = s[i];
        pesme[n].izvodjac[j-1] = '\0';

        // naziv pesme ucitavamo od i (koje cuva karakter kod kog smo stali sa citanjem) pa jos dva karaktera desno, do zareza
        for(i=i+2,j=0;s[i]!=',';i++,j++)    
            pesme[n].naslov[j] = s[i];
        pesme[n].naslov[j-1] = '\0';

        // sada smo na itoj poziciji, ali krecemo sa citanjem od i+2 da ne bismo ucitali zarez i belinu
        // koristim pomocnu nisku pom, u kojoj cu cuvati broj u obliku niske
        char pom[20];
        pesme[n].brGledanja = 0;
        for(i=i+2, j=0;s[i]!='\n';i++, j++)  
            pom[j] = s[i];
            pom[j] = '\0';
            pesme[n].brGledanja = atoi(pom);
        

        n++;
    }

    // kriterijum po default vrednosti neka stoji na b; u slucaju da je unesena opcija, dolazi do izmene
    kriterijum = 'b';

    if(strcmp(argv[1],"-i") == 0 || strcmp(argv[1], "-n") == 0)
        kriterijum = argv[1][1];

    // kriterijum se cuva u globalnoj promenljivoj, tako da funkcija uporedi na osnovu njega vraca odgovarajucu vrednost
    qsort(pesme, n, sizeof(Pesme), &uporedi);
    
    // ispisujemo sortiran niz struktura
    for(i=0;i<n;i++)
        printf("%s - %s, %d\n", pesme[i].izvodjac, pesme[i].naslov, pesme[i].brGledanja);

    // oslobadjamo alociranu memoriju
    free(pesme);
    // zatvaramo datoteku
    fclose(ulaz);
    

    // saljemo informaciju o uspesnom izvrsavanju programa. the end.
    return 0;
}

int uporedi(const void* pPesma1, const void* pPesma2) {
    Pesme Pesma1 = *(Pesme*)pPesma1;
    Pesme Pesma2 = *(Pesme*)pPesma2;

    if(kriterijum == 'i')
        return strcmp(Pesma1.izvodjac, Pesma2.izvodjac);
    if(kriterijum == 'n')
        return strcmp(Pesma1.naslov, Pesma2.naslov);
    
        return Pesma1.brGledanja - Pesma2.brGledanja;
}
[ ___ @ 11.05.2011. 22:55 ] @
Rešen problem...
[ Sonec @ 15.05.2011. 17:44 ] @
Evo ovde celokupan kod

Code:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct
{
    char *izvodjac;
    char *naslov;
    int brGledanja;
}pesma;

char tip;

int poredi(const void *a, const void *b)
{
    pesma p1 = *(pesma*)a;
    pesma p2 = *(pesma*)b;
    
    if(tip == 'b')
        return p1.brGledanja - p2.brGledanja;
    else if(tip == 'i')
        return strcmp(p1.izvodjac, p2.izvodjac);
    else if(tip == 'n')
        return strcmp(p1.naslov, p2.naslov);
}

char* ucitaj_nisku(FILE *f)
{
    char c, *r = NULL;
    int n = 0;
    if(feof(f))
        return NULL;
    c = fgetc(f);
    while(c != ' ' && c != EOF)
    {
        if(c == '\n')
        {
            c = fgetc(f);
            continue;
        }
        n++;
        r = realloc(r, sizeof(char) * n);
        if(r == NULL)
        {
            printf("greska");
            exit(EXIT_FAILURE);
        }
        r[n - 1] = c;
        c = fgetc(f);
    }
    n++;
    r = realloc(r, sizeof(char) * n);
    if(r == NULL)
    {
        printf("greska");
        exit(EXIT_FAILURE);
    }
    r[n - 1] = 0;
    return r;
}

int main(int argc, char *argv[])
{
    pesma *pesme;
    FILE *f;
    char pom1[1000], pom2[1000], p[10], *r1, *r2, *r3;
    int pom3, n, i, uspesno_citanje;
    
    f = fopen("pesme.txt", "r");
    if(f == NULL)
    {
        printf("Greska");
        exit(EXIT_FAILURE);
    }
    
    n = 0;
    pesme = NULL;
    uspesno_citanje = 1;
    while(uspesno_citanje)
    {
        r1 = ucitaj_nisku(f);
        r2 = ucitaj_nisku(f);
        r3 = ucitaj_nisku(f);
        
        if(r1 == NULL || r2 == NULL
            || r3 == NULL 
            || fscanf(f, "%d", &pom3) != 1)
        {
            uspesno_citanje = 0;
            continue;
        }
        
        n++;
        pesme = (pesma*)realloc(pesme, n * sizeof(pesma));
        if(pesme == NULL)
        {
            printf("Greska");
            exit(EXIT_FAILURE);
        }
        r3[strlen(r3) - 1] = 0;
        
        pesme[n - 1].brGledanja = pom3;
        pesme[n - 1].izvodjac 
            = (char*)malloc((strlen(r1) + 1) * sizeof(char));
        pesme[n - 1].naslov 
            = (char*)malloc((strlen(r3) + 1) * sizeof(char));
        if(pesme[n - 1].izvodjac == NULL
            || pesme[n - 1].naslov == NULL)
        {
            printf("Greska");
            exit(EXIT_FAILURE);            
        }
        strcpy(pesme[n - 1].izvodjac, r1);
        strcpy(pesme[n - 1].naslov, r3);
        free(r1);
        free(r2);
        free(r3);
    }
    /*while(fscanf(f, "%s%s%s%d", 
        pom1, p, pom2, &pom3) == 4)
    {
        n++;
        pesme = (pesma*)realloc(pesme, n * sizeof(pesma));
        if(pesme == NULL)
        {
            printf("Greska");
            exit(EXIT_FAILURE);
        }
        pom2[strlen(pom2) - 1] = 0;
        pesme[n - 1].brGledanja = pom3;
        pesme[n - 1].izvodjac 
            = (char*)malloc((strlen(pom1) + 1) * sizeof(char));
        pesme[n - 1].naslov 
            = (char*)malloc((strlen(pom2) + 1) * sizeof(char));
        if(pesme[n - 1].izvodjac == NULL
            || pesme[n - 1].naslov == NULL)
        {
            printf("Greska");
            exit(EXIT_FAILURE);            
        }
        strcpy(pesme[n - 1].izvodjac, pom1);
        strcpy(pesme[n - 1].naslov, pom2);
    }*/
    fclose(f);
    
    if(argc == 1)
    {
        tip = 'b';
    }
    else if(argc == 2)
    {
        tip = argv[1][1];
    }
    else
    {
        printf("greska");
    }
    
    qsort(pesme, n, sizeof(pesma), &poredi);
    
    for(i = 0; i < n; i++)
        printf("%s %s %d\n"
            , pesme[i].izvodjac
            , pesme[i].naslov
            , pesme[i].brGledanja);
    
    for(i = 0; i < n; i++)
    {
        free(pesme[i].izvodjac);
        free(pesme[i].naslov);
    }
    free(pesme);
    
    system("PAUSE");

    return 0;
}



Datoteka je "pesme.txt" i moze da izgleda npr. ovako:
Code:

izvodjac1 - naslov1, 5
izvodjac2 - naslov2, 4
izvodjac3 - naslov3, 7
izvodjac4 - naslov4, 2
izvodjac5 - naslov5, 9
izvodjac6 - naslov6, 6

Inace kod nije moj, al sam postavio da vide ljudi, ako nekoga zanima...

P.S Pozdrav kolega sa faxa!
[ ___ @ 15.05.2011. 18:23 ] @
Zahvaljujem :) rešila sam na kraju, do duše drugačije :)
[ Sonec @ 15.05.2011. 19:17 ] @
Kod je odavde http://www.matf.bg.ac.rs/p/dje...-dinamicka-alokacija-memorije/

Ja sam iz 1o4B, nije ovo moj asistent, vec od 1o4A, al rece mi drug iz 1o4A da je njima asistent pokazao kako se radi.....

Mogla bi i ti tvoj "nov" kod da postavis, cisto da vidim ideju, ako ti nije frka...

P.S Izvinjavam se na spemu, al koleginica mi je poslala privatnu poruku, a posto nisam clan vise od 7 dana, moram ovako da joj odgovorim.
[ Intex @ 02.07.2011. 23:18 ] @
U pitanju je unija dva skupa, A i B, pise se u C koji se u toku rada relocira. Nikako na izlazu da dobijem ok rezultat.
Code:
#include <stdio.h>
#include <stdlib.h>
int main() {
    int *A, *B, *C;
    int i, j, k=0, n1, p, n2, n3;
    printf("Unwsite dimenzije nizova A i B: \n");
    scanf("%d%d", &n1, &n2);
    A=(int*)malloc(n1*sizeof(int));
    B=(int*)malloc(n2*sizeof(int));
    printf("\n Unesite elemente niza A:");
    for(i=0;i<n1;i++) {
        printf("\n %d. element: ", i+1);
        scanf("%d", &A[i]); }
    printf("\n Unesite elemente niza B:");
    for(i=0;i<n2;i++) {
        printf("\n %d. element: ", i+1);
        scanf("%d", &B[i]); }
    C=(int*)malloc((n1+n2)*sizeof(int));
    for(i=0;i<n1;i++)
        C[i]=A[i];
        for(i=0;i<(n1+n2);i++) 
            if(A[i]!=B[i]) {
                for(j=n1;j<(n1+n2);j++)
                C[j]=B[i];
                k++; }
    p=n1+k;
    C=(int*)realloc(C, p*sizeof(int));
    printf("\n Elementi skupa c su: ");
    for(i=0;i<k;i++) {
        printf("\n %d. element niza je: %d .", i+1, C[i]);
    }
    system("PAUSE");
    return 0;
}
[ Mihajlo Cvetanović @ 04.07.2011. 09:02 ] @
Prvo što bode oči je "%d%d" prilikom čitanja dva broja. Stavi neki spejs između, "%d %d". Ako to nije rešenje onda nam daj više informacija. Šta imaš kao ulazne podatke, šta očekuješ kao izlazne, a šta zapravo dobiješ na izlazu?
[ Intex @ 04.07.2011. 14:09 ] @
To čitanje dva broja radi i tako. Program treba da nadje uniju dva dinamički alocirana niza i prebaci ih u novi, takođe dinamički alociran niz, koji se na kraju relocira. Konkretno, problem je u petlji koja treba da kopira elemente iz B niza, kojih nema u A nizu, u C niz.
[ Picsel @ 04.07.2011. 16:05 ] @
Umesto
Code:
        for(i=0;i<(n1+n2);i++) 
            if(A[i]!=B[i]) {
                for(j=n1;j<(n1+n2);j++)
                C[j]=B[i];
                k++; }


trebalo bi nesto ovako
Code:
for (i=0; i<n2; i++)
{
  int vecPostoji=0;
  for (j=0; j<n1; j++)
    if (B[i]==A[j])
    {
       vecPostoji=1;
       break;
    }
  if (!vecPostoji)
  {
     C[n1+k]=B[i];
     k++;
  }
}
[ Intex @ 05.07.2011. 21:29 ] @
Nisam baš uspeo da uklopim ovu petlju u program, i nije mi baš nešto naročito jasna... :/
[ Picsel @ 05.07.2011. 22:49 ] @
Potrebno je i izmeniti
Code:
    for(i=0;i<k;i++) {
        printf("\n %d. element niza je: %d .", i+1, C[i]);
    }

i staviti
Code:
    for(i=0;i<p;i++) {
        printf("\n %d. element niza je: %d .", i+1, C[i]);
    }


Ceo program bi tad izgledao ovako
Code:
#include <stdio.h>
#include <stdlib.h>
int main() {
    int *A, *B, *C;
    int i, j, k=0, n1, p, n2, n3;
    printf("Unwsite dimenzije nizova A i B: \n");
    scanf("%d%d", &n1, &n2);
    A=(int*)malloc(n1*sizeof(int));
    B=(int*)malloc(n2*sizeof(int));
    printf("\n Unesite elemente niza A:");
    for(i=0;i<n1;i++) {
        printf("\n %d. element: ", i+1);
        scanf("%d", &A[i]); }
    printf("\n Unesite elemente niza B:");
    for(i=0;i<n2;i++) {
        printf("\n %d. element: ", i+1);
        scanf("%d", &B[i]); }
    C=(int*)malloc((n1+n2)*sizeof(int));
    for(i=0;i<n1;i++)
        C[i]=A[i];
    for (i=0; i<n2; i++)
    {
      int vecPostoji=0;
      for (j=0; j<n1; j++)
        if (B[i]==A[j])
        {
           vecPostoji=1;
           break;
        }
      if (!vecPostoji)
      {
         C[n1+k]=B[i];
         k++;
      }
    }
    p=n1+k;
    C=(int*)realloc(C, p*sizeof(int));
    printf("\n Elementi skupa c su: ");
    for(i=0;i<p;i++) {
        printf("\n %d. element niza je: %d .", i+1, C[i]);
    }
    system("PAUSE");
    return 0;
}


Sto se tice petlje koja je nejasna - Pre te petlje u C se stave svi clanovi niza A. Zatim se redom prolazi kroz niz B. Za trenutni clan niza B, postavi se 'vecPostoji' flag na 0, koji oznacava da tog elementa nema u skupu A. Zatim se sa for (j=0; j<n1; j++) petljom prolazi kroz niz A i poredi se da li se taj trenutni clan u nizu B nalazi u nizu A. Ako se nalazi, postavlja se 'vecPostoji' na 1 i iskace se iz petlje. Na kraju, proverava se da li smo taj trenutni clan niza B nasli u skupu A (pomocu 'vecPostoji') i ako nismo, dodaje se na zacelje niza C (na n1+k-to mesto, gde je k brojac koji oznacava koliko je clanova niza B dodato u C).
[ Intex @ 06.07.2011. 18:01 ] @
Ok, hvala, lepo je resenje. U medjuvremenu sam nasao jos jedno resenje, ali i ovo je skroz ok.