punteros - La asignación hace un puntero desde un entero sin conversión
punteros de char en c (8)
Como ya se ha dicho en otros, en un caso está intentando devolver cString
(que es un valor char *
en este contexto, un puntero) desde una función que se declara para devolver un char
(que es un número entero). En otro caso, haga lo contrario: está asignando un valor de retorno de char
a un puntero char *
. Esto es lo que dispara las advertencias. Ciertamente, debe declarar sus valores de retorno como char *
, no como char
.
Tenga en cuenta que, por cierto, estas asignaciones son de hecho restricciones de restricciones desde el punto de vista del idioma (es decir, son "errores"), ya que es ilegal mezclar punteros y enteros en C así (aparte de la constante cero). Su compilador simplemente es demasiado indulgente a este respecto e informa de estas violaciones como meras "advertencias".
Lo que también quería señalar es que, en varias respuestas, es posible que note la sugerencia relativamente extraña de devolver el void
de sus funciones, ya que está modificando la cadena en el lugar. 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 lenguaje C donde corresponda (eche un vistazo a las funciones estándar como strcpy
y otras), ya que habilita el "encadenamiento" de llamadas a funciones si decide usarlas, y no cuesta nada si no las usa. no utilice "encadenamiento".
Dicho esto, las asignaciones en su implementación de compareString
parecen completamente superfluas (aunque no rompan nada). O me deshago de ellos
int compareString(char cString1[], char cString2[]) {
// To lowercase
strToLower(cString1);
strToLower(cString2);
// Do regular strcmp
return strcmp(cString1, cString2);
}
o usar "encadenamiento" y hacer
int compareString(char cString1[], char cString2[]) {
return strcmp(strToLower(cString1), strToLower(cString2));
}
(esto es cuando tu char *
return vendría a la mano). Solo tenga en cuenta que tales llamadas a funciones "encadenadas" a veces son difíciles de depurar con un depurador paso a paso.
Como una nota adicional, no realizada, diría que implementar una función de comparación de cadenas de una manera tan destructiva (que 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, por lo general es una mejor idea implementar una función de comparación de cadenas personalizada sin distinción de mayúsculas y minúsculas y usarla en lugar de llamar al strcmp
estándar.
Desde el fondo de Java, estoy aprendiendo C, pero los mensajes de error de compilación vagos me parecen cada vez más frustrantes. Aquí está mi código:
/*
* 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 hace puntero de entero sin una conversión
- cString1 = strToLower (cString1);
- cString2 = strToLower (cString2);
- return hace un entero desde el puntero sin una conversión
- volver cString;
¿Alguien puede explicar estas advertencias?
El tipo de retorno de strToLower debe ser char*
not char
(o no debe devolver nada, ya que no vuelve a asignar la cadena)
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 una modificación en el lugar, puede solicitar un puntero ya asignado (char *) como parámetro o un puntero sin inicializar. En este último caso, debe asignar el número adecuado de caracteres para la nueva cadena y recuerde que en los parámetros C pasados por el valor SIEMPRE, debe usar char ** como parámetro en el caso de la matriz asignada internamente por función. Por supuesto, la persona que llama debe liberar ese puntero más tarde.
Las cadenas C no se parecen en nada a las cadenas Java. Son esencialmente matrices de personajes.
Recibirá el error porque strToLower devuelve un char. Un char es una forma de entero en C. Lo estás asignando a un char [] que es un puntero. Por lo tanto, "convertir entero a puntero".
Su strToLower realiza todos los cambios en su lugar, no hay razón para que devuelva nada, especialmente no un char. Usted debe "devolver" el vacío, o un char *.
En la llamada a strToLower, tampoco hay necesidad de asignación, básicamente solo 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 cualquiera que venga de Java / C # y vuelva a C. Las personas pueden llevarse bien con la asignación de memoria (ya que incluso en Java a menudo asignas arrays). 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 use la cadena C ++ de STL.
No necesitas estos dos compromisos:
cString1 = strToLower(cString1);
cString2 = strToLower(cString2);
Estás modificando las cadenas en su lugar.
Las advertencias se deben a que está devolviendo un char y asignándolo a un char [] (que es equivalente a char *)
strToLower debe devolver un char * en lugar de un char. Algo como esto haría.
char *strToLower(char *cString)
char cString1[]
Esta es una matriz, es decir, un puntero al primer elemento de un rango de elementos del mismo tipo de datos. Tenga en cuenta que no está pasando el valor de matriz sino el puntero.
char strToLower(...)
Sin embargo, esto devuelve un char. Entonces tu tarea
cString1 = strToLower(cString1);
tiene diferentes tipos en cada lado del operador de asignación ... en realidad estás asignando un ''char'' (tipo de entero) a 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 una basura y un mayor acceso a la matriz provoca un comportamiento indefinido.
La solución es hacer que strToLower
devuelva caracteres char*
.
1) ¡No usar se
gets
! Estás introduciendo una vulnerabilidad de desbordamiento de búfer. Usefgets(..., stdin)
lugar.2) En
strToLower
estás devolviendo unchar
lugar de unchar
array. Devuelvachar*
como sugirió Autopulated, o simplemente devuelvavoid
ya que de todos modos está modificando la entrada. Como resultado, solo escribe
strToLower(cString1);
strToLower(cString2);
- 3) Para comparar cadenas que no distinguen entre mayúsculas y minúsculas, puede usar
strcasecmp
(Linux y Mac) ostricmp
(Windows).