谢谢sp2danny的回答!
HEADER FILE:
#ifndef EMPLOYEERECORD_H
#define EMPLOYEERECORD_H
#include <iostream>
#include <string>
using namespace std;
class EmployeeRecord
{
char m_sLastName[31]; // employee last name
char m_sFirstName[31]; // employee first name
EmployeeRecord(); // default constructor
EmployeeRecord(int ID, char *fName, char *lName, int dept, double sal);
};
#endif
SOURCE FILE:
#include "EmployeeRecord.h"
//constructor 1 (default)
EmployeeRecord::EmployeeRecord()
{
m_iEmployeeID = 0;
m_sLastName == "";
m_sFirstName == "";
m_iDeptID = 0;
m_dSalary = 0.0;
}
// this constructor shall set the member variables to the values passed into the function
EmployeeRecord::EmployeeRecord(int ID, char *fName, char *lName, int dept, double sal)
{
unsigned int i = 0;
m_iEmployeeID = ID;
for (i = 0; i < 31; i++)
{
m_sFirstName[i] = *(fName + i);
m_sLastName[i] = *(lName + i);
}
m_iDeptID = dept;
m_dSalary = sal;
}
// destructor - cleans up and deallocates any memory that pointers within this class may have referenced to
EmployeeRecord::~EmployeeRecord(){};
// this function shall print to the screen all data found in the employee's record
void EmployeeRecord::printRecord()
{
cout << "Employee ID: " << m_iEmployeeID << endl;
cout << "First Name: " << m_sFirstName << endl;
cout << "Last Name: " << m_sLastName << endl;
cout << "Department ID: " << m_iDeptID << endl;
cout << "Salary: $ " << m_dSalary << endl;
}
我如何打电话:
/*******************************************************************
* main function for project Prog1
*******************************************************************/
#include <stdio.h>
#include <time.h>
#include <cstdlib>
#include <stdlib.h>
#include <windows.h>
#include <string>
#include <iostream>
using namespace std;
#include "EmployeeRecord.h"
int main(void)
{
int answer, employee_id, dept_id;
unsigned int i;
char firstname[31], lastname[31];
double *salary, _salary;
salary = &_salary;
EmployeeRecord Employee1 = EmployeeRecord();
firstname[0] = 'J';
firstname[1] = 'h';
firstname[2] = 'o';
firstname[3] = 'n';
firstname[4] = 'n';
firstname[5] = 'y';
lastname[0] = 'D';
lastname[1] = 'o';
lastname[2] = 'e';
lastname[3] = 'b';
lastname[4] = 'e';
lastname[5] = 'r';
EmployeeRecord Employee2 = EmployeeRecord(0, firstname, lastname, 0, 0.0);
Employee2.printRecord();
system("pause");
所以说我已经将m_sFirstName设置为&#34; Johnny&#34;和m_sLastName等于&#34; Doeber&#34;其中m_sFirstName [0] =&#39; J&#39;,m_sLastName =&#39; D&#39;等... 每次调用printRecord函数时,都会得到以下结果:
Fist Name: Johnny########################### (2 more spaces than were allocated)
Last Name: Doeber#########################Johnny###########################
其中#是空字符(在真实程序中看起来很奇怪)
因此,不仅m_sFirstName不能正确地将前3个字符打印到屏幕上,而且m_sFirstName的整个混乱版本正被添加到m_sLastName字符数组的末尾...
我是如何在世界上对自己做的?
答案 0 :(得分:2)
这行代码:
m_sLastName == "";
什么都不做。它将指向空字符串的指针与字符数组进行比较。并计算它们是否指向同一块内存(不是相同的内容)。然后我们扔掉那个结果。
如果要使用所有空字符初始化m_sLastName
,则应执行以下操作:
memset(m_sLastName, '\0', sizeof(m_sLastName));
如果不这样做,m_sLastName
将初始化为未指定的值。也就是随机垃圾。
相反,如果您希望这些字符串为空字符串,那么您可以这样做:
m_sLastName[0] = '\0';
您当前将代码值复制到对象几乎的代码有效。您不会终止字符串,并假设传入的字符串长度为31个字符。在你的main()
中,这是真的。但这是一件非常糟糕的事情。
让我们解决一下:
strncpy(m_sLastName, lName, 31);
m_sLastName[30] = '\0'; // If lName was too long, then strncpy won't null terminate the string.
我们也可以使用snprintf()
,这有点慢,但更安全。
snprintf(m_sLastName, sizeof(m_sLastName), "%s", lName);
firstname
和lastname
已终止。他们真的应该。所以你需要添加:
firstname[6] = '\0';
lastname[6] = '\0';
#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <string>
using namespace std;
class EmployeeRecord {
private:
char m_sLastName[31];
char m_sFirstName[31];
public:
EmployeeRecord();
EmployeeRecord(int ID, const char *fName, const char *lName, int dept, double sal);
public:
void printRecord();
};
EmployeeRecord::EmployeeRecord() {
memset(m_sFirstName, '\0', sizeof(m_sFirstName));
memset(m_sLastName, '\0', sizeof(m_sLastName));
}
EmployeeRecord::EmployeeRecord(int ID, const char *fName, const char *lName, int dept, double sal) {
snprintf(m_sFirstName, sizeof(m_sLastName), "%s", fName);
snprintf(m_sLastName, sizeof(m_sLastName), "%s", lName);
}
void EmployeeRecord::printRecord() {
cout << "First Name: " << m_sFirstName << endl;
cout << "Last Name: " << m_sLastName << endl;
}
int main() {
EmployeeRecord Employee1 = EmployeeRecord();
Employee1.printRecord();
printf("\n");
char firstname[31] = "Jhonny";
char lastname[31] = "Doeber";
EmployeeRecord Employee2 = EmployeeRecord(0, firstname, lastname, 0, 0.0);
Employee2.printRecord();
printf("\n");
EmployeeRecord Employee3 = EmployeeRecord(0, "John", "Smith", 0, 0.0);
Employee3.printRecord();
printf("\n");
}
First Name:
Last Name:
First Name: Jhonny
Last Name: Doeber
First Name: John
Last Name: Smith
Employee3.firstname
实际上是什么?所以,这就是我对Employee3的第一个名字的了解。有31个字符可供空间使用。我知道前5个包含{'J', 'o', 'h', 'n', '\0'}
。
我不知道剩下的内容。它可能有一些不是所有空字符的垃圾。问题是,我们不在乎。字符串的有效内容以第一个空字符结束。
答案 1 :(得分:1)
对std::string
和m_sFirstName
使用m_sLastName
,行为将更接近您的期望。
答案 2 :(得分:-1)
清除构造函数中的名称字段应为
m_sLastName[0] = 0
m_sFirstName[0] = 0;
其他构造函数中的名称字段设置应为
strncpy( m_sFirstName, fName, 31 );
strncpy( m_sLastName, lName, 31 );
主要的本地人应该用
设置strncpy(firstname, "Johnny", 31 );
strncpy(lasname, "Doeber", 31 );
并非需要那些当地人
<string.h>
strncpy
另请注意,您的教授应该为此作业获得F,从C开始是最差教授C ++的方式