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/1994char birth[10] (即 10 个字节)完全一样长,没有为 NULL 终止符留出空间,因此当打印出字符串时, cout 开始读取,继续从结尾到.birthbirthclassroom

另请注意,您始终使用比实际缓冲区大一号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 回答