форматированный ввода. scanf или что-то другое?
От: vandi711  
Дата: 21.03.13 03:50
Оценка:
Здравствуйте!

Облазил поисковик, но ответа на свой вопрос так и не нашел.

Есть две строки, которые вводятся в консоли с клавиатуры:

1) " folder2 10"
Эту строку я хочу записать в масис char, как " folder2" (включая пробелы)
а цифру "10" в переменную типа int/
2) "4 1 2 3"
Эту строку я хочу записать, как int в Массив int.

Как это можно сделать?

Пробовал различные комбинации форматированного ввода scanf, но не помогло, также пробовал делать scanf в цикле.
Получать строку целиком, а потом переводить цифры с помощью atoi — не вариант.
Получить ввод с клавиатуры хочется стандартными методами, без использования специфических библиотек.
Кто-нибудь может помочь?)
c++ консоль scanf ввод с клавиатуры
Re: форматированный ввода. scanf или что-то другое?
От: jazzer Россия Skype: enerjazzer
Дата: 21.03.13 03:59
Оценка: 2 (1) +1
Здравствуйте, vandi711, Вы писали:

V>Есть две строки, которые вводятся в консоли с клавиатуры:


V>1) " folder2 10"

V> Эту строку я хочу записать в масис char, как " folder2" (включая пробелы)
V> а цифру "10" в переменную типа int/
V>2) "4 1 2 3"
V> Эту строку я хочу записать, как int в Массив int.

Boost.Spirit2. Решение будет записываться в одну, максимум две строчки.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[2]: форматированный ввода. scanf или что-то другое?
От: vandi711  
Дата: 21.03.13 04:17
Оценка:
Здравствуйте, jazzer, Вы писали:

J>Boost.Spirit2. Решение будет записываться в одну, максимум две строчки.


Прошу прощения, нужно было более конкретизировать. Требуется использовать только стандартную библиотеку, Boost, к сожалению не подходит...
Но, спасибо, буду знать)

По поводу второго типа строк, забыл сказать, что заранее количество цифр в строке неизвестно.
Re: форматированный ввода. scanf или что-то другое?
От: uzhas Ниоткуда  
Дата: 21.03.13 07:19
Оценка: 3 (1) +1
Здравствуйте, vandi711, Вы писали:

V>Как это можно сделать?


для простых сценариев предлагаю использовать std::stringstream
пример: http://liveworkspace.org/code/3ZgZML$0
при этом ваш первый пример распарсится не так, как вы хотите, ибо пробелы проглотятся, ибо считается разделителем
Re[3]: форматированный ввода. scanf или что-то другое?
От: uzhas Ниоткуда  
Дата: 21.03.13 07:23
Оценка:
Здравствуйте, vandi711, Вы писали:

V>По поводу второго типа строк, забыл сказать, что заранее количество цифр в строке неизвестно.

если вы еще опишите какими могут быть строки первого типа, то мы можем составить регулярное выражение для парсинга и воспользоваться std::regexp (вы каким компиляторм пользуетесь? не все поддерживают std::regexp )
Re[2]: форматированный ввода. scanf или что-то другое?
От: vandi711  
Дата: 21.03.13 07:49
Оценка:
Здравствуйте, uzhas, Вы писали:

U>для простых сценариев предлагаю использовать std::stringstream

U>пример: http://liveworkspace.org/code/3ZgZML$0
U>при этом ваш первый пример распарсится не так, как вы хотите, ибо пробелы проглотятся, ибо считается разделителем

Ага, хорошо, спасибо, посмотрю, пощупаю))
Re[4]: форматированный ввода. scanf или что-то другое?
От: vandi711  
Дата: 21.03.13 07:54
Оценка:
V>>По поводу второго типа строк, забыл сказать, что заранее количество цифр в строке неизвестно.
U>если вы еще опишите какими могут быть строки первого типа, то мы можем составить регулярное выражение для парсинга и воспользоваться std::regexp (вы каким компиляторм пользуетесь? не все поддерживают std::regexp )

Использую я g++.

Строки первого типа идут примерное по следующей схеме:
(Некоторое количество пробелов от 0 до n) + (строка, содержащая как буквы, так и цифры) + пробел + идентификатор.
Примеры:
1) "root 1"
2) " root/folder 5"
3) " root/folder/example1000 10"
Re[2]: форматированный ввода. scanf или что-то другое?
От: vandi711  
Дата: 21.03.13 08:05
Оценка:
Упс, криво примеры привел
В первом примере пробелов вначале нет
Во втором примере два пробела вначале
В третьем примере 4 пробела вначале

Долгими мурыжаньями у меня получилась регуляярка вида .*?(?=\s\d)
Но вот, если писать:

scanf("%[.*?(?=\s\d)]%d", str, &digit)


, то что-то он не то заносит...
Re[5]: форматированный ввода. scanf или что-то другое?
От: uzhas Ниоткуда  
Дата: 21.03.13 08:26
Оценка:
Здравствуйте, vandi711, Вы писали:

V>Использую я g++.


пишут, что regexp на gcc unusable
http://stackoverflow.com/questions/14776605/c-11-regex-error
этот код у меня работает на VS
на gcc не взлетело

  Скрытый текст
#include <regex>
#include <iostream>
#include <sstream>

int AsInt(const std::string& s)
{
    int r = 0;
    std::istringstream p(s);
    p >> r;
    return r;
}

void Parse(const std::string& s)
{
    std::regex r("^(\\s*[^\\s-]+) (\\d+)$");
    std::smatch m;

    if (!std::regex_match(s, m, r))
    {
        std::cout << "NO MATCH for string '" << s << "'" <<std::endl;
        return;
    }

    std::cout << "parsed string '" << s << "'" << std::endl;

    const std::string s1 = m[1].str();
    const int id = AsInt(m[2].str());
    std::cout << "s1 = '" << s1 << "', n = " << id << std::endl;
}

int main()
{
    const char* source[] = {"root 1", " root/folder 5", " root/folder/example1000 10", " a b c d 4", "a b c"};
    for(auto& i : source)
    {
        Parse(i);
    }
    return 0;
}


успехов
Re[3]: форматированный ввода. scanf или что-то другое?
От: uzhas Ниоткуда  
Дата: 21.03.13 08:38
Оценка:
Здравствуйте, vandi711, Вы писали:

V>Но вот, если писать:


scanf не поддерживает регулярки, однако поддерживает классы символов
http://stackoverflow.com/questions/1247989/how-do-you-allow-spaces-to-be-entered-using-scanf
но ваши примеры не могу распарсить одним scanf =\
Re[5]: форматированный ввода. scanf или что-то другое?
От: Кодт Россия  
Дата: 21.03.13 09:39
Оценка: +1
Здравствуйте, vandi711, Вы писали:


V>>>По поводу второго типа строк, забыл сказать, что заранее количество цифр в строке неизвестно.

U>>если вы еще опишите какими могут быть строки первого типа, то мы можем составить регулярное выражение для парсинга и воспользоваться std::regexp (вы каким компиляторм пользуетесь? не все поддерживают std::regexp )

V>Использую я g++.


V>Строки первого типа идут примерное по следующей схеме:

V>(Некоторое количество пробелов от 0 до n) + (строка, содержащая как буквы, так и цифры) + пробел + идентификатор.
V>Примеры:
V>1) "root 1"
V>2) " root/folder 5"
V>3) " root/folder/example1000 10"

Казалось бы! "%s %d" именно это и распарсит. Выкинет ведущие пробелы, возьмёт текст без пробелов, выкинет промежуточные пробелы, возьмёт число.
Перекуём баги на фичи!
Re[3]: форматированный ввода. scanf или что-то другое?
От: korzhik Россия  
Дата: 21.03.13 09:57
Оценка:
Здравствуйте, vandi711, Вы писали:

V>Долгими мурыжаньями у меня получилась регуляярка вида .*?(?=\s\d)

V>Но вот, если писать:

V>
V>scanf("%[.*?(?=\s\d)]%d", str, &digit)
V>


Очень оптимистично было регулярку в scanf засунуть -)
Читай доки: http://pubs.opengroup.org/onlinepubs/009695399/functions/scanf.html

Можно конечно и scanf'ом такое сделать.
Вот код для первой типа строк:

bool parse(const char* str, int* term_width, int* value)
{
    if (!str || !*str || !term_width || !value) return false;

    const char* p = str;
    
    // skip leading white-spaces
    while (std::isspace(*p)) ++p;

    int n = p - str;
    int result = std::sscanf(p, "%*s%n%d", term_width, value);

    if (result != 1 || result == EOF)
        return false;

    *term_width += n;
    return true;
}

int main()
{
    int v,w;
    assert(!parse(0,0,0));
    assert(!parse("",0,0));
    assert(!parse(0,&w,&v));
    assert(!parse("",&w,&v));
    assert(!parse("p",&w,&v));
    assert(!parse(" 1",&w,&v));
    {
        const char* str = "p 1";
        assert(parse(str, &w, &v));
        std::string s(str, w);
        assert(s == "p");
        assert(v == 1);
    }
    {
        const char* str = "root 1";
        assert(parse(str, &w, &v));
        std::string s(str, w);
        assert(s == "root");
        assert(v == 1);
    }
    {
        const char* str = "  root/folder 5";
        assert(parse(str, &w, &v));
        std::string s(str, w);
        assert(s == "  root/folder");
        assert(v == 5);
    }
    {
        const char* str = "    root/folder/example1000 10";
        assert(parse(str, &w, &v));
        std::string s(str, w);
        assert(s == "    root/folder/example1000");
        assert(v == 10);
    }
    return 0;
}


для второго типа как то так:

#include <vector>

int main()
{
    const char* str = "1 2 13 40 5";
    const char* p = str;
    std::vector<int> arr;

    int value, n;
    while (sscanf(p, "%d%n", &value, &n) != EOF)
    {
        arr.push_back(value);
        p += n;
    }
    return 0;
}
Re[4]: форматированный ввода. scanf или что-то другое?
От: korzhik Россия  
Дата: 21.03.13 11:19
Оценка:
Здравствуйте, korzhik, Вы писали:

K>Здравствуйте, vandi711, Вы писали:


V>>Долгими мурыжаньями у меня получилась регуляярка вида .*?(?=\s\d)

V>>Но вот, если писать:

V>>
V>>scanf("%[.*?(?=\s\d)]%d", str, &digit)
V>>


Что то я заманьячился. Для первого типа строк там достаточно вот такого кода:

bool parse(const char* str, int* term_width, int* value)
{
  if (!str || !*str || !term_width || !value) return false;
  return std::sscanf(str, "%*s%n%d", term_width, value) == 1;
}
Re[6]: форматированный ввода. scanf или что-то другое?
От: niXman Ниоткуда https://github.com/niXman
Дата: 21.03.13 12:00
Оценка:
Здравствуйте, uzhas, Вы писали:

U>пишут, что regexp на gcc unusable

U>http://stackoverflow.com/questions/14776605/c-11-regex-error
U>этот код у меня работает на VS
U>на gcc не взлетело
да, регулярки пока не реализованы. их оставили для 4.9 версии.
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re[4]: форматированный ввода. scanf или что-то другое?
От: vandi711  
Дата: 22.03.13 03:13
Оценка:
std:isstringstream подошел. Всем спасибо)
Re[4]: форматированный ввода. scanf или что-то другое?
От: vandi711  
Дата: 22.03.13 03:19
Оценка:
Здравствуйте, korzhik, спасибо за пример, посмотрю, пощупаю, выглядит интересно,
хотя, как уже написал выше, подошел istringstream =)

Тему, можно, считать закрытой)
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.