IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Thinking in C++ - Volume 2


précédentsommaire

5. B: Etc

This appendix contains files that are required to build the examples in Volume 2.

 
Sélectionnez
//: :require.h
// Test for error conditions in programs.
#ifndef REQUIRE_H
#define REQUIRE_H
#include <cstdio>
#include <cstdlib>
#include <fstream>
 
inline void require(bool requirement,
  const char* msg = "Requirement failed") {
  // Local "using namespace std" for old
compilers:
  using namespace std;
  if(!requirement) {
    fputs(msg, stderr);
    fputs("\n", stderr);
    exit(EXIT_FAILURE);
  }
}
 
inline void requireArgs(int argc, int args,
  const char* msg = "Must use %d arguments")
{
  using namespace std;
  if(argc != args + 1) {
    fprintf(stderr, msg, args);
    fputs("\n", stderr);
    exit(EXIT_FAILURE);
  }
}
 
inline void requireMinArgs(int argc, int minArgs,
  const char* msg = "Must use at least %d
arguments") {
  using namespace std;
  if(argc < minArgs + 1) {
    fprintf(stderr, msg, minArgs);
    fputs("\n", stderr);
    exit(EXIT_FAILURE);
  }
}
 
inline void assure(std::ifstream& in,
  const char* filename = "") {
  using namespace std;
  if(!in) {
    fprintf(stderr, "Could not open file
%s\n", filename);
    exit(EXIT_FAILURE);
  }
}
 
inline void assure(std::ofstream& in,
  const char* filename = "") {
  using namespace std;
  if(!in) {
    fprintf(stderr, "Could not open file
%s\n", filename);
    exit(EXIT_FAILURE);
  }
}
 
inline void assure(std::fstream& in,
  const char* filename = "") {
  using namespace std;
  if(!in) {
    fprintf(stderr, "Could not open file
%s\n", filename);
    exit(EXIT_FAILURE);
  }
}
#endif // REQUIRE_H ///:~
 
Sélectionnez
//: C0B:Dummy.cpp
// To give the makefile at least
// one target for this directory.
int main() {} ///:~

The Date class files:

 
Sélectionnez
//: C02:Date.h
#ifndef DATE_H
#define DATE_H
#include <string>
#include <stdexcept>
#include <iosfwd>
 
class Date {
  int year, month, day;
  int compare(const Date&) const;
  static int daysInPrevMonth(int year, int mon);
public:
  // A class for date calculations
  struct Duration {
    int years, months, days;
    Duration(int y, int m, int d)
    : years(y), months(m) ,days(d) {}
  };
  // An exception class
  struct DateError : public std::logic_error {
    DateError(const std::string& msg =
"")
: std::logic_error(msg) {}
  };
  Date();
  Date(int, int, int) throw(DateError);
  Date(const std::string&) throw(DateError);
  int getYear() const;
  int getMonth() const;
  int getDay() const;
  std::string toString() const;
  friend Duration duration(const Date&, const
Date&);
  friend bool operator<(const Date&, const
Date&);
  friend bool operator<=(const Date&, const
Date&);
  friend bool operator>(const Date&, const
Date&);
  friend bool operator>=(const Date&, const
Date&);
  friend bool operator==(const Date&, const
Date&);
  friend bool operator!=(const Date&, const
Date&);
  friend std::ostream&
operator<<(std::ostream&,
                                  const Date&);
  friend std::istream&
operator>>(std::istream&, Date&);
};
#endif // DATE_H ///:~
 
Sélectionnez
//: C02:Date.cpp {O}
#include "Date.h"
#include <iostream>
#include <sstream>
#include <cstdlib>
#include <string>
#include <algorithm> // For swap()
#include <ctime>
#include <cassert>
#include <iomanip>
using namespace std;
 
namespace {
  const int daysInMonth[][13] = {
    { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
},
    { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
}
  };
  inline bool isleap(int y) {
    return y%4 == 0 && y0 != 0 || y@0 ==
0;
  }
}
 
Date::Date() {
  // Get current date
  time_t tval = time(0);
  struct tm *now = localtime(&tval);
  year = now->tm_year + 1900;
  month = now->tm_mon + 1;
  day = now->tm_mday;
}
 
Date::Date(int yr,int mon,int dy)
throw(Date::DateError) {
  if(!(1 <= mon && mon <= 12))
    throw DateError("Bad month in Date
ctor");
  if(!(1 <= dy && dy <=
daysInMonth[isleap(year)][mon]))
    throw DateError("Bad day in Date ctor");
  year = yr;
  month = mon;
  day = dy;
}
 
Date::Date(const std::string& s)
throw(Date::DateError) {
  // Assume YYYYMMDD format
  if(!(s.size() == 8))
    throw DateError("Bad string in Date
ctor");
  for(int n = 8; --n >= 0;)
    if(!isdigit(s[n]))
      throw DateError("Bad string in Date
ctor");
  string buf = s.substr(0, 4);
  year = atoi(buf.c_str());
  buf = s.substr(4, 2);
  month = atoi(buf.c_str());
  buf = s.substr(6, 2);
  day = atoi(buf.c_str());
  if(!(1 <= month && month <= 12))
    throw DateError("Bad month in Date
ctor");
if(!(1 <= day && day
<=
  daysInMonth[isleap(year)][month]))
    throw DateError("Bad day in Date ctor");
}
 
int Date::getYear() const { return year; }
 
int Date::getMonth() const { return month; }
 
int Date::getDay() const { return day; }
 
string Date::toString() const {
  ostringstream os;
  os.fill('0');
  os << setw(4) << year
     << setw(2) << month
     << setw(2) << day;
  return os.str();
}
 
int Date::compare(const Date& d2) const {
  int result = year - d2.year;
  if(result == 0) {
    result = month - d2.month;
    if(result == 0)
      result = day - d2.day;
  }
  return result;
}
 
int Date::daysInPrevMonth(int year, int month) {
  if(month == 1) {
    --year;
    month = 12;
  }
  else
    --month;
  return daysInMonth[isleap(year)][month];
}
 
bool operator<(const Date& d1, const Date&
d2) {
  return d1.compare(d2) < 0;
}
bool operator<=(const Date& d1, const Date&
d2) {
  return d1 < d2 || d1 == d2;
}
bool operator>(const Date& d1, const Date&
d2) {
  return !(d1 < d2) && !(d1 == d2);
}
bool operator>=(const Date& d1, const Date&
d2) {
  return !(d1 < d2);
}
bool operator==(const Date& d1, const Date& d2)
{
  return d1.compare(d2) == 0;
}
bool operator!=(const Date& d1, const Date& d2)
{
  return !(d1 == d2);
}
 
Date::Duration
duration(const Date& date1, const Date& date2)
{
  int y1 = date1.year;
  int y2 = date2.year;
  int m1 = date1.month;
  int m2 = date2.month;
  int d1 = date1.day;
  int d2 = date2.day;
 
  // Compute the compare
  int order = date1.compare(date2);
  if(order == 0)
    return Date::Duration(0,0,0);
  else if(order > 0) {
    // Make date1 precede date2 locally
    using std::swap;
    swap(y1, y2);
    swap(m1, m2);
    swap(d1, d2);
  }
 
  int years = y2 - y1;
  int months = m2 - m1;
  int days = d2 - d1;
  assert(years > 0 ||
     years == 0 && months > 0 ||
     years == 0 && months == 0 && days
> 0);
 
  // Do the obvious corrections (must adjust days
  // before months!) - This is a loop in case the
  // previous month is February, and days < -28.
  int lastMonth = m2;
  int lastYear = y2;
  while(days < 0) {
    // Borrow from month
    assert(months > 0);
    days += Date::daysInPrevMonth(
      lastYear, lastMonth--);
    --months;
  }
 
  if(months < 0) {
    // Borrow from year
    assert(years > 0);
    months += 12;
    --years;
  }
  return Date::Duration(years, months, days);
}
 
ostream& operator<<(ostream& os, const
Date& d) {
  char fillc = os.fill('0');
  os << setw(2) << d.getMonth() <<-<< setw(2) << d.getDay() <<-<< setw(4) << setfill(fillc) <<
d.getYear();
  return os;
}
 
istream& operator>>(istream& is,
Date& d) {
  is >> d.month;
  char dash;
  is >> dash;
  if(dash != '-')
    is.setstate(ios::failbit);
  is >> d.day;
  is >> dash;
  if(dash != '-')
    is.setstate(ios::failbit);
  is >> d.year;
  return is;
} ///:~

The file test.txt used in Chapter 6:

 
Sélectionnez
//: C06:Test.txt
f a f d A  G f d F a A F h f A d f f a a
///:~

précédentsommaire

Ce document est issu de http://www.developpez.com et reste la propriété exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise à l'obtention préalable de l'autorisation de l'auteur.