1

私はいくつかのプログラミング演習を実行していますが、1 つには、日付クラス オブジェクトを最初から実装することが含まれます。

全体として、クラスの設計と実装の部分は簡単でしたが、日付の入力とプライベート データ メンバーへのコピー中に問題が発生しました。

演習では、日付入力メソッドは MM/DD/YY の形式である必要があり、クラス データ メンバーは 3 つの int 型 (月、日、年) である必要があります。

したがって、私の実装では、cin を使用して入力を文字配列に取得し、それらの配列要素をクラス データ メンバーの int データ型に変換します。

最初は、各数値列を個別に取り、10 列に 10 を掛け、1 列を追加して int を取得することを考えましたが、文字データ型で数学オペランドをまだ実行しているため、うまくいきませんでした。

私は解決策を見つけましたが、それは面倒であり、これを行うためのより良い、より雄弁な方法が必要だと感じています。

また、補足として、char 配列のサイズを 9 から 8 に減らすと、実行時にスタック オーバーフロー エラーが発生する理由を誰かに教えてもらえないかと思っていました。 . 私の計算では、合計 9 スポット (2 日 2 月 2 年 および 2 / および 1 \0 =9) の temp[8] でうまくいくはずです。ここで何かが欠けていると確信しています。とにかく、それが重要な場合は、コンパイラに 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 の配列に収まると思いますcharか?

于 2012-10-05T19:36:54.520 に答える
3

非常に単純な解決策 (C スタイルですが) は、 function を使用して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*ため、メインの本体は次のようになります。

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;
}

また、ASCII の 0 ~ 9 がすべて連続して配置されているという事実を利用して、chartoint 関数を作成する短い方法は次のとおりです。

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

また、配列を宣言する場合、[] 内の値は実際には SIZE であり、最後の正当なインデックスではないことに注意してください。したがって、temp[8] の配列宣言は、インデックス 0 ~ 7 で 8 つの値のみを保持します。

于 2012-10-05T19:44:05.073 に答える