C++ C++;屏幕上打印的奇怪字符

C++ C++;屏幕上打印的奇怪字符,c++,C++,谢谢你的回答 头文件: #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 firs

谢谢你的回答

头文件:

#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
其中#是空字符(在实际程序中看起来很奇怪)

因此,不仅m_sFirstName没有正确地将前3个字符打印到屏幕上,而且整个混乱版本的m_sFirstName被添加到m_sLastName字符数组的末尾


我究竟是如何做到这一点的?

使用
std::string
作为
m\u sFirstName
m\u sLastName
,这样的行为将更接近您的预期。

清除构造函数中的名称字段应为

m_sLastName[0] = 0
m_sFirstName[0] = 0;
strncpy( m_sFirstName, fName, 31 );
strncpy( m_sLastName,  lName, 31 );
其他构造函数中名称字段的设置应为

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 );
并不是说需要那些当地人

对于
strncpy

还要注意的是,你的教授在这项作业中应该得到F,从C开始是教C++最糟糕的方法。

比较与作业 这行代码:

m_sLastName == "";
什么也不做。它将指向空字符串的指针与字符数组进行比较。并计算它们是否指向同一块内存(不是相同的内容)。然后我们扔掉这个结果

如果要使用所有空字符初始化
m_sLastName
,则应执行以下操作:

memset(m_sLastName, '\0', sizeof(m_sLastName));
如果不这样做,
m_sLastName
将被初始化为未指定的值。也就是说,随机垃圾

相反,如果希望这些字符串为空字符串,则只需执行以下操作:

m_sLastName[0] = '\0';
我们如何复制字符串? 将名称值复制到对象的当前代码几乎有效。您不能以null结尾字符串,并且假设传入的字符串长度为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);
在main()中创建的字符串 main中的
firstname
lastname
不是以null结尾的。他们真的应该这样。因此,您需要添加:

firstname[6] = '\0';
lastname[6] = '\0';
实现所有这些的代码是什么样子的: 员工3.firstname中的实际内容是什么? 以下是我对员工名字的了解。空格中有31个字符。我知道前5个包含
{'J','o','h','n','0'}


我不知道剩下的是什么。它可能有一些不全是空字符的垃圾。问题是,我们不在乎。字符串的有效内容以第一个空字符结尾。

您认为这有什么作用<代码>m_sLastName==“”。它为字符串m_sLastName的每个字符放置一个空字符。而且,我已经用多种方法定义了它,但它仍然给我同样的错误。不,它肯定不会这样做。它没有任何效果。@deviantfan什么任务?从什么时候开始数组是可赋值的?;-)@比尔·林奇:我把它修剪了一点。这两个变量必须是字符数组。它们不可能是弦,为什么?你期望有什么不同?这是一个项目任务。教授只是想要这样,我想只是让它更难。好吧,学校的一个项目。阅读指针和数组之间的差异,并查看
strcpy()
和用于复制字符的函数族。哇,完美的答案。做得很好。一点也不完美,更喜欢sizeof而不是幻数。初始化
m_sLastName
的值比执行整个memset操作更容易。@juanchopanza:我同意,但是我们必须在初始化器列表中而不是在构造函数主体中进行初始化。我想在这一点上,这可能有点太多了。这也可能会混淆OP的“教授”。
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