2009-07-03 7 views
0

c'est une question plutôt étrange.Cette fonction peut-elle être plus sûre? Vous cherchez des conseils et vos pensées!

J'ai écrit une fonction C. C'est «comme» strchr/strrchr. Il est supposé chercher un personnage dans un c-string, mais revenir en arrière, et lui renvoyer un pointeur. Comme les chaînes c ne sont pas "nulles", il faut aussi un troisième paramètre "count", indiquant le nombre de caractères qu'il doit regarder en arrière.

/* 
*s: Position from where to start looking for the desired character. 
*c: Character to look for. 
*count: Amount of tests to be done 
* 
* Returns NULL if c is not in (s-count,s) 
* Returns a pointer to the occurrence of c in s. 
*/ 
char* b_strchr(const char* s,int c,size_t count){ 

    while (count-->0){ 

     if (*s==c) return s; 
     s--; 
    } 
    return NULL; 
} 

Je l'ai fait des tests sur, mais Voyez-vous des défauts en elle? Problèmes de sécurité ou autre? Des améliorations? Pourrait-il être amélioré? Et plus important: est-ce une mauvaise idée?

Certains usages.

char* string = "1234567890"; 

    printf("c: %c\n",*b_strchr(string+9,'5',10));//prints 5 

    printf("c: %c\n",*b_strchr(string+6,'1',7));//prints 1 

EDIT: Nouvelle interface, quelques modifications.

/* 
* from: Pointer to character where to start going back. 
* begin: Pointer to characther where search will end. 
* 
* Returns NULL if c is not between [begin,from] 
* Otherwise, returns pointer to c. 
*/ 
char* b_strchr(const char* begin,int c,const char* from){ 


    while (begin<=from){ 

     if (*from==c) return from; 
     from--; 
    } 
    return NULL; 
} 

Répondre

5

Il vaut mieux le modifier, mais l'interface est toujours surprenante. Je mettrais le paramètre begin (la botte de foin recherchée) comme premier paramètre, le paramètre c (l'aiguillerecherchée) deuxième, et le paramètre from (position de départ de la recherche) troisième. Cet ordre semble être idiomatique sur un ensemble assez important d'API.

+0

Merci! Je n'avais pas pensé à ça. – Tom

2

Le code a une interface ésotérique - passer un pointeur sur le dernier caractère de la chaîne et la longueur de la chaîne. Cela conduira à des problèmes d'utilisation.

(Sinon, le code a un bug - vous devez ajouter le nombre de s avant que la boucle.)

+0

@Jonathan Merci pour votre avis. À quel bug faites-vous référence? Ce que je visais est que s pointe vers le personnage d'où commencer à regarder en arrière. – Tom

+1

@Tom: si l'interface est comme vous le vouliez, il n'y a pas de bug. Cependant, la plupart des gens, la plupart du temps, gardent un pointeur vers le début de la chaîne et parfois (dans ce cas nécessairement) la longueur de la chaîne. Cela signifie que les gens devront faire l'addition que vous montrez. Une interface plus conventionnelle aurait le premier argument au début de la chaîne; la fonction ferait l'addition. Notez, aussi, le modèle inconfortable 's + 9' et 10, 's + 6' et 7. Quel est le pari que quelqu'un va se tromper? –

+0

@Jonathan, Merci encore. Je vois ce que tu veux dire. Interface de la fonction modifiée, voir mon édition, je pense que c'est beaucoup mieux maintenant. – Tom

1

Si le début est à partir de, le code actuel retournera toujours commencer, ce qui n'est pas ce que vous voulez. Le code après la boucle peut juste être retourné NULL. Et au lieu de commencer! = À partir de la condition de boucle, j'utiliserais < sinon, vous pointerez le dépassement arithmétique quand quelqu'un mélange l'ordre des paramètres.

Edit: à la réflexion puisque vous voulez [commencer, à partir] inclus, il devrait être commencer < = de

+0

Merci pour votre contribution. – Tom

1

J'ai écrit une fonction C. C'est «comme» strchr/strrchr.

Vous avez tenté de réinventer strrchr(), il est pas comme strchr().

Y a-t-il des failles?

Oui. Nombreuses. :-(

Depuis b_strchr() peut revenir NULL, vous ne devriez pas le mettre directement dans la déclaration printf(). Deferencing NULL se traduit généralement par une erreur de segmentation.

Vous pouvez être mieux avec votre variation préférée ...

char *result; 

result = b_strchr(string + 9, 'a', 10)); 
if (result == NULL) 
{ 
    printf("c: NULL\n"); 
} 
else 
{ 
    printf("c: %c\n", *result); 
} 

Aussi, lorsque

(count >= length of the input string) and the character is not found 

vous allez obtenir des résultats unpredicable parce s est pas plus dirigée vers un caractère dans la chaîne — s pointe vers la mémoire avant le début de la chaîne. A titre d'exemple, essayez

result = b_strchr(string + 9, 'a', 11)); 
if (result == NULL) 
{ 
    printf("c: NULL\n"); 
} 
else 
{ 
    printf("c: %c\n", *result); 
} 

et de voir ce qui se passe.

Développez vos scénarios de test d'utilisation pour inclure des conditions en dehors de ce que vous savez fonctionner correctement. Demandez à quelqu'un d'autre de vous aider à concevoir des cas de test qui vont vraiment tester votre code.

Et plus important: est-ce une mauvaise idée?

Comme un exercice d'apprentissage, absolument pas.

Cependant, dans ce cas, pour le code de production, il serait préférable de s'en tenir à la norme strrchr().

+0

Je vois ce que tu veux dire, mais strrchr n'est pas ce dont j'ai besoin. Ce dont j'ai besoin, c'est de chercher un personnage dans les adresses inférieures où je suis debout. En ce qui concerne les tests printf, oui vous avez raison. J'ai fait ceux intentionnellement sur des cas qui ne renverraient pas null, mais merci pour votre contribution. S'il vous plaît, voir qu'il y a une version mise à jour. – Tom

Questions connexes