Patryk
Patryk

Reputation: 24092

How to generate 'consecutive' c++ strings?

I would like to generate consecutive C++ strings like e.g. in cameras: IMG001, IMG002 etc. being able to indicate the prefix and the string length.

I have found a solution where I can generate random strings from concrete character set: link

But I cannot find the thing I want to achieve.

Upvotes: 2

Views: 3302

Answers (10)

hmjd
hmjd

Reputation: 121971

A possible solution:

#include <iostream>
#include <string>
#include <sstream>
#include <iomanip>

std::string make_string(const std::string& a_prefix,
                        size_t a_suffix,
                        size_t a_max_length)
{
    std::ostringstream result;
    result << a_prefix <<
              std::setfill('0') <<
              std::setw(a_max_length - a_prefix.length()) <<
              a_suffix;
    return result.str();
}

int main()
{
    for (size_t i = 0; i < 100; i++)
    {
        std::cout << make_string("IMG", i, 6) << "\n";
    }
    return 0;
}

See online demo at http://ideone.com/HZWmtI.

Upvotes: 8

Some programmer dude
Some programmer dude

Reputation: 409176

You have to keep a counter that is increased everytime you get a new name. This counter has to be saved when your application is ends, and loaded when you application starts.

Could be something like this:

class NameGenerator
{
public:
    NameGenerator()
        : m_counter(0)
        {
            // Code to load the counter from a file
        }

    ~NameGenerator()
        {
            // Code to save the counter to a file
        }

    std::string get_next_name()
        {
            // Combine your preferred prefix with your counter
            // Increase the counter
            // Return the string
        }

private:
    int m_counter;
}

NameGenerator my_name_generator;

Then use it like this:

std::string my_name = my_name_generator.get_next_name();

Upvotes: 0

Cat Plus Plus
Cat Plus Plus

Reputation: 129764

Well, the idea is rather simple. Just store the current number and increment it each time new string is generated. You can implement it to model an iterator to reduce the fluff in using it (you can then use standard algorithms with it). Using Boost.Iterator (it should work with any string type, too):

#include <boost/iterator/iterator_facade.hpp>
#include <sstream>
#include <iomanip>

// can't come up with a better name
template <typename StringT, typename OrdT>
struct ordinal_id_generator : boost::iterator_facade<
    ordinal_id_generator<StringT, OrdT>, StringT,
    boost::forward_traversal_tag, StringT
> {
    ordinal_id_generator(
        const StringT& prefix = StringT(),
        typename StringT::size_type suffix_length = 5, OrdT initial = 0
    ) : prefix(prefix), suffix_length(suffix_length), ordinal(initial)
    {}
private:
    StringT prefix;
    typename StringT::size_type suffix_length;
    OrdT ordinal;

    friend class boost::iterator_core_access;

    void increment() {
        ++ordinal;
    }

    bool equal(const ordinal_id_generator& other) const {
        return (
               ordinal == other.ordinal
            && prefix == other.prefix
            && suffix_length == other.suffix_length
        );
    }

    StringT dereference() const {
        std::basic_ostringstream<typename StringT::value_type> ss;
        ss << prefix << std::setfill('0')
           << std::setw(suffix_length) << ordinal;
        return ss.str();
    }
};

And example code:

#include <string>
#include <iostream>
#include <iterator>
#include <algorithm>

typedef ordinal_id_generator<std::string, unsigned> generator;

int main() {
    std::ostream_iterator<std::string> out(std::cout, "\n");

    std::copy_n(generator("IMG"), 5, out);
    // can even behave as a range
    std::copy(generator("foo", 1, 2), generator("foo", 1, 4), out);

    return 0;
}

Upvotes: 1

Srinivasan Annamalai
Srinivasan Annamalai

Reputation: 369

char * seq_gen(char * prefix) {
    static int counter;
    char * result;
    sprintf(result, "%s%03d", prefix, counter++);
    return result;
}

This would print your prefix with 3 digit padding string. If you want a lengthy string, all you have to do is provide the prefix as much as needed and change the %03d in the above code to whatever length of digit padding you want.

Upvotes: 1

cppKoder
cppKoder

Reputation: 1

it's pseudo code. you'll understand what i mean :D

int counter = 0, retval;
do
{
char filename[MAX_PATH];
sprintf(filename, "IMG00%d", counter++);
if(retval = CreateFile(...))
//ok, return
}while(!retval);

Upvotes: 0

viraj
viraj

Reputation: 1814

What exactly do you mean by consecutive strings ?

Since you've mentioned that you're using C++ strings, try using the .string::append method.

string str, str2;
str.append("A");
str.append(str2);

Lookup http://www.cplusplus.com/reference/string/string/append/ for more overloaded calls of the append function.

Upvotes: 0

Shahbaz
Shahbaz

Reputation: 47523

You have many ways of doing that.

The generic one would be to, like the link that you showed, have an array of possible characters. Then after each iteration, you start from right-most character, increment it (that is, change it to the next one in the possible characters list) and if it overflowed, set it to the first one (index 0) and go the one on the left. This is exactly like incrementing a number in base, say 62.

In your specific example, you are better off with creating the string from another string and a number.

If you like *printf, you can write a string with "IMG%04d" and have the parameter go from 0 to whatever.

If you like stringstream, you can similarly do so.

Upvotes: 0

Zyx 2000
Zyx 2000

Reputation: 1705

Take a look at the standard library's string streams. Have an integer that you increment, and insert into the string stream after every increment. To control the string length, there's the concept of fill characters, and the width() member function.

Upvotes: 0

Ivaylo Strandjev
Ivaylo Strandjev

Reputation: 70929

 const int max_size = 7 + 1; // maximum size of the name plus one 
 char buf[max_size];
 for (int i = 0 ; i < 1000; ++i) {
   sprintf(buf, "IMG%.04d", i);
   printf("The next name is %s\n", buf);
 }

Upvotes: 1

parapura rajkumar
parapura rajkumar

Reputation: 24403

Something like this would work

#include <string>
#include <iomanip>
#include <sstream>


std::string GetNextNumber( int &lastNum )
{
    std::stringstream ss;
    ss << "IMG";
    ss << std::setfill('0') << std::setw(3) << lastNum++;

    return ss.str();
}

int main()
{
    int x = 1;

    std::string s = GetNextNumber( x );
    s = GetNextNumber( x );


    return 0;
}

You can call GetNextNumber repeatedly with an int reference to generate new image numbers. You can always use sprintf but it won't be the c++ way :)

Upvotes: 2

Related Questions