1

我正在做一些编程练习,其中一个涉及从头开始实现一个日期类对象。

总的来说,它的类设计和实现部分是小菜一碟,但在日期输入和复制到私有数据成员时出现了问题。

日期输入法必须是MM/DD/YY格式,类数据成员必须是三种int类型(月、日、年)才能进行练习。

所以我的实现包括使用 cin 将输入输入到字符数组,然后将这些数组元素转换为类数据成员的 int 数据类型。

最初我想分别取每个数字列,将 10 列乘以 10 并添加 one 列以获得 int 但这并没有成功,因为您仍在对字符数据类型进行数学操作数。

我确实找到了解决方案,但它是一个杂项,我觉得必须有一个更好、更有说服力的方法来做到这一点。

另外作为旁注,我想知道是否有人可以告诉我为什么当我将 char 数组大小从 9 减少到 8 时在运行时出现堆栈溢出错误。我认为 char 数组只需要 \0 字符的大小 + 1 . 根据我的计算,我应该对 temp[8] 总共 9 个位置(2 天 2 个月 2 年和 2 / 和 1 \0 =9)很好,我确定我在这里遗漏了一些东西。无论如何,如果这很重要,我正在为我的编译器使用 VC++ 2008。

#include <iostream>
#include <iomanip>

using std::cout;
using std::endl;
using std::cin;

//---------------------------------------------------------------------------
class date {
private:
    int day, month, year;
public:
    date() : day(0), month(0), year(0) {};
    void getDate(char*);
    void showDate();
    int chartoint(char);
};

int date::chartoint(char a) {
    switch(a) {
        case '0': return 0;
        case '1': return 1;
        case '2': return 2;
        case '3': return 3;
        case '4': return 4;
        case '5': return 5;
        case '6': return 6;
        case '7': return 7;
        case '8': return 8;
        case '9': return 9;
    };
};

void date::getDate(char dArray[]) {

    day=(chartoint(dArray[3])*10+chartoint(dArray[4])); 
    month=(chartoint(dArray[0])*10+chartoint(dArray[1])); 
    year=(chartoint(dArray[6])*10+chartoint(dArray[7])); 


};

void date::showDate()
{
    cout << std::setiosflags(std::ios::fixed | std::ios::showpoint);
    (month<10) ? cout << std::setw(2) << std::setfill('0') << month : cout << month;
    cout << "/";
    (day<10) ? cout << std::setw(2) << std::setfill('0') << day : cout << day;
    cout << "/";
    (year<10) ? cout << std::setw(2) << std::setfill('0') << year : cout << year;
    cout << endl;


};
//---------------------------------------------------------------------------
int main()
{
    date a;
    char temp[9];

    cout << "Enter Date (mm/dd/yy): ";
    cin >> temp;

    a.getDate(temp);

    a.showDate();
    return 0;
}
4

3 回答 3

4

看来,最简单的方法是读入int变量并跳过分隔/字符。也就是说,您将定义一个输入运算符:

std::istream& operator>> (std::istream& in, date& value) {
    // read the value for a date
    return in;
}

如果你将一个字符串读入一个char数组,你需要确保你不会尝试存储比char数组中的空间更多的字符。此外,您应该始终验证读取是否成功:

if (std::cin >> std::setw(sizeof(temp) >> temp) {
    // process the read characters
}

请注意:不要尝试sizeof()像上面那样使用指向char数组的指针:它会确定指针的大小,而不是指向数组的大小。

顺便说一句,您正确计算出存储日期及其终止空字符需要 9char秒。为什么你认为它们会适合 8 chars 的数组?

于 2012-10-05T19:36:54.520 回答
3

极其简单的解决方案(尽管是 C 风格)是使用函数int直接读取:char*sscanf()

void date::getDate(const char *sDate) // const = "getDate will not change sDate"
{
    sscanf(sDate, "%d/%d/%d", &month, &day, &year);
};

C++ 解决方案将使用std::string代替char*,因此 main 的主体应如下所示:

date a;
std::string temp;

cout << "Enter Date (mm/dd/yy): ";
cin >> temp;

a.getDate(temp);
a.showDate();

那么你的getDate方法可以引用std::string对象,换句话说,它不会改变const std::string&。要从您那里读取值,则std::string可以构造std::istringstream对象:

#include <sstream>
...
void date::getDate(const std::string& sDate)
{
    std::istringstream ssDate(sDate);
    ssDate >> month;
    ssDate.ignore();
    ssDate >> day;
    ssDate.ignore();
    ssDate >> year;
};

另请注意,该方法chartoint是多余的,showDate()可能很简单,如下所示:

void date::showDate()
{
    cout << std::setw(2) << std::setfill('0') << month << '/';
    cout << std::setw(2) << std::setfill('0') << day << '/';
    cout << std::setw(2) << std::setfill('0') << year << endl;
};
于 2012-10-05T19:46:48.367 回答
1

这是使用 std::stringstream 的解决方案:

#include <iostream>
#include <iomanip>
#include <sstream>

using std::cout;
using std::endl;
using std::cin;
using std::stringstream;

//---------------------------------------------------------------------------                                                                                                                                                                                                                                                                                             
class date {
private:
  int day, month, year;
public:
  date() : day(0), month(0), year(0) {};
  void getDate(char*);
  void showDate();
};

void date::getDate(char dArray[]) {
  std::stringstream ss(dArray);
  ss>>month;
  ss.ignore();
  ss>>day;
  ss.ignore();
  ss>>year;
};

void date::showDate()
{
  cout << std::setiosflags(std::ios::fixed | std::ios::showpoint);
  (month<10) ? cout << std::setw(2) << std::setfill('0') << month : cout << month;
  cout << "/";
  (day<10) ? cout << std::setw(2) << std::setfill('0') << day : cout << day;
  cout << "/";
  (year<10) ? cout << std::setw(2) << std::setfill('0') << year : cout << year;
  cout << endl;


};
//---------------------------------------------------------------------------                                                                                                                                                                                                                                                                                             
int main()
{
  date a;
  char temp[9];

  cout << "Enter Date (mm/dd/yy): ";
  cin >> temp;

  a.getDate(temp);

  a.showDate();
  return 0;
}

还有一种更短的方法来编写你的 chartoint 函数,它利用了 ASCII 中的 0-9 都是连续布局的事实:

int date::chartoint(char a) {
  return a-'0';
};

另请注意,当您声明一个数组时,[] 内的值实际上是 SIZE,而不是最后一个合法索引。因此 temp[8] 的数组声明在索引 0-7 中仅包含 8 个值。

于 2012-10-05T19:44:05.073 回答