1

I am writing a method in C++ which will take a string of 2 or more words and output each individual word of the string separated by a second or so, using the sleep() method. I am trying to do this using a for loop and substrings. I am unsure also of the regexs which should be used, and how they should be used, to achieve the desired output.

I have reviewed this and this and find my question differs since I am trying to do this in a loop, and not store the individual substrings.

Input:

"This is an example"

Desired output:

"This " (pause) "is " (pause) "an " (pause) "example."

Community
  • 1
  • 1
A. Takami
  • 318
  • 4
  • 16

3 Answers3

8

Use std::stringstream, no regular expressions required:

#include <iostream>
#include <sstream>
using namespace std;

int main() {
    stringstream ss("This is a test");
    string s;

    while (ss >> s) {
        cout << s << endl;
    }

    return 0;
}

Also, see How do I tokenize a string in C++?

rainer
  • 6,769
  • 3
  • 23
  • 37
  • An elegant solution. – caps Sep 14 '16 at 19:33
  • As of now my implementation looks as follows: `void speak(string statement){ string temp; stringstream ss(statement); while(ss >> temp){ sleep(1); cout << temp << " "; }` How might I make this pause before putting out each individual word? – A. Takami Sep 14 '16 at 19:43
  • @A.Takami This is exactly what your implementation does; you'll just need to flush the output to make sure it it's written to the console immediately: `cout << temp << " " << std::flush;`. – rainer Sep 14 '16 at 19:51
  • @A.Takami the program likely is pausing but it is doing so for too short a period. Sleep takes values in ms so try something larger like sleep(500); – Russ Sep 14 '16 at 19:53
  • 1
    @A.Takami If you can use C++11, a better solution would probably be http://en.cppreference.com/w/cpp/thread/sleep_for. – rainer Sep 14 '16 at 19:55
  • @rainer Awesome. Thank you very much I appreciate it. – A. Takami Sep 14 '16 at 19:56
  • @rainer Any ideas why `usleep(750)` may not be working in place of the `sleep(1)`? With `sleep(1)` and using `flush` I get the pause, but `usleep(750)` just outputs all the text at once again, after implementing `flush` as well. – A. Takami Sep 14 '16 at 20:01
  • You should try using `sleep_for` instead, as rainer suggested. – caps Sep 14 '16 at 20:34
  • 1
    `usleep` take microseconds, so `usleep(750)` will wait for 0.00075 seconds. See http://linux.die.net/man/3/usleep – rainer Sep 15 '16 at 07:18
2

Here are a pair of implementations that don't involve creating any extraneous buffers.

#include <boost/range/adaptor/filtered.hpp>
#include <boost/range/algorithm/copy.hpp>   //for boost::copy

#include <chrono>
#include <iostream>
#include <string>
#include <experimental/string_view> //in clang or gcc; or use boost::string_ref in boost 1.53 or later; or use boost::iterator_range<char*> in earlier version of boost
#include <thread>

void method_one(std::experimental::string_view sv)
{
    for(auto b = sv.begin(), e = sv.end(), space = std::find(b, e, ' ')
        ; b < e
        ; b = space + 1, space = std::find(space + 1, e, ' '))
    {
        std::copy(b, space, std::ostreambuf_iterator<char>(std::cout));
        std::cout << " (pause) ";   //note that this will spit out an extra pause the last time through
        std::this_thread::sleep_for(std::chrono::seconds(1));
    }
}

void method_two(std::experimental::string_view sv)
{
    boost::copy(
        sv | boost::adaptors::filtered([](const char c) -> bool
        {
            if(c == ' ')
            {
                std::cout << " (pause) ";   //note that this spits out exactly one pause per space character
                std::this_thread::sleep_for(std::chrono::seconds(1));
                return false;
            }

            return true;
        })
        , std::ostreambuf_iterator<char>(std::cout)
    );
}

int main() {
    const std::string s{"This is a string"};

    method_one(s);
    std::cout << std::endl;
    method_two(s);
    std::cout << std::endl;

    return 0;
}

Live on coliru, if you're into that.

caps
  • 1,225
  • 14
  • 24
1

you can implement your own method:

    //StrParse.h

    #pragma once

    #include <iostream>

    static counter = 0;

    char* strPar(char* pTxt, char c)
    {

        int lenAll = strlen(pTxt);

        bool strBeg = false;
        int nWords = 0;


        for(int i(0); i < lenAll; i++)
        {
            while(pTxt[i] != c)
            {
                strBeg = true;
                i++;
            }
            if(strBeg)
            {
                nWords++;
                strBeg = false;
            }

        }

        int* pLens = new int[nWords];
        int j = 0;
        int len = 0;

        for(i = 0; i < lenAll; i++)
        {
            while(pTxt[i] != c)
            {
                strBeg = true;
                i++;
                len++;
            }
            if(strBeg)
            {
                pLens[j] = len;
                j++;
                strBeg = false;
                len = 0;
            }

        }

        char** pStr = new char*[nWords + 1];

        for(i = 0; i < nWords; i++)
            pStr[i] = new char[pLens[i] + 1];

        int k = 0, l = 0;

        for(i = 0; i < lenAll; i++)
        {
            while(pTxt[i] != c)
            {
                strBeg = true;
                pStr[k][l] = pTxt[i];
                l++;
                i++;
            }
            if(strBeg)
            {
                pStr[k][l] = '\0';
                k++;
                l = 0;
                strBeg = false;     
            }

        }

        counter++;

        if(counter <= nWords)
            return pStr[counter - 1];
        else
            return NULL;
    }


    //main.cpp


    #include "StrParse.h"

    void main()
    {

        char* pTxt  = "   -CPlusPlus -programming -is -a    -   superb thing ";
        char* pStr1 = NULL;
        int i = 1;
        char sep;

        std::cout << "Separator: ";
        sep = std::cin.get();
        std::cin.sync();

        while(pStr1 = strPar(pTxt, sep))
        {
            std::cout << "String " << i << ": " << pStr1 << std::endl;
            delete pStr1;
            i++;
        }

        std::cout << std::endl;
    }
Raindrop7
  • 3,889
  • 3
  • 16
  • 27