Ricavare ultimo carattere di una stringa

torn24:
Si, funziona con qualunque lunghezza della stringa.

Si ma aggiungerei, sempre per completezza di informazione per l'OP (non per te :wink: ), "...a patto che la stringa sia correttamente terminata dal carattere 0x0".
Questo perché di fatto strlen() cerca il primo byte a zero a partire dall'indirizzo specificato.

Ossia la strlen() fa questo (dalla "bibbia del C" ossia il K&R):

size_t strlen(const char * str)
{
    const char * s = str;
    for (; *s; ++s);
    return(s - str);
}

Quindi funziona SOLAMENTE se la stringa C è "ben formata", altrimenti arriverà "casualmente" al primo byte a zero che si trova dopo il primo byte della stringa passata, o, nel peggiore dei casi, andrà a sforare lo spazio disponibile per il programma causando un errore o un blocco.

Standardoil:
io ti consiglio, come tutti qui, il buon K&R, magari la seconda edizione italiana, se non mastichi bene l'inglese
io ho questa: Linguaggio C, Gruppo Editoriale Jackson, ISBN 88-7056-443-6
ma credo piu' facile trovare in commercio questa: Il Linguaggio C, Pearson Education Italia, ISBN 88-7192-200-X

Standardoil, ho cercato la seconda edizione in italiano del K&R ma non sono sicuro che sia lo stesso di cui parli...
Possibile avere foto copertina o link?
Grazie...

manolomao:
Possibile avere foto copertina o link?

La "Bibbia"? ... questa:


... la trovi su Amazon :slight_smile:

Guglielmo

docdoc:
Ossia la strlen() fa questo (dalla "bibbia del C" ossia il K&R):

size_t strlen(const char * str)

{
    const char * s = str;
    for (; *s; ++s);
    return(s - str);
}

da quale pagina?
Letta tutta e no la ho trovata,...

Sul K&R (edizione in lingua Inglese) ci sono almeno due versioni della strlen(), una a pagina 38 ed una a pagina 89. La seconda è la più simile a quella riportata sopra che però ... NON si trova nel K&R, bensì nello "The Standard C Library" (che si può acquistare QUI), a pagina 403. :slight_smile:

Guglielmo

Ma dove vogliamo andare a parare? Cosa deve fare strlen() lo sappiamo tutti, com'è implementata cosa importa?

SukkoPera:
Cosa deve fare strlen() lo sappiamo tutti, com'è implementata cosa importa?

Beh, immagino a fini educativi ...
... può servire a capire che: 1. buona parte delle funzioni della libreria standard 'C' sono scritte ... in 'C' :smiley: (... le rimanenti in assembler :wink:), 2. puo mostrare dei buoni "esempi" di programmazione dato che ... è stata rivista, ottimizzata e corretta parecchie volte fino ad arrivare a quella che è :wink:

Guglielmo

... ha, che poi quella è tutta la teoria, in pratica, ogni "implementazione" fa come gli pare e ... su AVR, la AVR libc, implementa la strlen() ... in assembler :smiley: :smiley: :smiley:

/* Copyright (c) 2002, 2007 Marek Michalkiewicz
   All rights reserved.

   Redistribution and use in source and binary forms, with or without
   modification, are permitted provided that the following conditions are met:

   * Redistributions of source code must retain the above copyright
     notice, this list of conditions and the following disclaimer.
   * Redistributions in binary form must reproduce the above copyright
     notice, this list of conditions and the following disclaimer in
     the documentation and/or other materials provided with the
     distribution.
   * Neither the name of the copyright holders nor the names of
     contributors may be used to endorse or promote products derived
     from this software without specific prior written permission.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  POSSIBILITY OF SUCH DAMAGE. */

/* $Id: strlen.S 1944 2009-04-01 23:12:20Z arcanum $ */

/** \file */
/** \ingroup avr_string
    \fn size_t strlen(const char *src)
    \brief Calculate the length of a string.

    The strlen() function calculates the length of the string src, not
    including the terminating '\\0' character.

    \returns The strlen() function returns the number of characters in
    src.  */

#if !defined(__DOXYGEN__)

#include "macros.inc"

#define src_hi r25
#define src_lo r24

; 10 words, (14 + strlen(src) * 5) cycles

	ASSEMBLY_CLIB_SECTION
	.global	_U(strlen)
	.type	_U(strlen), @function
_U(strlen):
	X_movw	ZL, src_lo
.L_strlen_loop:
	ld	__tmp_reg__, Z+
	tst	__tmp_reg__
	brne	.L_strlen_loop
; Z points one character past the terminating NUL
; return Z - 1 - src = (-1 - src) + Z = ~src + Z
	com	src_lo
	com	src_hi
	add	src_lo, ZL
	adc	src_hi, ZH
	ret
.L_strlen_end:
	.size	_U(strlen), .L_strlen_end - _U(strlen)

#endif /* not __DOXYGEN__ */

Guglielmo

Beh OK, il fatto è che l'implementazione non è univoca. Varia a seconda della piattaforma, forse del livello di ottimizzazione, ecc...

Scrive una strlen() qualunque è ovviamente banale. Essendo però una funzione chiamata spessissimo, ogni libc si premurerà di implementarla nel modo più efficiente possibile.

Beccatevi, ad esempio, l'implementazione di glibc. Allucinante :o.

Librerie con un target meno ampio possono addirittura contenere funzioni scritte direttamente in assembly, tipo quella della AVR libc (che è quella che usiamo su Arduino). Potrebbero anche sfruttare hardware dedicato per accelerare le cose, tipo DMA, MMX, SSE, ecc...

Infine, tenete presente che GCC ha delle ottimizzazioni particolari per quanto riguarda alcune funzioni di utilizzo comune come questa. Cosa facciano di preciso non lo so, comunque:

-foptimize-strlen
Optimize various standard C string functions (e.g. strlen, strchr or strcpy) and their _FORTIFY_SOURCE counterparts into faster alternatives.

Enabled at levels -O2, -O3.

PS: Sovrapposto con gpb!

Standardoil:
da quale pagina? Letta tutta e no la ho trovata,...

Mi ha anticipato Guglielmo :wink: comunque si, pagina 38 del second edition c'è la versione "simile" generica, ma io l'ho presa proprio dallo "Standard C", per me punto di riferimento più aggiornato e completo del K&R, anche se quest'ultimo lo si deve conservare come una sacra reliquia :wink:
Pensa che ho ancora la prima edizione che acquistai quando ero ancora all'Università.
(nota: lo presi per mia passione, all'epoca ad Ingegneria oltre al Fortran ci insegnavano il Pascal mica il C, purtroppo... Per lo stesso motivo presi anche il Turbo Prolog, un linguaggio che amavo per la sua originalità, derivato dal Lisp.. Ma sto divagando :wink: ).

Comunque, per tornare alla sezione "accademica", è esatto, in base alla piattaforma dove si lavora basta cercare l'implementazione nella libreria string, dove ovviamente si devono tenere in conto delle caratteristiche e limitazioni della piattaforma stessa.

Ad esempio come ha scritto SukkoPera nella glibc la strlen() inizia con la sola parte che di fatto ci interessa:

 for (char_ptr = str; ((unsigned long int) char_ptr
            & (sizeof (longword) - 1)) != 0;
       ++char_ptr)
    if (*char_ptr == '\0')
      return char_ptr - str;

ma il resto, che riguarda longword (che non sono spade medievali :wink: ) magic bits (altra roba apparentemente "medievale" :D) e altro, ignoratelo per evitare mal di testa. :wink: