2010-01-15 16 views
19

Procedente de un fondo de Java, estoy aprendiendo C, pero los mensajes de error del compilador son cada vez más frustrantes. Aquí está mi código:Asignación hace puntero desde entero sin conversión

/* 
* PURPOSE 
*  Do case-insensetive string comparison. 
*/ 
#include <stdio.h> 
#include <string.h> 
#include <ctype.h> 

int compareString(char cString1[], char cString2[]); 
char strToLower(char cString[]); 

int main() { 
    // Declarations 
    char cString1[50], cString2[50]; 
    int isEqual; 

    // Input 
    puts("Enter string 1: "); 
    gets(cString1); 
    puts("Enter string 2: "); 
    gets(cString2); 

    // Call 
    isEqual = compareString(cString1, cString2); 
    if (isEqual == 0) 
     printf("Equal!\n"); 
    else 
     printf("Not equal!\n"); 

    return 0; 
} 

// WATCH OUT 
//  This method *will* modify its input arrays. 
int compareString(char cString1[], char cString2[]) { 
    // To lowercase 
    cString1 = strToLower(cString1); 
    cString2 = strToLower(cString2); 

    // Do regular strcmp 
    return strcmp(cString1, cString2); 
} 

// WATCH OUT 
//  This method *will* modify its input arrays. 
char strToLower(char cString[]) { 
    // Declarations 
    int iTeller; 

    for (iTeller = 0; cString[iTeller] != '\0'; iTeller++) 
     cString[iTeller] = (char)tolower(cString[iTeller]); 

    return cString; 
} 

Esto genera dos advertencias.

  • asignación crea un puntero desde un entero sin una conversión
    • cString1 = strtolower (cString1);
    • cString2 = strToLower (cString2);
  • retorno crea un entero desde un puntero sin una conversión
    • retorno cCadena;

¿Puede alguien explicar estas advertencias?

Respuesta

36

Las cadenas de caracteres C no se parecen en nada a las cadenas de Java. Son esencialmente matrices de caracteres.

Recibirá el error porque strToLower devuelve un carácter. Un char es una forma de entero en C. Lo está asignando en un char [] que es un puntero. Por lo tanto, "convertir entero en puntero".

Su strToLower hace todos sus cambios en su lugar, no hay razón para que devuelva nada, especialmente un chasquido. Deberías "devolver" el vacío, o un char *.

En la llamada a strToLower, tampoco hay necesidad de asignación, básicamente está pasando la dirección de memoria para cString1.

En mi experiencia, las cadenas en C son la parte más difícil de aprender para cualquier persona que venga del fondo Java/C# a C. La gente puede llevarse bien con la asignación de memoria (ya que incluso en Java a menudo se asignan matrices). Si su objetivo final es C++ y no C, es posible que prefiera concentrarse menos en las cadenas C, asegúrese de comprender los conceptos básicos y simplemente utilice la cadena C++ de STL.

+0

(+1) esto agrega el valor de la respuesta automática –

+0

Esto ** no aborda ** directamente el tema de su pregunta, es una solución indirecta: D para eliminar la advertencia del compilador La respuesta automática es más adecuada: D –

+0

Ok, aclaró la respuesta aquí. – Uri

4

de strtolower tipo de retorno debe ser char* no char (o debería devolver nada en absoluto, ya que no se vuelve a asignar la cadena)

+0

(+1, casi -1 = D) Lo que quiere decir es cambiar el tipo de devolución ..... está volviendo char *, sin embargo, esto está en conflicto con el tipo de devolución ... –

+0

Solucionado. Gracias, no fui muy claro en eso :) – James

1
  • 1) No utilice gets! Está introduciendo una vulnerabilidad de desbordamiento de búfer. Use fgets(..., stdin) en su lugar.

  • 2) En strToLower está devolviendo char en lugar de char -array. Devuelva char* como se sugirió Autopulated, o simplemente devuelva void ya que está modificando la entrada de todos modos.Como resultado de ello, acaba de escribir

 

strToLower(cString1); 
strToLower(cString2); 
  • 3) para comparar cadenas entre mayúsculas y minúsculas, puede utilizar strcasecmp (Linux & Mac) o stricmp (Windows).
0

No es necesario estos dos Traspaso:

cString1 = strToLower(cString1); 
cString2 = strToLower(cString2); 

está modificando las cuerdas en su lugar.

Las advertencias son porque va a devolver un char, y asignar a un char [] (que es equivalente a char *)

-1
char cString1[] 

Esta es una matriz, es decir, un puntero al primer elemento de una gama de elementos del mismo tipo de datos. Tenga en cuenta que no está pasando el valor por defecto de la matriz, sino por el puntero.

char strToLower(...) 

Sin embargo, esto devuelve un char. Por lo que su asignación

cString1 = strToLower(cString1); 

tiene diferentes tipos en cada lado del operador de asignación .. en realidad estás asignando un 'carbón' (especie de número entero) en una matriz, que se resuelve en un simple puntero. Debido a las reglas de conversión implícitas de C++ esto funciona, pero el resultado es basura y el acceso posterior a la matriz causa un comportamiento indefinido.

La solución es hacer strToLower devolver char*.

0

Está devolviendo char, y no char *, que es el puntero al primer carácter de una matriz.

Si desea devolver una nueva matriz de caracteres en lugar de realizar modificaciones in situ, puede solicitar un puntero ya asignado (char *) como parámetro o un puntero no inicializado. En este último caso, debe asignar el número adecuado de caracteres para la nueva cadena y recordar que en los parámetros C se pasa por el valor SIEMPRE, por lo que debe usar el parámetro char ** como en el caso de la matriz asignada internamente por la función. Por supuesto, el que llama debe liberar ese puntero más tarde.

0

strToLower debe devolver un char * en lugar de un char. Algo como esto haría.

char *strToLower(char *cString) 
2

Como otros ya se ha señalado, en un caso que está intentando volver cString (que es un valor char * en este contexto - un puntero) de una función que se declara para devolver un char (que es un entero) . En otro caso, haga lo contrario: está asignando un valor de retorno char a un puntero char *. Esto es lo que desencadena las advertencias. Sin duda debe declarar sus valores de devolución como char *, no como char.

Nota Por cierto que estas asignaciones son de hecho infracciones de constricción desde el punto de vista del lenguaje (es decirson "errores"), ya que es ilegal mezclar punteros y enteros en C de esa manera (aparte del cero constante integral). Su compilador simplemente es demasiado indulgente en este aspecto e informa estas violaciones como meras "advertencias".

Lo que también quería señalar es que en varias respuestas podría notar la sugerencia relativamente extraña de devolver void de sus funciones, ya que está modificando la cadena en contexto. Si bien funcionará (ya que de hecho está modificando la cadena en el lugar), no hay nada realmente malo en devolver el mismo valor de la función. De hecho, es una práctica bastante estándar en el lenguaje C donde corresponda (eche un vistazo a las funciones estándar como strcpy y otras), ya que habilita el "encadenamiento" de llamadas a función si elige usarlo, y no cuesta prácticamente nada si no use "encadenamiento".

Dicho esto, las asignaciones en su implementación de compareString me parecen superfluas (a pesar de que no romperán nada). Yo bien deshacerse de ellos

int compareString(char cString1[], char cString2[]) { 
    // To lowercase 
    strToLower(cString1); 
    strToLower(cString2); 

    // Do regular strcmp 
    return strcmp(cString1, cString2); 
} 

o use "encadenamiento" y hago

int compareString(char cString1[], char cString2[]) { 
    return strcmp(strToLower(cString1), strToLower(cString2)); 
} 

(esto es cuando su declaración char * podría venir a mano). Solo tenga en cuenta que las llamadas a funciones "encadenadas" a veces son difíciles de depurar con un depurador paso a paso.

Como nota adicional no realizada, diría que la implementación de una función de comparación de cadenas de una manera tan destructiva (modifica las cadenas de entrada) podría no ser la mejor idea. Una función no destructiva sería de mucho mayor valor en mi opinión. En lugar de realizar una conversión explícita de las cadenas de entrada a minúsculas, generalmente es una mejor idea implementar una función de comparación de cadenas insensible a mayúsculas/minúsculas personalizada y usarla en lugar de llamar al estándar strcmp.

Cuestiones relacionadas