J'ai besoin d'un code capable de compter les mots d'une chaîne sans compter plusieurs espaces entre eux.

Je pourrais coder un programme qui compte les mots avec seulement 1 espace vide entre eux, mais je ne sais pas comment je devrais le coder quand il y aurait plus d'un espace vide. J'ai pensé à quelque chose comme une boucle for qui vérifie si le caractère avant est un espace, mais je ne sais pas comment faire cela. Et je tiens à mentionner que je suis un débutant en C.

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

int main()
{
char s[200];
int count = 0, i;

printf("enter the string: ");
fgets(s,200,stdin);
for (i = 0;s[i] != '\0';i++)
{
    if (s[i] == ' ')
        count++;    
}
printf("number of words in given string are: %d\n", count+ 1);

return(0);
} 
c
0
atiufi 26 janv. 2019 à 20:33

5 réponses

Meilleure réponse

Vous pouvez introduire un drapeau pour dire si le caractère précédent était un espace. Quelque chose comme:

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

int main()
{
    char s[200];
    int count = 0, i;
    int last_was_space = 1;

    printf("enter the string: ");
    fgets(s,200,stdin);
    for (i = 0;s[i] != '\0';i++)
    {
        if (s[i] == ' ')
        {
            if (!last_was_space) 
            {
                count++; // Only count when last char wasn't a space
                last_was_space = 1;
            }
        }
        else
        {
            // Update flag (unless this char is a newline)
            if (s[i] != '\n') last_was_space = 0;
        }
    }
    if (!last_was_space) ++count; // Count the last word if there wasn't a space before

    printf("number of words in given string are: %d\n", count);

    return(0);
}
0
4386427 26 janv. 2019 à 18:04

Formuler le problème en termes généraux aide ici. Ne pensez pas à cela comme "compter les mots" ou "compter les espaces". Considérez-le comme comptant les "transitions du séparateur au non-séparateur". Définition de nos termes:

  • Séparateur: début de chaîne, ou un seul espace ASCII
  • Non-séparateur: tout le reste

Exemples (^ est le début de la chaîne, _ est un espace littéral, $ est la fin de la chaîne):

^a_quick_brown_fox_jumps$
 ^ ^     ^     ^   ^               5 transitions

^_a__quick___brownfox_jumps___$
  ^  ^       ^        ^            4 transitions

^$
                                   0 transitions

^___$
                                   0 transitions

^__x$
   ^                               1 transition

Maintenant en pseudocode:

def is_separator(char x):
  return (x == NULL or x == ' ')

def is_non_separator(char x):
  return (! is_separator(x))

let count = 0, last_char = NULL
while current_char = read_char():
  if (is_non_separator(current_char) and is_separator(last_char)):
    count++

De là, vous pouvez traduire dans des langues spécifiques ou changer la signification des séparateurs sans affecter la logique de comptage.

0
bishop 26 janv. 2019 à 18:05

compter les mots d'une chaîne sans compter plusieurs espaces entre eux

Définissez un indicateur pour déterminer si le début d'un mot est possible. Moins de cas particuliers que de chercher la fin du mot.

En règle générale, l'exigence «d'espaces» implique n'importe quel espace blanc, alors la tâche est facilement codée:

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

int main(void) {
  char s[200];
  printf("enter the string: ");
  fgets(s, sizeof s, stdin);

  int count = 0;
  bool beginning_of_word_possible = true;

  for (const char *p = s; *p; p++) {
    if (isspace((unsigned char ) *p)) {
      beginning_of_word_possible = true;
    } else {
      if (beginning_of_word_possible) {
        count++;
      }
      beginning_of_word_possible = false;
    }
  }

  printf("number of words in given string are: %d\n", count);
  return (0);
}

@P__J__ a offert une bonne idée qui passe dans une liste de délimiteurs. Voici une solution similaire et courte qui n'alloue pas de mémoire ni ne modifie la chaîne fournie.

#include <string.h>

size_t word_count(const char *s, const char *delimiters) {
  size_t count = 0;
  while (*(s += strspn(s, delimiters))) {  // Advance s by the matching delimiters.
    count++;
    s += strcspn(s, delimiters);           // Advance s by the non-matching delimiters.
  }
  return count;
}

Tester

int main(void) {
  const char *de = " \n";
  printf("%zu\n", word_count("", de));
  printf("%zu\n", word_count("\n", de));
  printf("%zu\n", word_count("  ", de));
  printf("%zu\n", word_count("abc", de));
  printf("%zu\n", word_count(" abc", de));
  printf("%zu\n", word_count(" abc \n", de));
  printf("%zu\n", word_count("abc xyz", de));
  printf("%zu\n", word_count(" abc  xyz", de));
  printf("%zu\n", word_count(" abc  xyz  \n", de));
}

Production

0
0
0
1
1
1
2
2
2
0
chux - Reinstate Monica 26 janv. 2019 à 20:50

Version courte et simple:

#include <stdio.h>

int main(void) {
    char str[] = "  Hello, This is   a test  of a word     counter";
    int i = 0;
    for(char* s=str; strtok(s," "); i++) s = NULL;
    printf("number of words in given string are: %d\n", i);
    return 0;
}

Sortie

Success #stdin #stdout 0s 9424KB
number of words in given string are: 9
0
abelenky 26 janv. 2019 à 20:55

Un peu plus universel

size_t wcount(const char *s, const char *del, int countempty)
{
   char *token;
   size_t count = 0;
   char *str = strdup(s);

   if(str)
   {
        token = strtok(str, del);
        while( token != NULL ) 
        {
          if(!strlen(token))
          {
              if(countempty)
              {
                  count++;
              }
          }
          else
          {
              count++;
          }
          token = strtok(NULL, del);
        }
   }
   free(str);
   return count;
}

int main () 
{
    char str[] = "something to   count    ,., , . !! Stack    overflow  ";

    printf("With empty %zu, Without empty%zu\n", wcount(str," ", 1), wcount(str," .,", 0));
}
0
P__J__ 26 janv. 2019 à 19:19