#c #c 11
#c #c 11
Вопрос:
У меня ошибка в моем коде. Как я могу с этим справиться?
Не удается успешно скомпилировать, но я не могу найти ничего неправильного.
Day.h
#pragma once
#include<iostream>
#include<string>
typedef unsigned ud;
using std::string;
class Day
{
public:
Day() = default;
Day(string a) {
decltype(a.size()) pos;
if (a.find("Jan") != string::npos)
month = 1;
else if (a.find("Feb") != string::npos)
month = 2;
else if (a.find("Mar") != string::npos)
month = 3;
else if (a.find("Apr") != string::npos)
month = 4;
else if (a.find("May") != string::npos)
month = 5;
else if (a.find("Jun") != string::npos)
month = 6;
else if (a.find("Jul") != string::npos)
month = 7;
else if (a.find("Aug") != string::npos)
month = 8;
else if (a.find("Sep") != string::npos)
month = 9;
else if (a.find("Oct") != string::npos)
month = 10;
else if (a.find("Nov") != string::npos)
month = 11;
else if (a.find("Dec") != string::npos)
month = 12;
else {
pos = a.find_first_not_of("123456789");
month = stoi(a.substr(0, pos));
}
pos ;
auto now = a.find_first_not_of("123456789", pos);
day = stoi(a.substr(pos, now - pos));
pos = now 1;
year = stoi(a.substr(pos, a.size() - pos));
}
ud get_year() {
return year;
}
ud get_month() {
return month;
}
ud get_day() {
return day;
}
std::ostreamamp; print(std::ostreamamp; os) {
os << year << ' ' << month << ' ' << day;
return os;
}
private:
ud year;
ud month;
ud day;
bool iszm(char x) {
return (x >= 'A'amp;amp;x <= 'z');
}
};
main.cpp
#include"pch.h"
#include<iostream>
#include<forward_list>
#include<deque>
#include<vector>
#include<string>
#include<list>
#include<array>
#include<cstdlib>
#include"Day.h"
using namespace std;
int main()
{
Day tmp("March 27,2019");
tmp.print(cout);
return 0;
}
Комментарии:
1. Сообщение об ошибке довольно четкое. Вы используете
pos
без предварительной инициализации значения2. Это не решает вопрос, но
x >= 'A'amp;amp;x <= 'z'
выглядит странно. Если предполагается, что код распознает букву, используйтеstd::isalpha
. Если ваша система использует ASCII (что почти наверняка так и есть), найдите значение символов ASCII, чтобы увидеть, что на самом деле делает исходное выражение. Если ваша система использует EBCDIC (постоянный дочерний элемент проблемы),'z'
меньше'A'
, и это выражение всегда будет false.3. @Pete Beckeя понимаю, большое вам спасибо.
Ответ №1:
...
else {
pos = a.find_first_not_of("123456789");
month = stoi(a.substr(0, pos));
}
pos ; //<<<<<<<<<<<<<<
auto now = a.find_first_not_of("123456789", pos);
day = stoi(a.substr(pos, now - pos));
...
Как только вы доберетесь до строки, pos ;
она pos
будет иметь известное значение, только если было выполнено else
предложение выше, содержащее pos = a.find_first_not_of("123456789");
, и это происходит, только если a
отличается от "Jan"
, "Feb"
и т.д.
Не забывайте, что локальные переменные не инициализируются некоторым значением по умолчанию, но их начальное содержимое не определено.
Не по теме: этот код действительно уродлив, и может возникнуть больше проблем.
Комментарии:
1. Спасибо за ваш совет, преимущества велики!
2. @Kdlyh это другой вопрос, но обычно, если у вас есть код с повторяющимся шаблоном
if
s с небольшим количеством изменений, обычно есть способ получше.3. Поймите, я собираюсь использовать map вместо duplicate if.
4. @Kdlyh да,
std::map
это одна из возможностей. Не забудьте сделать этоstatic
в противном случае карта будет заполняться при каждом вызове конструктора5. Хорошо, я понимаю. Вы мне очень помогли в моем самообучении!
Ответ №2:
decltype(a.size()) pos;
if (a.find("Jan") != string::npos)
month = 1;
// other else if statements removed
else {
pos = a.find_first_not_of("123456789");
month = stoi(a.substr(0, pos));
}
pos ;
В приведенном выше примере я удалил целую серию else if
инструкций.
pos
определена и неинициализирована.
If a.find("Jan") != string::npos
then pos
никогда не присваивается. Следующая операция pos
извлекает значение pos
для того, чтобы увеличить его. Поскольку pos
она неинициализирована, поведение не определено.
В вашем коде единственное место, где pos
присваивается значение в последовательности else if
s, находится в final else
. Любой другой путь в этом коде приводит к pos
неопределенному поведению, поскольку — как предупреждает ваш компилятор — pos
неинициализирован.
Способ устранить проблему заключается в том, чтобы гарантировать, что, независимо от того, как происходит поток выполнения, pos
инициализируется перед его увеличением.
Одним из простых способов убедиться в этом было бы изменить определение на
decltype(a.size()) pos = 0;
Правильно ли это для вашего кода или нет, зависит от того, что вы ожидаете, произойдет во всех случаях, отличных от окончательного else
.
Комментарии:
1. Спасибо, в то время я не был серьезен.
2. Ваш ответ очень подробный, но Jabberwocky ответил ранее, поэтому я принял его ответ, пожалуйста, поймите
Ответ №3:
Спасибо.Я решил проблему.
#pragma once
#include<iostream>
#include<string>
typedef unsigned ud;
using std::string;
class Day
{
public:
Day() = default;
Day(string a) {
decltype(a.size()) pos=0;
if (a.find("Jan") != string::npos)
month = 1;
else if (a.find("Feb") != string::npos)
month = 2;
else if (a.find("Mar") != string::npos)
month = 3;
else if (a.find("Apr") != string::npos)
month = 4;
else if (a.find("May") != string::npos)
month = 5;
else if (a.find("Jun") != string::npos)
month = 6;
else if (a.find("Jul") != string::npos)
month = 7;
else if (a.find("Aug") != string::npos)
month = 8;
else if (a.find("Sep") != string::npos)
month = 9;
else if (a.find("Oct") != string::npos)
month = 10;
else if (a.find("Nov") != string::npos)
month = 11;
else if (a.find("Dec") != string::npos)
month = 12;
else {
pos = a.find_first_not_of("123456789");
month = stoi(a.substr(0, pos));
}
pos = pos ? pos : a.find_first_not_of("QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm");
pos ;
auto now = a.find_first_not_of("123456789", pos);
day = stoi(a.substr(pos, now - pos));
pos = now 1;
year = stoi(a.substr(pos, a.size() - pos));
}
ud get_year() {
return year;
}
ud get_month() {
return month;
}
ud get_day() {
return day;
}
std::ostreamamp; print(std::ostreamamp; os) {
os << year << ' ' << month << ' ' << day;
return os;
}
private:
ud year;
ud month;
ud day;
};