[ EmmaR @ 17.11.2012. 22:50 ] @
Navodim ono što "znam" i ono što sam pronašla.

1. String je u stvari polje znakova, niz znakova.

2. Svaki string se završava sa '\0'.

3. Deklaracija
Code:

char s1[] = {‘s’, ‘t’, ‘r’,’i’,’n’,’g’,’ ’, ‘1’ ‘\0’};
char s2[] = "string 2";
char *s3 = "string 3";
char s4[10] = "string 4"


Nije dozvoljena deklaracija bez inicijalne dodele vrednosti ? Osim u slučajevima:
Code:

char string1[15];
char *string2;


4. prikaz stringa
Code:

printf("%s",string);


5. Unos nove vrednosti, promena vrednosti
Code:

//za deklaracije
char s1[] = {‘s’, ‘t’, ‘r’,’i’,’n’,’g’,’ ’, ‘1’ ‘\0’};
char s2[] = "string 2";
char s4[10] = "string 4"

scanf("%s",string);   //OK ukoliko se ne unese duzi "niz" od inicijalnog  - poruka o gresci 1

//za deklaraciju
char *s3 = "string 3";

s3 = "string03"; //OK i za duze "nizove" od originala 


Citat:

Poruka o grešci 1
originalna rec ...>>> zdravo
izmeni rec... zdravo1234567890

rec izmenjena sa scanf ... zdravo1234567890

originalna rec ...>>> zdravo
izmeni rec...
rec izmenjena sa dodelom vrednosti .... ZDRAVO-duzeodoriginala

unesi neko ime... ime-neko
Ime: ime-neko
Prezime: neko_prezime


*** stack smashing detected ***: ./mojc.out terminated
======= Backtrace: =========
/lib/i386-linux-gnu/libc.so.6(__fortify_fail+0x50)[0x7540a0]
/lib/i386-linux-gnu/libc.so.6(+0xe704a)[0x75404a]
./mojc.out[0x80485ec]
/lib/i386-linux-gnu/libc.so.6(__libc_start_main+0xe7)[0x683e37]
./mojc.out[0x8048401]
======= Memory map: ========
003a7000-003c1000 r-xp 00000000 08:07 875 /lib/i386-linux-gnu/libgcc_s.so.1
003c1000-003c2000 r--p 00019000 08:07 875 /lib/i386-linux-gnu/libgcc_s.so.1
003c2000-003c3000 rw-p 0001a000 08:07 875 /lib/i386-linux-gnu/libgcc_s.so.1
0066d000-007c9000 r-xp 00000000 08:07 6315 /lib/i386-linux-gnu/libc-2.13.so
007c9000-007cb000 r--p 0015c000 08:07 6315 /lib/i386-linux-gnu/libc-2.13.so
007cb000-007cc000 rw-p 0015e000 08:07 6315 /lib/i386-linux-gnu/libc-2.13.so
007cc000-007cf000 rw-p 00000000 00:00 0
008b6000-008b7000 r-xp 00000000 00:00 0 [vdso]
00e03000-00e1f000 r-xp 00000000 08:07 6312 /lib/i386-linux-gnu/ld-2.13.so
00e1f000-00e20000 r--p 0001b000 08:07 6312 /lib/i386-linux-gnu/ld-2.13.so
00e20000-00e21000 rw-p 0001c000 08:07 6312 /lib/i386-linux-gnu/ld-2.13.so
08048000-08049000 r-xp 00000000 08:07 573667 /home/emma/mojc.out
08049000-0804a000 r--p 00000000 08:07 573667 /home/emma/mojc.out
0804a000-0804b000 rw-p 00001000 08:07 573667 /home/emma/mojc.out
08e74000-08e95000 rw-p 00000000 00:00 0 [heap]
b774b000-b774c000 rw-p 00000000 00:00 0
b7760000-b7764000 rw-p 00000000 00:00 0
bfb16000-bfb37000 rw-p 00000000 00:00 0 [stack]
Aborted


Kao što se vidi, kod se izvršio ali na kraju je poruka o grešci.




Šta raditi u slučaju kada je potrebno nešto ovako:
Code:

char string1[] = "string 1";

printf("Unesi pravu vrednost stringa1 ... ");
scanf("%s", string1);

if (uslov)
   string1 = "izraz 1";
else
   string1 = "izraz 2";

printf("%s", string1);


Ima li nekog elegantnog rešenja?

osim varijanti:
1. Koristiti za svaku situaciju posebne promenljive (stringove):
- Kada je potreban unos sa tastature, deklarisati sa char string[] = <neka vrednost>; i pri deklaraciji dodeliti proizvoljnu vrednost tako da bude duža od najdužeg mogućeg unosa; ili sa char string[n]; gde je n za 1 veće od maksimalno očekivane dužine "niza".
- Kada se očekuje promena stringa unutar programskog koda bez spoljnog unosa, deklarisati sa char *string
2. Napraviti f-ju / f-je koje će rešiti problem.
[ Nedeljko @ 18.11.2012. 06:20 ] @
Code (c):

char *string1;
char *string2 = "zdravo";
char string3[] = "zdravo";
char string4[15];
char string[15] = "zdravo";

string1 = "zdravo"; // moze
string2 = "zdravo"; // moze
string3 = "zdravo"; // greska
string4 = "zdravo"; // greska
string5 = "zdravo"; // greska
 

Pokazivačima možeš dodeljivati vrednost, tj. preusmeravati ih negde, ali nizovi su konstantni pokazivači. Tu su gde su i ne mogu se premeštati.

Dodela stringova se u principu vrši tako što moraš imati unapred rezervisan prostor, pa onda koristiti funkciju strcpy.
Code (c):

char *string1;
char *string2 = "zdravo";
char string3[] = "zdravo";
char string4[15];
char string[15] = "zdravo";

strcpy(string1, "zdravo"); // greska, prostor nije rezervisan
strcpy(string2, "zdravo"); // moze
strcpy(string3, "zdravo"); // moze
strcpy(string4, "zdravo"); // moze
strcpy(string5, "zdravo"); // moze
 

Za bezbednu dodelu (sa kontrolom veličine zauzetog prostora) koristi funkciju strncpy.
Code (c):

char string[15];

strncpy(string, "zdravo", sizeof(string));
 

[ EmmaR @ 18.11.2012. 20:45 ] @
Hvala.

Ako sam dobro razumela:

Code:

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

main()
{
    char rec[]="zdravo";
    char *reci="zdravo";
    
    char rec50[50];

    char ime[30];
    char *prezime;

    char slovo;

    // rec[]="zdravo"
    printf("\n\nDeklaracija: rec[]=\"zdravo\";");
    printf("\nOriginalna rec ...>>> %15s \n",rec);

    printf("izmeni rec (ne sme biti duze od originala+1) ... ");
    scanf("%s[^\n]\n",rec); //max do duzine originala + 1 (inicijalna dodela)
    printf("\nrec izmenjena sa scanf ... %15s \n",rec);
    //rec="ZDRAVO"; - ne funkcionise
    strcpy(rec,"ZDRAVO"); //ne moze da bude duza od inicijalne dodele+1
    printf("rec izmenjena sa dodelom vrednosti, strcpy .... %15s\n",rec);
    strncpy(rec, "hello", sizeof(rec)); //ne moze da bude duza od inicijalne dodele
    printf("rec izmenjena sa dodelom vrednosti .... %15s\n",rec);

    
    // *reci="zdravo"
    printf("\n\nDeklaracija: *reci=\"zdravo\";");
    printf("\n\nOriginalna rec ...>>> %15s \t L = %3d\n",reci,strlen(reci));
    printf("izmeni rec ... ");
    //scanf("%s",reci); // ovo ne radi za char *reci
    printf("\nrec izmenjena sa scanf ... %15s \n",reci);
    reci="ZDRAVO-duzeodoriginaladozvoljeno";
    printf("rec izmenjena sa dodelom vrednosti .... %s\n",reci,strlen(reci));

    // rec50[50] - velicina unosa ogranicena duzinom "niza", preveliki unosi se skracuju, nema poruke o gresci
    printf("\n\nDeklaracija: rec50[50];");
    printf("\nUnesi sadrzaj za rec50 ... ");
    scanf("%50s",rec50);
    printf("\nrec50 uneta preko scanf(): %s \t duzina: %3d",rec50,strlen(rec50));
    strcpy(rec50, "moze biti duze od prethodnih unosa");
    printf("\nrec50 izmenjeno dodelom, strcpy(): %s \t duzina: %3d",rec50,strlen(rec50));
    printf("\nUnesi sadrzaj za rec50 ... ");
    scanf("%50s",rec50);
    printf("\nrec50 uneta preko scanf(): %s \t L = %3d",rec50,strlen(rec50));
    strncpy(rec50, "Uneto sa strncpy", sizeof(rec50));
    printf("\nrec50 uneta sa strncpy(): %s \t L = %3d",rec50,strlen(rec50));
    printf("\nUnesi sadrzaj za rec50 ... ");
    scanf("%50s",rec50);
    printf("\nrec50 uneta preko scanf(): %s \t L = %3d",rec50,strlen(rec50));


    //ime[30], *prezime
    printf("\n\nDeklaracija: ime[30], *prezime;");
    printf("\nunesi neko ime... ");
    scanf("%s", ime);    
    prezime = "neko_prezime";
    printf("Ime: \t%s\n",ime);
    printf("Prezime: \t%s\n",prezime);
    //strcpy(prezime,"strcpy prezime"); ne moze za deklaraciju *prezime
    printf("Prezime (strcpy) : %s\n",prezime);

    //jedno slovo -> char slovo;
    printf("\n\nDeklaracija: slovo; (jedan znak - character)");
    slovo = 'Z';
    printf("\nDodeljeno slovo: %c",slovo);
    
    //nema greske ali ni rezultata
    printf("\nUnesi samo JEDAN znak ... ");
    scanf("%c",&slovo); //nema ulaza    
    printf("\nSlovo uneto sa scanf(): %c",slovo); //rezultat je NISTA

    slovo = 'W';
    printf("\nDodeljeno slovo: %c",slovo);

    printf("\nUnesi samo JEDAN znak getchar()... ");
    slovo = getchar();
    putchar(slovo);
    printf("\nUneto slovo sa getchar(): %c",slovo);    
    
    /* ukoliko prethodi getchar() gde je dodeljeno vise od 1 karaktera, 
    kao rezultat prikazuje drugi karakter iz getchar - printf, dok se
    scanf ignorise */    
    printf("\nUnesi samo JEDAN znak ... ");    
    scanf("%2c",&slovo); //scanf trazi 1 znak vise, "blokira" getchar() ako sledi iza
    printf("\nSlovo uneto sa scanf(): %3c",slovo); //rezultat je NISTA     
    
}


Mogući slučaj:
Code:

char string1[] = "string 1";

printf("Unesi pravu vrednost stringa1 ... ");
scanf("%s", string1);

if (uslov)
   string1 = "izraz 1";
else
   string1 = "izraz 2";

printf("%s", string1);


rešenje je:
Code:

char string1[n]; //n maximalna ocekivana duzina stringa

printf("Unesi pravu vrednost stringa1 ... ");
scanf("%s", string1);

if (uslov)
   strcpy( string1, "izraz 1" );
else
   strcpy( string1, "izraz 2" );

printf("%s", string1);

?
[ Nedeljko @ 18.11.2012. 22:49 ] @
Možeš ti da koristiš i klasičnu dodelu za stringove ako znaš šta radiš.
Code (c):

char s1[] = "Hello!", s2 = s1;
scanf("%s", s1);
printf("%s",s2);
 

Ispisaće ono što si unela. U gornjem primeru su s1 i s2 zapravo dva naziva za jedan string.

Ovo ti nije radilo
Code (c):

char *rec = "zdravo";
scanf("%s", rec);
 

zato što je pokazivač rec pokazivao na konstantan sadržaj "zdravo", koga ne možeš da menjaš. Sa druge strane, sa
Code (c):

char s[] = "Hello";
 

se rezerviše prostor čiji se sadržaj može menjati, a kome je početna vrednost "Hello".

Za bezbedno čitanje stringova koristi sledeće

Code (c):

char ime[10];
char *prezime;
int duzina_prezimena;

fgets(ime, sizeof(ime), stdin);
getline(&prezime, &duzina_prezimena, stdin);
/* ... */
free(prezime);
 

[ EmmaR @ 19.11.2012. 11:38 ] @
Citat:
Nedeljko: Možeš ti da koristiš i klasičnu dodelu za stringove ako znaš šta radiš.
Code (c):

char s1[] = "Hello!", s2 = s1;
scanf("%s", s1);
printf("%s",s2);
 

Ispisaće ono što si unela. U gornjem primeru su s1 i s2 zapravo dva naziva za jedan string.



Ne prihvata mi (nije monodevelop, vec konzola - gcc).

kod:
Code:

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

main()
{
    char s1[] = "Hello!", s2 = s1;
    scanf("%s", s1);
    printf("%s",s2);
 
}


"rezultat"
Citat:

gcc mojcn.c -o mojcn.out
mojcn.c: In function ‘main’:
mojcn.c:6:29: warning: initialization makes integer from pointer without a cast
mojcn.c:8:2: warning: format ‘%s’ expects type ‘char *’, but argument 2 has type ‘int’

./mojcn.out
nekiunos
Segmentation fault


ni ove varijante ne rade:
Code:

char s1[] = "Hello!", s2[] = s1;

...

char s1[] = "Hello!", s2[10] = s1;


a ovo radi, ali opet ne moze duze od inicijalne vrednosti:
Code:

...
char s1[] = "Hello!", *s2 = s1;
...


rezultat (kada nije prekoracena inicijalna duzina s1):
Citat:

gcc mojcn.c -o mojcn.out
./mojcn.out


s1 = Hello!
s2 = Hello!
imee

Posle:
s1 = imee
s2 = imee



ni ovo ne radi:
Citat:


Za bezbedno čitanje stringova koristi sledeće

Code (c):

char ime[10];
char *prezime;
int duzina_prezimena;

fgets(ime, sizeof(ime), stdin);
getline(&prezime, &duzina_prezimena, stdin);
/* ... */
free(prezime);
 


kod:
Code:

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

main()
{
    /*char s1[] = "Hello!", s2 = s1;
    scanf("%s", s1);
    printf("%s",s2);*/

    char ime[10];
    char *prezime;
    int duzina_prezimena;

    fgets(ime, sizeof(ime), stdin);
    getline(&prezime, &duzina_prezimena, stdin);
    /* ... */
    free(prezime);     
}


"rezultat"
Citat:

gcc mojcn.c -o mojcn.out
mojcn.c: In function ‘main’:
mojcn.c:18:2: warning: incompatible implicit declaration of built-in function ‘free’

./mojcn.out
ime
prezime
*** glibc detected *** ./mojcn.out: free(): invalid pointer: 0xbfdafa08 ***
======= Backtrace: =========
/lib/i386-linux-gnu/libc.so.6(+0x6cbe1)[0xd21be1]
/lib/i386-linux-gnu/libc.so.6(+0x6e50b)[0xd2350b]
/lib/i386-linux-gnu/libc.so.6(cfree+0x6d)[0xd2669d]
./mojcn.out[0x80484f1]
[0xa656d69]
======= Memory map: ========
00411000-0042d000 r-xp 00000000 08:07 6312 /lib/i386-linux-gnu/ld-2.13.so
0042d000-0042e000 r--p 0001b000 08:07 6312 /lib/i386-linux-gnu/ld-2.13.so
0042e000-0042f000 rw-p 0001c000 08:07 6312 /lib/i386-linux-gnu/ld-2.13.so
004bb000-004d5000 r-xp 00000000 08:07 875 /lib/i386-linux-gnu/libgcc_s.so.1
004d5000-004d6000 r--p 00019000 08:07 875 /lib/i386-linux-gnu/libgcc_s.so.1
004d6000-004d7000 rw-p 0001a000 08:07 875 /lib/i386-linux-gnu/libgcc_s.so.1
00c86000-00c87000 r-xp 00000000 00:00 0 [vdso]
00cb5000-00e11000 r-xp 00000000 08:07 6315 /lib/i386-linux-gnu/libc-2.13.so
00e11000-00e13000 r--p 0015c000 08:07 6315 /lib/i386-linux-gnu/libc-2.13.so
00e13000-00e14000 rw-p 0015e000 08:07 6315 /lib/i386-linux-gnu/libc-2.13.so
00e14000-00e17000 rw-p 00000000 00:00 0
08048000-08049000 r-xp 00000000 08:07 609849 /home/emma/mojcn.out
08049000-0804a000 r--p 00000000 08:07 609849 /home/emma/mojcn.out
0804a000-0804b000 rw-p 00001000 08:07 609849 /home/emma/mojcn.out
09752000-09773000 rw-p 00000000 00:00 0 [heap]
b7873000-b7874000 rw-p 00000000 00:00 0
b7889000-b788c000 rw-p 00000000 00:00 0
bfd91000-bfdb2000 rw-p 00000000 00:00 0 [stack]
Aborted


kada iskljucim
Code:
free(prezime);
(pretpostavljam da ne ukljucim odgovarajuce zaglavlje?)

"rezultat"
Citat:

gcc mojcn.c -o mojcn.out
./mojcn.out

ime
prezime
Segmentation fault

[ djoka_l @ 19.11.2012. 11:56 ] @
@EmmaR

Kada stavljaš code tag, možeš da staviš i jezik u kojem je kod, na primer [ code:c ]
Ako primećuješ, Nedeljko stavlja ono :c

Jedna od finih osobina je i to što kada staviš ispravan tag
Code (c):

free(nesto);
 


Dobijaš link na funkciju. Proverom linka, vidiš da se free koristi za oslobađanje prostora koji je prethodno urađen funkcijom malloc ili nekom sličnom iz te porodice funkcija. E pa, Nedeljko je propustio da to uradi, ali bez obzira na to, ipak je potrošio dosta vremena odgovorajući na tvoja pitanja.

Dakle, proveri malo literaturu, proveri izvore na netu ako ti neka funkcija nije jasna, nemoj da čekaš da ti se sve sažvaće.
[ Mihajlo Cvetanović @ 19.11.2012. 12:05 ] @
Pogledao sam objašnjenje za C funkciju getline i da bi funkcija unutra alocirala bafer moraš da joj inicijalno daš NULL vrednost: char *prezime = NULL;

Da bi mogla da dealociraš bafer neko mora prvo da ga alocira, bilo da si to ti funkcijom alloc, bilo da to neka funkcija interno uradi (kao što to radi funkcija getline).
[ X Files @ 19.11.2012. 12:50 ] @
@EmmaR

Jedna od dobrih navika u programiranju je da izbegavaš eksplicitne numeričke konstante, tj "magične brojeve" koji su proizvod brze pretpostavke o potencijalnoj veličini nekog buffera.

Drugim rečima, izbegavaj ovo:
char ime[10];
char rec50[50];
... čak i ovo, jer se svodi na isto:
char s1[] = "Hello!"


Ako je potrebno da unapred rezervišeš prostor (tj izbegneš malloc()), upotrebi prethodno: #define ... ili const ... da na jednom centralnom mestu definišeš veličinu. Dalje, kadgod budeš u kodu zahtevala tu konstantu, pozivaš se na identifikator. Da ne ulazimo sada u detalje šta je "bolje" od toga dvoje...

Tako ćeš jednim potezom moći da uskladiš eventualnu promenu veličine buffera, a takođe olakšavaš i održavanje programa, jer će "neko tamo" znati o čemu se radi, i znaće koja su sva mesta u kodu pogođena konstantom.


U realnim situacijama, pronaćićeš neke definicije tipa _MAX_PATH, koje nisu deo standarda, ali se makar i tako kod čini manje osetljivkm na ličnu arbitražu.
[ Nedeljko @ 19.11.2012. 16:24 ] @
Evo programa koji radi na linuksu:
Code (c):

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

int main()
{
    char hello1[] = "Hello!", *hello2 = hello1;
    char firstname[10], *lastname = NULL;
    size_t lastname_size;

    printf("%s\n%s\n", hello1, hello2);
    scanf("%s", hello1); /* Insecure read. */
    printf("%s\n%s\n", hello1, hello2);
    scanf("%s", hello2); /* Insecure read. */
    printf("%s\n%s\n", hello1, hello2);
    getchar();
    fgets(firstname, sizeof(firstname), stdin); /* Secure read. */
    getline(&lastname, &lastname_size, stdin); /* Secure read. */
    printf("%s%s", firstname, lastname);
    free(lastname);

    return 0;
}
 

Međutim, na vindouzu zaboravite na getline funkciju.
[ EmmaR @ 19.11.2012. 22:38 ] @
kod

Citat:
djoka_l
Code (c):

free(nesto);
 



mi je ovo nedostajalo (na početku):
Code:
#include <stdlib.h>

a pretpostavljala sam čemu služi (na osnovu naziva).

Pređi na dial-up pa koristi google pa kada ti bude izbacivao gomilu gluposti (na 1 pravi link bude bar 10 pogrešnih i zahtevnih: za dobar deo "našminkanih stranica" dok se učitaju mogu pošteno da se naspavam) //doduše nisam na dial-up ali na 2G koji je samo za jednu stotinku brži.


Citat:
X Files: @EmmaR

Jedna od dobrih navika u programiranju je da izbegavaš eksplicitne numeričke konstante, tj "magične brojeve" koji su proizvod brze pretpostavke o potencijalnoj veličini nekog buffera.

Drugim rečima, izbegavaj ovo:
char ime[10];
char rec50[50];
... čak i ovo, jer se svodi na isto:
char s1[] = "Hello!"


Ako je potrebno da unapred rezervišeš prostor (tj izbegneš malloc()), upotrebi prethodno: #define ... ili const ... da na jednom centralnom mestu definišeš veličinu. Dalje, kadgod budeš u kodu zahtevala tu konstantu, pozivaš se na identifikator. Da ne ulazimo sada u detalje šta je "bolje" od toga dvoje...

Tako ćeš jednim potezom moći da uskladiš eventualnu promenu veličine buffera, a takođe olakšavaš i održavanje programa, jer će "neko tamo" znati o čemu se radi, i znaće koja su sva mesta u kodu pogođena konstantom.


U realnim situacijama, pronaćićeš neke definicije tipa _MAX_PATH, koje nisu deo standarda, ali se makar i tako kod čini manje osetljivkm na ličnu arbitražu.


A kako da ih definišem? Hoću i ja da izbegnem (sve ovo vreme mi je to cilj) ...brze pretpostavke o potencijalnoj veličini nekog buffera.

zar
Code (c):

#define MAX 100
 

ne predstavlja simboličku konstantu
a
Code (c):

const int brojmax = 100;
 

običnu konstantu.

Citat:
Nedeljko: Evo programa koji radi na linuksu:
Code (c):

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

int main()
{
    char hello1[] = "Hello!", *hello2 = hello1;
    char firstname[10], *lastname = NULL;
    [b]size_t lastname_size[/b];

    printf("%s\n%s\n", hello1, hello2);
    scanf("%s", hello1); /* Insecure read. */
    printf("%s\n%s\n", hello1, hello2);
    scanf("%s", hello2); /* Insecure read. */
    printf("%s\n%s\n", hello1, hello2);
    getchar();
    fgets(firstname, sizeof(firstname), [b]stdin[/b]); /* Secure read. */
    getline(&lastname, &lastname_size, stdin); /* Secure read. */
    printf("%s%s", firstname, lastname);
    free(lastname);

    return 0;
}
 

Međutim, na vindouzu zaboravite na getline funkciju.


Hoćeš li da mi pojasniš boldirane delove koda?
I dalje pravi problema kod prekoračenja inicijalne dužine stringa (hello1,hello2): prihvata vrednost, izvršava ceo program tačno onako kako je zamišljeno, ali na kraju "časti" kilometarskom porukom o grešci.

Poenta cele ove zbrke je da tražim elegantno, jednostavno rešenje u smislu:
Code:

...deklaracija stringa bez obaveznog navođenja-predviđanja njegove maximalne dužine, bilo kao string[50], bilo kao string[] = "neki izraz" ...
..izbegavanje formiranje konstante na bilo koji način...

...da tako deklarisan string može da prihvata izraz neodređene dužine (podrazumevano do 255 znaka, a ne kompletan "Rat i mir")...



Stalno me navodi da je, za takav slučaj, najbolja deklaracija
Code:

char *string1 = NULL;
char *string2;
char *string3 = "neki izraz";


iz razloga što char *string, u sva tri slučaja, ne rezerviše fixan bafer, pa naredni unosi nisu ograničeni inicijalnom dužinom stringa.

Međutim, u jednom od postova, savetovano je da treba maximalno izbegavati char *string ???

Kada sam već, kod char *string maglovito se sećam da ima veze gde se nalazi zvezdica (pokazivač), tj da:
char *string, nije isto što i char* string, odnosno nije isto što i char * string ??? (nisam sigurna za ovo).

Evo još jednog koda (inspirisano by Nedeljko):
Code (c):

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

#include <string.h>

int main()
{
     char *rec = "zdravo";
     size_t rec_size;
     printf("\nRec - original: %s",rec);

     rec = "novo zdravo";
     printf("\nRec dodeljena: %s",rec);

     rec = NULL; //zbog getline
     printf("\nunesi neku novu rec: ");
     //getchar(); //visak, radi i bez ovoga
     getline(&rec, &rec_size, stdin); /* Secure read. */
     printf("\nRec - getchar unos: %s",rec);
     
   
     char reci[] = "zdravo"; // znam da treba na pocetku, ali ovde je namerno privremeno smesteno

     printf("\n\nReci - original: %s",reci);

     strcpy(reci,"hello");
     printf("\nReci - dodela: %s",reci);

     printf("\nUnesi reci do 7char max: ");
     scanf("%s",reci);
     printf("\nReci - scanf: %s",reci);
     
     printf("\nUnesi reci - max 7char: ");
     getchar();
     fgets(reci, sizeof(reci), stdin); //prihvata samo do 7char (6+1) - nema poruke o gresci ukoliko se unese vise
     printf("\nReci - getchar + fgets: %s",reci);

     printf("\n");
}
 


Izvinjavam se ako zbog koda (a možda i zbog čitavog ovog posta) dobijete napade smeha, ali meni je ovako lakše da povežem šta koji deo koda radi. Normalno, u nekoj potencijalnoj programerskoj budućnosti, sve će biti na svom mestu i bez viškova.
[ Nedeljko @ 19.11.2012. 23:53 ] @
Da
Code (c):

#define MAX 100
 

predstavlja simboličku konstantu i X Files je upravo na to mislio.

Poenta je sledeća: kada hoćeš tu konstantu da izmeniš, da je dovoljno da je izmeniš na jednom mestu, a ne na više mesta. U programiranju je vrlo bitno da nema ponavljanja koda u izvornom kodu programa. Zamisli da ti je kod za nešto pogrešan ili da je dobar ali da želiš da ga izmeniš. Ako se kod za to nešto javlja na samo jednom mestu u programu, onda je izmena toga na jednom mestu u programu izmena toga u celom programu. To čini kod mnogo lakšim za održavanje.

Što se tiče problema sa prekoračenjem inicijalne dužine stringova hello1 i hello2, oni postoje i taj deo koda je prokomentarisan sa "nesigurno čitanje". Ilustrovana je upotreba scanf funkcije, ali uz napomenu da je ne treba koristiti za stringove upravo zbog tog problema.

U svakom slučaju, funkcija scanf ostavlja za sobom đubre u baferu za čitanje u vidu znaka za nov red ili tako nečega, dok funkcije fgets i getline ne tolerišu nikakvo đubre. Tome služi funkcija getchar. Ona će za scanf funkcijama počistiti đubre u baferu za čitanje.

Što se elegantnog i bezbednog rešenja tiče, koristi funkcije fgets i getline na opisani način. Ako je maksimalna veličina poznata i treba da popuniš rezervisani prostor, onda koristi fgets, a ako nema ograničenja dužine unapred, onda koristi getline, koji mora kasnije da bude praćen sa free.
Code (c):

char limited[10], *unlimited = NULL;
size_t size;

fgets(limited, sizeof(limited), stdin);
getline(&unlimited, &size, stdin);
/* ... */
free(unlimited);
 

Pročitao sam tvoj primer i izgleda da si shvatila fabulu radnje.
[ nemanja11111 @ 20.11.2012. 09:55 ] @
scanf("%s", &string1);

zaboravila si &
[ Nedeljko @ 20.11.2012. 12:48 ] @
Ne, kod stringova se to ne stavlja. Već smo raspravljali o tome.
[ EmmaR @ 20.11.2012. 14:09 ] @
Citat:
nemanja11111: scanf("%s", &string1);

zaboravila si &


Nisam. Kompajliraj kod onakav kakav jeste, izvrši ga; a onda sve to isto sa & (radiće ali će te pod Linux-om "častiti" upozorenjem). & ide kod brojeva, a ne kod stringova (što sam pametna kad me juče naučiše nešto što je trebalo da znam pre x godina).

Citat:
Nedeljko: Da
Code (c):

#define MAX 100
 

predstavlja simboličku konstantu i X Files je upravo na to mislio.

Poenta je sledeća: kada hoćeš tu konstantu da izmeniš, da je dovoljno da je izmeniš na jednom mestu, a ne na više mesta. U programiranju je vrlo bitno da nema ponavljanja koda u izvornom kodu programa. Zamisli da ti je kod za nešto pogrešan ili da je dobar ali da želiš da ga izmeniš. Ako se kod za to nešto javlja na samo jednom mestu u programu, onda je izmena toga na jednom mestu u programu izmena toga u celom programu. To čini kod mnogo lakšim za održavanje.

Što se tiče problema sa prekoračenjem inicijalne dužine stringova hello1 i hello2, oni postoje i taj deo koda je prokomentarisan sa "nesigurno čitanje". Ilustrovana je upotreba scanf funkcije, ali uz napomenu da je ne treba koristiti za stringove upravo zbog tog problema.

U svakom slučaju, funkcija scanf ostavlja za sobom đubre u baferu za čitanje u vidu znaka za nov red ili tako nečega, dok funkcije fgets i getline ne tolerišu nikakvo đubre. Tome služi funkcija getchar. Ona će za scanf funkcijama počistiti đubre u baferu za čitanje.

Što se elegantnog i bezbednog rešenja tiče, koristi funkcije fgets i getline na opisani način. Ako je maksimalna veličina poznata i treba da popuniš rezervisani prostor, onda koristi fgets, a ako nema ograničenja dužine unapred, onda koristi getline, koji mora kasnije da bude praćen sa free.
Code (c):

char limited[10], *unlimited = NULL;
size_t size;

fgets(limited, sizeof(limited), stdin);
getline(&unlimited, &size, stdin);
/* ... */
free(unlimited);
 

Pročitao sam tvoj primer i izgleda da si shvatila fabulu radnje.


Skapirah da je najpametnije koristiti fgets ( getchar()+fgets(...) ) za char string[...]... i getline za char *string... ( getline(...) + free(string) - ovo mi je promaklo; string mora biti inicijalizovan sa NULL - bilo na početku/pri deklaraciji ili neposredno pre getline)

Biće ovde još pitanja...

Npr nadovezivanje stringova - strcat(string1, string2)
Pri normalnoj deklaraciji, string1 mora da bude deklarisano kao char string[]....
Ako se unos u char *string... vrši sa getline (poslednji unos pre strcat) onda prihvata da string1 bude deklarisano kao char *string..., uz jedan (mali) problem: getline ubacuje na kraju i oznaku za kraj reda pa novonastali string (proširen string1) se sastoji iz 2 reda - u prvom je prvobitni sadržaj a u drugom sadržaj pridodatog stringa ??
To sam rešila uvođenjem dodatne promenljive:
Code:

int i = 0;
char *string1 = NULL;
char string2[] = "string2";
size_t string1_size;

...

getline(&string1,&string1_size,stdin);
...
char string_temp[ (strlen(string1)-1) ]; 
//?? koliko je ovo pametno: možda bolje #define MAXL 100 ....... char string_temp[MAXL] ??
...
//prebacivanje podataka - cilj je izostaviti poslednji karakter, koji označava prelazak u novi red
for(i=0; i<(strlen(string1)-1); i++)
    string_temp[i] = string1[i];
...
strcat(string_temp,string2);



Mana ovakvog koda jeste da između ovakvog popunjavanja string_temp promenljive ne sme da stoji dodela vrednosti nekoj drugoj promenljivoj slične inicijalizacije (char string[] ), niti inicijalizacija iste.
Ako se to ispoštuje, ne pravi problema oko prekoračenja inicijalne dužine.

Pokušavam li da izmislim toplu vodu, ili postoji neka funkcija koja skraćuje string, odnosno briše neki znak iz stringa?
[ Nedeljko @ 20.11.2012. 14:23 ] @
Ne zezaj se sa inicijalnom dužinom nego,
Code (c):
char *string1 = NULL, *string2 = NULL, *result;
size_t size1, size2;

getline(&string1, &size1, stdin);
getline(&string2, &size2, stdin);
result = (char*) malloc(size1 + size2 - 1);
strcpy(result, string1);
strcat(result, string2);
/* ... */
free(string1);
free(string2);
free(result);
 

Druga varijanta
Code (c):
char *string1 = NULL, *string2 = NULL, result[1000];
size_t size1, size2;

getline(&string1, &size1, stdin);
getline(&string2, &size2, stdin);
result = (char*) malloc(size1 + size2 - 1);
strncpy(result, string1, sizeof(result));
strcat(result, string2, sizeof(result));
/* ... */
free(string1);
free(string2);
 

Što se tiče kraja reda, dovoljno je uraditi
Code (c):

string1[strlen(string1)] = 0;
 
[ staticInt @ 20.11.2012. 14:25 ] @
Citat:
EmmaR
Mana ovakvog koda jeste da između ovakvog popunjavanja string_temp promenljive ne sme da stoji dodela vrednosti nekoj drugoj promenljivoj slične inicijalizacije (char string[] ), niti inicijalizacija iste.
Ako se to ispoštuje, ne pravi problema oko prekoračenja inicijalne dužine.

Pokušavam li da izmislim toplu vodu, ili postoji neka funkcija koja skraćuje string, odnosno briše neki znak iz stringa?


Nemoj ovo da shvatis kao uvredu ili bilo sta slicno ali mislim da se vrtis u krug i ne vidis koji problem imas na prvom mestu a to je osnovno nerazumevanje koncepta programiranja u C-u, API za C je prilicno jednostavan i primera na netu imas na tone samim tim pronalazak funkcije koja ti treba da odradi odredjenu stvar je vrlo lak task ali moras da znas sta trazis, problem kod tebe je sto ne znas sta da trazis jer imas ogromnu rupu u elementarnom znanju programiranja.

Ja bih ti toplo preporucio da procitas neke knjige dobar start bi bio "white bible" ili


Kad ustanovis osnovne programiranja i shvatis tipove varijabla onda mozes da krenes da radis konkretne stvari, bez toga ces jednostavno udarati u zid svaki put kad zelis nesto da napravis, ako posedujes dobro predznanje i znanje da nadjes sta ti treba dalje ces sama lako da nadjes stvari, za neke druge komplikovanije probleme mozes koristiti forume ali koristiti forum da bi pitala kako se koriste Stringovi nema puno smisla.

Eto izvini ako sam bio pregrub ali jednostavno tako je :)
[ Mihajlo Cvetanović @ 20.11.2012. 14:31 ] @
Citat:
Nedeljko:

Što se tiče kraja reda, dovoljno je uraditi
Code (c):

string1[strlen(string1)] = 0;
 


Zar nije ovo redundantno? Pronađeš kraj stringa i onda tu postaviš nulu, koja je već bila tu.
[ EmmaR @ 20.11.2012. 15:25 ] @
Nadjoh nešto i sama

Code (c):

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

#define RED '\n'

void squeeze(char s[], int c);

main()
{
     char *recz1 = NULL;
     char *recz2 = "DODATAK";
     size_t recz1_size;

     printf("\nUnesi recz1: ");
     getline(&recz1,&recz1_size,stdin);
     free(recz1);

     printf("\n\nPre spajanja ");
     printf("\nRecz1 : %s",recz1);
     printf("\nRecz2 : %s",recz2);

     strcat(recz1,recz2);
     printf("\n\nPosle spajanja ");
     printf("\nRecz1 : %s",recz1);
     printf("\nRecz2 : %s",recz2);

     
     squeeze(recz1,RED);

     strcat(recz1,recz2);
     printf("\n\nPosle spajanja i squeeze");
     printf("\nRecz1 : %s",recz1);
     printf("\nRecz2 : %s",recz2);


     

     printf("\n");
     return 0;
}

/* squeeze: brisanje svih c iz s */
void squeeze(char s[], int c)
{
     int i,j;

     for(i=j=0;s[i]!='\0';i++)
          if(s[i]!=c)
               s[j++]=s[i];
     s[j]='\0';
}


 


Za squeeze, literatura: Dennis M. Ritchie, Brian W. Kernighan: "Programski jezik C" (Drugo izdanje, Prijevod: Ante Denić)
Ako postoji predefinisana funkcija squeeze, dajte *.h gde se nalazi. Imam spisak nekih predefinisanih C funkcija i tamo je nema a ni na sajtu cprogramming.com


brži ste od mene.

@staticInt: nema ljutnje, već mi se stvarno vrti u glavi (daj neki link for free)

@Nedeljko: hvala ti što se toliko trudiš da mi pomogneš.

Evo malčice ispravljen tvoj kod, koji kod mene (Linux-Mint, gcc kompajler) radi ono što sam zamislila da treba: spaja dva stringa u jedan (tj. pridružuje drugi string prvom) a rezultujući string (nova vrednost prvog stringa - string1) je izraz koji se sastoji samo od jednog reda.

Code (c):

        char *string1 = NULL, *string2 = NULL, *result;
     size_t size1, size2;
     
     getline(&string1, &size1, stdin);
     getline(&string2, &size2, stdin);
     result = (char*) malloc(size1 + size2 - 1);

     string1[ ( strlen(string1) - 1 ) ] = 0; //znak u stringu sa indexom za 1 manji od dužine stringa (mora da se još nekome zavrtelo u glavi)

     strcpy(result, string1);
     strcat(result, string2);
     
     printf(".... %s",result);

     /* ... */
     free(string1);
     free(string2);
     free(result);
 


rezultat (obuhvaćen i deo gde je upotrebljena squeeze funkcija):
Citat:

Unesi recz1: Prva Rec


Pre spajanja
Recz1 : Prva Rec

Recz2 : DODATAK

Posle spajanja
Recz1 : Prva Rec
DODATAK
Recz2 : DODATAK

Posle spajanja i squeeze
Recz1 : Prva Rec DODATAKDODATAK
Recz2 : DODATAK
Petar
Petrovic
.... Petar Petrovic




[ Nedeljko @ 20.11.2012. 22:25 ] @
Citat:
Mihajlo Cvetanović: Zar nije ovo redundantno? Pronađeš kraj stringa i onda tu postaviš nulu, koja je već bila tu.

Slažem se. Trebalo je
Code (c):

string1[strlen(string1) - 1] = 0;
 

Na taj način se ukokava kraj reda na kraju stringa.

EmmaR

Napravila si jednu ozbiljnu grešku. Prvo si pročitala recz1, što je u redu, zatim oslobodila prostor koji je string recz1 zauzimao, a onda pristupala njegovom sadržaju. To ne smeš da radiš. Oslobađaj prostor nekog podatka tek onda kada ga više nećeš koristiti. Štaviše, savetujem ti da posle oslobađanja prostora na koji pokazuje neki pokazivač, samom pokazivaču dodeliš vrednost NULL, da bi ti se greške tog tipa ispoljile ako ih napraviš. No, ni to rešenje nije svemoguće. Recimo, možeš napraviti sledeću grešku:
Code (c):

char *p = NULL, *q;
size_t size;

getline(&p, &size, stdin);
q = p;
printf("%s", p);
free(p);
p = NULL;
printf("%s", q);
 

Dakle, u ovom primeru q pokazuje na isti prostor kao p, nakon toga se taj prostor oslobađa, a onda isti oslobođeni prostor koristi preko q.

No, dokle god si početnik (a i posle) ti preporučujem da sve pokazivače inicijalizuješ tamo gde ih definišeš (bilo na NULL, bilo na neku drugu smislenu vrednost) i da svako free(p) pratiš sa p = NULL, bez obzira što ni onda nisi 100% bezbedna.
[ EmmaR @ 21.11.2012. 17:06 ] @
Nedeljko,

bilo mi sumnjivo, ali začudo Linux se nije bunio, ni posle ko zna kog kompajliranja i izvršavanja.

Znači,
Code (c):

//pozeljno
char *string1 = NULL; // ili
char *string2 = "string2";
size_t s1, s2;

//
getline( &string1, &s1, stdin ); //za string1

string2 = NULL; //obavezna postavka na NULL, poslednja vrednost pred getline
getline( &string2, &s2, stdin );
/* ... */
//pa kad vise nema potrebe za string1 i string2
free(string1);
free(string2);
//i, za svaki slučaj
string1 = NULL;
string2 = NULL;
 
???

vec sam imala pokusaje stampe stringa sa null vrednost i sve je proslo OK.
Code:

char *string1 = NULL;
/* ... */
printf("Sadrzaj promenljive string1: %s",string1); //rez: [i]Sadrzaj promenljive string1: (null)[/i]
/* ... */

Mada, verovatno, da sam pokusala da uradim nesto mnogo slozenije, bilo bi podjednako loše (ako ne i gore) nego kao deljenje sa 0.

Još jedno zapažanje, za stringove deklarisane kao "niz"
Code:

char string[15];
/* ... */
scanf("%s",string); //unos preko scanf
/* ... */
//[u]prvi [/u]unos preko fgets
getchar();
fgets(string, sizeof(string), stdin);
/* ... */
//svaki naredni fgets i u slucaju kada nije pre toga dodeljena vrednost sa scanf
fgets(string, sizeof(string), stdin);

Odnosno da getchar(); je obavezno ispred fgets(...) jedino kada je ciljnom stringu pre toga u nekom trenutku bila dodeljena vrednost sa scanf( ... ) (bez obzira da li je u međuvremenu vršena i dodela sa strcpy(...) ); Ako se navede getchar() u ostalim slučajevima, treba uneti jedan (prvi) karakter za getchar(), a zatim niz karaktera koji prihvata promenljiva preko fgets() ( npr. 12345 -> string = "2345", 1 je otišlo za getchar() ). ???
Takođe, scanf( ... ) ne prihvata blankove (probala sam i bez navodnika i sa jednostrukim-apostrof i sa dvostrukim navodnicima) i u situaciji
Code (c):

char string[15];
/* ... */
scanf("%s",string); //unos preko scanf : Zdravo, svete!
printf("%s",string); // rez: Zdravo,
/* ... */
//[u]prvi [/u]unos preko fgets
getchar();
fgets(string, sizeof(string), stdin); //ovaj deo se preskače, nije omogućen unos
printf("%s",string); // rez, preuzet deo iza blanka iz scanf: svete!  
/* ... */
//svaki naredni fgets i u slucaju kada nije pre toga dodeljena vrednost sa scanf
fgets(string, sizeof(string), stdin);
 


Izvinjavam se što ovoliko proveravam (naizgled) banalne stvari: nisam očekivala da će me stringovi zakopati na par dana i noći.
Mislila sam (naivno): promenljiva kao promenljiva, s tom razlikom što se može tretirati i kao niz (a opet, za razliku od niza lakši je unos - formiranje); važe ista pravila za unos / štampu kao i za druge promenljive (ispostavilo se da je samo prikaz sličan); ima svoje funkcije koje joj se ili dodeljuju ili u kojima je jedan od parametara,... i to je to...
Ali, ... ispostavilo se da dalja primena MNOGO zavisi od načina na koji se ne samo deklarišu već i na koji se inicijalizuju; i da
Code:
char string [15] = "Zdravo";
ne znači da u daljem unos string ne prihvata ni 15 znaka, ni 14 ( 15.ti rezervisan za obavezni kraj \0; ajde ovo 1 znak gore dole, u većini sutuacija nebitno), već samo 7 znaka (1 više od inicijalne vrednosti pri deklaraciji)....
[ Nedeljko @ 21.11.2012. 23:02 ] @
NULL vrednost nije besmislica, već vrednost sa tačno određenim značenjem, pa ako ne zbuni neku funkciju, nemoj da te to iznenadi.

getchar() stavljaj posle scanf(), a pre fgets().

scanf čita do prve beline (razmak ili tabulator ili kraj reda), a fgets do kraja reda.

Sve što važi za nizove, važi i za stringove, osim što se stringovi mogu osim kao nizovi tretirati i kao stringovi. Kod
Code (c):

char string[15] = "zdravo";
 

rezerviše (najmanje) 15 bajtova prostora.
[ EmmaR @ 22.11.2012. 21:36 ] @
Citat:
Nedeljko
Code (c):

char string[15] = "zdravo";
 

rezerviše (najmanje) 15 bajtova prostora.


A zašto onda ne dopušta da se unese više od 6+1 znak?

evo i malog doprinosa, kod koji radi pod Win - Borland C++ 3.1 for Win (uz komentare, komentare, ... i komentare win vs pingvini).
[code: c]
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

main()
{
//voditi racuna o velicini stringa
char string1p[15]; // Win: kod prekoracenja, menja vrednost promenljivih koje slede, sem *string ; Linux: ignorise visak
char stringp[15] = "zdravo"; //Win - prihvata ceo unos bez uticaja na ostale prom; Linux - samo max 7 char
char string2p[] = "zdravo"; // prekoracenje zaustavlja izvrsenje programa, max 7 / 6+1 char


//neogranicena velicina
char *string="string"; //isto i za: *string, *string=NULL
//size_t string_size; // Linux: za getline f-ju, ime nebitno, bitno da svaki *string ima svoju "velicinu" //Win ne poznaje

int broj = 888;

printf("\n\nInicijalne vrednosti - bez string1p");
printf("\nString2p: %s",string2p);
printf("\nString: %s",string);
printf("\nBroj: %d",broj);

printf("\n\n Unesi vrednost za string1p - 14char ... L=%d ... ",sizeof(string1p));
scanf("%s",string1p);
printf("\n Rezultat:\n\tString1p: %s\t String2p: %s", string1p, string2p);

//"besmisleni" deo koji treba da prikaze sta se desava kod Win kada se prekoraci velicina za string1p
printf("\n\nVrednosti posle \"prekoracenja\" string1p");
printf("\nString1p: %s \t L=%d",string1p,strlen(string1p));
//ako nema prekoracenja, treba da imaju inicijalne vrednosti
printf("\nString2p: %s",string2p);
printf("\nString: %s",string);
printf("\nBroj: %d",broj);

//*string, string1p[15]
strcat(string,string1p); //radi
printf("\nRezultat - ujedinjenje * []: %s",string );
strcpy(string2p, "ZDRAVO"); //ako napadne string1, da ima normalnu vrednost
printf("\n\nPrvi Broj... %3d",broj); //prekoracenje kod string[n] menja i ovde vrednost
printf("\nUnesi neki broj: ");
scanf("%d",&broj); // brojevi idu ovako
printf("\nBroj... %3d",broj);

//isto to, pokusaj sa string[]
printf("\n\n Unesi vrednost za string1p - 14char ... ");
//Unos: getchar + gets(string) za sve stringove, prvo pojavljivanje gets() iza bilo kog scanf, nije bitno koja promenljiva
getchar();
gets(string1p); //Linux: getline + free za *string; getchar + fgets za string[] - getchar() prethodi samo ako je scanf primenenjeno na ciljnu promenlj.
/* Linux sintaksa:
fgets(string, sizeof(string),stdin); //za string[];
getline(&string, &string_size, stdin); //za *string, inicijalizovan sa NULL ili mu je ta vrednost dodeljena pre getline - OBAVEZNO */
printf("\n Rezultat:\n\tString1p: %s\t String2p: %s", string1p, string2p);


printf("\n\n Unesi vrednost za string - no limitt ... ");
//Unos: gets(string) za sve stringove, naredna pojavljivanja gets() i prvo gets bez scanf ispred
gets(string);
printf("\n Rezultat:\tString: %s", string);

//*string + string1p[] in *string
strcat(string,string1p); //radi. Linux: da bi *string bilo prvo, dodela mora da bude preko getline
printf("\nRezultat: %s",string );

//strcpy dodela
strcpy(string2p,"hello");
printf("\nString2p - strcpy: %s", string2p);
strcpy(string,"string Hello"); //Linux - ne vazi za *string
printf("\nString - strcpy: %s",string);

//dodela - vazi samo za brojeve i *string, ne vazi za string[] -Linux, isto
string = "hello world";
printf("\nString - dodela : %s",string);

//stringp[15] = zdravo
printf("\n\n Unesi vrednost za stringp - 15 or 7 ... ");
gets(stringp);
printf("\n Rezultat:\tStringp: %s", stringp);
printf("\n\n Unesi vrednost za string2p - 7 ... ");
gets(string2p);
printf("\n Rezultat:\tString2p: %s", string2p);


printf("\n\nVrednosti posle prekoracenja string1"); //ne utice na druge promenljive
printf("\nStringp: %s \t L=%d",stringp,strlen(stringp));
printf("\nString2p: %s",string2p);
printf("\nString: %s",string);
printf("\nBroj: %d",broj);


printf("\n\n");
}

[/code]
Napomena: MS Visual C++ 6.0 ne uspeva da izvrši kod (možda je moj kompajler neisravan, a možda je do koda).
[ Nedeljko @ 22.11.2012. 22:52 ] @
Citat:
EmmaR: A zašto onda ne dopušta da se unese više od 6+1 znak?

Ne znam kako si došla do tog zaključka. Ispod si u komentaru napisala da ne radi pod linuksom, ali evo, testiram pod linuksom i radi.
Code (c):

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

int main()
{
    char hello[100] = "Hello!";
    char hello2[] = "Hello, again!";

    fgets(hello, sizeof(hello), stdin);
    printf("%s%s\n", hello, hello2);

    return 0;
}
 

Uz to, taj stari borlandov prevodilac je jako zastareo. Preporučujem ti Code::Blocks sa kompajlerom koji ide uz njega. Majkrosoft baš i ne poštuje standarde, tako da nemoj da se iznenadiš kada na njihovom prevodiocu neki kod iz knjiga ne radi.

[Ovu poruku je menjao Nedeljko dana 23.11.2012. u 00:44 GMT+1]
[ EmmaR @ 23.11.2012. 00:08 ] @
Citat:
Nedeljko: Ne znam kako si došla do tog zaključka. Ispod si u komentaru napisala da ne radi pod linuksom, ali evo, testiram pod linuksom i radi.
Code (c):

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

int main()
{
    char hello[100] = "Hello!";
    char hello2[] = "Hello, again!";

    fgets(hello, sizeof(hello), stdin);
    printf("%s%s\n", hello, hello2);

    return 0;
}
 

Uz to, taj stari borlandov prevodilac je jako zastareo. Preporučujem ti Code::Blocks sa kompajlerom koji ide uz njega. Majkrosoft baš i ne poštuje standarde, tako da nemoj da se iznenadiš kada na njihovom prevodiocu neki kod iz knjiga ne radi.

[Ovu poruku je menjao Nedeljko dana 23.11.2012. u 00:44 GMT+1]


Stvarno radi. Borland je zaostavština iz perioda DOS+Win3.1/95, u ovoj fazi je OK.