2010-01-04 2 views
2

Je résoudre ce K & exercice R:Comment écrire des fonctions de chaîne C: strncpy, strncat et strncmp

versions d'écriture des fonctions de bibliothèque strncpy, strncat et strncmp, qui fonctionnent sur au plus la première n caractères de leurs chaînes d'arguments. Par exemple, strncpy (s, t, n) copie au plus n caractères de t à s. Les descriptions complètes sont dans l'annexe B.

Donc je me promenais s'il y a un site qui contient le code source pour ces fonctions de chaîne afin que je puisse vérifier si j'ai fait quelque chose de mal.

Ce sont les versions que j'ai écrites: j'apprécierais si vous me diriez si j'ai des bogues dans les fonctions ou quelque chose que je devrais ajouter/corriger/améliorer!

int strncmp(char *s, char *t, int n) 
{ 

    if(strlen(s) == strlen(t)) { 

     while(*s == *t && *s && n) 
      n--, s++, t++; 

     if(!n) 
      return 0; /* same length and same characters */ 
     else 
      return 1; /* same length, doesnt has the same characters */   
    } 
    else 
     return strlen(s) - strlen(t); 
} 

char *strncpy(char *s, char *t, int n) 
{ 
    while(n-- && *s) { 
     *s = *t; 
     s++, t++; 
    } 

    if(strlen(t) < n) 
     *s = '\0'; 

    return s; 
} 

char *strncat2(char *s, char *t, int n) 
{ 
    while(*s) 
     s++; 

    while(n-- && *t) 
     *s = *t, s++, t++; 

    *s = '\0'; 
    return s; 
} 

Répondre

4

Un rapide coup d'oeil semble révéler à Au moins quelques problèmes:

  • Dans strncmp: L'appel de strlen() sur l'entrée n'est pas valide. Ils ne doivent pas être terminés par null. En outre, la valeur de retour doit être < 0, = 0,> 0 en fonction de l'égalité. Strncpy: Je crois que la version de la bibliothèque remplit la chaîne avec \ 0 jusqu'à la fin.
+1

+1, et vous avez raison: 'pads strncpy()' la destination avec '0's à la fin. –

3

Bien sûr, il y a beaucoup d'implémentations open source de strncmp et amis (par exemple, strncmp here), mais ils ne seront pas nécessairement vous aider beaucoup.

Votre strncmp par exemple implémente simplement le mauvais algorithme: il est pas le cas où une chaîne plus courte est toujours « inférieur à » une plus longue, par exemple, "z" est pas moins de "aa" - donc vous pouvez » Commencez par comparer les longueurs seulement.

Votre strncpy vérifie *s où il devrait vérifier *t à la place, entre autres questions.

Voir alternatives implémentations open source ne va pas aider beaucoup à diagnostiquer vos bogues: examen par les pairs de votre code, que vous obtenez en postant à SO, aide probablement plus ;-)

0

Pour les solutions, voir CLC Wiki page.

maintenant quelques commentaires au sujet de votre code:

Pour strncmp:

if(strlen(s) == strlen(t)) { 

Vous n'avez pas besoin cette vérification. strlen() traverse la chaîne, donc vous allez traiter les chaînes deux fois si les longueurs sont égales. Cela peut devenir cher. En général, les fonctions de bas niveau comme celles-ci, que l'on peut appeler beaucoup dans n'importe quel programme, devraient être efficaces (bien que l'optimisation prématurée soit la racine de tout mal!). En outre, vous appelez à nouveau strlen() pour les deux chaînes si les longueurs ne sont pas égales. En plus d'être cher, c'est faux aussi, mais nous y reviendrons plus tard. A propos de votre boucle while:

while(*s == *t && *s && n) 
    n--, s++, t++; 

Pourquoi abuser l'opérateur virgule?Je simplifierait et écrire ce qui précède que (non testé, après tout, c'est un exercice vous résolvez!):

while (*s && *t && *s == *t && n--) { 
    s++; 
    t++; 
} 
if (!n) return 0; 
else return *s - *t; 

Vos valeurs de retour sont fausses. strncmp() doit renvoyer 0, inférieur à 0 ou supérieur à 0 selon que les premiers caractères n de la première chaîne sont égaux à, inférieurs ou supérieurs (lexicographiquement) à la deuxième chaîne. De même, vous devez modifier vos fonctions strncpy() et strncat2(). Je n'ai pas examiné ces deux points en détail, mais puisque c'est un exercice, vous voudrez probablement faire les changements vous-même de toute façon.

+0

Lexicographical - est-ce que cela signifie soustraire leurs valeurs ASCII? – Tool

+0

Non, ASCII ne vient pas dans l'image ici. Si un jeu de caractères est tel que ''a''>'' b'', alors 'strcmp (" a "," b ")' retournera un nombre supérieur à 0, ce qui pourrait être surprenant. L'ordre lexicographique est "ordre du dictionnaire", mais en utilisant un codage spécifique à la plate-forme pour les caractères. Si vous devez vous fier à l'ordre relatif des chaînes, 'strcmp()' ne sera peut-être pas le meilleur moyen de le faire (à moins d'être sûr que vous êtes sur des systèmes "sains"!). –

+0

Il est courant de faire "' return * s - * t; "" comme pour les fonctions de comparaison de chaînes, mais la norme ne spécifie que les valeurs de retour 0,> 0 et <0, donc on peut retourner toutes les valeurs satisfaisant ce critère. –

0

Pour référence:

char* strncpy(char* s, const char* t, size_t n) 
{ 
    char* ret = s; // need to return this 
    while (n-- && *s++ = *t++) 
     ; 
    if (n) *s = 0; 
    return ret; 
} 

// be lazy, there's no reason to write the copy part of strncpy and strncat twice. 
char* strncat(char* s, const char* t, size_t n) 
{ 
    char *ret = s; 
    strncpy(s+strlen(s), t, n); 
// 
// // if you don't want to call strlen, you can do this 
// while (*s++) ; 
// strncpy(s, t, n); 
// 
    return ret; 
} 

int strncmp(const char* s, const char* t, size_t n) 
{ 
    while (n-- && *s == *t) { 
      ++s; 
      ++t; 
    } 
    if (n) return *s - *t; 
    return 0; 
} 
Questions connexes