0
votes

Calculer le nombre de fois que chaque lettre apparaît dans une chaîne

J'ai joué avec un code ancien et je suis tombé sur une fonction que j'ai passé il y a quelque temps qui calcule le nombre de fois que chaque lettre alphabétique apparaît dans une chaîne donnée. Dans ma fonction initiale, je voudrais parcourir la chaîne 26 fois en comptant le nombre de fois que chaque lettre apparaît à mesure qu'elle bouge. Cependant, je savais que c'était vraiment inefficace, alors j'ai essayé de le faire: xxx pré>

Le code ci-dessus boucle via une chaîne et vérifie chaque caractère. Si le caractère est une lettre alphabétique (AZ ou AZ), je incrémente le nombre de fréquences à un indice spécifique dans le tableau code> FreqCount code> (où index 0 = A \ A, 1 = b \ b ,. .., 25 = z \ z). P>

Le code semble compter bien, mais lorsque j'imprime la matrice, je reçois la sortie suivante: P>

chaîne: "ABCDEFGHIJKLMNOPQRSTUVWXYZIII" P> blockQquote> xxx pré>

Pour référence, j'imprime le tableau de la manière suivante: p>

for (i = 0; i < 26; i++) {
     printf("%c/%c     %d\n", i + 97, i + 65, freqCount[i]);
}


9 commentaires

Vous ne définissez jamais les valeurs du tableau à 0, vous êtes donc ++ des ordures laissées dans la mémoire.


malloc n'initialise pas le tableau, le code doit donc l'initialiser, soit avec MEMSET ou une boucle, ou à l'aide de calloc au lieu de malloc


BTW, 65 et 97 doivent être écrits comme 'A' et 'a' respectivement. Cela rend le code plus facile à lire et vous n'avez pas à vous souvenir de ce que sont ces chiffres.


@Timothy Cattana par la manière dont toutes les lettres ne se succèdent pas sans des lacunes. Par exemple, pour le codage EBCDIC, le programme ne fonctionnera pas.


D'accord, donc i memset (freqcount, 0, 26) et corrige la sortie d'un \ a-f \ f. Mais je reçois toujours une sortie des ordures pour g \ g et h \ h.


MEMSET (FREQCOUTE, 0, 26 * TAILLEOF (INT)) ... ou JUST CALOCOC () Au lieu de MALLOC () ... Ou tout n'utilisez pas d'allocation dynamique du tout puisqu'il s'agit juste d'un ensemble de 26 int array: int freqcount [26] = {0}; .


@Marcobonelli Yea, j'ai oublié que j'utilisais un pointeur, mon mal. Je n'ai jamais utilisé CalloC avant, je vais regarder. De plus, quand j'ai écrit ce code, j'apprendais toujours une allocation dynamique, c'est pourquoi j'utilise un pointeur.


J'ai compris. calloc () est probablement le moyen le plus simple de résoudre ce problème, c'est la même chose que masloc () mais initialise tous les éléments à 0 .


(Techniquement, il initialise tous les bytes zéro, mais ... c'est rarement un problème autre que les personnes qui l'indiquent dans des commentaires et que la norme ne garantit pas que l'allocation de CalloC entraînera des pointeurs Null ...)


3 Réponses :


2
votes
  • Comme beaucoup mentionné, vous devez initialiser la valeur à 0
  • Vous pouvez également utiliser ci-dessous Trick pour accélérer la lettre de lettre: s'il s'agit d'une lettre que vous effacez le bit 32, qui est la différence de bits entre majuscules et minuscules, ce qui vous donnera l'index correct.
  • Enfin, vous pouvez utiliser un court tableau à moins que vous vous attendiez à beaucoup de lettres. xxx

    essai principal: xxx


5 commentaires

En ce qui concerne: printf ("% d \ n", n [4]); Qu'attendez-vous que cette déclaration fasse-elle? Il n'imprimera que le compte dans l'élément 5 de la matrice de fréquence.


Il imprime 3, puisque la 5ème lettre est E, si vous vérifiez la fin de la chaîne, j'ai écrit "Troisième E", avec les minuscules et majuscules de T "Bonjour"


Le code posté des OPS imprime tous les 26 chefs qui font partie de la question, alors il suffit d'imprimer un décompte n'est pas suffisant.


Des tours laids tels que freqcount [(C & ~ 32) - 65] ++; apportez un code illisible et immobile. Au moins écrire 'a' au lieu de 65 .


Je ne pense pas que ce soit un moche mais assez efficace et élégant pour quiconque comprend la table ASCII.



0
votes

Le code proposé suivant:

  1. évite malloc () , calloc () , etc
  2. conserve la définition des données, etc. à l'intérieur de la fonction principale ()
  3. effectue la fonctionnalité souhaitée
  4. compile parfaitement
  5. utilise des littéraux de caractères simples plutôt que des chiffres de «magie»
  6. attend le jeu de caractères ASCII

    et maintenant, le code proposé: xxx

    une exécution du code donne: xxx < / p>


6 commentaires

Sur les systèmes avec signature char , vous devez lancer l'argument char sur isalpha () comme isalpha ((non signé) chaîne [i ]) parce que isalpha () a un comportement non défini pour les valeurs négatives, sauf eof .


@chqrlieforyLockLockQuotes, la séquence alpha est toutes dans les 127 premiers caractères ASCII, de sorte que le signe d'un caractère n'a aucun effet


Vous passez tous les caractères de la chaîne à isalpha () , comment savez-vous s'ils sont tous positifs? Par exemple, si la chaîne contient des points de code non ascii codés UTF-8, ces octets seraient considérés comme négatifs. Techniquement, la distribution n'est pas requise pour l'appel car tous les caractères alpha sont effectivement positifs, mais il est nécessaire pour le isalpha () appelé comme vous ne pouvez pas faire de hypothèse sur le contenu de la chaîne.


La fonction: isalpha () renvoie false si la lettre est en dehors de la plage 0x00 ... 0x7f et retourne false pour de nombreux personnages à l'intérieur de cette plage


C17 7.4 Manutention de caractères déclare plusieurs fonctions utiles pour les caractères de classification et de mappage. Dans tous les cas, l'argument est un int , la valeur qui doit être représentable sous forme de char non signé ou doit être égal à la valeur de la macro EOF . Si l'argument a une autre valeur, le comportement est indéfini. Les tests isalpha pour n'importe quel caractère pour lequel isupper ou isslower est vrai, ou n'importe quel caractère qui est l'un des paramètres alphabétiques spécifiques à la localisation. Caractères pour lesquels aucun de iscntrl , isdigit , ispunct ou Isspace est vrai.


Le problème est celui-ci sur les plates-formes où char est signé par défaut: si l'argument de chaîne contient des octets extérieurs 0x00-0x7f , ces octets sont lus comme char Les valeurs ont une valeur négative, pour laquelle le comportement de isalpha () est indéfini. Pour éviter ce comportement potentiel non défini, Char Les valeurs qui ne sont pas connues pour être positives doivent être modifiées comme (non signé) . Par conséquent, vous devriez écrire isalpha ((sans signé Char) chaîne [i]) .



2
votes

Il y a 2 problèmes dans votre code:

  • Le tableau freqcount est ininitialisé.
  • Vous devez éviter de passer Char Valeurs sur ISALPHA car il provoquerait un comportement non défini si chaîne contient négatif char Valeurs sur les systèmes où Char est signé par défaut.

    au lieu d'un opérateur ternaire ou d'une instruction si , vous pouvez utiliser toupper () pour convertir des caractères minuscules en majuscule et il est plus lisible à Écrivez 'A' ou 'A' au lieu de leurs valeurs ASCII codées durement 65 et 97 .

    Voici une version corrigée: xxx


0 commentaires