我正在制作一个小文件阅读和数据验证程序,作为我的TAFE(大专院校)课程的一部分,这包括检查和验证日期。
我决定最好使用单独的类,而不是将其集成到我的主驱动程序类中。
问题是我的测试程序运行后出现了分段错误(核心转储)。我可以说,在程序终止时发生错误,在调用析构函数后弹出。到目前为止,我没有找到这个错误的原因,并且希望一些开明的灵魂可能会向我展示我的方式的错误。
date.h
#ifndef DATE_H
#define DATE_H
#include <string>
using std::string;
#include <sstream>
using std::stringstream;
#include <cstdlib>
using std::exit;
#include <iostream>
using std::cout;
using std::endl;
class date {
public:
explicit date();
~date();
bool before(string dateIn1, string dateIn2);
int yearsBetween(string dateIn1, string dateIn2);
bool isValid(string dateIn);
bool getDate(int date[], string dateIn);
bool isLeapYear(int year);
private:
int days[];
};
#endif
date.cpp
#include "date.h"
date::date() {
days[0] = 31;
days[1] = 28;
days[2] = 31;
days[3] = 30;
days[4] = 31;
days[5] = 30;
days[6] = 31;
days[7] = 31;
days[8] = 30;
days[9] = 31;
days[10] = 30;
days[11] = 31;
}
bool date::before(string dateIn1, string dateIn2) {
int date1[3];
int date2[3];
getDate(date1, dateIn1);
getDate(date2, dateIn2);
if (date1[2] < date2[2]) {
return true;
} else if (date1[1] < date2[1]) {
return true;
} else if (date1[0] < date2[0]) {
return true;
}
return false;
}
date::~date() {
cout << "this is for testing only, plox delete\n";
}
int date::yearsBetween(string dateIn1, string dateIn2) {
int date1[3];
int date2[3];
getDate(date1, dateIn1);
getDate(date2, dateIn2);
int years = date2[2] - date1[2];
if (date1[1] > date2[1]) {
years--;
}
if ((date1[1] == date2[1]) && (date1[0] > date2[1])) {
years--;
}
return years;
}
bool date::isValid(string dateIn) {
int date[3];
if (getDate(date, dateIn)) {
if (date[1] <= 12) {
int extraDay = 0;
if (isLeapYear(date[2])) {
extraDay++;
}
if ((date[0] + extraDay) <= days[date[1] - 1]) {
return true;
}
}
} else {
return false;
}
}
bool date::getDate(int date[], string dateIn) {
string part1, part2, part3;
size_t whereIs, lastFound;
whereIs = dateIn.find("/");
part1 = dateIn.substr(0, whereIs);
lastFound = whereIs + 1;
whereIs = dateIn.find("/", lastFound);
part2 = dateIn.substr(lastFound, whereIs - lastFound);
lastFound = whereIs + 1;
part3 = dateIn.substr(lastFound, 4);
stringstream p1(part1);
stringstream p2(part2);
stringstream p3(part3);
if (p1 >> date[0]) {
if (p2>>date[1]) {
return (p3>>date[2]);
} else {
return false;
}
return false;
}
}
bool date::isLeapYear(int year) {
return ((year % 4) == 0);
}
最后,测试程序
#include <iostream>
using std::cout;
using std::endl;
#include "date.h"
int main() {
date d;
cout << "1/1/1988 before 3/5/1990 [" << d.before("1/1/1988", "3/5/1990")
<< "]\n1/1/1988 before 1/1/1970 [" << d.before("a/a/1988", "1/1/1970")
<<"]\n";
cout << "years between 1/1/1988 and 1/1/1998 ["
<< d.yearsBetween("1/1/1988", "1/1/1998") << "]\n";
cout << "is 1/1/1988 valid [" << d.isValid("1/1/1988") << "]\n"
<< "is 2/13/1988 valid [" << d.isValid("2/13/1988") << "]\n"
<< "is 32/12/1988 valid [" << d.isValid("32/12/1988") << "]\n";
cout << "blerg\n";
}
我留下了一些无关的cout语句,我一直在尝试找出错误。
我提前感谢你。
答案 0 :(得分:3)
变化:
private:
int days[];
为:
private:
int days[12];
答案 1 :(得分:3)
问题是您实际上从未初始化类型days
中的date
字段。这意味着当您在构造函数中设置值时,您正在访问未初始化的内存。
您需要以某种方式显式初始化days
值。最简单的解决方法是使用vector
作为类型,或者将数组的大小硬编码为12。
private:
int days[12];
或者
private:
std:vector<int> days;
...
date::date() {
days.push_back(31);
days.push_back(28);
...
}
答案 2 :(得分:2)
您没有说明您使用的是哪种编译器,但是如果我使用带有-Wall
和-pedantic
标志的g ++编译此代码:
struct S {
int a[];
};
int main() {
S s;
}
我收到警告信息:
warning: ISO C++ forbids zero-size array 'a'
道德观点是你应该总是使用尽可能多的编译器警告进行编译 - 它可以节省大量时间并产生更正确的代码。
答案 3 :(得分:1)
int days[];
这是非标准扩展名。您必须指定数组的大小,例如:
static const MonthCount = 12;
int days[MonthCount];
实际上要使用一个数组。否则你有一个“零大小的数组”(不标准!)。每次使用当前数组的任何元素时,你的程序都会在内存上进行操控。
答案 4 :(得分:1)
我同意此问题的先前答案,但我会补充其正确性的理由:
每当您尝试访问不允许访问的内存时,都会导致分段错误。
http://en.wikipedia.org/wiki/Segmentation_fault
您不能通过“[11]”天访问“days [0]”,因为计算机没有给出“days []”变量,您声明了足够的内存来容纳任何元素,因此当您尝试访问所述元素,它引发了一个段落错误。
使用“new”运算符声明的任何 not 变量都放在“堆栈”上,这是计算机已分开供程序使用的连续内存块。为了使存储在堆栈中的所有内容保持连续,计算机将只提供您在请求时使用所需的内存量,因此,如果您请求创建int,例如,它只会给您足够的用于存储单个int的内存。
当你写行int days [];计算机试图评估它需要多少内存,将其评估为空数组,并为您提供足够的内存来存储所述空数组。因为计算机没有给你的数组提供超出空数组所需的额外空间,所以它知道你试图在该数组中访问的内存没有分配给它,因此它抛出了一个分段错误并崩溃了。
如果你还没有在计算机科学课上学过“堆栈”和“堆”,那么对不起,如果这有点压倒性的,但我可能会过于复杂化,我想你很快就会这样。