先看一段代码:
#include<iostream>
#include<cstring>
using namespace std;
int main() {
char s[105], t[105][105];
cin>>(s);
int h = 0, p = 0;
for (int i = 0; s[i]; i++) {
if (!(s[i] >= '0' && s[i] <= '9')) {
int k = 0;
if (h != i) {
for (int j = h; j < i; j++)t[p][k++] = s[j];
t[p++][k++] = '\0';
t[p][0] = s[i]; t[p++][1] = '\0';
}
else {
t[p][0] = s[i];
t[p++][1] = '\0';
}
h = i + 1;
}
if (s[i + 1] == '\0') {
int k = 0;
for (int j = h; s[j]; j++)t[p][k++] = s[j];
t[p++][k++] = '\0';
}
}
for (int i = 0; i < p; i++)
cout << t[i] << endl;
return 0;
}
运行结果:
这是我写的一个不论表达式中的数是多少位,都可以将其分割的程序(这个其实跟将一句英语中的单词分开差不多)
后面转换为后缀表达式的时候,将会用到这个原理进行处理
后面这里就直接上代码:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef char ElementType;
typedef struct SNode {//定义结构体
ElementType Data;
struct SNode* Next;
}*Stack;
Stack CreateStack() {//创建堆栈
Stack S = (Stack)malloc(sizeof(struct SNode));
S->Next = NULL;
return S;
}
bool IsEmpty(Stack S) {//判断堆栈是否为空,空则返回真值
return (S->Next == NULL);
}
Stack Push(Stack S, int x) {//堆栈是要求后入先出,所以用头插法
Stack p = (Stack)malloc(sizeof(struct SNode));
p->Data = x;
p->Next = S->Next;
S->Next = p;
return S;
}
ElementType Pop(Stack S) {//将栈顶元素返回并将其删除
if (IsEmpty(S)) {
//printf("堆栈为空\n");
return 0;
}
Stack p = S->Next;
ElementType x = p->Data;
S->Next = p->Next;
free(p);
return x;
}
void Change(char s[]) {//将中序表达式转为后缀表达式(读取的是一行字符串)
//首先将输入的字符串处理一下
for (int i = 0; s[i]; i++) { //进行判断,字符串中是否存在除空格、数字和四则运算符以及括号外的字符
if (s[i] != ' ' && !(s[i] >= '0' && s[i] <= '9')
&& !(s[i] == '+' || s[i] == '-' || s[i] == '*' || s[i] == '/') && !(s[i] == '(' || s[i] == ')')) {
printf("表达式错误!\n");
return;
}
}
int i = 0;
while (s[i]) {//将字符串中的空格全部删去
if (s[i] == ' ')for (int j = i; s[j]; j++)s[j] = s[j + 1];
else i++;
}
char t[105][105];
int h = 0, p = 0;
for (int i = 0; s[i]; i++) {
if (!(s[i] >= '0' && s[i] <= '9')) {
int k = 0;
if (h != i) {
for (int j = h; j < i; j++)t[p][k++] = s[j];
t[p++][k++] = '\0';
t[p][0] = s[i]; t[p++][1] = '\0';
}
else {
t[p][0] = s[i];
t[p++][1] = '\0';
}
h = i + 1;
}
if (s[i + 1] == '\0') {
int k = 0;
for (int j = h; s[j]; j++)t[p][k++] = s[j];
t[p++][k++] = '\0';
}
}
Stack S = CreateStack();//创建堆栈,用来存运算符
for (int i = 0; i < p; i++) {
if (t[i][0] >= '0' && t[i][0] <= '9') {//是数字,直接输出
printf("%s ", t[i]);
//要说的是,因为数字可能是多位的,为了方便,统一隔开一个空格
}
else if (t[i][0] == '(' || IsEmpty(S)) {//'('直接入栈,栈为空也直接入栈
char b = t[i][0];
S = Push(S, b);
}
else if (t[i][0] == ')') {// ')' 将符号栈中的元素依次出栈并输出, 直到 “(“, “(“只出栈, 不输出
//有')'出现,则一定有'('出现
char b = Pop(S);
while (b != '(') {
printf("%c ", b);
b = Pop(S);
}
//if (b != '(') S = Push(S, b);
}
else {
char b = t[i][0];
char c = Pop(S);//将栈顶元素取出
//当新的运算符的优先级小于等与栈顶元素,将栈顶元素输出,而后往下继续判断
if (c == '+' || c == '-') {
if (b == '+' || b == '-') {//优先级等于栈顶元素
printf("%c ", c);
c = Pop(S);//往后继续判断
while (c != '(' && !IsEmpty(S)) {
//因为加法与减法优先级最小,所以不用进行判断,直接输出
printf("%c ", c);
c = Pop(S);
}
}
}
else if (c == '/' || c == '*') {//因为最大的优先级就是乘法和除法
if (b == '/' || b == '*') {
printf("%c ", c);
c = Pop(S);
while (c != '-' && c != '+' && !IsEmpty(S)) {
printf("%c ", c);
c = Pop(S);
}
}
else if (b == '+' || b == '-') {
printf("%c ", c);
c = Pop(S);//往后继续判断
while (c != '(' && !IsEmpty(S)) {
printf("%c ", c);
c = Pop(S);
}
}
}
S = Push(S, c);//将c重新压回堆栈
S = Push(S, b);//将新的运算符压栈
}
}
//将输入的数组遍历一遍后,将栈中的元素全部输出
while (!IsEmpty(S)) printf("%c ", Pop(S));
printf("\n");
}
int main() {
char s[1005];
while (gets_s(s)) {
Change(s);
printf("\n");
}
return 0;
}
/*
测试样例一:
输入:2*(9+6/3-5)+4
输出:2 9 6 3 / + 5 - * 4 +
测试样例二:
输入:16568*(9846+666/333-984)+4562
输出:16568 9846 666 333 / + 984 - * 4562 +
测试样例三:
输入:5+6/2-3*4
输出:5 6 2 / 3 4 * - +
测试样例四:
输入:3+(2-5)*6/3
输出: 3 2 5 - 6 * 3 / +
测试样例五:
输入:(3+4)*5-6
输出:3 4 + 5 * 6 -
*/
运行结果:
堆栈的实现是挺简单的,比较难的是对字符串的操作,博主也是调了挺久的bug
嗯,再代码的最后有测试样例,都是博主亲自运行过了,就比较懒,不想贴图了
如果大家拿代码去运行出现什么bug的话,欢迎评论哦!
因为本来是想将求得的后缀表达式变成一个字符串进行输出的,但是估计比较复杂,而且没多少时间来琢磨这个,后面有时间会再写一遍博客,将它真正的按字符串输出顺便进行计算。