鱼C论坛

 找回密码
 立即注册
查看: 1717|回复: 2

C++,用户输入的字符数组结尾在程序运行中自动变空格,而不是'\0'

[复制链接]
发表于 2020-12-14 12:55:17 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
简单计算器的实现(实现整数的加减乘除)用了继承的方法,通过data和char的两个栈分别存放操作数和运算符来实现
先不看逆波兰的计算,先实现简单的1+2

  1. //counter.cpp

  2. #include <iostream>
  3. #include<string.h>
  4. #include<stdio.h>
  5. #include "counter_char.h"
  6. #include "counter_data.h"
  7. using namespace std;

  8. void append_data(char*& rpn,int opnd)//将操作数接至RPN末尾
  9. {
  10.         int n = strlen(rpn);//RPN当前长度(以'\0'结尾,长度n+1)
  11.         char buf[64];
  12.         sprintf(buf,"%d \0",(int)opnd);//将一个格式化的字符串输出到一个目的字符串中
  13.         //rpn = (char*)realloc(rpn,sizeof(char)*(n+strlen(buf)+1));//扩展空间
  14.         strcat(rpn,buf);//把buf所指向的字符串追加到rpn的末尾,RPN加长
  15. }

  16. void append_char(char*& rpn,char optr)//将运算符接至RPN末尾
  17. {
  18.         int n = strlen(rpn);////RPN当前长度(以'\0'结尾,长度n+1)
  19. //        rpn = (char*)realloc(rpn,sizeof(char)*(n+3));//扩展空间
  20.         sprintf(rpn+n,"%c ",optr);
  21.         rpn[n+2] = '\0';//接入指定的运算符
  22. }

  23. void readNumber(char*& p,Stack_data & stk)//将起始于p的子串解析为数值,并存入操作数栈
  24. {
  25.         stk.push((int)(*p - '0'));//当前数位对应的数值进栈
  26.         while(isdigit(*(++p)))//只要后续还有紧邻的数字(即多位整数的情况),则
  27.                 stk.push(stk.pop()*10+(*p - '0'));//弹出原操作数并追加新位数后,新数值重新入栈
  28. }

  29. #define N_OPTR 5//运算符总数
  30. typedef enum{ADD,SUB,MUL,DIV,EOE}Operator;//运算符集合
  31. //加、减、乘、除、起始符与终止符

  32. const char pri[N_OPTR][N_OPTR]=//运算符优先等级[栈顶][当前]
  33. {
  34.         '>', '>', '<', '<', '>',
  35.         '>', '>', '<', '<', '>',
  36.         '>', '>', '>', '>', '>',
  37.         '>', '>', '>', '>', '>',
  38.         '<', '<', '<', '<', '='
  39. };

  40. OperType optr2rank(char op)//由运算符转译出编号
  41. {
  42.         cout << "op:" << int(op) << endl;
  43.         switch(op)
  44.         {
  45.         case '+':return ADD;//加
  46.         case '-':return SUB;//减
  47.         case '*':return MUL;//乘
  48.         case '/':return DIV;//除
  49.         case '\0':return EOE;//起始符与终止符
  50.         default:printf("语法错误3\n");exit(-1);//未知运算符
  51.         }
  52. }

  53. char orderBetween(char op1,char op2)//比较两个运算符之间的优先级
  54. {
  55.         return pri[optr2rank(op1)][optr2rank(op2)];
  56. }

  57. int calcu(int pOpnd1,char op,int pOpnd2)//op为操作符,pOpnd1和2为操作数
  58. {
  59.         int result;
  60.         switch(op)
  61.         {
  62.                 case ADD:
  63.                         result = pOpnd1 + pOpnd2;
  64.                         break;
  65.                 case SUB:
  66.                         result = pOpnd1 - pOpnd2;
  67.                         break;
  68.                 case MUL:
  69.                         result = pOpnd1 * pOpnd2;
  70.                         break;
  71.                 case DIV:
  72.                         result = pOpnd1 / pOpnd2;
  73.                         break;
  74.                 default:printf("语法错误2\n");exit(-1);
  75.         }
  76.         return result;
  77. }

  78. float evaluate(char* S,char* RPN)//对(已删除白空格的)表达式S求值,并转换为逆波兰式RPN
  79. {//S为存放字符数组的指针
  80.         Stack_data opnd;
  81.         Stack_char optr;
  82.         optr.push('\0');//尾哨兵'\0'也作为头哨兵首先入栈
  83.         while(!optr.empty())//在运算符栈非空之前,逐个处理表达式中各字符
  84.         {
  85.                 if(isdigit(*S))//如果当前字符为操作符,则
  86.                 {
  87.                         cout << "这一轮while是if" << endl;
  88.                         cout << "*S是:" << *S << endl;
  89.                         readNumber(S,opnd);
  90.                         append_data(RPN,opnd.top());//读入操作数,并将其接至RPN末尾→拼成逆波兰式
  91.                 }
  92.                 else//若当前字符为运算符,则
  93.                 {
  94.                         cout << "这一轮while是else" << endl;
  95.                         cout << "*S是:" << *S << endl;

  96.                         cout << "orderBetween(optr.top(),*S):" << orderBetween(optr.top(),*S) << endl;
  97.                         switch(orderBetween(optr.top(),*S))//视其与栈顶运算符之间优先级高低分别处理
  98.                         {
  99.                                 case'<'://栈顶运算符优先级更低时
  100.                                         optr.push(*S);S++;//计算推迟,当前运算符进栈
  101.                                         break;
  102.                                 case'='://优先级相等(当前运算符为右括号或尾部哨兵'\0')时
  103.                                         optr.pop();S++;//脱括号并接收下一个字符
  104.                                         break;
  105.                                 case'>'://栈顶运算符优先级更高时,可实施相应的计算,并将结果重新入栈
  106.                                 {
  107.                                         char op = optr.pop();append_char(RPN,op);//栈顶运算符出栈并续接至RPN末尾
  108.                                         int pOpnd2 = opnd.pop(),pOpnd1 = opnd.pop();//取出后、前操作数
  109.                                         opnd.push(calcu(pOpnd1,optr2rank(op),pOpnd2));
  110.                                         break;
  111.                                 }
  112.                                 default:printf("语法错误1\n");exit(-1);//逢语法错误,不做处理直接退出
  113.                         }
  114.                 }
  115.         }
  116.         return opnd.pop();//弹出并返回最后的计算结果
  117. }

  118. int main()
  119. {

  120.         char expression[20];
  121.         char RPN[10];
  122.         cout << "请输入要计算的式子:";
  123.         gets(expression);
  124.         expression[4] = '\0';
  125.         cout << "计算结果为:" << evaluate(expression,RPN) << endl;
  126.         cout << "逆波兰表达式为:" << *RPN << endl;
  127.        
  128.         return 0;
  129. }
复制代码

  1. //vector_char.cpp

  2. #include "vector_char.h"
  3. #include <iostream>

  4. using namespace std;

  5. Vector_char::Vector_char()
  6. {
  7.         _size = 4;
  8.         _capacity = 4;
  9.         elem = new OperType[_capacity];//建立容量为_size的数组
  10. }

  11. void Vector_char::expand()//空间不足时扩容
  12. {
  13.         if(_size < _capacity)//尚未满员时,不必扩容
  14.                 return;       
  15.         OperType * oldElem = elem;
  16.         elem = new OperType[_capacity <<= 1];//容量加倍
  17.         for(int i= 0;i < _size;i++)
  18.                 elem[i] = oldElem[i];//复制原向量内容
  19.         delete []oldElem;//释放原空间
  20.         cout << "该向量扩容后容量为:" << _capacity << endl;
  21. //        print();
  22. }

  23. void Vector_char::shrink()//缩容
  24. {
  25.         if(_size << 2 > _capacity)//以25%为界
  26.         {
  27.                 cout << "不需要缩容" << endl;
  28.                 return;
  29.         }
  30.         cout << "缩容后:";
  31. //        print();
  32.         OperType * oldElem = elem;
  33.         elem = new OperType[_capacity >>= 1];//容量减半
  34.         for(int i= 0;i < _size;i++)
  35.                 elem[i] = oldElem[i];//复制原向量内容
  36.         cout << "缩容后有" << _size << "个单位" << endl;
  37.         delete [] oldElem;//释放原空间

  38. }

  39. Rank Vector_char::insert(Rank r,OperType optr)//插入
  40. {
  41. //        expand();//如果有必要,扩容
  42.         for(int i = _size;i>r;i--)
  43.                 elem[i] = elem[i-1];//自后向前,后继元素顺次后移一个单位
  44.         elem[r]=optr;
  45.         _size++;//置入新元素并更新容量
  46. //        cout << "插入e后:";
  47. //        print();
  48.         return r;//返回秩
  49. }

  50. int Vector_char::remove(Rank r)//删除秩为r的元素
  51. {
  52.         int e = elem[r];//备份被删除的元素
  53.         remove(r,r+1);//调用区间删除算法,等效于对区间[r,r+1)的删除
  54.         return e;//返回被删除元素
  55. }

  56. void Vector_char::remove(Rank lo,Rank hi)//删除区间[lo,hi]
  57. {
  58.         while(hi < _size)
  59.                 elem[lo++] = elem[hi++];//[hi,_size)顺次前移hi-lo个单元
  60.         _size = lo;//更新规模,丢弃尾部[lo,_size = hi)区间
  61. //        cout << "删除后:";
  62. //        print();
  63.         shrink();//若有必要,缩容
  64.        
  65. //        return hi - lo;//返回被删除元素的数目
  66. }

  67. void Vector_char::print()
  68. {
  69.         for(int i =0;i<_size;i++)
  70.                 cout << elem[i] << "\t";
  71.         cout << endl;
  72. }

  73. OperType * Vector_char::back(int r)//返回elem指针
  74. {
  75.         return elem+r;
  76. }

  77. bool Vector_char::empty()//判断栈内是否为空
  78. {
  79.         int elem_length = sizeof(elem)/sizeof(*elem);
  80.         if (elem_length == 0)
  81.                 return true;
  82.         else
  83.                 return false;
  84. }
复制代码

  1. //vector_data.cpp

  2. #include "vector_data.h"
  3. #include <iostream>

  4. using namespace std;

  5. Vector_data::Vector_data()
  6. {
  7.         _capacity = 4;
  8.         elem = new DataType[_capacity];//建立容量为_capacity的数组
  9.         _size = 4;
  10. }

  11. void Vector_data::expand()//空间不足时扩容
  12. {
  13.         if(_size < _capacity)//尚未满员时,不必扩容
  14.                 return;       
  15.         DataType * oldElem = elem;
  16.         elem = new DataType[_capacity <<= 1];//容量加倍
  17.         for(int i= 0;i < _size;i++)
  18.                 elem[i] = oldElem[i];//复制原向量内容
  19.         delete []oldElem;//释放原空间
  20. //        cout << "该向量扩容后容量为:" << _capacity << endl;
  21. //        print();
  22. }

  23. void Vector_data::shrink()//缩容
  24. {
  25.         if(_size << 2 > _capacity)//以25%为界
  26.         {
  27.                 cout << "不需要缩容" << endl;
  28.                 return;
  29.         }
  30. //        cout << "缩容后:";
  31. //        print();
  32.         DataType * oldElem = elem;
  33.         elem = new DataType[_capacity >>= 1];//容量减半
  34.         for(int i= 0;i < _size;i++)
  35.                 elem[i] = oldElem[i];//复制原向量内容
  36. //        cout << "缩容后有" << _size << "个单位" << endl;
  37.         delete [] oldElem;//释放原空间
  38. }

  39. Rank Vector_data::insert(Rank r,DataType opnd)//插入
  40. {
  41. //        expand();//如果有必要,扩容
  42.         for(int i = _size;i>r;i--)
  43.                 elem[i] = elem[i-1];//自后向前,后继元素顺次后移一个单位
  44.         elem[r]=opnd;
  45.         _size++;//置入新元素并更新容量
  46. //        cout << "插入e后:";
  47.         return r;//返回秩
  48. }

  49. int Vector_data::remove(Rank r)//删除秩为r的元素
  50. {
  51.         int e = elem[r];//备份被删除的元素
  52.         remove(r,r+1);//调用区间删除算法,等效于对区间[r,r+1)的删除
  53.         return e;//返回被删除元素
  54. }

  55. void Vector_data::remove(Rank lo,Rank hi)//删除区间[lo,hi]
  56. {
  57.         while(hi < _size)
  58.                 elem[lo++] = elem[hi++];//[hi,_size)顺次前移hi-lo个单元
  59.         _size = lo;//更新规模,丢弃尾部[lo,_size = hi)区间
  60. //        cout << "删除后:";
  61. //        cout << "_size是:" << _size << endl;
  62.         shrink();//若有必要,缩容
  63.        
  64. //        return hi - lo;//返回被删除元素的数目
  65. }

  66. void Vector_data::print()
  67. {
  68.         for(int i =0;i<_size;i++)
  69.                 cout << elem[i] << "\t";
  70.         cout << endl;
  71. }

  72. DataType * Vector_data::back(int r)
  73. {
  74.         return elem+r;
  75. }
复制代码

  1. //counter_char.h

  2. #ifndef _COUNTER_CHAR_H_
  3. #define _COUNTER_CHAR_H_

  4. #include<iostream>
  5. #include "vector_char.h"//以向量为基类,派生出栈模板类

  6. using namespace std;

  7. class Stack_char:public Vector_char{//将向量的 首/末端 作为 栈底/顶
  8. public:
  9.         void push(OperType optr){insert(size(),optr);}//入栈,常引用作参数
  10.         OperType pop(){return remove(size()-1);}//出栈,删除末元素  将末元素改为其前驱
  11.         OperType & top(){return *(back(size())-1);}//取顶 ,引用作为返回值
  12. };
  13. #endif
复制代码

  1. //counter_data.h

  2. #ifndef _COUNTER_DATA_H_
  3. #define _COUNTER_DATA_H_

  4. #include<iostream>
  5. #include "vector_data.h"//以向量为基类,派生出栈模板类

  6. using namespace std;

  7. class Stack_data:public Vector_data{//将向量的 首/末端 作为 栈底/顶
  8. public:
  9.         void push(DataType opnd){insert(size(),opnd);}//入栈,常引用作参数
  10.         DataType pop(){return remove(size()-1);}//出栈,删除末元素  将末元素改为其前驱
  11.         DataType & top(){return *(back(size())-1);}//取顶 ,引用作为返回值
  12. };

  13. #endif
复制代码

  1. //vector_char.h

  2. //存放操作符

  3. //存放数字
  4. //存放字符
  5. #ifndef _VECTOR_CHAR_H_
  6. #define _VECTOR_CHAR_H_

  7. #include<iostream>
  8. using namespace std;

  9. typedef int Rank;
  10. typedef char OperType;

  11. class Vector_char
  12. {
  13. private:
  14.         char *p;//p指向数组elem,用于释放数组
  15.         OperType *elem;
  16.         int _capacity;//_capacity是数组容量
  17.        
  18. public:
  19.         Rank _size;//_size是实际规模
  20.         Rank size()const{return _size;}//规模
  21.         void expand();//空间不足时扩容
  22.         void shrink();//缩容
  23.         Rank insert(Rank r,OperType optr);//插入
  24.         int remove(Rank r);//删除秩为r的元素
  25.         void remove(Rank lo,Rank hi);//删除区间[lo,hi]
  26.         void print();
  27.         OperType * back(int r);//返回elem指针
  28.         bool empty();
  29.        
  30.         //构造函数
  31.         Vector_char();
  32. };

  33. #endif
复制代码

  1. //counter_data.h

  2. //存放数字
  3. #ifndef _VECTOR_DATA_H_
  4. #define _VECTOR_DATA_H_

  5. #include<iostream>
  6. using namespace std;

  7. typedef int Rank;
  8. typedef int DataType;

  9. class Vector_data
  10. {
  11. private:
  12.         int *p;//p指向数组elem,用于释放数组
  13.         DataType *elem;
  14.         int _capacity;//_capacity是数组容量
  15.        
  16. public:
  17.         Rank _size;//_size是实际规模
  18.         Rank size()const{return _size;}//规模
  19.         void expand();//空间不足时扩容
  20.         void shrink();//缩容
  21.         Rank insert(Rank r,DataType opnd);//插入
  22.         int remove(Rank r);//删除秩为r的元素
  23.         void remove(Rank lo,Rank hi);//删除区间[lo,hi]
  24.         void print();
  25.         DataType * back(int r);//返回elem指针
  26.        
  27.         //构造函数
  28.         Vector_data();
  29. };

  30. #endif
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2020-12-14 13:00:54 | 显示全部楼层
main函数改一下:
  1. int main()
  2. {
  3.         char expression[20];
  4.         char RPN[10];
  5.         cout << "请输入要计算的式子:";
  6.         cin.getline(expression,20);
  7.         for(int i=0;i<4;i++)
  8.                 cout << expression[i];
  9.         cout << endl;
  10.         cout << int(expression[3]) << endl;//我输入1+2,expression[3]为2后面的字符
  11.         cout << "计算结果为:" << evaluate(expression,RPN) << endl;
  12.         cout << "逆波兰表达式为:" << *RPN << endl;
  13.        
  14.         return 0;
  15. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-12-14 13:08:36 | 显示全部楼层
以下为输出:

请输入要计算的式子:1+2
1+2
0
这一轮while是if
*S是:1
这一轮while是else
*S是:+
op:0
op:43
orderBetween(optr.top(),*S):<
op:0
op:43
这一轮while是if
*S是:2
不需要缩容
这一轮while是else
*S是:
op:43
op:32
语法错误3
Press any key to continue

第三行的输出为0,说明用户输入的“1+2”的2后面是'\0'
'+'对应的ascii码为43
但是在最后一轮while循环中,却是表明2后面是空格(空格对应的ascii码为32)
就是这个地方debug了我一整天都没搞懂……求助各位,这是为什么?
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-5-8 02:26

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表