0
#include <iostream>
#include <string>
#include <cctype>
size_t countwords(const char *);
using namespace std;

int main()
{
    char a[] =  "Four score and seven years ago";
    cout << countwords(a);

    return 0;
}

size_t countwords( const char *s )
{
    size_t count = 0;

    while ( *s )
    {
        while ( isspace( *s )) ++s;
        if ( *s ) ++count;
        while ( isalnum( *s )) ++s;
    }



    return ( count );
}

The only thing i'm missing and don't know how to perform is to print the length of each word in the sentence. I need my function to print the word and it's length side by side besides returning the word count. And also to print the average number of characters. so for example if the sentence was "four scores" I need:

Four 4
scores 5

average: 4.5
Amber Roxanna
  • 1,529
  • 4
  • 21
  • 28

6 Answers6

1

If you've got C++11, you can do this with <regex>. Note that some compilers aren't very compliant on this yet, but VC++12 (VS2013) seems to do it well, and GCC is coming along. Here's the entire program:

#include <iostream>
#include <string>
#include <functional>
#include <regex>
int main() {
    std::string input("Four score and seven years ago");
    std::regex exp(R"([\w]+)");
    int matches = 0, lengthSum = 0;
    std::for_each(
        std::sregex_token_iterator(input.begin(), input.end(), exp),
        std::sregex_token_iterator(),
        [&](std::ssub_match sm) {
            std::cout << sm << ": " << sm.str().size() << std::endl;
            matches++;
            lengthSum += sm.str().size();
        });
    std::cout << "Average: " << static_cast<float>(lengthSum) / matches << std::endl;
}
Sam Cristall
  • 4,170
  • 14
  • 27
0

pseudo code in while()

if issapce() s++ print count count=0;
else count++ s++;

there is no difference with numbers and letters.

Bill
  • 13,485
  • 4
  • 38
  • 54
zawdd
  • 283
  • 3
  • 11
0

Consider this line...

while ( isalnum( *s )) ++s;

Before it starts, s points to the first character of a new word. After, it points to the first character after that new word. If we capture those two pointers...

const char *wordbegin = s;
while ( isalnum( *s )) ++s;
const char *wordend   = s;

You have pointers into your original string that identify the word. To get the length of the word, you can subtract the begin pointer from the end pointer. To output the word (using similar C-style code), you can loop through that range character by character.

To avoid that loop, you could temporarily change the pointed-to end character to a null, then back again after printing. [sorry - thinking of the old days before we used const].

You could also use one of the constructors of std::string to copy out and store that word, and then you could use the length method to read its length.

Steve314
  • 26,453
  • 12
  • 57
  • 119
0

Without testing:

size_t countwords( const char *s )
{
    size_t count = 0;
    size_t total_length = 0;

    while ( *s )
    {
        while ( isspace( *s )) ++s;
        if ( *s )
        {
            ++count;

            size_t word_length = 0;
            while ( isalnum( *s ))
            {
                std::cout << *s;
                word_length++;
                ++s;
            }
            std::cout << '\t' << word_length << std::endl;
            total_length += word_length;
        }
    }

    std::cout << "average: " << ( count == 0 ? 0.0 : static_cast<double>( total_length ) / count )
              << std::endl; 

    return ( count );
}
Vlad from Moscow
  • 224,104
  • 15
  • 141
  • 268
0
#include <iostream>
#include <vector>
#include <sstream>


int main() {
    std::string line =  "Four score and seven years ago";
    std::vector<std::string> words;
    std::istringstream iss(line);
    std::string word;
    while( iss>>word ){
        words.push_back(word);
    }
    double sum = 0;
    for(int i=0; i<  words.size(); ++i){
        std::cout<<words[i]<<" "<<words[i].size()<<std::endl;
        sum += words[i].size();
    }

    std::cout<< "average:"<< sum/words.size()<<std::endl;
    return 0;
}
Luke
  • 1,047
  • 1
  • 9
  • 14
  • Check the result of the extraction - if(iss >> word) - not the state before –  Dec 02 '13 at 19:55
  • @Luke See [this answer](http://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-considered-wrong) – Sam Cristall Dec 02 '13 at 19:55
  • Oh that's why ;) Thanks guys it is always good to learn sth new. My answer has been edited. – Luke Dec 02 '13 at 20:12
-1

Note: count should be of type unsigned int, not size_t.

You can edit your code like this:

size_t countwords( const char *s )
{
    char *tmpWord = (char*) malloc(sieof(char)*strlen(s));
    int tmpLength = 0;
    while ( *s )
        {
            tmpLength = 0;
            while ( isspace( *s )) ++s;

            do{
                tmpWord[tmpLength++] = *s;
                ++s;
            }while(!isspace(*s));

            if ( *s ){ 
                ++count;
                printf("\n%s %d",tmpWord,--tmpLength);
            }
            while ( isalnum( *s )) ++s;
        }
free(tmpWord);
}
HAL9000
  • 3,169
  • 2
  • 22
  • 43
  • Why use `malloc` in C++? – crashmstr Dec 02 '13 at 19:35
  • Why count should be unsigned int and not size_t? – Vlad from Moscow Dec 02 '13 at 19:43
  • @crashmstr to allocate memory in an array of char – HAL9000 Dec 02 '13 at 19:52
  • @VladfromMoscow because count simply indicates a number of occurrences, so, conceptually, it's better to use an unsigned int rather than a size. – HAL9000 Dec 02 '13 at 19:53
  • @ HAL9000 I hear this the first time. What is the such conception? Where did you read it? Do you know for example that std::strlen which you are using has return type size_t? – Vlad from Moscow Dec 02 '13 at 19:59
  • @VladfromMoscow in that case size_t is related to a lenght of a block of memory, which makes sense. In this case, count, indicates a non-negative integer, than, I don't see why one should use size_t just to make the code looking less clear. – HAL9000 Dec 02 '13 at 20:04
  • @HAL9000 I meant: "Why `malloc` instead of `new` in C++" – crashmstr Dec 02 '13 at 20:31
  • @crashmstr I always use malloc to allocate memory for basic types pointers. new is used to allocate objects in order to call their constructor. I simply prefer malloc. Don't you agree with my choice? – HAL9000 Dec 02 '13 at 20:38
  • @HAL9000 To me, `new` and `delete` are C++, `malloc` and `free` are C. Have not really seen this in practice anywhere, and don't see how it would be better or simpler than just using `new` when needed. – crashmstr Dec 02 '13 at 20:42
  • @crashmstr never said it's better. I simply don't think it's less good than new. In my opinion it's a matter of choices. – HAL9000 Dec 02 '13 at 20:44