Как сканировать две строки, разделенные `/`, используя sscanf?

Я хочу сканировать отдельные строки, разделенные /, используя sscanf, но это не работает. Он отлично работает с пробелом.

Например, я хочу разделить строку 50%/60% на две строки, например 50% и 60%.

Вы можете посмотреть код здесь:

#include <iostream>
using namespace std;

int extract_break_rewrites(int *m, int *n, const char *arg)
{
    char m_str[10];
    char n_str[10];
    int err;

    int count = sscanf(arg, "%s %s", n_str, m_str);
    printf("%s %s %d\n",n_str, m_str,count);
    if (count == 0) {
        count = sscanf(arg, "/%s", m_str);
        if (count == 0) {
            *m = 0;
            *n = 0;
            return -1;
        }
        if (sscanf(m_str, "%d%%", m) != 1) 
            return -1;
    }
    else if (count == 1) {
        if (sscanf(n_str, "%d%%", n) != 1) 
            return -1;
    }
    else if (count==2) {
        if (sscanf(n_str, "%d%%", n) != 1) 
            return -1;
        if (sscanf(m_str, "%d%%", m) != 1) 
            return -1;
    }
    return 1;
}

int main() {
    int n,m;
    const char * command = "50% 60%";
    if (extract_break_rewrites(&m,&n,command)!=-1)
        cout<<"Successful. The values of m and n are "<<m<<" and "<<n<<", respectively.\n";
    else
        cout<<"There was error in processing, may be input was not in the correct format.\n";
    return 0;
}

Вам не нужно беспокоиться о том, что делает код, важные строки — это 10, 11 и основная функция.


person Saurabh Jain    schedule 04.04.2016    source источник
comment
Пожалуйста, разместите код здесь вместо ссылки на код.   -  person R Sahu    schedule 05.04.2016
comment
Это называется проблемой x-y. Вы хотите разобрать строку и считаете, что sscanf — подходящий инструмент. Это не так.   -  person stark    schedule 05.04.2016
comment
Ваш код написан на C++, вы должны изменить свой тег на C++. Однако, если вы хотите анализировать строки, вы можете использовать что-то вроде strtok, чтобы разделить строку на токены.   -  person DMH    schedule 05.04.2016
comment
Код написан на C++, но используемая библиотека функций получена на C++ только из C, поэтому не думайте, что нужно менять ее на C++. @DMH   -  person Saurabh Jain    schedule 05.04.2016
comment
@stark, какой правильный инструмент тогда, пожалуйста, предложите.   -  person Saurabh Jain    schedule 05.04.2016
comment
@SaurabhJain C++ имеет лучшие инструменты для использования со строками, которые безопаснее и лучше, чем те, что из C. Есть ли какая-то особая причина для использования C в коде C++?   -  person DMH    schedule 05.04.2016
comment
Данные вашего образца не включают /, который обсуждается в вашем вопросе. Это, по крайней мере, слегка сбивает с толку. Что должно произойти, если символы % отсутствуют? Что должно произойти, если / отсутствует?   -  person Jonathan Leffler    schedule 05.04.2016
comment
Это C++, а не C. Не добавляйте тег C для кода C++.   -  person too honest for this site    schedule 05.04.2016
comment
Почему -1 за вопрос, есть причины?   -  person Saurabh Jain    schedule 05.04.2016


Ответы (3)


Попробуйте следующее (при условии, что из стандартного ввода):

scanf("%[^/]/%s");

Используйте sscanf(buf, ...); при чтении из буфера.

Проблема в том, что %s вместо scanf предполагает, что за строкой следует пробел. Этот подход указывает scanf найти строку, разделенную /, а затем сопоставить остальную часть как отдельную строку.

РЕДАКТИРОВАТЬ: случайно уронил / в строке сканирования

person AlexO'Neill    schedule 04.04.2016
comment
Как это сканирует две строки? - person Saurabh Jain; 05.04.2016
comment
@SaurabhJain: полный код должен быть if (sscanf(arg, "%9[^/]/%9s", n_str, m_str) == 2) { …OK… } else { …Deal with errors… }. 9 — это количество места в строковых переменных, исключая конечный нуль. - person Jonathan Leffler; 05.04.2016

Использовать набор сканирования

char a[100];
char b[100];
scanf("%[^/]/%s", a, b);

Это сканирует все, пока не получит /, затем запустится и прочитает строку.

person Harry    schedule 04.04.2016

Вы также можете использовать std::strings и их возможности для достижения того же результата:

#include <iostream>
#include <string>

using std::string;
using std::cout;
using std::stoi;

bool extract_break_rewrites(int &m, int &n, const string &arg) {
    // find position of %/ in the string
    string::size_type pos_first = arg.find("%/");
    // check if the return value is valid (the substring is present and there
    // is something else first)
    if ( pos_first == string::npos  ||  !pos_first )    // wrong input
        return false;

    string::size_type pos_2 = pos_first + 2,
                      pos_last = arg.find("%", pos_2);
    if ( pos_last == string::npos  ||  pos_last == pos_2 )  
        return false;

    try {
        m = stoi(arg.substr(0, pos_first));
        n = stoi(arg.substr(pos_2, pos_last - pos_2));
    }
    // invalid argument or out of range
    catch (...) {
        return false;
    }

    return true;
}

int main() {
    int n = 0, m = 0;
    string command = "150%/60%";

    if ( extract_break_rewrites(m, n, command) )
        cout << "Successful. The values of m and n are "
             << m << " and " << n << ", respectively.\n";
    else
        cout << "There was error in processing, "
             << "maybe input was not in the correct format.\n";

    return 0;
}
person Bob__    schedule 04.04.2016