Как генерировать «последовательные» строки C ++? - PullRequest
2 голосов
/ 03 января 2012

Я хотел бы генерировать последовательные строки C ++, например, в камерах: IMG001, IMG002 и т. Д., Чтобы иметь возможность указать префикс и длину строки.

Я нашел решение, в котором я могу генерировать случайные строки изконкретный набор символов: ссылка

Но я не могу найти то, чего хочу достичь.

Ответы [ 10 ]

8 голосов
/ 03 января 2012

Возможное решение:

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

См. Онлайн-демонстрацию на http://ideone.com/HZWmtI.

2 голосов
/ 03 января 2012

Примерно так будет работать

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

Вы можете несколько раз вызвать GetNextNumber со ссылкой на int для генерации новых номеров изображений.Вы всегда можете использовать sprintf, но это не будет способом c ++:)

1 голос
/ 03 января 2012

Ну, идея довольно проста.Просто сохраните текущий номер и увеличивайте его каждый раз, когда генерируется новая строка.Вы можете реализовать его, чтобы смоделировать итератор, чтобы уменьшить пух при его использовании (затем вы можете использовать стандартные алгоритмы с ним).Использование Boost.Iterator (он также должен работать с любым типом строки):

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

И пример кода:

#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;
}
1 голос
/ 03 января 2012
char * seq_gen(char * prefix) {
    static int counter;
    char * result;
    sprintf(result, "%s%03d", prefix, counter++);
    return result;
}

Это напечатало бы ваш префикс с 3-разрядной строкой заполнения. Если вы хотите длинную строку, все, что вам нужно сделать, это предоставить префикс столько раз, сколько необходимо, и заменить % 03d в приведенном выше коде на любую необходимую вам длину набивки цифр.

1 голос
/ 03 января 2012
 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);
 }
0 голосов
/ 03 января 2012

это псевдокод.вы поймете, что я имею в виду: D

int counter = 0, retval;
do
{
char filename[MAX_PATH];
sprintf(filename, "IMG00%d", counter++);
if(retval = CreateFile(...))
//ok, return
}while(!retval);
0 голосов
/ 03 января 2012

Вы должны держать счетчик, который увеличивается каждый раз, когда вы получаете новое имя.Этот счетчик должен быть сохранен, когда ваше приложение заканчивается, и загружен, когда ваше приложение запускается.

Может быть что-то вроде этого:

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;

Затем используйте его так:

std::string my_name = my_name_generator.get_next_name();
0 голосов
/ 03 января 2012

Что именно вы подразумеваете под последовательными строками?

Поскольку вы упомянули, что используете строки C ++, попробуйте использовать метод .string::append.

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

Lookup http://www.cplusplus.com/reference/string/string/append/ для более перегруженных вызовов функции добавления.

0 голосов
/ 03 января 2012

У вас есть много способов сделать это.

В общем случае, как и на показанной вами ссылке, есть множество возможных символов.Затем после каждой итерации вы начинаете с самого правого символа, увеличиваете его (т. Е. Меняете его на следующий в списке возможных символов) и, если он переполняется, устанавливаете его на первый (индекс 0) и переходите кналево.Это похоже на увеличение числа в базе, скажем 62.

В вашем конкретном примере вам лучше создать строку из другой строки и числа.

Если вам нравится *printf, вы можете написать строку с "IMG%04d" и получить от 0 значение параметра.

Если вам нравится stringstream, вы можете сделать то же самое.

0 голосов
/ 03 января 2012

Посмотрите на строковые потоки стандартной библиотеки. Имейте целое число, которое вы увеличиваете, и вставляете в поток строк после каждого приращения. Для управления длиной строки есть концепция символов заполнения и функция-член width ().

...