2010-06-03 18 views
6

Estoy buscando un carácter en la primera aparición en una cadena usando el siguiente código. Pero lleva algo de tiempo cuando el carácter es demasiado largo o el carácter que estoy buscando está muy lejos, lo que retrasa otras operaciones. ¿Cómo podría abordar este problema? El código está debajo aquí.búsqueda de caracteres en el lenguaje de la secuencia C

Nota: attrPtr es un que contiene una referencia a una cadena que contiene '"' carácter en gran medida.

int position = 0; 

char qolon = '"';//character to search 

while (*(attrPtr + position++) != qolon); 

char* attrValue = NULL; 

attrValue = (char*)malloc(position * sizeof(char)); 

strncpy(attrValue, attrPtr, position-1); 

Respuesta

22

strchr suele ser algo más rápido. Además, debe verificar el terminador NUL, que strchr manejará por usted.

char *quotPtr = strchr(attrPtr, qolon); 
if(quotPtr == NULL) 
{ 
    ... // Handle error 
} 
int position = quotPtr - attrPtr; 
char* attrValue = (char*) malloc((position + 1) * sizeof(char)); 
memcpy(attrValue, attrPtr, position); 
attrValue[position] = '\0'; 

No he probado, sin embargo.

EDITAR: Reparar off-by-one.

+2

+1 deletreando NUL correctamente. –

+2

'NUL' es el apodo ASCII, el estándar C usa el término 'carácter nulo'. – dreamlax

+0

@Mathew Gracias por su sugerencia .... – boom

2

Requiere un algoritmo O(n) para buscar un carácter en la cadena. Entonces no puedes hacer mucho mejor de lo que ya estás haciendo. Además, tenga en cuenta que falta memset(attrValue, 0, position);, de lo contrario su cadena attrValue no tendrá terminación nula.

7

C tiene una función incorporada para buscar un carácter en una cadena - strchr(). strchr() devuelve un puntero al carácter encontrado, no a la posición de la matriz, por lo que debe restar el puntero al inicio de la cadena del puntero devuelto para obtenerlo. Puede reescribir su función como:

char qolon = '"';//character to search 
char *found; 
char *attrVal = NULL; 

found = strchr(attrPtr, qolon); 

if (found) 
{ 
    size_t len = found - attrPtr; 

    attrVal = malloc(len + 1); 
    memcpy(attrVal, attrPtr, len); 
    attrVal[len] = '\0'; 
} 

Esto puede ser más rápido que su original por un pequeño factor constante; sin embargo, no obtendrá una aceleración de orden de magnitud. La búsqueda de un personaje dentro de una cadena no ordenada es fundamentalmente O (n) en la longitud de la cadena.

2

El algoritmo que ha publicado no maneja correctamente el caso donde el carácter no existe en la cadena. Si eso sucede, simplemente marchará merily a través de la memoria hasta que al azar encuentre un byte que coincida con su char, o soplará más allá de su memoria asignada y obtendrá un segfault. Sospecho que es por eso que parece ser "tomar demasiado tiempo" a veces.

En C, las cadenas generalmente terminan con un 0 (ascii nul, o '\0'). Alternativamente, si conoce la longitud de la cadena antes de tiempo, puede usar eso.

Por supuesto, hay una rutina estándar de biblioteca C que hace exactamente esto: strchr(). Un programador inteligente usaría eso en lugar de los errores de riesgo lanzando los propios.

4

Dos cosas importantes:

1) Compruebe si hay un terminador NULL cuando se busca una cadena de esta manera:

while (*(attrPtr + position++) != qolon); 

debería ser:

while (attrPtr[position] && attrPtr[position++] != qolon); 

(si se aprueba una cadena que carece su personaje buscado, podría tomar mucho tiempo ya que escanea toda la memoria). Editar: Acabo de notar que alguien más publicó esto antes, yo, pero bueno.No estoy de acuerdo, por cierto, strchr() está bien, pero un simple bucle que también verifica el terminador está bien (y a menudo también tiene ventajas).

2) GUARDE de strncpy()!

strncpy(attrValue, attrPtr, position-1); 

strlen (attrPtr)> = (posición 1) por lo que este será NO nula terminar la cadena en attrvalue, lo que podría causar todo tipo de problemas (incluyendo desaceleración increíble en código más adelante). Como nota relacionada, strncpy() es erm, de diseño único, por lo que si haces algo como:

char buf[512]; 
strncpy(buf,"",4096); 

Usted va a escribir 4096 bytes de ceros.

Personalmente, uso lstrcpyn() en Win32, y en otras plataformas tengo una implementación simple de la misma. Es mucho más útil para mí.

Cuestiones relacionadas