Newsgroup: it.comp.lang.c
Titolo: strncpy come funziona

Ciao a tutti ho un problema nel comprendere strncpy.
io pensavo data la stringa:
 stringa= "abcdef"
lunghezza = strlen(stringa)
for (i=0;i<lunghezza;i+=2){
            strncpy(to, scrivo+i,i+2);
ottengo "ab" al primo ciclo
poi io pensavo di ottenere "cd"
invece ottengo "cdef"
dove sbaglio?
Grazie luca


dovrei aver capito
to mi ero dimenticato di scriverlo:
char *to = (char*) malloc(3);
char stringa[] = "abcdef";
int i;
diventa
for (i=0;i<lunghezza;i+=2){
             strncpy(to,scrivo+i,2)}
Saluti

luca72 ha scritto:

Sbagli a prescindere se usi strncpy/strncat: sono scritte malissimo, 
credo per applicare un po' di selezione naturale sui programmatori o 
qualcosa del genere - lo trovi spiegato diffusamente su internet, 
assieme alle possibili alternative razionali(*).
Quanto all'esempio, il valore di i viene aumentato di due a ogni 
iterazione: 2->4->6... (per la serie "doh!")
Ciao
(*) Sarebbe un argomento da flame, ma fra le 10e9 alternative, quella 
che si discosta di meno (niente malloc/realloc, ...) imho ï¿œ l'accoppiata 
strlcpy/strlcat; sono due piccoli files .c che puoi semplicemente 
copiaincollare da qualche parte nel tuo progetto.
Se non ti interessano, leggi almeno la descrizione, spiega chiaramente i 
problemi degli originali che intendono rimpiazzare.

 problemi degli originali che intendono rimpiazzare.
Lungi da me fomentare il flame, aggiungo solo che la strncpy _non_ è
standard C89, ma è standard POSIX e dovrebbe (se non ricordo male)
anche essere standard C99 (oltre che BSD4.3).
Ovviamente standard significa solamente che un sistema che si
definisce compliant garantisce che quella funzione sia presente, non
che funzioni bene.
Ciao!
P.S. Sempre se non ricordo male (ultimamente la mia memoria fa spesso
cilecca e non do più niente per scontato), per gli GNU-isti, ci
dovrebbe essere un'implementazione nella libiberty, quindi puoi sia
linkare con quella o copiare le solite venti-trenta di funzione nel
tuo codice nel caso sia l'unica che ti serve...

 che funzioni bene.
Che significa "non che funzioni bene"? 
Standard significa che quella funzione � presente ed ha il comportamento
standard.
-- 
questo articolo e` stato inviato via web dal servizio gratuito 
http://www.newsland.it/news
 segnala gli abusi ad 
ab...@newsland.it


Come ha precisato Lorenzo Beretta, semplicemente alcune funzioni
standard in determinati ambienti sono "scritte male" - credo
intendesse che, oltretutto, anche il comportamento standard della
strncpy sia fuorviante (il problema della strncpy/strncat risiede
semplicemente nella difficoltà di utilizzo, nella necessità di
terminare la stringa, etc.etc.)
P.S. Detto questo, il fatto che lo sviluppatore di libreria standard
abbia scritto una funzione alla carlona solo per dire di essere
compliant non significa che, benché la funzione svolga il suo compito,
questa funzione debba essere usata se si conoscono penalità derivanti
dal suo utilizzo (mancate ottimizzazioni, eccessivo uso della memoria,
etc.). E' il principale motivo del perché su numerosi ambienti non si
usano le funzioni di allocazione della memoria standard ma soluzioni
alternative.
Ciao!

 Ciao!
Non avevo mai sentito parlare così male delle povere strncpy & co.
Potete illuminarmi su come si fa a "scrivere male" la strncpy ? Per
un'implementazione banale sono sufficienti due righe.
Quanto al fatto che sia fuorviante in effetti ci può stare; d'altronde
il poster originale ne ha sbagliato l'uso sull'esempio postato nel
post precendete. Tuttavia non mi sembra il caso di evitare l'uso di
una funzione perché il suo nome è fuorviante : ) Voglio dire, se sai
cosa fa, la usi per quello che fa.
Altre problematiche, oltre alla necessita di terminare la stringa, non
ne vedo. Che intendevi per "etc.etc." ?
Quanto alle implementazioni in "numerosi ambienti" non saprei, mi fido
di quello che dici, anche se credo si parli di ambienti un po' piu di
nicchia. Le glibc (appena controllato) implementano la strncpy in 30
linee poiché fanno loop unrolling, quindi quanto a ottimizzazioni su
ambienti piu.. "commerciali" diciamo, non c'è nulla da temere. Per
l'"uso eccessivo della memoria" non saprei come implementare una
strncpy che sprechi memoria..
Ciao
Giacomo


ehehe, sì, mi sono lasciato trasportare ed ho fatto un discorso più
generale. :)
A dirla tutta, è anche una funzione che uso spesso (anche se quando
posso uso la memcpy).
P.S. per la strncpy che spreca memoria:
char *strncpy(char *s1, const char *s2, size_t n)
{
    char *p = malloc(UINT_MAX);
    return do_the_strncpy(s1, s2, n);
}

 strncpy sia fuorviante
Ma � anche bene dire che neanche strlcpy and strlcat sono esenti da
critiche. Ad esempio mi sembra non siano incluse nella glibc.


 }
ma lol...

 
Ma nessuno dice che siano perfette, ho messo quelle perchï¿œ fra le 
funzioni che usano semplici stringhe terminate con '\0' (e non, poniamo, 
struct miastringa *) e non gestiscono loro la memoria credo che siano 
molto sensate, tutto qui; sono anche discretamente diffuse (eg su 
cygwin) e liberamente usabili se non le hai, ma nessuno vieta di usare 
altro, mi *sembra* per esempio che la stessa funzionalitï¿œ venga offerta 
da win32 - e in quel caso, perchï¿œ non usare quelle?
Inoltre se leggi i messaggi con cui Drepper le ha rifiutate scopri che 
la motivazione ï¿œ "troppo inefficienti, ï¿œ cosa buona e giusta tenersi la 
lunghezza di tutte le stringhe e usare memcpy/mempcpy"; che in teoria 
sarï¿œ anche fattibile, ma in pratica ï¿œ un delirio, la cosa piï¿œ sensata in 
quel caso ï¿œ usare un'api  che si tenga la lunghezza di suo e faccia 
realloc quando serve - tipo quelle riportate su 
http://www.and.org/vstr/comparison
Dico "la" motivazione, al singolare, perchï¿œ gli esempi di codice 
scorretto di cui parla li ha promessi ma non forniti, per cui ho il 
sospetto che intenda "basta ignorare il valore di ritorno e tronchi le 
stringhe!" - ma appunto, il valore di ritorno ï¿œ fatto apposta per essere 
consultato, dice appunto quanto spazio serve...

     }
In questo caso non userei strncat, questo codice che hai scritto ha 
complessitï¿œ n^2 dove copiando i caratteri a mano avresti complessitï¿œ n.
E.


Sì e no. In caso volessi la massima efficienza senza copiare lo zero
useresti la memcpy. Sarebbe logico pensare che la strncpy facesse
qualcosa di diverso, quantomeno allineato alle altre funzioni
"str"qualcosa che gestiscono il terminatore.
Comunque sì, il problema di scrivere la specifica di una funzione
pensando a tutti i possibili usi che gli sviluppatori ne faranno è
un'impresa tutt'altro che banale.. del resto IMHO una delle grandi
fortune del C è quella di avere un set di funzioni standard abbastanza
snello, in modo che impararsi _tutte_ le funzioni sia abbastanza
semplice, e le possibilità di sbagliare siano quindi ridotte (comunque
ridotte rispetto ad altri linguaggi dove la quantità di funzioni
standard è così elevata che per scegliere la funzione da utilizzare si
va ad intuito - vedi Java).
Ciao!

 E.
Lo so, sembra la barzelletta dei carabinieri che devono dipingere le 
strisce per strada ;=)
Seriamente, non ï¿œ che difenda l'uso di str*cat in un ciclo, era solo per 
dire che con strncat ï¿œ macchinoso e viene piï¿œ facile sbagliare; cioï¿œ, se 
sono pigro e non m'importa di essere lento, almeno ci imbrocco?
lb

 "str"qualcosa che gestiscono il terminatore.
In effetti mi pare che l'unica differenza sia il tipo di valori passati. 
Il che, comunque, ha un suo perch�...
E.

 perchï¿œ c'ï¿œ spazio, piï¿œ altri *duecentoquarantasei* '\0'...
In molte situazioni potrebbe essere piï¿œ veloce fare la copia di tutti i 
caratteri piuttosto che andare a cercare lo '\0'.
E.

?manu* ha scritto:

Ok, ma non capisco cosa c'entra: strncpy prima va a cercare lo '\0', e 
poi fa memset a zero di tutto quello che avanza.
Non so, magari abbiamo in mente scenari diversi: io quando penso a 
queste cose mi immagino sempre il caso in cui la grandezza del buffer 
sia infinito (cose del tipo "I nomi dei file sono di lunghezza infinita, 
dove infinito ï¿œ settato a 255 caratteri"), per cui il caso tipico ï¿œ che 
la parte effettivamente utilizzata ï¿œ molto minore della dimensione 
massima e copiare tutto ï¿œ uno spreco allucinante.
Tu cos'hai in mente? che so, database con varchar piccoli piccoli?
lb

 Tu cos'hai in mente? che so, database con varchar piccoli piccoli?
Per esempio metti di voler creare un array di codici fiscali. Sono tutti 
della stessa lunghezza, tranne i codici fiscali delle aziende, che sono 
piï¿œ corti (credo!). In questo caso potresti copiarli qua e lï¿œ usando 
strncpy. Il riempimento con zeri ti assicura che i dati in memoria non 
contengano byte "casuali" (cosa che potrebbe essere utile in particolari 
situazioni, ad esempio se fai un checksum dell'intero array).
E.

 }
Qualcuno mi spiega per cortesia a che serve quel *p ?
Grazie.

On Jan 21, 4:14 pm, Santo Capolozo

a nulla (come del resto a nulla serve la malloc). Del resto non credo
sia una quelle situazioni in cui ti devi preoccupare delle
performances ;-)

 performances ;-)
Questo l'avevo capito ma, intendo dire, che ci sta a fare l� quella riga 
di codice? Che senso ha di esistere?

 di codice? Che senso ha di esistere?
:-| probabilmente non hai seguito il thread. Era un'iperbole per
dimostrare che è possibile scrivere una strncpy che spreca memoria.

 dimostrare che � possibile scrivere una strncpy che spreca memoria.
Chiedo venia...