LINUX.ORG.RU

Собрать строку из аргументов в C++

 ,


0

3

Да я понимаю что здесь мешанина с++11 и с++98(?)

Надо получить объединённую строку из параметров командной строки:

Сделал такой корявокод:

#include <iostream>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>

using namespace std;

int main(int argc, char *argv[])
{
    char * devicestr {}; //инициализация в стиле C++11 не ругайте, но так удобно
    char * numstr {};
    int port = 0;

    string concated_string {};

        cout << argv[0];
        for (int i = 1; i < argc; i++) {
            if (i + 1 != argc) {
                if (0 == strcmp("--devicestr", argv[i])) {
                    devicestr = argv[i + 1];
                } else (0 == strcmp("--port", argv[i])) {
                    port = std::stoi(argv[i + 1]);
                } else if (0 == strcmp("--numstr", argv[i])) {
                    numstr = argv[i + 1];
                }
            }
        }
    std::string str1(devicestr);
    std::string str2(numstr);
    concated_string = str1 + ":"+ std::to_string(port) + "/"+str2;
    cout << concated_string;
    return 0;
}

Ошибка такая: Error call overloaded «to_string(int&)» is ambiguous

как вообще правильно делать такие преобразования?

★★★★★

как вообще правильно делать такие преобразования?

Прежде всего не используй atol (есть std::stol и std::stoi).

В остальном - склейка строк делается именно так и твой код вполне компилируется.

tailgunner ★★★★★ ()

В твоём коде не хватает:

#include <string>
Поэтому ошибка:
Error call overloaded «to_string(int&)» is ambiguous
Ну и как заметили выше, так не сравнивают
argv[i] == "--port"

fsb4000 ★★★★ ()
Ответ на: комментарий от sniper21

а ничего что string.h и string - это совсем разные заголовки? (не путай c cstring )

Deleted ()

а если так?

string devicestr {}; //инициализация в стиле C++11 не ругайте, но так удобно
string numstr {};
string sport {};
int port=0;
string concated_string {};
cout << argv[0];
        for (int i = 1; i < argc; i++) {
            if (i + 1 != argc) {
                if (string(argv[i])=="--devicestr") {
                    devicestr = argv[i + 1];
                } else if (string(argv[i]) == "--port") {
                    sport = argv[i + 1];
                    port=stoi(sport);
                } else if (string(argv[i])=="--numstr") {
                    numstr = argv[i + 1];
                }
            }
        }
concated_string = devicestr + ":"+ sport + "/"+numstr;

Silerus ★★★ ()
Ответ на: комментарий от Silerus

а если так?

Ты осознаешь, что у тебя на каждой итерации цикла по 3 лишних никому не нужных выделения/освобождения памяти, чтобы создать временную строку из argv?

kawaii_neko ★★★★ ()
Ответ на: комментарий от sniper21

да еще

--if (i + 1 != argc)
++if (i + 1 < argc)
И если мы точно знаем минимальное ожидаемое количество аргументов - это стоит проверить перед разбором, а то смысла нет разбирать не верное количество данных

Silerus ★★★ ()
Ответ на: комментарий от kawaii_neko

а так и так будет, если создать буфферную переменную, она будет тоже играть с памятью так как скорее всего «=» будет создовать новый объект. Если рассматривать strcmp там будет работа со стеком, но опять прыжок в функцию возврат. Помоему здесь не тот пример где надо бороться за время.

Silerus ★★★ ()
Ответ на: комментарий от Ivan_qrt

согласен так лучше. Хотя нет тут for вообще лучше заменить на while если элемент найден, то следующий сразу обрабатывается - нахрена его проверять

Silerus ★★★ ()
Последнее исправление: Silerus (всего исправлений: 1)
Ответ на: комментарий от KennyMinigun

using namespace std;

Вот єто фу

Чушь. using namespace в *.cpp-файлах - это нормально.

anonymous ()
Ответ на: комментарий от KennyMinigun

С чего бы это? Понятно чем это чревато в заголовочных файлах вне определения функций, но в cpp файлах это на вкус и цвет.

dzidzitop ★★ ()
Ответ на: комментарий от Unicode4all

Вот несколько причин.

1) clang-tidy выдаёт предупреждение на using namespace std

warning: do not use namespace using-directives; use using-declarations instead [google-build-using-namespace]
using namespace std;

2) Полезный скрипт iwyu.py (который считывает все использования стандартных функций/классов и выдаёт необходимые заголовочные файлы которые нужно подключить, в правильном виде)

Includes for main.cpp:
#include <iostream>
#include <string>
....
не будет работать правильно, потому что он находит именно std::<какое-то слово>, а с using std::<какое-то слово> всё будет работать правильно

3) Если есть несколько using namespace, например std и boost то код который собирался раньше может перестать компилироваться при обновлении компилятора/библиотек. Например, когда в C++11 добавили std::array, код в котором использовали boost::array, перестал работать, так как в cpp файле было написано

using namespace std;
using namepspace boost;
и компилятор не знал какой класс array использовать, std::array или boost::array.

fsb4000 ★★★★ ()
Ответ на: комментарий от anonymous

Причина два на самом деле полезна. Вот например pull request сделанный с помощью этого скрипта https://github.com/danmar/cppcheck/pull/906 Скрипт позволяет добавить, те стандартные include которые нужны по стандарту, но которых нет(например #include<string> из примера в этом посте, в gcc нормально, в MSVC была бы ошибка...), или которые подключены в пользовательских #include. Так же скрипт позволяет убрать лишние #include... Так что если программа компилируется, не обязательно что нет проблем с #include.

fsb4000 ★★★★ ()
Ответ на: комментарий от fsb4000

Причина два на самом деле полезна.

Любую маргинальную фигню кто-то находит полезной.

anonymous ()
Ответ на: комментарий от Silerus

Помоему здесь не тот пример где надо бороться за время

По-моему, делать string из char* (да еще и три раза!) только для сравнения — крайне херовая идея.

А вообще подумай на досуге, почему сегодня для выполнения тех же задач, с которыми справлялся, скажем Microsoft Office 97 на Pentium 166, нужен свеженький Core i5, а то openoffice тормозит.

kawaii_neko ★★★★ ()
Ответ на: комментарий от kawaii_neko

ну хорошо, давай перейдем на ассемблер - там все будет просто (всмысле примитивно, ну так как ассемблер язык примитивных команд), но за то быстро, если у программиста мозги будут правильно работать. У нас нет упора ни в железо ни во время, на памяти мы в данном случае тоже ничего не теряем, сам говоришь как выделилась, так и очистилась. И кстати, 97 офис на 166 пне тупил, я застал то время можешь не рассказывать. А про крайне херовые идеи - это когда у нас хардтайм - вот там надо извращаться и то можно такого наворотить с оптимизациями - что хуже будет.

Silerus ★★★ ()
Ответ на: комментарий от Unicode4all

using namespace std;

Вот єто фу. Не делай так никогда, даже в «наколенном» коде.

А что в этом такого? Мне вот глаза режет обилие :: в коде.

На самом деле никакой дилеммы тут нет. Директиву using нужно использовать, но прицельно - только на то, что действительно потребовалось в коде.

#include <iostream>

using std::cout;
using std::endl;

int main()
{
    cout << "eins" << endl;
    cout << "zwei" << endl;
    cout << "drei" << endl;
    cout << "vier" << endl;
    return 0;
}
Crocodoom ★★★★ ()
Ответ на: комментарий от a1batross

Кстати да. Поискал снова этот проект. Он обновился за время когда я скачивал последний раз. Теперь он использует LLVM, и ему без разницы на std::. На код из первоначального поста даёт такой вывод:

main.cpp should add these lines:
#include <string>    // for allocator, operator+, string, operator<<, stoi

main.cpp should remove these lines:
- #include <stdio.h>  // lines 4-4
- #include <stdlib.h>  // lines 3-3

The full include-list for main.cpp:
#include <string.h>  // for strcmp
#include <iostream>  // for char_traits, operator<<, cout, ostream
#include <string>    // for allocator, operator+, string, operator<<, stoi
---
Вот исходники: https://github.com/include-what-you-use/include-what-you-use

Легко интегрируется в make, просто добавьте лишнюю цель, для которой измените CXX и CC на include-what-you-use

fsb4000 ★★★★ ()
Ответ на: комментарий от anonymous

Это компилятор оратору написал. Я только подчеркнул что unspecified behaviour и undefined behavour это разные понятия.

dzidzitop ★★ ()
Ответ на: комментарий от Silerus

ну хорошо, давай перейдем на ассемблер - там все будет просто

«Ассемблер — это просто» — слова, которые говорят люди, ничего на этом самом асме в жизни не писавшие. Зачем ты приплел ассемблер мне вообще непонятно.

У нас нет упора ни в железо ни во время,

Ну да. Именно поэтому современный софт пожирает гигабайты оперативки и несколько ядер CPU, оставаясь при этом на уровне софта десятилетней давности по функционалу.

на памяти мы в данном случае тоже ничего не теряем, сам говоришь как выделилась, так и очистилась

Типичный кресторебенок не в состоянии понять, что такое фрагментация heap-а. Вот тебе простое правило: большое количество «мусорных» аллокаций и освобождений памяти (особенно если это происходит в разных тредах) приводит к фрагментации памяти, что снаружи выглядит как увеличение RSS.

А про крайне херовые идеи

Крайне херовая идея — это твоя лень, от которой ты пишешь string(argv[i]) == "--devicestr" вместо strcmp. Заметь, я даже не требую от тебя напрячь межушный нервный ганглий и использовать, как и положено, getopt.

можно такого наворотить с оптимизациями - что хуже будет

Я говорю не советовать писать говнокод. Об оптимизации, судя по выдаваемым идеям, 99% крестодетей и правда не стоит задумаваться — просто не осилят.

kawaii_neko ★★★★ ()
Ответ на: комментарий от kawaii_neko

Крайне херовая идея — это твоя лень, от которой ты пишешь string(argv) == "--devicestr" вместо strcmp

Лень - это плохо, но в создании временного автоматического объекта в main нет ничего страшного.

anonymous ()
Ответ на: комментарий от kawaii_neko

Типичный кресторебенок не в состоянии понять, что такое фрагментация heap-а. Вот тебе простое правило: большое количество «мусорных» аллокаций и освобождений памяти (особенно если это происходит в разных тредах) приводит к фрагментации памяти, что снаружи выглядит как увеличение RSS.

Справедливости ради, в случае правильных аргументов там не будет мусорных аллокаций. Точнее может быть одна на 32-ух битах. Ибо small string optimization.

А вообще там нужно использовать string_view и fmtlib. И всё будет читабельно и быстро.

Ivan_qrt ★★★★★ ()
Ответ на: комментарий от kawaii_neko

от которой ты пишешь string(argv) == "--devicestr" вместо strcmp.

Хорошая идея это

std::string_view("--devicestr").compare(argv[i])

А не strcmp

P.S. Кстати, а почему у стринг вью нет operator==(Char* T) ?

Dudraug ★★★★★ ()
Ответ на: комментарий от Ivan_qrt

А вообще там нужно использовать string_view

Тот же вопрос почему у вью надо использовать не такой наглядный compare, а не интуитивно понятный ==? Оператора == для CharT* у стринг вью нет же...

Dudraug ★★★★★ ()
Последнее исправление: Dudraug (всего исправлений: 1)
Ответ на: комментарий от Dudraug

А не strcmp

Такое ощущение, что тебе платят посимвольно за написанный код.

kawaii_neko ★★★★ ()
Ответ на: комментарий от kawaii_neko

Раз уж мы переходим на личности то:

  • Выпей пустырника, водки или что ты там используешь для успокоения нервов.
  • Загляни в морозилку, возьми что-нибудь холодное и положи под «нижние полушария мозга».
  • Если такие ситуации возникают слишком часто - обратись к профильному специалисту.
  • Невнимательность может быть, как признаком общей хронической усталости,так и признаком нервных заболеваний - подумай о здоровье
  • Излишняя раздражительность - тоже.
  • Я понимаю что «чукча - писатель»
  • Черезмерное использование терминов свидетельствует о желание индивида показаться умнее чем он есть на самом деле.
  • Если есть раздражители - то от них стоит абстрагироваться
Silerus ★★★ ()
Ответ на: комментарий от Dudraug

Тот же вопрос почему у вью надо использовать не такой наглядный compare, а не интуитивно понятный ==?

Понятия не имею. Наверное, не договорились с кем-то. Добавят в C++20.

Я бы делал так:

#include <string>
#include <string_view>
#include <fmt/format.h>

using namespace std;

int main(int argc, char *argv[]) {
    string_view devstr;
    string_view numstr;
    int port = 0;

    string url{};

    fmt::print("{}.\n", argc);
    for (int i = 1; i < argc - 1; i++) {
        string_view arg = argv[i];
        if (arg == "--devicestr"sv) {
            devstr = argv[i + 1];
        } else if (arg == "--port"sv) {
            port = std::stoi(argv[i + 1]);
        } else if (arg == "--numstr"sv) {
            numstr = argv[i + 1];
        }
    }
    if(!devstr.empty() && !numstr.empty()) {
        url = fmt::format("{}:{}/{}", devstr.data(), port, numstr.data());
    }
    fmt::print("{}.\n", url);
    return 0;
}

Ivan_qrt ★★★★★ ()
Ответ на: комментарий от kawaii_neko

Ну во первых бабануло у тебя, иначе ты бы не скатывался на личности и именно по этому я не вижу дальнейшего диалога, а твой монолог мне не интересен, так как однобок. Во вторых мяукать - это видимо к твоему подвиду кошачих. В третьих о чем с тобой вообще можно дискутировать если ты видишь только то что хочешь видеть - это разговор глухого с немым. Дискутирующие не оскорбляют друг друга в процессе дискусии, но тебя этому не обучили.

Silerus ★★★ ()
Ответ на: комментарий от Silerus

Дискутирующие не оскорбляют друг друга в процессе дискусии, но тебя этому не обучили

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

Во-вторых, если человек сначала делает мудацкое предложение «а давай char* в std::string оборачивать на каждый чих», а потом продолжает настаивать, что в этом нет ничего плохого — он по-твоему заслуживает уважения? Ну иди уважай себя, если хочешь, но за подобные джуниорские высеры в любом мало-мальски грамотном коллективе ты будешь получить ссаным веником по морде.

И в-третьих, тебе есть что сказать по поводу фрагментации кучи, или ты решил перейти на общение в личностном плане от безысходности, поскольку в профессиональном ты ноль без палочки?

kawaii_neko ★★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.