2010-07-09 23 views
36

En este momento estoy tratando esto:¿Cómo iterar sobre una cadena en C?

#include <stdio.h> 

int main(int argc, char *argv[]) { 

    if (argc != 3) { 

     printf("Usage: %s %s sourcecode input", argv[0], argv[1]); 
    } 
    else { 
     char source[] = "This is an example."; 
     int i; 

     for (i = 0; i < sizeof(source); i++) { 

      printf("%c", source[i]); 
     } 
    } 

    getchar(); 

    return 0; 
} 

Esto también no funciona:

char *source = "This is an example."; 
int i; 

for (i = 0; i < strlen(source); i++){ 

    printf("%c", source[i]); 
} 

consigo el error

excepción no controlada en 0x5bf714cf (msvcr100d.dll) en Test.exe: 0xC0000005: infracción de acceso al leer en la posición 0x00000054.

(vagamente traducido del alemán)

Entonces, ¿qué hay de malo en mi código?

+3

por favor, no edite el código que ha preguntado. Eso cambia tu pregunta bastante para que muchas de las respuestas sean irrelevantes. En su lugar, solo publica todas las cosas que has intentado y menciona cuáles de ellas respondieron a las respuestas. –

+0

La nueva prueba contra argc que ha agregado es incorrecta. –

Respuesta

41

que desee:

for (i = 0; i < strlen(source); i++){ 

sizeof le da el tamaño del puntero, no la cadena. Sin embargo, habría funcionado si se hubiera declarado el puntero en forma de matriz:

char source[] = "This is an example."; 

pero si se pasa la matriz a funcionar, eso también decaerá a un puntero. Para cuerdas, es mejor usar siempre strlen. Y tenga en cuenta lo que otros han dicho sobre el cambio de printf para usar% c. Y también, teniendo mmyers comentarios sobre la eficiencia en cuenta, que sería mejor para mover la llamada a strlen fuera del circuito:

int len = strlen(source); 
for (i = 0; i < len; i++){ 

o reescribir el bucle:

for (i = 0; source[i] != 0; i++){ 
+2

Uh, dudo que quiera usar 'strlen' como límite. (Aunque se concede, en un programa de 10 líneas no hace mucha diferencia.) –

+1

@mmyers Um, ¿por qué no? –

+9

Bueno, la última vez que lo comprobé, strlen tuvo que recorrer todos los caracteres para determinar la longitud. Y dado que el char * puede cambiar en el ciclo, el compilador no puede sacar el strlen fuera de los límites de verificación; eso hace que el bucle O (n^2) en lugar de O (n). Por favor corrígeme si estoy equivocado. –

0

Simplemente cambie sizeof con strlen.

De esta manera:

char *source = "This is an example."; 
int i; 

for (i = 0; i < strlen(source); i++){ 

    printf("%c", source[i]); 

} 
+0

este código todavía tendrá una excepción debido a% s y char pasó a printf – ULysses

+0

Gracias por señalarlo. –

2

sizeof(source) devuelve el número de bytes requeridos por el puntero char*. Debe reemplazarlo por strlen(source), que será la longitud de la cadena que está tratando de mostrar.

Además, probablemente debería reemplazar printf("%s",source[i]) con printf("%c",source[i]) ya que está mostrando un personaje.

+0

entonces ... probable 'printf ("% c ", fuente [i])' con 'putchar (fuente [i])' ... – ShinTakezou

0

Reemplace sizeof con strlen y debería funcionar.

0

Necesita un puntero al primer carácter para tener una cadena ANSI.

printf("%s", source + i); 

hará el trabajo

Además, por supuesto que debería haber significado strlen(source), no sizeof(source).

1

Esto debería funcionar

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

int main(int argc, char *argv[]){ 

    char *source = "This is an example."; 
    int length = (int)strlen(source); //sizeof(source)=sizeof(char *) = 4 on a 32 bit implementation 
    for (int i = 0; i < length; i++) 
    { 

     printf("%c", source[i]); 

    } 


} 
1
  • sizeof(source) está volviendo a que el tamaño de un char*, no la longitud de la cadena.Debería usar strlen(source), y debería moverlo fuera del ciclo, o de lo contrario, volverá a calcular el tamaño de la cadena en cada ciclo.
  • Al imprimir con el modificador de formato %s, printf está buscando char*, pero en realidad está pasando char. Debe usar el modificador %c.
2
  1. sizeof() incluye el carácter nulo de terminación. Debería usar strlen() (pero coloque la llamada fuera del ciclo y guárdela en una variable), pero probablemente eso no sea lo que está causando la excepción.
  2. debe usar "% c", no "% s" en printf; está imprimiendo un carácter, no una cadena.
31

Un idioma común es:

char* c = source; 
while (*c) putchar(*c++); 

Unas pocas notas:

  • En C, las cadenas son null-terminated. Usted itera mientras que el carácter leído no es el carácter nulo.
  • *c++ incrementa c y devuelve el viejo sin referencia valor de c.
  • printf("%s") imprime una cadena terminada en nulo, no es un char. Esta es la causa de su violación de acceso.
+1

¿Puedo usar 'while (* C++) putc (* c);' ? –

+0

-1 "En C, las cadenas terminan en cero". Esto no tiene sentido. Tal vez lo que estás tratando de decir es que c-strings debe terminarse nulo. – Celeritas

+3

@Celeritas: Considero que el downvote es un poco duro: C tiene soporte de lenguaje para cadenas terminadas en cero, y el OP las está usando. De acuerdo, puede usar cadenas contadas (por ejemplo, 'BSTR's en el mundo de Windows), pero son menos comunes, y la pregunta no es ambigua en cuanto a qué tipo de cadena uno está usando. –

2

En lugar de utilización STRLEN como se sugirió anteriormente, sólo se puede comprobar el carácter nulo:

#include <stdio.h> 

int main(int argc, char *argv[]) 
{ 
    const char *const pszSource = "This is an example."; 
    const char *pszChar = pszSource; 

    while (pszChar != NULL && *pszChar != '\0') 
    { 
     printf("%s", *pszChar); 
     ++pszChar; 
    } 

    getchar(); 

    return 0; 
} 
+1

Funcionará, pero recomendaría verificar 'pszChar! = '\ 0'' para que sea explícito de todos modos. No está comparando contra 'NULL' (típicamente para punteros), sino contra el carácter nulo, que termina con las cadenas C. (Alternativamente, ambos son iguales a cero, por lo que 'pszChar && * pszChar' también es una buena condición, si estás interesado en ese tipo de cosas). –

0

sizeof(source) vuelve sizeof un puntero como fuente es declarado como char *. La forma correcta de usarlo es strlen(source).

siguiente:

printf("%s",source[i]); 

espera cadena. es decir,% s espera una cadena pero está iterando en un bucle para imprimir cada carácter. Por lo tanto, use% c.

Sin embargo, su forma de acceder (iterar) una cadena utilizando el índice i es correcta y, por lo tanto, no hay otros problemas en ella.