Из документа Java:
https://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html
Начать новый процесс, который использует рабочий каталог и среду по умолчанию, очень просто:
blockquote>Process p = new ProcessBuilder("myCommand", "myArg").start();
Таким образом, в основном, вы собираетесь разветвлять подпроцесс, который будет
[ 118] запустите интерпретатор Python
- со скриптом Python, который вы указали в качестве аргумента.
Путь к вашему сценарию должен быть обычным путем, который ваша ОС может понять, поэтому вы не должны указывать URI? как путь (
protocol:address/path
).if (path.contains(":")) path = (path.split(":"))[1];
Также обратная косая черта
\
перед__init__.py
выглядит подозрительно.Вы должны быть в состоянии запустить
ls /home/path-to-project/project-name/out/production/resources/Scripts/Brokers/__init__.py
и посмотреть файл, то же самое относится и кls /usr/bin/python3.6
.
Используйте infix_iterator:
// infix_iterator.h
//
// Lifted from Jerry Coffin's 's prefix_ostream_iterator
#if !defined(INFIX_ITERATOR_H_)
#define INFIX_ITERATOR_H_
#include <ostream>
#include <iterator>
template <class T,
class charT=char,
class traits=std::char_traits<charT> >
class infix_ostream_iterator :
public std::iterator<std::output_iterator_tag,void,void,void,void>
{
std::basic_ostream<charT,traits> *os;
charT const* delimiter;
bool first_elem;
public:
typedef charT char_type;
typedef traits traits_type;
typedef std::basic_ostream<charT,traits> ostream_type;
infix_ostream_iterator(ostream_type& s)
: os(&s),delimiter(0), first_elem(true)
{}
infix_ostream_iterator(ostream_type& s, charT const *d)
: os(&s),delimiter(d), first_elem(true)
{}
infix_ostream_iterator<T,charT,traits>& operator=(T const &item)
{
// Here's the only real change from ostream_iterator:
// Normally, the '*os << item;' would come before the 'if'.
if (!first_elem && delimiter != 0)
*os << delimiter;
*os << item;
first_elem = false;
return *this;
}
infix_ostream_iterator<T,charT,traits> &operator*() {
return *this;
}
infix_ostream_iterator<T,charT,traits> &operator++() {
return *this;
}
infix_ostream_iterator<T,charT,traits> &operator++(int) {
return *this;
}
};
#endif
Использование будет примерно таким:
#include "infix_iterator.h"
// ...
std::copy(keywords.begin(), keywords.end(), infix_iterator(out, ","));
Комбинация C++ 11 лямбд и макрос:
#define INFIX_PRINTER(os, sep)([&]()->decltype(os)&{static int f=1;os<<(f?(f=0,""):sep);return os;})()
Использование:
for(const auto& k: keywords)
INFIX_PRINTER(out, ", ") << k;
Я бы выбрал что-то вроде этого, простое решение, которое должно работать для всех итераторов.
int maxele = maxele = v.size() - 1;
for ( cur = v.begin() , i = 0; i < maxele ; ++i)
{
std::cout << *cur++ << " , ";
}
if ( maxele >= 0 )
{
std::cout << *cur << std::endl;
}
Вы можете использовать цикл do
, переписать условие цикла для первой итерации и использовать оператор замыкания &&
и тот факт, что действительный поток является true
.
auto iter = keywords.begin();
if ( ! keywords.empty() ) do {
out << * iter;
} while ( ++ iter != keywords.end() && out << ", " );
out << endl;
Я думаю, это должно работать
while (iter != keywords.end( ))
{
out << *iter;
iter++ ;
if (iter != keywords.end( )) out << ", ";
}
Есть небольшая проблема с оператором ++
, который вы используете.
Вы можете попробовать:
if (++iter != keywords.end())
out << ", ";
iter--;
Таким образом, ++
будет оцениваться до сравнения итератора с keywords.end()
.
Попробуйте следующее:
typedef std::vector<std::string> Container;
typedef Container::const_iterator CIter;
Container data;
// Now fill the container.
// Now print the container.
// The advantage of this technique is that ther is no extra test during the loop.
// There is only one additional test !test.empty() done at the beginning.
if (!data.empty())
{
std::cout << data[0];
for(CIter loop = data.begin() + 1; loop != data.end(); ++loop)
{
std::cout << "," << *loop;
}
}
Что-то вроде этого?
while (iter != keywords.end())
{
out << *iter;
iter++;
if (iter != keywords.end()) cout << ", ";
}
Мой типичный метод использования разделителей (на любом языке ) - это использовать промежуточный цикл. Код C ++ будет выглядеть так:
for (;;) {
std::cout << *iter;
if (++iter == keywords.end()) break;
std::cout << ",";
}
(примечание: дополнительная проверка if
необходима перед циклом, если ключевые слова могут быть пустыми)
Большинство других показанных решений в конечном итоге выполняют целую дополнительную проверку каждую итерацию цикла. Вы занимаетесь вводом-выводом, поэтому время, затраченное на это, не является большой проблемой, но это оскорбляет мою чувствительность.
Предполагая, что поток вывода не совсем нормальный, так что запись в него пустой строки действительно ничего не дает:
const char *padding = "";
for (auto iter = keywords.begin(); iter != keywords.end(); ++iter) {
out << padding << *iter;
padding = ", "
}
Один из распространенных подходов - распечатать первый элемент перед циклом и перебирать только оставшиеся элементы, предварительно выводя запятую перед каждым оставшимся элементом.
В качестве альтернативы вы должны иметь возможность создать свой собственный поток, который поддерживает текущее состояние строки (до endl) и помещает запятые в соответствующие места.
РЕДАКТИРОВАТЬ: Вы также можете использовать цикл с промежуточной проверкой, предложенный T.E.D. Это будет примерно так:
if(!keywords.empty())
{
auto iter = keywords.begin();
while(true)
{
out << *iter;
++iter;
if(iter == keywords.end())
{
break;
}
else
{
out << ", ";
}
}
}
Я сначала упомянул метод «напечатать первый элемент перед циклом», потому что он сохраняет тело цикла очень простым, но любой из подходов работает нормально.
Поскольку все решили сделать это с помощью циклов while, я приведу пример с циклами for.
for (iter = keywords.begin(); iter != keywords.end(); iter++) {
if (iter != keywords.begin()) cout << ", ";
cout << *iter;
}
Может быть так ..
bool bFirst = true;
for (auto curr = keywords.begin(); curr != keywords.end(); ++curr) {
std::cout << (bFirst ? "" : ", ") << *curr;
bFirst = false;
}