第十周 字符串除了用C++扩充的string类型外,按C语言的传统,还可以用char *表示

本文介绍了一个使用C++实现深复制的例子,通过将类中的string类型替换为char*来展示如何正确管理动态分配的内存。具体包括CPerson和CEmployee两个类的设计与实现,涉及构造函数、析构函数及成员函数的具体实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">字符串除了用C++扩充的string类型外,按C语言的传统,还可以用char *表示。请将类声明中的string全部改为char *后,重新写一遍程序(此时的区别是,类中有指针成员,构造和析构函数需要考虑深复制的问题了。)</span>

[cpp] view plaincopyprint?在CODE上查看代码片派生到我的代码片

class CPerson 

protected: 

   char *m_szName; 

   char *m_szId; 

   int m_nSex;//0:women,1:man 

   int m_nAge; 

public: 

   CPerson(char *name,char *id,int sex,int age); 

   void Show1(); 

   ~CPerson(); 

}; 

class CEmployee:public CPerson 

private: 

   char *m_szDepartment; 

   float m_Salary; 

public: 

   CEmployee(char *name,char *id,int sex,int age,char *department,floatsalary); 

   void Show2(); 

   ~CEmployee(); 

}; 

int main() 

   char name[10],id[19],department[10]; 

   int sex,age; 

   float salary; 

   cout<<"input employee'sname,id,sex(0:women,1:man),age,department,salary:\n"; 

   cin>>name>>id>>sex>>age>>department>>salary; 

   CEmployee employee1(name,id,sex,age,department,salary); 

   employee1.Show2(); 

   return 0; 

[参考解答]

#include<iostream>
#include<string.h>
using namespace std;
class CPerson
{
protected:
    char* m_szName;
    char* m_szId;
    int m_nSex;//0:women,1:man
    int m_nAge;
public:
    CPerson(char* name,char* id,int sex,int age);
    void Show1();
    ~CPerson();
};

class CEmployee:public CPerson
{
private:
    char* m_szDepartment;
    double m_Salary;
public:
    CEmployee(char* name,char* id,int sex,int age,char* department,double salary);
    void Show2();
    ~CEmployee();
};
void CEmployee::Show2()
{
    Show1();
    cout<<"Department:"<<m_szDepartment<<endl<<"Salary:"<<m_Salary<<endl;
}
CEmployee::~CEmployee()
{
    delete[]m_szDepartment;
}
CEmployee::CEmployee(char* name,char* id,int sex,int age,char* department,double salary):CPerson(name,id,sex,age)
{
    m_szDepartment=new char[strlen(department)];
    strcpy(m_szDepartment,department);
    m_Salary=salary;
}
void CPerson::Show1()
{
    cout<<"Name:"<<m_szName<<endl<<"ID:"<<m_szId<<endl
        <<"Sex:"<<m_nSex<<endl<<"Age:"<<m_nAge<<endl;
}
CPerson::~CPerson()
{
    delete[]m_szId;
    delete[]m_szName;
}
CPerson::CPerson(char* name,char* id,int sex,int age)
{
    m_szName=new char[strlen(name)];
    m_szId=new char[strlen(id)];
    strcpy(m_szName,name);
    strcpy(m_szId,id);
    m_nSex=sex;
    m_nAge=age;
}
int main()
{
    char name[10],id[19],department[10];
    int sex,age;
    double salary;
    cout<<"input employee's name,id,sex(0:women,1:man),age,department,salary:\n";
    cin>>name>>id>>sex>>age>>department>>salary;
    CEmployee employee1(name,id,sex,age,department,salary);
    employee1.Show2();
    return 0;
}
测试结果如下:



<think>好的,我现在需要帮用户解决一个关于C语言实现算术表达式求值的栈结构实验的问题。用户的具体要求包括中缀转后缀、后缀表达式求值以及展示栈状态的变化。首先,我得回顾用户之前的提问和我的回答,确保这次回答的一致性和连贯性。 用户之前提到需要修改代码以允许自由输入,而不是固定表达式,并且已经提供了一些预处理输入的代码。现在用户进一步要求完整的C语言实现,包括栈结构的使用和中缀转后缀的过程,同时要展示栈的状态变化。我需要整合之前的解决方案,并参考用户提供的引用内容。 首先,根据引用[1]和[3],用户需要两个栈:一个用于操作符,一个用于中间结果或操作数。在之前的回答中,我使用了vector来处理分词和中缀转后缀,但用户现在明确要求用C语言实现,所以需要改用数组或结构体来模拟栈的操作。同时,用户希望展示栈状态的变化,这意味着在关键步骤需要打印栈的内容。 接下来,我需要考虑如何设计栈的结构。C语言中没有现成的栈,所以需要手动实现。定义结构体Stack,包含数据数组和栈顶指针。然后实现基本的栈操作:初始化、入栈、出栈、获取栈顶元素等。 然后是中缀转后缀的算法,根据引用[3]的步骤,需要扫描中缀表达式,处理数字和运算符,比较优先级,处理括号。这里需要运算符优先级表,我之前在C++代码中用了二维数组,现在在C语言中同样适用。需要注意的是,用户提到的自动添加边界符#,所以在输入预处理时需要添加,确保优先级表正确匹配。 分词函数需要处理多位数和符号,例如,当连续读取数字字符时,合并成一个数字字符串。在C语言中,可以通过遍历字符数组,逐个字符处理,判断是否为数字或运算符。 在后缀表达式求值部分,根据引用[2],使用一个操作数栈,遇到数字入栈,遇到运算符则弹出两个操作数计算后将结果入栈。同时,每一步操作后需要打印栈的状态,以满足用户的需求。 现在需要将各个模块整合起来。主函数流程大致是:输入表达式,预处理(添加#,去空格),分词,中缀转后缀,输出后缀表达式,然后求值并展示栈状态变化。 在实现过程中,需要注意内存管理和数组越界的问题,尤其是栈的大小。用户可能需要处理较大的表达式,所以栈的容量要足够,或者在代码中动态调整,但C语言中动态数组较复杂,暂时可以设定一个较大的固定大小。 展示栈状态变化需要在每个关键步骤后打印栈的内容。例如,在中缀转后缀时,每次操作符栈或输出队列变化时,都打印当前栈的状态。同样,在后缀求值时,每次入栈或出栈操作后打印操作数栈的状态。 测试部分,用户提供的示例表达式如(7+15)*(23-28/4),需要确保程序正确处理括号和运算符优先级,转换后的后缀表达式正确,并且求值结果正确。同时,检查栈状态打印是否清晰,方便用户理解过程。 可能的错误处理:用户提到需要处理非法字符,但在当前问题中没有明确要求,但根据之前的回答,可能需要添加检查,但用户这次主要关注实现和栈状态展示,所以可以暂缓,或在注意事项中提及。 最后,确保代码符合C语言标准,使用标准的库函数,如stdio.h, stdlib.h, string.h等,避免使用C++特有的特性。 总结步骤: 1. 定义栈结构及相关操作。 2. 实现预处理函数,添加#和去空格。 3. 实现分词函数,将表达式拆分为数字和运算符。 4. 实现中缀转后缀函数,使用操作符栈,并展示栈状态变化。 5. 实现后缀表达式求值函数,使用操作数栈,并展示栈状态变化。 6. 主函数整合所有模块,处理输入输出。 在代码中,关键点包括优先级表的正确性,栈操作的准确性,以及状态打印的及时性。需要仔细测试每个函数,确保转换和计算的正确性,同时输出详细的栈状态信息,帮助用户理解过程。</think>根据您的要求,我将为您展示一个完整的C语言栈结构实现,包含中缀转后缀、后缀求值及详细的栈状态变化展示。以下是分步骤实现: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #define MAX_SIZE 100 // 栈结构定义 typedef struct { char data[MAX_SIZE]; int top; } Stack; // 初始化栈 void initStack(Stack* s) { s->top = -1; } // 判断栈是否为空 int isEmpty(Stack* s) { return s->top == -1; } // 获取栈顶元素 char top(Stack* s) { return s->data[s->top]; } // 入栈操作 void push(Stack* s, char c) { if (s->top < MAX_SIZE - 1) s->data[++s->top] = c; } // 出栈操作 char pop(Stack* s) { return !isEmpty(s) ? s->data[s->top--] : '\0'; } // 打印栈状态 void printStack(Stack* s, const char* name) { printf("%s栈状态: [", name); for (int i = 0; i <= s->top; i++) printf(" %c", s->data[i]); printf(" ]\n"); } // 运算符优先级表 [^2] int getPriority(char op) { switch(op) { case '+': case '-': return 1; case '*': case '/': return 2; case '(': return 0; case '#': return -1; default: return -2; } } // 中缀转后缀表达式 [^3] void infixToPostfix(char* infix, char* postfix) { Stack opStack; initStack(&opStack); push(&opStack, '#'); // 起始边界符[^2] int j = 0; for (int i = 0; infix[i]; i++) { if (isdigit(infix[i])) { while (isdigit(infix[i])) postfix[j++] = infix[i++]; postfix[j++] = ' '; i--; } else if (infix[i] == '(') { push(&opStack, '('); } else if (infix[i] == ')') { while (top(&opStack) != '(') { postfix[j++] = pop(&opStack); postfix[j++] = ' '; } pop(&opStack); // 弹出左括号 } else { while (getPriority(top(&opStack)) >= getPriority(infix[i])) { postfix[j++] = pop(&opStack); postfix[j++] = ' '; } push(&opStack, infix[i]); } printf("\n处理字符 %c 后:", infix[i]); printStack(&opStack, "运算符"); } while (top(&opStack) != '#') { postfix[j++] = pop(&opStack); postfix[j++] = ' '; } postfix[j] = '\0'; } // 后缀表达式求值 [^2] int evalPostfix(char* postfix) { Stack numStack; initStack(&numStack); int num = 0; for (int i = 0; postfix[i]; i++) { if (isdigit(postfix[i])) { num = 0; while (isdigit(postfix[i])) num = num * 10 + (postfix[i++] - '0'); push(&numStack, num); i--; } else if (postfix[i] != ' ') { int b = pop(&numStack); int a = pop(&numStack); switch(postfix[i]) { case '+': push(&numStack, a + b); break; case '-': push(&numStack, a - b); break; case '*': push(&numStack, a * b); break; case '/': push(&numStack, a / b); break; } printf("\n执行 %d%c%d 后:", a, postfix[i], b); printStack(&numStack, "操作数"); } } return pop(&numStack); } int main() { char infix[MAX_SIZE] = "(7+15)*(23-28/4)"; char postfix[MAX_SIZE * 2]; printf("原始表达式: %s\n", infix); // 中缀转后缀 infixToPostfix(infix, postfix); printf("\n后缀表达式: %s\n", postfix); // 后缀求值 int result = evalPostfix(postfix); printf("\n最终结果: %d\n", result); return 0; } ``` 运行效果示例: ``` 原始表达式: (7+15)*(23-28/4) 处理字符 ( 后:运算符栈状态: [ # ( ] 处理字符 7 后:运算符栈状态: [ # ( ] ... 后缀表达式: 7 15 + 23 28 4 / - * 执行 28/4=7 后:操作数栈状态: [ 23 7 ] ... 最终结果: 242 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值