C++ 在C+;中调用while循环内的函数时出错+;

C++ 在C+;中调用while循环内的函数时出错+;,c++,string,loops,while-loop,C++,String,Loops,While Loop,如果这是一份副本,我提前表示歉意。我试图找到一个类似的问题,但没有找到解决方案。当我询问用户是否希望再次输入时,我会出现以下错误:“libc++abi.dylib:终止时出现std::out_of_range:basic_string类型的未捕获异常”。如果您输入'N',程序将结束,但当您输入'Y',它将显示上面的错误。我的程序要求用户输入格式为:(2019年12月25日)的日期,并将其转换为格式:(MM/DD/YYYY)。代码可以工作,但我在循环代码时只遇到了一个错误 这是我的密码: #inc

如果这是一份副本,我提前表示歉意。我试图找到一个类似的问题,但没有找到解决方案。当我询问用户是否希望再次输入时,我会出现以下错误:“libc++abi.dylib:终止时出现std::out_of_range:basic_string类型的未捕获异常”。如果您输入'N',程序将结束,但当您输入'Y',它将显示上面的错误。我的程序要求用户输入格式为:(2019年12月25日)的日期,并将其转换为格式:(MM/DD/YYYY)。代码可以工作,但我在循环代码时只遇到了一个错误

这是我的密码:

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

void getDate(string &mdy){
    cout<<"Enter Any Date in Format: (December 25th, 2019) ";
    getline(cin, mdy);
}
void extract (string &mdy, string &m, string &d, string &y){
    int startIndex, endIndex, endIndexDay, startIndexDay, startIndexYear, endIndexYear;

    startIndex = 0;
    endIndex = mdy.find(' ');
    startIndexDay = ((endIndex - startIndex) +1);
    endIndexDay = mdy.find(',');
    startIndexYear = (endIndexDay +2);
    endIndexYear = mdy.find(' ');

    m = mdy.substr(startIndex, endIndex - startIndex);
    d = mdy.substr(startIndexDay, (endIndexDay - startIndexDay) - 2);
    y = mdy.substr(startIndexYear, endIndexYear - startIndexYear);
}
void convertDigits(string &mdy, string &d, string &y, int &dInt, int &yInt){
    dInt = stoi(d);
    yInt = stoi(y);
}
void convertMonths(string &mdy, string &m, int &mInt, int &dInt, int &yInt){

    if (m == "january" || m == "January")
        mInt = 1;
    else if (m == "febraury" || m == "February")
        mInt = 2;
    else if (m == "march" || m == "March")
        mInt = 3;
    else if (m == "april" || m == "April")
        mInt = 4;
    else if (m == "may" || m == "May")
        mInt = 5;
    else if (m == "june" || m == "June")
        mInt = 6;
    else if (m == "july" || m == "July")
        mInt = 7;
    else if (m == "august" || m == "August")
        mInt = 8;
    else if (m == "september" || m == "September")
        mInt = 9;
    else if (m == "october" || m == "October")
        mInt = 10;
    else if (m == "november" || m == "November")
        mInt = 11;
    else if (m == "december" || m == "December")
        mInt = 12;
    else
        cerr<<"Error...Please check your spelling and the date format and try again.";

    cout<<endl<<"Another Date Format is: "<<dInt<<"/"<<mInt<<"/"<<yInt<<endl;   //Outputting the new date.
}
int main() {
    string date, month, day, year;
    int monthInt, dayInt, yearInt;
    char tryAgain = 'Y';

    while (tryAgain =='Y' || tryAgain == 'y'){

        getDate(date);
        extract(date, month, day, year);
        convertDigits(date, day, year, dayInt, yearInt);
        convertMonths(date, month, monthInt, dayInt, yearInt);

        cout<<"Try Again? Type Y or N: ";
        cin>>tryAgain;
    }
    return 0;
}
#包括
#包括
使用名称空间std;
作废getDate(字符串和mdy){

cout如果在
cin>
之后使用
getline
,则需要将换行符从中间的缓冲区中清除

向getDate()函数添加
cin.ignore()

void getDate(字符串&mdy){
cin.ignore();

cout有几个错误会阻止发布的代码按预期工作

如前所述,
std::cin
在输入流中保留任何换行符,因此对
std::getline
的后续调用将导致一个空字符串。您只需跳过每个只包含换行符的输入行即可

while ( getline(cin, mdy)  &&  mdy.empty() )
    ;
另一个问题是
extract
函数,其中有多个对的调用,但没有指定起始位置(该位置总是隐式设置为0):

当找不到搜索的字符时(这与传递空字符串的预期结果差不多),
find
返回,定义为

static const size_type npos = -1;
其中,
size\u type
是一种无符号类型。因此,当将空字符串传递给此函数时,会发生这种情况

startIndex = 0;
endIndex = mdy.find(' ');                        // --> -1
startIndexDay = ((endIndex - startIndex) +1);    // -->  0
endIndexDay = mdy.find(',');                     // --> -1  
startIndexYear = (endIndexDay +2);               // -->  1
endIndexYear = mdy.find(' ');                    // --> -1 

m = mdy.substr(startIndex, endIndex - startIndex);                 // --> ""
d = mdy.substr(startIndexDay, (endIndexDay - startIndexDay) - 2);  // --> ""
y = mdy.substr(startIndexYear, endIndexYear - startIndexYear);
//             ^^^^^^^^^^^^^^ mdy[1] is out of bounds, so it throws an exception
使用它可以更容易地提取这些代币并形成转换日期

#include <string>
#include <sstream>
#include <iomanip>

std::string convert_date(std::string const& mdy)
{
    std::string s_month;
    std::string s_day;
    int year;

    std::istringstream iss{mdy};

    iss >> s_month >> s_day >> year;
    if ( !iss )
    {
        // Wrong format, deal with the error as you prefer
        return "";
    }

    // Convert a string to the corresponding month number. To be implemented.
    // E.g. "Jannuary" -> 1
    int month = get_month_num(s_month);

    // It extracts only the numbers, ignoring trailing "st," or "th,"
    int day = std::stoi(s_day);

    // Here you could validate those numbers, e.g. rejecting a day greater than 31

    // Now compose the converted string "MM/DD/YYYY"
    std::ostringstream oss;
    oss << std::setfill('0') << std::setw(2) << month << '/'
        << std::setfill('0') << std::setw(2) << day << '/' << year;
    return oss.str();
}
#包括
#包括
#包括
std::string convert_date(std::string const&mdy)
{
std::字符串s_月;
std::字符串s_日;
国际年;
std::istringstream iss{mdy};
国际空间站>>月>>日>>年;
如果(!iss)
{
//格式错误,请按您的喜好处理错误
返回“”;
}
//将字符串转换为要实现的相应月号。
//例如,“一月”->1
int MOUNT=获取月数(s月);
//它只提取数字,忽略尾随的“st”或“th”
int day=std::stoi(s_日);
//在这里,您可以验证这些数字,例如拒绝超过31天的天数
//现在编写转换后的字符串“MM/DD/YYYY”
std::ostringstream oss;

oss为我工作。这是什么编译器?我使用的不是编译器,它是IDE…我假设你使用的是gcc/g++…这种情况下,问题一定在别处。是的,对不起,我使用的编译器是gcc或g++
std::out_of_range:basic_string
意味着,你正在访问
std::string
后面的字符。不确定它发生在哪里,但是:混合流输入
>
std::getline()
需要一些额外的注意。因此,我将对此进行调试和检查。谢谢。这在我使用cin时起到了作用。如果他们想重试,请在的行下的while循环中忽略(100),\n')。
#include <string>
#include <sstream>
#include <iomanip>

std::string convert_date(std::string const& mdy)
{
    std::string s_month;
    std::string s_day;
    int year;

    std::istringstream iss{mdy};

    iss >> s_month >> s_day >> year;
    if ( !iss )
    {
        // Wrong format, deal with the error as you prefer
        return "";
    }

    // Convert a string to the corresponding month number. To be implemented.
    // E.g. "Jannuary" -> 1
    int month = get_month_num(s_month);

    // It extracts only the numbers, ignoring trailing "st," or "th,"
    int day = std::stoi(s_day);

    // Here you could validate those numbers, e.g. rejecting a day greater than 31

    // Now compose the converted string "MM/DD/YYYY"
    std::ostringstream oss;
    oss << std::setfill('0') << std::setw(2) << month << '/'
        << std::setfill('0') << std::setw(2) << day << '/' << year;
    return oss.str();
}