views:

173

answers:

3

Hi all,

I have a string, for example; "llama,goat,cow" and I just need to put a '@' in front of each word so my string will look like "@llama,@goat,@cow", but I need the values to be dynamic also, and always with a '@' at the beginning. Not knowing a great deal of C++ could someone please help me find the easiest solution to this problem? Many thanks in advance.

+2  A: 

Here's a C++-style way:

Use the basic_string class in the standard library: basic_string ('string' is an alias for basic_string) You can use find_first_of() to find the first character that matches one of your wordbreak delimiters. You can then use the append operator (+=) to append the segments of the string to a new string, and then append '@' symbols in between.

Here's a C-style way:

You could start with strtok_s

Which will "tokenize" the string by searching for word-break delimiters like commas or spaces. You'll then be able to copy the parts between the delimiters into another buffer and then put the '@' symbols between them as you go along

For that, I'd use strcpy_s to copy piece-by-piece into a new buffer.

Drew Hoskins
+4  A: 

For the moment, I'm going to assume that the words are always separated by commas. If that's correct, something like this should at least be fairly close:

// warning: untested.
std::string input("llama,goat,cow");
std::ostringstream o;

std::string word;

std::istringstream i(input);
while (std::getline(input, word, ','))
    o << "@" << word << ",";

std::string result(o.str(), o.str().size()-1);

// show the result:
std::cout << result;

Edit: there are two different functions named getline: one is a member of an iostream, and reads the input data into a "raw" array of char. The other is a global free function that reads the input data into a std::string. This is the one you want. To get it declared, you have to #include <string>.

Jerry Coffin
After removing the std:: from std::getline, I get this errorllama.cpp:15: error: cannot convert ‘std::string’ to ‘char**’ for argument ‘1’ to ‘__ssize_t getline(char**, size_t*, FILE*)’
I love the fact that your CPP file is named "llama.cpp"
Polaris878
+1  A: 

Judging by insertable's comments, (s?) he's trying to get this code working... So let me offer my take...

As with the others, I'm presuming each word is delimited by a single ",". If you can have multiple character delimiters, you'll need to add a second find (i.e. find_first_not_of) to find the start/end of each word.

And yes, you could insert the '@' characters into the preexisting string. But inserting for each word gets a little inefficient (O(N^2)) unless you're clever. That sort of cleverness usually comes with a high maintenance/debugging cost. So I'll just stick to using two strings...

(There ought to be some brilliant way to do this with STL algorithms. But I'm sick and I just don't see how to accommodate insertion right now...)

References: C++-strings     C++-strings     STL     count_if

#include <iostream>
#include <string>
#include <algorithm>
using namespace std;

#define SHOW(X)  cout << # X " = " << (X) << endl

int main()
{
             //     0123456789_123456789_1234
  string  inString(",llama,goat,cow,,dog,cat");
  string  outString;

/* This code assumes inString.size() > 0 */

  const iterator_traits<string::iterator>::difference_type  numberOfWords
    = count_if( inString.begin(), inString.end(),
                bind2nd( equal_to<char>(), ',' ) )
       + 1;

  string::size_type  startIndex, endIndex;


  outString.reserve( inString.length() + numberOfWords );


  for ( startIndex = endIndex = 0;
        endIndex != string::npos;
        startIndex = endIndex + 1 )
  {
    outString += "@";

      /* No startIndex+1 here.  We set startIndex=endIndex+1 in the for loop */
    endIndex = inString . find_first_of( ",", startIndex );

    outString . append ( inString, startIndex,
                         (   (endIndex == string::npos)
                           ? string::npos : endIndex - startIndex + 1) );
  }

  SHOW( numberOfWords );
  SHOW( inString );
  SHOW( outString );
  SHOW( inString.size() );
  SHOW( outString.size() );
  SHOW( inString.capacity() );
  SHOW( outString.capacity() );
}
Mr.Ree
Hoorah! This works perfectly thank you, and thank you for the references also. I appreciate the suggestions from Drew and Jerry, too.