获取函数 returns 无效值
get function returns invalid value
我正在为一个不能使用字符串的学校项目编写代码。
我在获取 hourlyPay 的值时遇到问题。
该程序的输出:
5 克里斯汀·金 4.94066e-324
虽然,该文件包含以下内容:
5 克里斯汀·金 30.00
#include <iostream>
#include <iomanip>
#include <fstream>
#include <cstring>
using namespace std;
//Class decleration
class Employee
{
private:
int id; //Employee ID.
char name[21]; //Employee name.
double hourlyPay; //Pay per hour.
public:
Employee(int initId=0, char [] =0, double initHourlyPay=0.0); //Constructor.
bool set(int newId, char [], double newHourlyPay);
int getId() { return id; }
const char * getName() { return name;}
double getHourlyPay() { return hourlyPay;}
};
Employee::Employee( int initId, char initName[], double initHourlyPay)
{
bool status = set( initId, initName, initHourlyPay);
if ( !status )
{
id = 0;
strcpy(name, "");
hourlyPay = 0.0;
}
}
bool Employee::set( int newId, char newName[], double newHourlyPay)
{
bool status = false;
if ( newId > 0)
{
status = true;
id = newId;
strcpy(name, newName);
hourlyPay = newHourlyPay;
}
return status;
}
const int MAX_SIZE = 100;
int main()
{
int id; //Employee ID.
char newName[21];
double hourlyPay; //Pay per hour.
Employee list[15]; //Array to store
ifstream masterFile; //Opens master file.
masterFile.open("master10.txt");
int count = 0;
if (masterFile)
{
for (count; count < 2; count++)
{
masterFile >> id;
masterFile.ignore();
masterFile.getline(newName, 21);
masterFile >> hourlyPay;
list[count].set(id, newName, hourlyPay);
}
}
masterFile.close(); //Close master file.
cout << list[0].getId() << " " << list[0].getName() << " " << list[0].getHourlyPay();
}
原始文件包含更多行,但我缩小了范围以找出我的错误。
我做错了什么?
在行中包含一个带有空白 space 的名称不是一个好主意,如果你坚持这样做,我想我们可以阅读该行并将名称和 hourlyPlay 分开。更好的方法是名称中不包含空格space,而是使用_
这样的字符,阅读后将字符替换为空格space,就可以简单地使用>>
读取每个字段
稍微修改一下,支持多行阅读打印,查看来源:
#include <iostream>
#include <iomanip>
#include <fstream>
#include <cstring>
#include <vector>
using namespace std;
//Class decleration
class Employee
{
private:
int id; //Employee ID.
char name[21]; //Employee name.
double hourlyPay; //Pay per hour.
public:
Employee(int initId = 0, const char* = 0, double initHourlyPay = 0.0); //Constructor.
bool set(int newId, const char*, double newHourlyPay);
int getId() { return id; }
const char * getName() { return name; }
double getHourlyPay() { return hourlyPay; }
};
Employee::Employee(int initId, const char* initName, double initHourlyPay)
{
bool status = set(initId, initName, initHourlyPay);
if (!status)
{
id = 0;
strcpy(name, "");
hourlyPay = 0.0;
}
}
bool Employee::set(int newId, const char* newName, double newHourlyPay)
{
bool status = false;
if (newId > 0)
{
status = true;
id = newId;
strcpy(name, newName);
hourlyPay = newHourlyPay;
}
return status;
}
int main()
{
int id; //Employee ID.
double hourlyPay; //Pay per hour.
vector<Employee> list; //Array to store
ifstream masterFile; //Opens master file.
char line[256];
masterFile.open("master10.txt");
if (masterFile)
{
while (!masterFile.eof())
{
masterFile >> id;
masterFile.getline(line, sizeof(line));
char* last_word = strrchr(line, ' ');
line[last_word - line] = 0;
hourlyPay = atof(last_word + 1);
list.push_back(Employee(id, line, hourlyPay));
}
}
//Close master file.
masterFile.close();
for (size_t i = 0; i < list.size(); ++i)
cout << list[i].getId() << " " << list[i].getName() << " " << list[i].getHourlyPay() << endl;
}
文件中的数据未正确输入代码中的变量。这是一个不言自明的解决方案。
for (count; count < 1; count++)
{
char secondname[11];
masterFile >> id;
masterFile.ignore();
masterFile >> newName;
masterFile >> secondname;
masterFile >> hourlyPay;
strcat(newName, " ");
strcat(newName, secondname);
list[count].set(id, newName, hourlyPay);
}
我想通了。
#include <iostream>
#include <iomanip>
#include <fstream>
#include <cstring>
using namespace std;
//Class decleration
class Employee
{
private:
int id; //Employee ID.
char name[21]; //Employee name.
double hourlyPay; //Pay per hour.
public:
Employee(int initId=0, char [] =0, double initHourlyPay=0.0); //Constructor.
bool set(int newId, char [], double newHourlyPay);
int getId() { return id; }
const char * getName() { return name;}
double getHourlyPay() { return hourlyPay;}
};
Employee::Employee( int initId, char initName[], double initHourlyPay)
{
bool status = set( initId, initName, initHourlyPay);
if ( !status )
{
id = 0;
strcpy(name, "");
hourlyPay = 0.0;
}
}
bool Employee::set( int newId, char newName[], double newHourlyPay)
{
bool status = false;
if ( newId > 0)
{
status = true;
id = newId;
strcpy(name, newName);
hourlyPay = newHourlyPay;
}
return status;
}
const int MAX_SIZE = 100;
int main()
{
int id; //Employee ID.
char newName[21];
double hourlyPay; //Pay per hour.
Employee list[15]; //Array to store
ifstream masterFile; //Opens master file.
masterFile.open("master10.txt");
int count = 0;
if (masterFile)
{
for (count; count < 2; count++)
{
masterFile >> id;
masterFile.ignore();
masterFile.get(newName, 21);
masterFile >> hourlyPay;
list[count].set(id, newName, hourlyPay);
}
}
masterFile.close(); //Close master file.
cout << list[0].getId() << " " << list[0].getName() << " " << list[0].getHourlyPay();
}
我只把getline改成了get,现在可以在一行中间读取,限制为20个字符。
感谢大家的关注和帮助。
所以..你真的想用一个普通的旧数组 Employee
和普通的旧字符数组和 cstring
?
这样做绝对没有错——它肯定会让您欣赏使用 string
和 vector
的便利。但是,就是说,通过每行数据遍历一个指针(或几个指针)以解析每行数据中的 id, name & hourlyPay
,可以获得大量有价值的学习。
整个解析过程的美中不足是不知道name
中可能包含多少spaces
(可能有none,一个,两个, 三, ...)。虽然,事情并不像看起来那么可怕。你知道你有一个开始数据行的 int
和一个结束的 double
- int
之后和 double
之前的空白之间的所有内容都是你的 name
.
这里的关键实际上是将每一行数据作为cstring
读取到缓冲区(字符数组)中。然后,您可以使用标准工具 strtol
读取 id
并将指针前进到 id
中最后一个数字的 1-过去。然后您可以简单地逐个字符地向前迭代检查 if (isspace(*p))
并继续前进直到找到非空白字符(或者您点击 nul-terminating字符在末尾)。一旦你找到你的非空白字符——你有一个指向 name
.
开头的指针
现在您必须在另一端工作并备份,直到找到hourlyPay
之前的space
。没那么难。您将需要 strlen (buf)
,但至少使用 masterFile.getline(..)
时,您无需通过用 nul-terminating[ 覆盖来从缓冲区末尾修剪 '\n'
=102=]字符。只需将结束指针设置为 buf + len - 1
,您就位于 hourlyPay
的最后一位。然后以类似的方式,备份 while (ep > sp && !isspace (*p))
只是一个问题(你知道你的终点指针是否到达位于 name
开头的起点指针,解析失败)
现在记住,这里是 hourlyPay
开头 之前的 1 个字符 ,所以当你使用 strtod
转换 hourlyPay
时],您必须记住使用 p + 1
作为转换 hourlyPay
的 cstring 段的开始。与任何 strtoX
转换一样,您有两个主要测试(1)转换后起始指针不等于 endptr
参数,表明数字实际上已转换为数字,以及(2) errno
未在转换期间设置 -- 表示实际转换失败。 (并且当转换为比转换更小的类型时——例如使用 strtol
转换为 int
—— 在分配给你的值之前,你必须检查转换的值是否在 int
的范围内.
现在您有了 id
和 hourlyPay
-- 剩下的就是 从 hourlyPay
开始备份 到name
结束。您以类似的方式检查 isspace()
直到它不再为真,并且指向 name
末尾的指针仍然大于指向 name
开头的指针。现在您可以使用 strncpy
通过复制 p - sp + 1
个字符将 name
复制到 newName
的变量中(记住您正坐在最后一个带有 p
的字符上,所以您将需要添加 1
以获取名称中的所有字符。
把它放在一起并在下面提供内联注释,你可以做类似下面的事情(注意你原来的 class
和成员函数保持不变——只有 id, name & hourlyPay
的解析main()
受到了显着影响)一如既往——关键是 验证每个步骤 —— 这样你就可以对你正在处理的数据充满信心。
#include <iostream>
#include <iomanip>
#include <fstream>
#include <cstring>
#include <cctype>
#include <limits>
#define MAXLIST 16 /* if you need constants, define one (or more) */
#define MAXNM 64
#define MAXBUF 1024
#define FNAME "dat/master10.txt"
using namespace std;
//Class decleration
class Employee
{
private:
int id; //Employee ID.
char name[MAXNM]; //Employee name.
double hourlyPay; //Pay per hour.
public:
Employee (int initId=0, char [] =0, double initHourlyPay=0.0);
bool set (int newId, char [], double newHourlyPay);
int getId() { return id; }
const char *getName() { return name;}
double getHourlyPay() { return hourlyPay;}
};
Employee::Employee (int initId, char initName[], double initHourlyPay)
{
bool status = set(initId, initName, initHourlyPay);
if (!status)
{
id = 0;
strcpy(name, "");
hourlyPay = 0.0;
}
}
bool Employee::set (int newId, char newName[], double newHourlyPay)
{
bool status = false;
if (newId > 0) {
status = true;
id = newId;
strcpy(name, newName);
hourlyPay = newHourlyPay;
}
return status;
}
int main (void) {
int id, //Employee ID.
count = 0;
long tmp; /* tmp for strtol conversion */
char newName[MAXNM] = "",
buf[MAXBUF] = ""; /* line buffer */
double hourlyPay; //Pay per hour.
Employee list[MAXLIST]; //Array to store
ifstream masterFile (FNAME); //Opens master file.
if (!masterFile.is_open()) { /* validate file open for reading */
cerr << "error: file open failed '" << FNAME << "'\n";
return 1;
}
/* read each line in masterFile into buf */
while (count < MAXLIST && masterFile.getline (buf, sizeof buf))
{
size_t len = strlen (buf); /* get length */
char *sp = buf, /* start pointer */
*p = buf + len - 1, /* working pointer */
*ep = NULL; /* end pointer for strtod conversion */
/* parse and convert id, leaving sp 1-past last digit */
errno = 0; /* zero errno before strtol conversion */
tmp = strtol (buf, &sp, 0); /* store conversion in tmp */
if (buf == sp) { /* validate characters were converted */
cerr << "error: no digits converted in id.\n";
return 1;
}
if (errno != 0) { /* validation errno not set */
cerr << "error: failed converstion for id.\n";
return 1;
}
/* validate tmp within range of integer */
if (tmp < numeric_limits<int>::min() ||
numeric_limits<int>::max() < tmp) {
cerr << "error: id not within integer range.\n";
return 1;
}
id = (int)tmp; /* assign tmp to id */
/* advance sp to 1st char in name */
while (*sp && isspace (*sp))
sp++;
/* parse hourlyPay */
/* work backward with p until space before hourlyPay found
* always validate p > sp so you don't back up beyond the start of
* name (or the beginning of buf).
*/
while (p > sp && !isspace (*p))
p--;
if (p > sp && !isdigit(*(p + 1))) { /* validate next char is digit */
cerr << "error: failed to parse hourlyPay.\n";
return 1;
}
errno = 0; /* zero errno before strtol conversion */
hourlyPay = strtod (p+1, &ep); /* convert hourlyPay to double */
if (p + 1 == ep) { /* validate characters were converted */
cerr << "error: no digits converted in hourlyPay.\n";
return 1;
}
if (errno != 0) { /* validation errno not set */
cerr << "error: failed converstion for hourlyPay.\n";
return 1;
}
/* continue working backwards to end of name */
while (p > sp && isspace (*p))
p--;
if (p <= sp) { /* validate chars between sp & p */
cerr << "error: failed to find end of name.\n";
return 1;
}
len = p - sp + 1; /* get number of chars in name */
if (len > MAXNM - 1) { /* validate it will fit in newName */
cerr << "error: name exceeds" << len << "characters.\n";
return 1;
}
strncpy (newName, sp, len); /* copy name to newName */
/* set values in list[count], on success, increment count */
if (list[count].set (id, newName, hourlyPay))
count++;
}
masterFile.close(); //Close master file.
/* outoput all employee id and hourlyPay information */
for (int i = 0; i < count; i++)
cout << list[i].getId() << " " << list[i].getName() <<
" " << list[i].getHourlyPay() << '\n';
}
(现在你明白为什么 string
和其他 C++ 工具让事情变得更好了吗?)
示例输入文件
您发布的唯一数据被用作输入文件,例如
$ cat dat/master10.txt
5 Christine Kim 30.00
例子Use/Output
$ ./bin/employeepay
5 Christine Kim 30
检查一下,如果您还有其他问题,请告诉我。
我正在为一个不能使用字符串的学校项目编写代码。
我在获取 hourlyPay 的值时遇到问题。
该程序的输出:
5 克里斯汀·金 4.94066e-324
虽然,该文件包含以下内容:
5 克里斯汀·金 30.00
#include <iostream>
#include <iomanip>
#include <fstream>
#include <cstring>
using namespace std;
//Class decleration
class Employee
{
private:
int id; //Employee ID.
char name[21]; //Employee name.
double hourlyPay; //Pay per hour.
public:
Employee(int initId=0, char [] =0, double initHourlyPay=0.0); //Constructor.
bool set(int newId, char [], double newHourlyPay);
int getId() { return id; }
const char * getName() { return name;}
double getHourlyPay() { return hourlyPay;}
};
Employee::Employee( int initId, char initName[], double initHourlyPay)
{
bool status = set( initId, initName, initHourlyPay);
if ( !status )
{
id = 0;
strcpy(name, "");
hourlyPay = 0.0;
}
}
bool Employee::set( int newId, char newName[], double newHourlyPay)
{
bool status = false;
if ( newId > 0)
{
status = true;
id = newId;
strcpy(name, newName);
hourlyPay = newHourlyPay;
}
return status;
}
const int MAX_SIZE = 100;
int main()
{
int id; //Employee ID.
char newName[21];
double hourlyPay; //Pay per hour.
Employee list[15]; //Array to store
ifstream masterFile; //Opens master file.
masterFile.open("master10.txt");
int count = 0;
if (masterFile)
{
for (count; count < 2; count++)
{
masterFile >> id;
masterFile.ignore();
masterFile.getline(newName, 21);
masterFile >> hourlyPay;
list[count].set(id, newName, hourlyPay);
}
}
masterFile.close(); //Close master file.
cout << list[0].getId() << " " << list[0].getName() << " " << list[0].getHourlyPay();
}
原始文件包含更多行,但我缩小了范围以找出我的错误。
我做错了什么?
在行中包含一个带有空白 space 的名称不是一个好主意,如果你坚持这样做,我想我们可以阅读该行并将名称和 hourlyPlay 分开。更好的方法是名称中不包含空格space,而是使用_
这样的字符,阅读后将字符替换为空格space,就可以简单地使用>>
读取每个字段
稍微修改一下,支持多行阅读打印,查看来源:
#include <iostream>
#include <iomanip>
#include <fstream>
#include <cstring>
#include <vector>
using namespace std;
//Class decleration
class Employee
{
private:
int id; //Employee ID.
char name[21]; //Employee name.
double hourlyPay; //Pay per hour.
public:
Employee(int initId = 0, const char* = 0, double initHourlyPay = 0.0); //Constructor.
bool set(int newId, const char*, double newHourlyPay);
int getId() { return id; }
const char * getName() { return name; }
double getHourlyPay() { return hourlyPay; }
};
Employee::Employee(int initId, const char* initName, double initHourlyPay)
{
bool status = set(initId, initName, initHourlyPay);
if (!status)
{
id = 0;
strcpy(name, "");
hourlyPay = 0.0;
}
}
bool Employee::set(int newId, const char* newName, double newHourlyPay)
{
bool status = false;
if (newId > 0)
{
status = true;
id = newId;
strcpy(name, newName);
hourlyPay = newHourlyPay;
}
return status;
}
int main()
{
int id; //Employee ID.
double hourlyPay; //Pay per hour.
vector<Employee> list; //Array to store
ifstream masterFile; //Opens master file.
char line[256];
masterFile.open("master10.txt");
if (masterFile)
{
while (!masterFile.eof())
{
masterFile >> id;
masterFile.getline(line, sizeof(line));
char* last_word = strrchr(line, ' ');
line[last_word - line] = 0;
hourlyPay = atof(last_word + 1);
list.push_back(Employee(id, line, hourlyPay));
}
}
//Close master file.
masterFile.close();
for (size_t i = 0; i < list.size(); ++i)
cout << list[i].getId() << " " << list[i].getName() << " " << list[i].getHourlyPay() << endl;
}
文件中的数据未正确输入代码中的变量。这是一个不言自明的解决方案。
for (count; count < 1; count++)
{
char secondname[11];
masterFile >> id;
masterFile.ignore();
masterFile >> newName;
masterFile >> secondname;
masterFile >> hourlyPay;
strcat(newName, " ");
strcat(newName, secondname);
list[count].set(id, newName, hourlyPay);
}
我想通了。
#include <iostream>
#include <iomanip>
#include <fstream>
#include <cstring>
using namespace std;
//Class decleration
class Employee
{
private:
int id; //Employee ID.
char name[21]; //Employee name.
double hourlyPay; //Pay per hour.
public:
Employee(int initId=0, char [] =0, double initHourlyPay=0.0); //Constructor.
bool set(int newId, char [], double newHourlyPay);
int getId() { return id; }
const char * getName() { return name;}
double getHourlyPay() { return hourlyPay;}
};
Employee::Employee( int initId, char initName[], double initHourlyPay)
{
bool status = set( initId, initName, initHourlyPay);
if ( !status )
{
id = 0;
strcpy(name, "");
hourlyPay = 0.0;
}
}
bool Employee::set( int newId, char newName[], double newHourlyPay)
{
bool status = false;
if ( newId > 0)
{
status = true;
id = newId;
strcpy(name, newName);
hourlyPay = newHourlyPay;
}
return status;
}
const int MAX_SIZE = 100;
int main()
{
int id; //Employee ID.
char newName[21];
double hourlyPay; //Pay per hour.
Employee list[15]; //Array to store
ifstream masterFile; //Opens master file.
masterFile.open("master10.txt");
int count = 0;
if (masterFile)
{
for (count; count < 2; count++)
{
masterFile >> id;
masterFile.ignore();
masterFile.get(newName, 21);
masterFile >> hourlyPay;
list[count].set(id, newName, hourlyPay);
}
}
masterFile.close(); //Close master file.
cout << list[0].getId() << " " << list[0].getName() << " " << list[0].getHourlyPay();
}
我只把getline改成了get,现在可以在一行中间读取,限制为20个字符。 感谢大家的关注和帮助。
所以..你真的想用一个普通的旧数组 Employee
和普通的旧字符数组和 cstring
?
这样做绝对没有错——它肯定会让您欣赏使用 string
和 vector
的便利。但是,就是说,通过每行数据遍历一个指针(或几个指针)以解析每行数据中的 id, name & hourlyPay
,可以获得大量有价值的学习。
整个解析过程的美中不足是不知道name
中可能包含多少spaces
(可能有none,一个,两个, 三, ...)。虽然,事情并不像看起来那么可怕。你知道你有一个开始数据行的 int
和一个结束的 double
- int
之后和 double
之前的空白之间的所有内容都是你的 name
.
这里的关键实际上是将每一行数据作为cstring
读取到缓冲区(字符数组)中。然后,您可以使用标准工具 strtol
读取 id
并将指针前进到 id
中最后一个数字的 1-过去。然后您可以简单地逐个字符地向前迭代检查 if (isspace(*p))
并继续前进直到找到非空白字符(或者您点击 nul-terminating字符在末尾)。一旦你找到你的非空白字符——你有一个指向 name
.
现在您必须在另一端工作并备份,直到找到hourlyPay
之前的space
。没那么难。您将需要 strlen (buf)
,但至少使用 masterFile.getline(..)
时,您无需通过用 nul-terminating[ 覆盖来从缓冲区末尾修剪 '\n'
=102=]字符。只需将结束指针设置为 buf + len - 1
,您就位于 hourlyPay
的最后一位。然后以类似的方式,备份 while (ep > sp && !isspace (*p))
只是一个问题(你知道你的终点指针是否到达位于 name
开头的起点指针,解析失败)
现在记住,这里是 hourlyPay
开头 之前的 1 个字符 ,所以当你使用 strtod
转换 hourlyPay
时],您必须记住使用 p + 1
作为转换 hourlyPay
的 cstring 段的开始。与任何 strtoX
转换一样,您有两个主要测试(1)转换后起始指针不等于 endptr
参数,表明数字实际上已转换为数字,以及(2) errno
未在转换期间设置 -- 表示实际转换失败。 (并且当转换为比转换更小的类型时——例如使用 strtol
转换为 int
—— 在分配给你的值之前,你必须检查转换的值是否在 int
的范围内.
现在您有了 id
和 hourlyPay
-- 剩下的就是 从 hourlyPay
开始备份 到name
结束。您以类似的方式检查 isspace()
直到它不再为真,并且指向 name
末尾的指针仍然大于指向 name
开头的指针。现在您可以使用 strncpy
通过复制 p - sp + 1
个字符将 name
复制到 newName
的变量中(记住您正坐在最后一个带有 p
的字符上,所以您将需要添加 1
以获取名称中的所有字符。
把它放在一起并在下面提供内联注释,你可以做类似下面的事情(注意你原来的 class
和成员函数保持不变——只有 id, name & hourlyPay
的解析main()
受到了显着影响)一如既往——关键是 验证每个步骤 —— 这样你就可以对你正在处理的数据充满信心。
#include <iostream>
#include <iomanip>
#include <fstream>
#include <cstring>
#include <cctype>
#include <limits>
#define MAXLIST 16 /* if you need constants, define one (or more) */
#define MAXNM 64
#define MAXBUF 1024
#define FNAME "dat/master10.txt"
using namespace std;
//Class decleration
class Employee
{
private:
int id; //Employee ID.
char name[MAXNM]; //Employee name.
double hourlyPay; //Pay per hour.
public:
Employee (int initId=0, char [] =0, double initHourlyPay=0.0);
bool set (int newId, char [], double newHourlyPay);
int getId() { return id; }
const char *getName() { return name;}
double getHourlyPay() { return hourlyPay;}
};
Employee::Employee (int initId, char initName[], double initHourlyPay)
{
bool status = set(initId, initName, initHourlyPay);
if (!status)
{
id = 0;
strcpy(name, "");
hourlyPay = 0.0;
}
}
bool Employee::set (int newId, char newName[], double newHourlyPay)
{
bool status = false;
if (newId > 0) {
status = true;
id = newId;
strcpy(name, newName);
hourlyPay = newHourlyPay;
}
return status;
}
int main (void) {
int id, //Employee ID.
count = 0;
long tmp; /* tmp for strtol conversion */
char newName[MAXNM] = "",
buf[MAXBUF] = ""; /* line buffer */
double hourlyPay; //Pay per hour.
Employee list[MAXLIST]; //Array to store
ifstream masterFile (FNAME); //Opens master file.
if (!masterFile.is_open()) { /* validate file open for reading */
cerr << "error: file open failed '" << FNAME << "'\n";
return 1;
}
/* read each line in masterFile into buf */
while (count < MAXLIST && masterFile.getline (buf, sizeof buf))
{
size_t len = strlen (buf); /* get length */
char *sp = buf, /* start pointer */
*p = buf + len - 1, /* working pointer */
*ep = NULL; /* end pointer for strtod conversion */
/* parse and convert id, leaving sp 1-past last digit */
errno = 0; /* zero errno before strtol conversion */
tmp = strtol (buf, &sp, 0); /* store conversion in tmp */
if (buf == sp) { /* validate characters were converted */
cerr << "error: no digits converted in id.\n";
return 1;
}
if (errno != 0) { /* validation errno not set */
cerr << "error: failed converstion for id.\n";
return 1;
}
/* validate tmp within range of integer */
if (tmp < numeric_limits<int>::min() ||
numeric_limits<int>::max() < tmp) {
cerr << "error: id not within integer range.\n";
return 1;
}
id = (int)tmp; /* assign tmp to id */
/* advance sp to 1st char in name */
while (*sp && isspace (*sp))
sp++;
/* parse hourlyPay */
/* work backward with p until space before hourlyPay found
* always validate p > sp so you don't back up beyond the start of
* name (or the beginning of buf).
*/
while (p > sp && !isspace (*p))
p--;
if (p > sp && !isdigit(*(p + 1))) { /* validate next char is digit */
cerr << "error: failed to parse hourlyPay.\n";
return 1;
}
errno = 0; /* zero errno before strtol conversion */
hourlyPay = strtod (p+1, &ep); /* convert hourlyPay to double */
if (p + 1 == ep) { /* validate characters were converted */
cerr << "error: no digits converted in hourlyPay.\n";
return 1;
}
if (errno != 0) { /* validation errno not set */
cerr << "error: failed converstion for hourlyPay.\n";
return 1;
}
/* continue working backwards to end of name */
while (p > sp && isspace (*p))
p--;
if (p <= sp) { /* validate chars between sp & p */
cerr << "error: failed to find end of name.\n";
return 1;
}
len = p - sp + 1; /* get number of chars in name */
if (len > MAXNM - 1) { /* validate it will fit in newName */
cerr << "error: name exceeds" << len << "characters.\n";
return 1;
}
strncpy (newName, sp, len); /* copy name to newName */
/* set values in list[count], on success, increment count */
if (list[count].set (id, newName, hourlyPay))
count++;
}
masterFile.close(); //Close master file.
/* outoput all employee id and hourlyPay information */
for (int i = 0; i < count; i++)
cout << list[i].getId() << " " << list[i].getName() <<
" " << list[i].getHourlyPay() << '\n';
}
(现在你明白为什么 string
和其他 C++ 工具让事情变得更好了吗?)
示例输入文件
您发布的唯一数据被用作输入文件,例如
$ cat dat/master10.txt
5 Christine Kim 30.00
例子Use/Output
$ ./bin/employeepay
5 Christine Kim 30
检查一下,如果您还有其他问题,请告诉我。