2017-07-01 1 views
1

Problème: http://docs.cs50.net/problems/initials/more/initials.html Comme je l'ai dit dans le titre, je ne peux pas obtenir le programme pour sortir les initiales sans espaces si l'utilisateur entre des espaces supplémentaires avant le nom ou entre des espaces supplémentaires entre le prénom et le nom.Comment traiter plusieurs espaces avant ou entre les mots dans les initiales de CS50 (plus à l'aise)?

À l'heure actuelle, cela ne fonctionne que si je saisis mon nom comme: First Last sans espaces avant le nom et un seul espace entre les deux mots. Il imprime FL sans espaces supplémentaires. Je veux qu'il le fasse, peu importe combien d'espaces supplémentaires j'ai avant ou entre le prénom et le nom de famille.

Mon code actuel:

#include <stdio.h> 
#include <cs50.h> 
#include <string.h> 
#include <ctype.h> 

int main(void) { 
    printf("Name: "); 
    string s = get_string(); 

    printf("%c", toupper(s[0])); 

    for (int i = 0; i < strlen(s); i++) { 
     if (s[i] == ' ') { 
      printf("%c", toupper(s[i +1])); 
     } 
} 

    printf("\n"); 
} 
+1

Une façon de le faire est d'utiliser une variable pour contenir le caractère précédent. Si le caractère précédent était un espace et que le caractère courant n'est pas un espace, affichez le caractère en cours en majuscules. – user3386109

+0

Il y a un [échange de pile cs50] (http://cs50.stackexchange.com/) si vous êtes intéressé. – pmg

Répondre

0

Ne pas utiliser strlen dans l'état de la for -loop, il sera exécuté à chaque étape, mieux enregistrer la valeur dans une variable et utiliser la variable la condition à la place.

Je voudrais utiliser dans ce cas strtok, il traite des entrées comme Tom marvolo riddle où vous avez plusieurs espaces blancs entre les noms.

#include <stdio.h> 
#include <ctype.h> 


int main(void) 
{ 

    char line[1024]; 

    fgets(line, sizeof line, stdin); 

    char *token, *src = line; 

    while(token = strtok(src, " \t")) 
    { 
     src = NULL; // subsequent calls of strtok must be called 
        // with NULL 

     printf("%c", toupper(*token)); 
    } 

    printf("\n"); 

    return 0; 
} 

Lorsque vous utilisez strtok vous devez vous rappeler de ne pas passer une chaîne littérale ("this is a string literal") parce qu'ils sont en lecture seule et strtok écrit un \0 à l'endroit où se trouve le séparateur. Si vous ne savez pas si vous avez un accès en écriture au tampon, vous devez faire une copie (soit dans un tampon statique avec une longueur suffisante, soit utiliser malloc), puis utiliser la copie dans strtok.

Dans mon exemple, je sais que line n'est pas une variable en lecture seule, donc je peux utiliser en toute sécurité dans strtok (à condition de ne plus l'utiliser, sinon une copie est requise).

Un problème avec strtok est qu'il n'est pas réentrant et il est préférable d'utiliser strtok_r à la place.

char *token, *src = line, *saveptr; 

while(token = strtok_r(src, " \t", &saveptr)) 
    ... 
+1

Le compilateur optimisera le code afin que 'strlen' ne soit pas appelé dans chaque boucle. Donc ce n'est pas un vrai problème. – 4386427

+1

Sur Windows, utilisez 'strtok_s()' au lieu de 'strtok_r()' - ils sont équivalents. (Une note_ ésotérique mystérieusement arcane_: la spécification C de l'annexe K standard de 'strtok_s()' diffère de Microsoft 'strtok_s()' et POSIX 'strtok_r()' - heureusement, la version de l'Annexe K n'est presque jamais implémentée.) –

2

Même si vous avez déjà une bonne réponse, en supposant que string s = get_string(); dans le monde cs50.h ne fait que remplir s avec une chaîne terminée par un NUL et s est soit un tableau de caractères ou pointeur vers la mémoire allouée Il y a quelques domaines où vous pourriez envisager des améliorations.

D'abord, n'utilisez pas printf pour imprimer un seul caractère. C'est ce que putchar (ou fputc) est pour. (Accordé un compilateur d'optimisation intelligente devrait le faire pour vous, mais ne vous fiez pas sur le compilateur pour corriger les inefficacités pour vous) Par exemple, au lieu de

printf("%c", toupper(s[0])); 

simplement

putchar (toupper(s[0])); 

En outre, il y a quelques les problèmes de logique que vous pourriez envisager. Ce que vous voulez savoir est (1) "Est-ce que le caractère courant est une lettre?" (par ex. , (2) "Est-ce le premier caractère (par exemple index 0), ou est-ce un caractère qui suit un espace? "(par ex.s[x-1] == ' '). Avec des informations, vous pouvez utiliser un seul putchar pour afficher les initiales.

En outre, avec s étant une chaîne, vous pouvez simplement utiliser pointeur arithmétique (par exemple while (*s) {.. do stuff with *s ..; s++;}) qui se termine lorsque vous atteignez le terminateur NUL, ou si vous souhaitez conserver s comme pointeur sur le premier caractère , ou si elle est un tableau , puis char *p = s; et fonctionnent sur p)

Mettre ces morceaux, vous pouvez faire quelque chose comme ce qui suit sans compter sur string.h (vous pouvez utiliser de simples if s et manipulations de bits du 6 bi t pour éliminer le recours à ctype.h fonctions aussi bien - c'est pour plus tard):

#include <stdio.h> 
#include <cs50.h> 
#include <ctype.h> 

int main (void) { 

    char *p = NULL; 

    printf ("Name: "); 
    string s = get_string(); /* assuming this works as it appears */ 

    for (p = s; *p; p++) 
     /* if current is [a-zA-Z] and (first or follows space) */ 
     if (isalpha (*p) && (p == s || (*(p - 1) == ' '))) 
      putchar (toupper (*p)); 

    putchar ('\n'); /* tidy up */ 

    return 0; 
} 

Exemple d'utilisation/sortie

$ ./bin/initials 
Name: David C. Rankin 
DCR 

$ ./bin/initials 
Name: Jane Doe 
JD 

$ ./bin/initials 
Name: d 
D 

$ ./bin/initials 
Name: George  W... Bush 
GWB 
0

Afin de rendre votre travail de code, une approche simple est d'ajouter un drapeau indiquant si le caractère précédent était un espace. Quelque chose comme:

#include <stdio.h> 
#include <cs50.h> 
#include <string.h> 
#include <ctype.h> 

int main(void) 
{ 
    int wasSpace = 1; // Add a flag. 
    printf("Name: "); 
    string s = get_string(); 

    for (int i = 0; i < strlen(s); i++) 
    { 
     if (wasSpace && s[i] != ' ') // Only print if previous was a space and this isn't 
     { 
      wasSpace = 0; 
      printf("%c", toupper(s[i])); 
     } 
     else if (s[i] == ' ') 
     { 
      wasSpace = 1; // Update the flag 
     } 
    } 
    printf("\n"); 
    return 0; 
}