2012-09-22 30 views
11

Dato un array di puntatori a stringhe letterali:determinare la lunghezza di una stringa letterale

char *textMessages[] = { 
    "Small text message", 
    "Slightly larger text message", 
    "A really large text message that " 
    "is spread over multiple lines" 
} 

Come si fa a determinare la lunghezza di una particolare stringa letterale - dice il terzo? Ho provato utilizzando il comando sizeof come segue:

int size = sizeof(textMessages[2]); 

Ma il risultato sembra essere il numero di puntatori nella matrice, piuttosto che la lunghezza della stringa letterale.

+3

'sizeof (textMessages [2])' darà la dimensione del tipo 'char *'. È puramente casuale che 'sizeof (char *)' capita di essere 4 sul tuo sistema, e nulla a che fare con il numero di elementi nel tuo array. –

+0

Si dovrebbe considerare l'uso della definizione 'static const char textMesssages [] [4]' per l'array. –

+1

@MichaelFoukarakis Ci sono solo * tre * puntatori nell'array (notare la concatenazione di stringhe). – Jens

risposta

17

Se si desidera che il numero calcolato al momento della compilazione (al contrario di in fase di esecuzione con strlen) è perfettamente a posto per usare un'espressione come

sizeof "A really large text message that " 
     "is spread over multiple lines"; 

Potresti voler utilizzare una macro per evitare di ripetere il letterale lungo, tuttavia:

Si noti che il valore restituito da sizeof include la terminazione NUL, quindi è uno più di strlen.

+0

Desidero determinare la lunghezza di ogni stringa in modo che sia possibile indicizzare le lunghezze e passarle a una funzione. È possibile calcolare una tale serie di lunghezze al momento della compilazione? – Zack

+1

Il mio approccio sarebbe quello di dichiarare e inizializzare un array di 'struct {char * ptr; size_t len; } x [] '. Quindi puoi chiamare 'pippo (x [i] .ptr, x [i] .len)'. Poiché C non mantiene le lunghezze delle stringhe in giro, non c'è altro modo che tenere traccia delle lunghezze delle stringhe nel codice. – Jens

0

strlen forse?

size_t size = strlen(textMessages[2]); 
+3

Perché calcolare questo numero in fase di esecuzione quando può essere determinato al momento della compilazione? – Jens

+0

@Jens: a meno che non si conosca anche la stringa al momento della compilazione. – Tudor

+0

@Tudor, sì - si conosce la lunghezza al momento della compilazione (la domanda dice "String Literal") – ideasman42

0

si dovrebbe utilizzare il metodo strlen() libreria per ottenere la lunghezza di una stringa. sizeof ti darà la dimensione di textMessages[2], un puntatore, che dipenderà dalla macchina (4 byte o 8 byte).

+0

Non intendi 4 o 8 byte? A meno che non si disponga di un computer a 16 bit ... – Tudor

+0

a destra, grazie per la correzione :) – Vikdor

0

strlen ti dà la lunghezza della stringa, mentre sizeof restituirà la dimensione del Tipo dati in byte immesso come parametro.

strlen

sizeof

-1

Ti dirò una cosa, come per i miei matrici di conoscenza i puntatori sono la stessa cosa tranne quando si utilizza sizeof.

Quando si utilizza sizeof su un puntatore tornerà sempre 4 BYTE indipendentemente la cosa che punta il puntatore, ma se utilizzato su array di esso tornerà quanto tempo l'array è grande in byte?.

In te esempio qui *textMessage[] è gamma di puntatore in modo che quando si utilizza sizeof(textMessage[2]) tornerà 4 BYTE perché textMessage[2] è un puntatore.

Spero che ti sia utile.

+0

Non ho capito cosa vuoi –

+0

Il mio intento era quello di dirti di migliorare le tue conoscenze sulla ** differenza ** di matrici e puntatori leggendo tutto su http://c-faq.com/aryptr/index.html Gli array non sono puntatori e sono spesso 2 o 8 anziché 4 byte e la loro dimensione può anche dipendere dal tipo a cui puntano. Quindi, la maggior parte di ciò che hai scritto è tecnicamente scorretto. – Jens

+0

Ok, grazie @jens –

0

Si può sfruttare il fatto che i valori di un array sono consecutive:

const char *messages[] = { 
    "footer", 
    "barter", 
    "banger" 
}; 

size_t sizeOfMessage1 = (messages[1] - messages[0])/sizeof(char); // 7 (6 chars + '\0') 

La dimensione è determinata in base alle confini degli elementi.Lo spazio tra l'inizio del primo e l'inizio del secondo elemento è la dimensione del primo.

Questo include lo \0 che termina. La soluzione, ovviamente, funziona correttamente solo con stringhe costanti. Se le stringhe fossero state puntatori, si otterrebbe la dimensione di un puntatore invece della lunghezza della stringa.

Non è garantito il funzionamento. Se i campi sono allineati, questo può dare taglie sbagliate e potrebbero esserci altre avvertenze introdotte dal compilatore, come la fusione di stringhe identiche. Inoltre avrai bisogno di almeno due elementi nella matrice.

+3

Non è garantito che funzioni. Mentre i puntatori nell'array devono essere consecutivi, i letterali di stringa non devono necessariamente. Pensa all'allineamento e così via. O usando lo stesso puntatore per letterali stringa identici. – Jens

+0

Hai ragione, l'allineamento potrebbe rompere questo (ma è controllabile). Anche le diverse dimensioni di 'char' potrebbero rompere questo. Segnerò la mia risposta come non affidabile. – nemo

+1

L'unione di stringhe identiche, un'ottimizzazione comune, lo spezza anche. – Jens

11

Il mio suggerimento sarebbe quello di utilizzare strlen e attivare le ottimizzazioni del compilatore.

Ad esempio, con gcc 4.7 su sistemi x86:

#include <string.h> 
static const char *textMessages[3] = { 
    "Small text message", 
    "Slightly larger text message", 
    "A really large text message that " 
    "is spread over multiple lines" 
}; 

size_t longmessagelen(void) 
{ 
    return strlen(textMessages[2]); 
} 

Dopo aver eseguito make CFLAGS="-ggdb -O3" example.o:

$ gdb example.o 
(gdb) disassemble longmessagelen 
    0x00000000 <+0>: mov $0x3e,%eax 
    0x00000005 <+5>: ret 

Vale a dire il compilatore ha sostituito la chiamata a strlen con il valore costante 0x3e = 62.

Non perdere tempo a eseguire ottimizzazioni che il compilatore può fare per te!

Problemi correlati