L'affectation rend le pointeur à partir d'un entier sans conversion

Venant D'un arrière-plan Java, j'apprends C, mais je trouve ces vagues messages d'erreur du compilateur de plus en plus frustrants. Voici mon code:

/*
 * 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] != ''; iTeller++)
        cString[iTeller] = (char)tolower(cString[iTeller]);

    return cString;
}

Cela génère deux avertissements.

  • l'affectation crée un pointeur à partir d'un entier sans conversion
    • cString1 = strToLower(cString1);
    • cString2 = strToLower(cString2);
  • return rend entier à partir du pointeur sans conversion
    • renvoie cString;

Quelqu'un peut-il expliquer ces mises en garde?

22
demandé sur jww 2010-01-15 21:59:06

8 réponses

Les chaînes C ne ressemblent pas à des chaînes Java. Ce sont essentiellement des tableaux de caractères.

Vous obtenez l'erreur car strToLower renvoie un caractère. Un char est une forme d'entier en C. Vous l'assignez dans un char [] qui est un pointeur. D'où "convertir un entier en pointeur".

Votre strToLower fait toutes ses modifications en place, il n'y a aucune raison pour qu'il retourne quoi que ce soit, surtout pas un char. Vous devriez "retourner" void, ou un char*.

Sur l'appel à strToLower, il n'y a pas non plus besoin d'affectation, vous ne faites que passer l'adresse mémoire pour cString1.

Dans mon expérience, les chaînes en C sont la partie la plus difficile à apprendre pour quiconque vient de Java/C# background vers C. Les gens peuvent s'entendre avec l'allocation de mémoire (puisque même en Java, vous allouez souvent des tableaux). Si votre objectif final est C++ et non C, vous préférerez peut-être vous concentrer moins sur les chaînes C, assurez-vous de comprendre les bases et utilisez simplement la chaîne C++ de STL.

38
répondu Uri 2010-01-15 19:45:08

Le type de retour de StrToLower doit être char* pas char (ou il ne devrait rien retourner du tout, car il ne ré-alloue pas la chaîne)

4
répondu James 2010-01-15 19:08:28

Comme d'autres l'ont déjà noté, dans un cas, vous essayez de retourner cString (qui est une valeur char * dans ce contexte-un pointeur) à partir d'une fonction déclarée pour retourner un char (qui est un entier). Dans un autre cas, vous faites l'inverse: vous attribuez une valeur de retour char à un pointeur char *. C'est ce qui déclenche les avertissements. Vous devez certainement déclarer vos valeurs de retour comme char *, pas comme char.

Notez que ces affectations sont en fait une contrainte violations du point de vue de la langue (c'est-à-dire ce sont des "erreurs"), car il est illégal de mélanger des pointeurs et des entiers en C comme ça (à part la constante intégrale zéro). Votre compilateur est tout simplement trop indulgent à cet égard et signale ces violations comme de simples "Avertissements".

Ce que je voulais aussi noter, c'est que dans plusieurs réponses, vous remarquerez peut-être la suggestion relativement étrange de retourner void de vos fonctions, puisque vous modifiez la chaîne sur place. Alors qu'il est le certainement travailler (puisque vous modifiez en effet la chaîne sur place), il n'y a rien de vraiment mal à renvoyer la même valeur de la fonction. En fait, c'est une pratique plutôt standard en langage C le cas échéant (jetez un oeil aux fonctions standard comme strcpy et autres), car elle permet le "chaînage" des appels de fonction si vous choisissez de l'utiliser, et ne coûte pratiquement rien si vous n'utilisez pas le "chaînage".

Cela dit, les affectations dans votre implémentation de compareString regardent complet superflu pour moi (même s'ils ne casseront rien). Soit je me débarrasse d'eux

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

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

Ou utilisez "chaînage" et faites

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

(c'est à ce moment que votre retour char * serait utile). Gardez simplement à l'esprit que de tels appels de fonction "enchaînés" sont parfois difficiles à déboguer avec un débogueur étape par étape.

En tant que note supplémentaire et irréelle, je dirais que l'implémentation d'une fonction de comparaison de chaînes de manière si destructrice (elle modifie l'entrée strings) pourrait ne pas être la meilleure idée. Une fonction non destructive serait d'une valeur beaucoup plus grande à mon avis. Au lieu d'effectuer une conversion explicite des chaînes d'entrée en minuscules, il est généralement préférable d'implémenter une fonction de comparaison de chaînes personnalisées non sensibles à la casse et de l'utiliser au lieu d'appeler la norme strcmp.

2
répondu AnT 2010-01-15 19:46:14
  • 1) Ne pas utiliser gets! Vous introduisez une vulnérabilité de dépassement de tampon. Utilisez fgets(..., stdin) à la place.

  • 2) Dans strToLower, vous êtes de retour d'un char au lieu de char-tableau. Soit return {[6] } comme suggéré par Autopulated, soit return void puisque vous modifiez l'entrée de toute façon. Par conséquent, il suffit d'écrire

 

 strToLower(cString1);
 strToLower(cString2);
  • 3) pour comparer les chaînes insensibles à la casse, vous pouvez utiliser strcasecmp (Linux et Mac) ou stricmp (Windows).
1
répondu kennytm 2010-01-15 19:05:13

Vous n'avez pas besoin de ces deux affectations:

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

Vous modifiez les chaînes en place.

Les Avertissements sont parce que vous renvoyez un char, et l'affectation à un char [] (qui est équivalent à char*)

0
répondu Ariel 2010-01-15 19:05:32

Vous renvoyez char, et non char*, qui est le pointeur vers le premier caractère d'un tableau.

Si vous voulez retourner un nouveau tableau de caractères au lieu de faire une modification sur place, vous pouvez demander un pointeur déjà alloué (char*) comme paramètre ou un pointeur non initialisé. Dans ce dernier cas, vous devez allouer le nombre approprié de caractères pour la nouvelle chaîne et rappelez-vous que dans les paramètres C transmis par la valeur toujours, vous devez donc utiliser char * * comme paramètre dans le cas du tableau alloué en interne par fonction. Bien sûr, l'appelant doit libérer ce pointeur plus tard.

0
répondu Hernán 2010-01-15 19:05:59

StrToLower devrait renvoyer un char * au lieu d'un char. Quelque chose comme ce serait le faire.

char *strToLower(char *cString)
0
répondu Suresh Krishnan 2010-01-15 19:06:32
char cString1[]

Ceci est un tableau, c'est à dire un pointeur vers le premier élément d'une série d'éléments du même type de données. Notez que vous ne passez pas le tableau par valeur mais par pointeur.

char strToLower(...)

Cependant, cela renvoie un caractère. Donc, votre mission

cString1 = strToLower(cString1);

A différents types de chaque côté de l'opérateur d'affectation .. vous assignez en fait un ' char '(sorte d'entier) à un tableau, qui se résout en un simple pointeur. En raison des règles de conversion implicites de C++, cela fonctionne, mais le résultat est ordures et un accès supplémentaire au tableau provoque un comportement indéfini.

La solution consiste à faire strToLower return char*.

-1
répondu Alexander Gessler 2010-01-15 19:05:33