Pointeur gratuit et non valide

Il y a quelques problèmes dans votre code:

  • la fonction getNofTokens() do Ne prenez pas la chaîne de séparation sous forme d’argument, indique le nombre de mots séparés par des espaces vides, ce qui peut renvoyer un nombre incohérent de votre interlocuteur.

  • la taille attribuée result = malloc(sizeof(char *) * count + 1); est incorrect: il devrait être:

     result = malloc(sizeof(char *) * (count + 1));

    Le stockage de NULL Le pointeur final écrira au-delà de la fin de l’espace assigné.

  • Store dit NULL Terminator à la fin de la matrice est vraiment nécessaire, car le bloc de mémoire renvoyé par malloc() n’est pas initialisé.

  • La copie de la chaîne attribuée et analysée par split_string ne peut pas être libéré en toute sécurité parce que le pointeur tmp n’est pas enregistré n’importe où. Le pointeur du premier jeton sera différent de tmp dans 2 cas: Si la chaîne ne contient que des délimiteurs (aucun jeton n’a été trouvé) ou si la chaîne commence par un délimiteur (les délimiteurs être omis des initiales). Pour simplifier le code et le rendre fiable, chaque jeton pourrait dupliquer et tmp devrait être libéré. En fait, votre free_split_string() fonctionne sur ce comportement. Avec la mise en œuvre actuelle, le comportement est indéfini.

  • qui utilise unsigned long e int De plus en plus pour les longueurs de chaîne et les variables d’indice de matrice. Par cohérence, vous devez utiliser size_t pour les deux.

  • avec lequel vous devez affecter des copies de chaîne strdup() Si cette fonction Standard POSIX n’est pas disponible sur votre système, entrez une implémentation simple.

  • Ne jamais tester la défaillance de la mémoire. C’est bon pour les tests et le code d’élimination, mais ces défaillances potentielles doivent toujours être prises en compte dans le code de production.

  • strtok() est une fonction difficile à utiliser: modifie la chaîne source et maintient un état statique caché qui ne le rend pas réentrant. Vous devez éviter d’utiliser cette fonction, bien que dans ce cas particulier, cela fonctionne correctement, mais si l’appelant split_string ou

    « 0164668ce7 »>

    base sur la préservation de Cet état caché, obtiendrait un comportement inattendu.

Voici une version modifiée:

#include <stdio.h>#include <string.h>#include <stdlib.h>#include "stringsplit.h"/* Split string by another string, return split parts + NULL in array. * * Parameters: * str: the string to split * split: the string to split str with * * Returns: * A dynamically reserved array of dynamically reserved string parts. * * For example called with "Test string split" and " ", * returns . * Or called with "Another - test" and " - ", * returns . */size_t getNofTokens(const char *string, const char *split) { char *tmp = strdup(string); size_t count = 0; if (strtok(tmp, split) != NULL) { count++; while (strtok(NULL, split) != NULL) count++; } free(tmp); return count;}char **split_string(const char *str, const char *split) { size_t count = getNofTokens(str, split); char **result = malloc(sizeof(*result) * (count + 1)); char *tmp = strdup(str); char *token = strtok(tmp, split); size_t idx = 0; while (token != NULL && idx < count) { result = strdup(token); token = strtok(NULL, split); } result = NULL; free(tmp); return result;}void print_split_string(char **split_string) { for (size_t i = 0; split_string != NULL; i++) { printf("%s\n", split_string); }}void free_split_string(char **split_string) { for (size_t i = 0; split_string != NULL; i++) { free(split_string); } free(split_string);}

ici est une alternative sans strtok() et sans affectations intermédiaires:

#include <stdio.h>#include <string.h>#include <stdlib.h>#include "stringsplit.h"size_t getNofTokens(const char *str, const char *split) { size_t count = 0; size_t pos = 0, len; for (pos = 0;; pos += len) { pos += strspn(str + pos, split); // skip delimiters len = strcspn(str + pos, split); // parse token if (len == '\0') break; count++; } return count;}char **split_string(const char *str, const char *split) { size_t count = getNofTokens(str, split); char **result = malloc(sizeof(*result) * (count + 1)); size_t pos, len, idx; for (pos = 0, idx = 0; idx < count; pos += len, idx++) { pos += strspn(str + pos, split); // skip delimiters len = strcspn(str + pos, split); // parse token if (len == '\0') break; result = strndup(str + pos, len); } result = NULL; return result;}void print_split_string(char **split_string) { for (size_t i = 0; split_string != NULL; i++) { printf("%s\n", split_string); }}void free_split_string(char **split_string) { for (size_t i = 0; split_string != NULL; i++) { free(split_string); } free(split_string);}

modifier après avoir relire la spécification dans votre commentaire, semble être une confusion possible concernant la sémantique de split argument:

  • si split est un Ensemble de délimiteurs, le code précédent fait le travail. Et les exemples seront divisés comme prévu.
  • si split est une vraie chaîne qui correspond explicitement, le code précédent ne fonctionne que par coïncidence dans les exemples donnés dans le commentaire.

Pour implémenter la dernière sémantique, vous devez utiliser strstr() pour trouver le split SUBKUE dans les deux getNofTokens et split_string.

Voici un exemple:

#include <stdio.h>#include <string.h>#include <stdlib.h>#include "stringsplit.h"/* Split string by another string, return split parts + NULL in array. * * Parameters: * str: the string to split * split: the string to split str with * * Returns: * A dynamically reserved array of dynamically reserved string parts. * * For example called with "Test string split" and " ", * returns . * Or called with "Another - test" and " - ", * returns . */size_t getNofTokens(const char *str, const char *split) { const char *p; size_t count = 1; size_t len = strlen(split); if (len == 0) return strlen(str); for (p = str; (p = strstr(p, split)) != NULL; p += len) count++; return count;}char **split_string(const char *str, const char *split) { size_t count = getNofTokens(str, split); char **result = malloc(sizeof(*result) * (count + 1)); size_t len = strlen(split); size_t idx; const char *p = str; for (idx = 0; idx < count; idx++) { const char *q = strstr(p, split); if (q == NULL) { q = p + strlen(p); } else if (q == p && *q != '\0') { q++; } result = strndup(p, q - p); p = q + len; } result = NULL; return result;}void print_split_string(char **split_string) { for (size_t i = 0; split_string != NULL; i++) { printf("%s\n", split_string); }}void free_split_string(char **split_string) { for (size_t i = 0; split_string != NULL; i++) { free(split_string); } free(split_string);}

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *