atiufi
atiufi

Reputation: 13

Count words from a string with multiple empty spaces

I need code that can count the words from a string without counting multiple spaces between them.

I could code a program that counts the words with only 1 empty space between them, but I don't know how I should code it when it would be more than 1 empty space. I thought something like a for loop that checks if the char before it is a space, but I don't know how to do that. And I want to mention that I'm a beginner in 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);
} 

Upvotes: 0

Views: 4360

Answers (5)

abelenky
abelenky

Reputation: 64682

Short and Simple Version:

#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;
}

Output

Success #stdin #stdout 0s 9424KB
number of words in given string are: 9

Upvotes: 0

chux
chux

Reputation: 153468

count the words from a string without counting multiple spaces between them

Set a flag to determine if the beginning of a word is possible. Fewer special cases than looking for the end of the word.

Typically the requirement for "spaces" implies any white-space, then the task is easily coded:

#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__ offered a good idea that passes in a list of delimiters. Below is a similar and short solution that does not allocate memory nor change the supplied string.

#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;
}

Test

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));
}

Output

0
0
0
1
1
1
2
2
2

Upvotes: 0

0___________
0___________

Reputation: 67516

A bit more universal

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));
}

Upvotes: 0

bishop
bishop

Reputation: 39414

Framing the problem in general terms helps here. Don't think of it as "counting words", or "counting spaces". Think of it as counting "transitions from separator to non-separator". Defining our terms:

  • Separator: start of string, or a single ASCII space
  • Non-separator: everything else

Examples (^ is start of string, _ is a literal space, $ is end of string):

^a_quick_brown_fox_jumps$
 ^ ^     ^     ^   ^               5 transitions

^_a__quick___brownfox_jumps___$
  ^  ^       ^        ^            4 transitions

^$
                                   0 transitions

^___$
                                   0 transitions

^__x$
   ^                               1 transition

Now in psuedo code:

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++

From here, you can translate into specific languages or change the meaning of separators without affecting the logic of counting.

Upvotes: 0

4386427
4386427

Reputation: 44274

You can introduce a flag to tell whether the previous character was a space. Something like:

#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);
}

Upvotes: 1

Related Questions