Формат определяет тип 'char *', но аргумент имеет тип 'std :: string *' (он же 'basic_string <char>*') - PullRequest
0 голосов
/ 30 марта 2020

Я пишу программу на C ++, где мне нужно прочитать некоторые отформатированные строки из файла на C ++, который имеет формат:

<N>
<x> blah blah blah <y>
<x1> blah blah blah <y1>
<x2> blah blah blah <y2>

, где x и y - строки. Я написал этот код для сканирования:

fscanf(fin, "%d\n", &N);
    for (int i = 0; i < N; i++) {
        if (fscanf(fin, "%s blah blah blah %s\n", &data::x, &data::y) != 1) break;
        pairs.push_back({(string) data::x, data::y});
}

, где N - это целое число, data - это пространство имен со строками x и y, а pairs - это vector<vector<string> , Несмотря на то, что scanf() и подобные не выдают ошибок чтения, CLion выдает мне предупреждение:

Формат указывает тип 'char *', но аргумент имеет тип 'std :: string *' (aka ' basic_string * ')

Я пытался изменить data::x и data::y на char *, но затем CLion выдает мне еще одно предупреждение:

Формат указывает тип' char * 'но аргумент имеет тип' char ** '

Когда я запускаю программу, ничего не выводится ни в стандартный вывод, ни в файл.

Вот полный код:

#include <bits/stdc++.h>
using namespace std;

namespace data {
    string x, y;
}

int main() {
    int N;
    FILE *fin = fopen("foo", "r");
    ofstream fout ("bar");
    vector<vector<string>> pairs;

    fscanf(fin, "%d\n", &N);
    for (int i = 0; i < N; i++) {
        if (fscanf(fin, "%s blah blah blah %s\n", &data::x, &data::y) != 1) break;
        pairs.push_back({(string) data::x, data::y});
    }
    cout << pairs.size();
    for (vector<string> i : pairs) {
        cout << i[0] << ' ' << i[1] << endl;
    }

    fclose(fin); fout.close();

    return 0;
}

Есть ли способ сделать это в стиле C ++ или есть что-то, что нужно изменить с помощью моего кода? Спасибо!

Ответы [ 2 ]

1 голос
/ 30 марта 2020

Есть ли способ сделать это в стиле C ++

Да. Стиль ввода в C ++ - использовать std::ifstream вместо std::fscanf.

Но как мне использовать форматирование, которое я использовал для fscanf, используя ifstream?

Вы извлекаете из потока в строку для чтения слова, что аналогично использованию %s, за исключением того, что вы можете читать в std::string, а также в любой другой тип, который его поддерживает.

Не существует аналогичной функции пропуска ожидаемого ввода, как у scanf. Вы можете реализовать это, используя следующий алгоритм:

Просмотр следующего символа. Если он соответствует ожидаемому, то извлеките его и переходите к следующему символу. В противном случае извлечение не удалось. Если нет следующего ожидаемого символа, тогда извлечение завершилось успешно, и вы можете приступить к извлечению data::y.

. Для сложных случаев использования я рекомендую более структурированный подход, такой как генератор синтаксических анализаторов, чем ad-ho c реализация.

0 голосов
/ 30 марта 2020

%s ожидает указатель char* на буфер для записи, а не std::string. Таким образом, вы можете исправить ошибку, используя промежуточный char[], например:

fscanf(fin, "%d\n", &N);
char tempx[256];
char tempy[256];
for (int i = 0; i < N; i++) {
    if (fscanf(fin, "%255s blah blah blah %255s\n", tempx, tempy) != 2)
        break;
    data::x = tempx;
    data::y = tempy;
    pairs.push_back({data::x, data::y});
}
...