2010-12-06 41 views
1

Pourquoi le code suivant génère-t-il une erreur de compilation? Je n'arrive pas à voir pourquoi les types sont incompatibles.C Erreur de compilation de structure

typedef char f_string[MAX_CHARS+1] ; /* string for each field */ 

/* 
* A parsed CSV line, with the number of fields and upto MAX_FIELDS themselves. 
*/ 

typedef struct { 
    int nfields ;    /* 0 => end of file */ 
    f_string field[MAX_FIELDS] ;  /* array of strings for fields */ 
} csv_line; 

.... 

csv_line sut; 
sut.field[0] = "Name, "; //Compile-time error. 

Erreur être:

error: incompatible types in assignment 

Répondre

1

sut.field[0] est un char[MAX_CHARS+1]

"Name, " est un const char*

Essayez ceci:

strcpy(sut.field[0], "Name, "); 
+0

Merci pour votre aide. Acceptation pour cette réponse parce que c'était le plus rapide, un peu difficile à choisir entre les autres. – Mike

2

Le type de sut.field [0] est array-of-char de taille MAX_CHARS + 1 - vous ne pouvez pas affecter un pointeur de chaîne à un tableau de caractères.

Vous devez soit changer le type de champ csv_line :: en un const char *, soit simplement faire une copie de chaîne du "Nom" littéral, au tableau cible.

Notez que les deux strcpy() et strncpy() ne sont pas sûrs: le premier risque de déborder votre tampon et le second risque de le quitter sans terminateur NUL. Vous devez être conscient de ces deux circonstances, même si vous «savez» que votre chaîne en question ne débordera jamais.

utiliser une fonction d'aide pour le faire en toute sécurité:

char * strncopy(char *dst, const char *src, int dstsize) 
{ 
    strncpy(dst, src, dstsize-1); 
    dst[dstsize-1] = '\0'; 

    return dst; 
} 

Puis:

strncopy(sut.field[0], "Name, ", sizeof sut.field[0]); 
+0

pas besoin de faire cette fonction; il existe déjà: 'strncpy', et IIRC,' strcpyn' sur certains compilateurs. – Will

+0

@Le code de 'strncopy' utilise' strncpy' en interne. L'OP ajoute une fonctionnalité à 'strncpy' qui garantit que la chaîne est toujours terminée par un caractère nul. – mgiuca

+0

cela étant le cas, n'utilisez pas du tout 'strncpy', et faites-le vous-même avec une simple boucle while et copiez char par char, en vous souvenant d'ajouter le null à la fin. – Will

3

Vous essayez d'assigner un const char * à un char[], ce qui est pas tout à fait la même chose. Cela fonctionne si votre f_string ont été définis comme

typedef const char * f_string; 

Ce que vous cherchez ici est

strcpy (sut.field[0], "Name, "); 

Ou utilisez strncpy de sorte que vous pouvez spécifier la taille de la mémoire tampon de destination ..

strncpy (sut.field[0], "Name, ", MAX_CHARS) 

Cela vous évitera de dépasser votre tampon.

+0

'strncpy()' est * pas * un "safe' strcpy' "- il est destiné à la gestion de champs de chaînes de longueur fixe, qui n'ont pas nécessairement de terminaison nulle. – caf

+0

Je ne suis pas vraiment sûr de ce que vous entendez par "safe' strcpy' ". 'strncpy' vous permet de limiter le nombre de caractères copiés dans le tampon de destination. Si vous définissez le nombre maximal de caractères à quelque chose de moins que la taille du tampon de destination, vous ne le dépasserez pas si le tampon source contient une chaîne plus grande que le tampon de destination peut contenir. Ce qui se passera, comme cela m'a été rappelé, c'est que vous n'aurez pas de nulle dans votre tampon de destination; cette affaire devra être traitée et le null ajouté. – Will

+0

À droite: il n'ajoute pas de «\ 0» fin si la chaîne source est trop longue; et si la chaîne source est courte, elle remplit le reste de la destination (qui peut être assez grande) avec ''\ 0''. Puisque le premier doit être manipulé, ce n'est pas le remplacement de 'strcpy()' que beaucoup semblent croire. – caf

3

Vous aurez besoin d'utiliser quelque chose comme:

strcpy(sut.field[0],"Name, "); 

Vous ne pouvez pas affecter des chaînes comme vous avez essayé les autres, sauf comme initializater au moment de la déclaration.

1

Le type de sut.field[0] est en effet char [MAX_CHARS+1]. Cependant, la plupart des autres réponses ont le type de "Name, " faux - il est en fait de type char [7] (utilisez sizeof "Name, " pour une démonstration facile de cela). Néanmoins, vous ne pouvez toujours pas attribuer directement un char [7] à char [MAX_CHARS+1].Vous ne pouvez même pas attribuer directement un char [7] à un autre char [7] (l'initialisation est traité différemment de affectation de cette manière). La réponse est probablement simplement d'utiliser une fonction coyping - par exemple, si vous êtes certain que MAX_CHARS >= 6, alors vous pouvez simplement utiliser strcpy(). Si vous ne pouvez pas être sûr de la longueur étant correcte, vous pouvez utiliser strncat() comme en tronquant copie chaîne:

sut.field[0][0] = '\0'; 
strncat(sut.field[0], "Name, ", MAX_CHARS); 

(Notez que malgré le nom, strncpy() est pas approprié pour cela, et en fait est très rarement la fonction désirée du tout).


Il convient de souligner, cependant, que vous pouvez affecter indirectement des réseaux (du même type) si elles sont enveloppés dans un struct. Cela signifie que ce qui suit fonctionnera (si vous avez un compilateur C99):

typedef struct { char s[MAX_CHARS+1] } f_string; /* string for each field */ 

csv_line sut; 
sut.field[0] = (f_string){"Name, "}; 
+0

+1 pour 'strncat'. A été rappelé que 'strncpy' ne se terminera pas si la source est plus grande que la destination; avait oublié aussi que 'strncat' * fait * terminer le tampon de destination avec un null. Travailler avec C++ std :: string depuis trop longtemps que j'oublie certaines des nuances des chaînes C. – Will