2

学生が18歳以上かどうかを確認する必要がある宿題をしています。私の機能は次のとおりです。

bool Student::isOverEighteen() {
  int date[3]; // D/M/Y
  char *pdata;

  pdata = strtok(Anagrafica::birth, "/"); // Anagrafica is the base class

  for (short i = 0; pdata != NULL; i++) {
    data[i] = pdata;
    pdata = strtok(NULL, "/");
  }

  time_t t    = time(NULL);
  tm *locale  = localtime(&t);

  if (data[0] < locale->tm_mday &&
     (data[1] < locale->tm_mon + 1  || data[1] == locale->tm_mon + 1) &&
     (locale->tm_year + 1900 - data[3] > 18))
  {
    return true;
  } else {
    return false;
  }
}

ただし、生年月日を表示すると、日付と生徒の教室が表示されます。例:25/06 / 19944A(4Aは教室の名前です)

学生情報を登録するために使用する関数:

Student::Student() {
  std::cout << "Name: ";
  std::cin.getline(Anagrafica::name, 101);
  std::cout << "Surname: ";
  std::cin.getline(Anagrafica::surname, 101);
  std::cout << "Birth (XX/XX/XXXX): ";
  std::cin.getline(Anagrafica::birth, 11);
  std::cout << "Classroom: ";
  std::cin.getline(Anagrafica::classroom, 101);
}

それらを表示するための関数:

void Anagrafica::Show() {
  std::cout << "\nName:" << this->name;
  std::cout << "\nSurname:" << this->surname;
  std::cout << "\nBirth:" << this->birth;
  std::cout << "\nClassroom: " << this->classroom;
  std::cout << std::endl;
}

そしてそれらは宣言されます:

char name[100];
char surname[100];
char birth[10];
char classroom[100];

これを機能させるための解決策はありますか?

編集(Nik Bougalisの場合):

これが私が今使っているものです。文字列の問題は、c_strを使用していたために始まりました。c_str();の代わりに

bool Entry::IsOverEighteen() {
  int date[3];

  date[0] = std::atoi(this->birth.substr(0, 2).c_str());  // Day
  date[1] = std::atoi(this->birth.substr(4, 2).c_str());  // Month
  date[2] = std::atoi(this->birth.substr(6, 4).c_str());  // Year

  time_t t  = time(NULL);
  tm *local = localtime(&t);

  // Perche' sia maggiorenne occorre che:
  //  Il giorno attuale sia maggiore di quello di nascita
  //  Il mese attuale sia maggiore o uguale a quello di nascita
  //  L' anno attuale - l' anno di nascita sia maggiore o uguale 18
  if (local->tm_mday > date[0] && 
     (local->tm_mon + 1 > date[1] || local->tm_mon + 1 == date[1]) && 
     (local->tm_year + 1900 - date[2] > 18 || local->tm_year + 1900 - date[2] == 18))
  {
    return true;
  } else {
    return false;
  }
}
4

1 に答える 1

5

問題は、文字列25/06/1994 (つまり 10 バイト)char birth[10]とまったく同じ長さで、NULL ターミネータ用のスペースが残っていないため、文字列を出力するときに cout が読み取りを開始し、最後を超えて.birthbirthclassroom

また、実際のバッファーよりも1大きいcin.getlineバッファー サイズで一貫して呼び出すことにも注意してください。あなたは本質的に次のように言っています:「ここに10バイトのバッファがあります... 11バイトを読み込んでください!」それはあなたが本当に意味するものですか?getline

もちろん、std::string代わりにchar[]. なぜしなかったのですか?

さて、関係するisOverEighteen限り、関数は完全に壊れており、実際、ここに示したバージョンはコンパイルさえしません. 修正できるかどうか見てみましょう。

もちろん、私の最初の質問は、誕生日を文字列として受け入れるのではなく、直接3 つの整数として入力しないのはなぜですか? しかし、あなたがあなたの任務のためにできないとしましょう。代わりにこれを使用してみてください:

bool isOverEighteen(const string &s) 
{ // s is in the form DD/MM/YYYY - if it's not, things blow up.  
  int birthday[3], bidx = 0; 

  birthday[0] = 0;
  birthday[1] = 0;
  birthday[2] = 0;

  for(int i = 0; i != s.length(); i++)
  {
    if(s[i] == '/')
    {
      bidx++;
      continue;
    }

    birthday[bidx] = (birthday[bidx] * 10) + (s[i] - '0');
  }

  // now birthday[0] is the day of birth as an integer, 
  // birthday[1] is the month of birth as an integer and
  // birthday[2] is the year of birth as an integer. You 
  // can use them.

  ...
}

これを行うためのより洗練された方法があり、それはあまり「C++」ではありませんが、機能します。これは改善です。

于 2012-11-28T18:36:51.677 に答える