C ++ c2664 error "невозможно преобразовать аргумент 1 из std :: string в _Elem *" - PullRequest
1 голос
/ 13 июня 2019

Я застрял на этом домашнем задании всю неделю. Когда я наконец-то запускаю программу, я понимаю, что, используя cin >> breed, если у моего ввода есть пробел, он разрушает код (так как моей программе требуется собрать 3 отдельные переменные, сначала int, затем строку и, наконец, бул). Поскольку это вторая переменная, она портит мой код, используя фразы, которые имеют белый символ. Когда я пытаюсь изменить его на cin.get или cin.getline, появляется следующее сообщение об ошибке:

c2664 error "невозможно преобразовать аргумент 1 из std :: string в _Elem *"

Ниже приведен код (средняя строка указывает на ошибку). Любая помощь будет принята с благодарностью!

#include <iostream>
#include <string>
using namespace std;

int main()
{
    int birthyear;  
    string breed;    
    bool vaccines;  

    cout << "Please enter value for dog's birth year: ";
    cin >> birthyear;
    cout << "What is the breed of the dog: ";
    cin.getline(breed, 100);
    cin.ignore();
    cout << "Has the dog been vaccinated (1 = Yes/ 0 = No): ";
    cin >> vaccines;
}

1 Ответ

1 голос
/ 13 июня 2019

Прежде всего, вы должны знать, что в C ++ есть две getline вещи, одна в области ввода-вывода и одна в стандартном пространстве имен верхнего уровня.

cin.getline(breed, 100) - это тот, что находится в области ввода / вывода (в частности, istream::getline(), и он не знает ничего о строках, предпочитая работать с массивами символов. Вам, вероятно, следует избегать этого.

Тот, который знает о строках, - это std::getline(), и это, как правило, предпочтительный вариант, если вы не хотите возвращаться к плохим старым временам "строк" C-legacy.

Кроме того, вам нужно быть осторожным в C ++, когда вы смешиваете операции ввода, специфичные для типа (например, <<), и операции ввода, специфичные для строки (например, getline). Важно знать, где находится указатель файла до и после каждой операции.

Например, cin << someInt оставит указатель файла сразу после целого числа, которое он читает. Это означает, что если ваша следующая операция будет getline(), то, вероятно, найдет все в строке после этого целого числа (как минимум) , это будет символ новой строки, который вы ввели для обработки целого числа), , а не следующая строка, где вы собираетесь вводить строку.

Простое решение для вашего случая - игнорировать все до и включая новую строку, прежде чем пытаться получить следующую строку. Это можно сделать с помощью ignore():

#include <iostream>
#include <string>
#include <limits>
using namespace std;

int main() {
    int birthyear; string breed; bool vaccines;

    cout << "Please enter value for dog's birth year: ";
    cin >> birthyear;

    cout << "What is the breed of the dog: ";
    cin.ignore(numeric_limits<std::streamsize>::max(), '\n');
    getline(cin, breed);

    cout << "Has the dog been vaccinated (1 = Yes/ 0 = No): ";
    cin >> vaccines;

    // Output what you got.

    cout << birthyear << " '" << breed << "' " << vaccines << '\n';
}

Вы также можете убедиться, что ввод all основан на строках (преобразование этих строк в правильный тип после их ввода), поскольку это, вероятно, облегчит вашу задачу обеспечения правильности указателей. место, и что ошибки ввода (например, ввод xyzzy для целого числа) могут быть лучше обработаны.

Примерно так должно быть хорошим началом:

#include <iostream>
#include <string>
#include <limits>
#include <set>
#include <cstdlib>
using namespace std;

// Get string, always valid. Optionally strip leading and
// trailing white-space.

bool getResp(const string &prompt, string &val, bool strip = false) {
    cout << prompt;
    getline(cin, val);
    if (strip) {
        val.erase(0, val.find_first_not_of(" \t"));
        val.erase(val.find_last_not_of(" \t") + 1);
    }
    return true;
}

// Get unsigned, must ONLY have digits (other than
// leading or trailing space).

bool getResp(const string &prompt, unsigned long &val) {
    string str;
    if (! getResp(prompt, str, true)) return false;

    for (const char &ch: str)
        if (! isdigit(ch)) return false;

    val = strtoul(str.c_str(), nullptr, 10);
    return true;
}

// Get truth value (ignoring leading/trailing space),
// and allow multiple languages.

bool getResp(const string &prompt, bool &val) {
    string str;
    if (! getResp(prompt, str, true)) return false;

    const set<string> yes = {"yes", "y", "1", "si"};
    const set<string> no = {"no", "n", "0", "nyet"};

    if (yes.find(str) != yes.end()) {
        val = true;
        return true;
    }

    if (no.find(str) != no.end()) {
        val = false;
        return true;
    }

    return false;
}

// Test driver for your situation.

int main() {
    unsigned long birthYear;
    std::string dogBreed;
    bool isVaccinated;

    if (! getResp("What year was the dog born? ", birthYear)) {
        std::cout << "** ERROR, invalid value\n";
        return 1;
    }

    if (! getResp("What is the breed of the dog? ", dogBreed, true)) {
        std::cout << "** ERROR, invalid value\n";
        return 1;
    }

    if (! getResp("Has the dog been vaccinated? ", isVaccinated)) {
        std::cout << "** ERROR, invalid value\n";
        return 1;
    }

    std::cout
        << birthYear
        << " '" << dogBreed << "' "
        << (isVaccinated ? "yes" : "no") << '\n';
}
...