一、括號匹配問題
1、題目和要求
時間限制:1s,內存限制:32MB,特殊判題:否
2、總結
1)c++有自帶的求char數組
長度的函數strlen()
,頭文件是string.h
。自己還花時間寫了一個函數來求長度。
自己寫的函數直接在else裏返回 ,但是不符合在線編譯器編譯規則,應改爲下面的寫法:在函數末尾return
。
//修改前,計算輸入字符串長度
int stringLength(char* c)
{
int i=0;
while(i<N)
{
if(c[i]!='\0'){i++;}
else{return i;}
}
}
//修改後,計算輸入字符串長度
int stringLength(char* c)
{
int i=0;
while(i<N)
{
if(c[i]!='\0'){i++;}
else{break;}
}
return i;
}
2)scanf("%s",input_string)
和scanf("%s",&input_string)
,第二種寫法 ,不符合在線編譯器編譯規則。數組名本來就表示了數組的首地址,多加一個&
,畫蛇添足!!!
3)由於系統通過判斷是否遇到’\0’,來決定是否終止字符串輸出;因此,當數組預留空間大於需要輸出的數組長度時,在輸出字符串的末尾一定要加上output_string[strlen(input_string)] = '\0'
作爲結束符,否則還會繼續輸出一些未知的東西。
怎樣的char數組,系統會自動在結尾加上’\0’呢?
1.當以字符串形式在代碼中爲數組賦值時,系統會自動爲’\0’開一個存儲空間。
2.字符串長度不包括’\0’。
3、思路
主要思路:輸入字符串後,從後往前遍歷。遇到右括號入棧;遇到左括號根據中間棧中的內容進行下一步操作,如果棧爲空則不匹配,如果棧頂爲右括號則出棧。當輸入字符串遍歷結束後,若棧中還剩餘則不匹配。
4、代碼
#include <stdio.h>
#include <stack>
#include <string.h>
using namespace std;
#define N 100
//)(rttyy())sss)(
//存儲括號和位置信息
class bracket
{
private:
int pos;
char value;
public:
bracket() {};
void set(int p,char v)
{
pos = p;
value = v;
};
int getPos()
{
return pos;
}
char getValue()
{
return value;
}
};
int main()
{
char input_string[N]; //記錄輸入字符串
char output_string[N]; //記錄輸出字符串
int i; //記錄輸入字符串、輸出字符串位置
char c; //記錄當前字符
bracket b;
stack<bracket> s; //中間棧
scanf("%s",input_string);
for(i=strlen(input_string)-1; i>=0; i--)
{
c = input_string[i];
switch (c)
{
case ')':
b.set(i,c);
s.push(b);
break;
case '(':
if(s.empty())
{
output_string[i] = '$';
}
else
{
b = s.top();
if(b.getValue()==')')
{
s.pop();
output_string[i] = ' ';
output_string[b.getPos()] = ' ';
}
}
break;
default:
output_string[i] = ' ';
}
}
while(!s.empty())
{
b = s.top();
output_string[b.getPos()] = '?';
s.pop();
}
output_string[strlen(input_string)] = '\0';
printf("%s\n",input_string);
printf("%s\n",output_string);
return 0;
}
二、簡單計算器
1、題目和要求
時間限制:1s,內存限制:32MB,特殊判題:否
2、總結
1)using namespace std
和.h
兩種方式的區別。選自:頭文件加.h和不加,h區別,以及using namespace std。
.h
是C語言中使用的,當使用.h
時,相當於在c中調用庫函數,使用的是全局命名空間。
C++ 標準程序庫中的所有標識符都被定義於一個名爲std的namespace中,因此使用前要聲明命名空間。using namespace std
是c++中聲明命名空間的一種方式。
2)stdio
和iostream
兩種標準輸入輸出庫的區別。
stdio
屬於c語言,輸入輸出爲printf(),scanf()。
iostream
屬於c++,輸入輸出爲cout<<…,cin>>…。
3)c++中字符串的存儲和讀取方式。c++存儲字符串的方法( 讀取字符串、char 數組、string 類型)
在下面的代碼中,沒有指定getline()
函數的結束符,輸入ctrl+z
即可結束。
4)C語言中保留小數點後兩位數:printf("%.2lf",a);
c++中保留小數點後兩位數:cout << fixed <<setprecision(2)<<a;
5)注意:
- 操作數出棧順序與入棧順序相反,除法和減法操作需注意。
- 進行 “一次” 運算要出棧 “兩個操作數” 和 “一個運算符” 。
- switch-case切記break!!
3、思路
1)設兩個堆棧,一個運算符棧,一個數字棧。
2)從左至右依次遍歷字符串。若遍歷到運算符,入運算符棧;若遍歷到數字,則開始拼接數字,完成後入數字棧。
3)開始計算。
1>若運算符棧棧頂運算符爲 × 、/,則彈出棧頂運算符,再從數字棧中依次彈出兩個棧頂數字,完成運算後,將結果壓入數字棧。
2>若運算符棧棧頂運算符爲 + 、- 且棧頂下一個運算符爲 × 、/,則彈出棧頂運算符和棧頂數字,保存。然後,彈出當前棧頂運算符,再從數字棧中依次彈出兩個棧頂數字,完成運算後,將結果壓入數字棧。最後,把剛剛保存的運算符和數字壓棧。
4)若運算符棧爲空,則運算結束,此時數字棧中唯一的數字即爲表達式的值,顯示後,彈出,爲下一輪運算清空棧。
4、代碼
#include <iostream>
#include <string>
#include <stack>
#include <iomanip>
using namespace std;
#define N 200
stack<char> op; //運算符棧
stack<double> num; //操作數棧
double a,b; //兩個操作數
double add()
{
a = num.top();
num.pop();
b = num.top();
num.pop();
return (a+b);
}
double jianfa()
{
a = num.top();
num.pop();
b = num.top();
num.pop();
return (b-a);
}
double mul()
{
a = num.top();
num.pop();
b = num.top();
num.pop();
return (a*b);
}
double div()
{
a = num.top();
num.pop();
b = num.top();
num.pop();
return (b/a);
}
int main()
{
string input_string;
char c,t;
double value = 0;
//使用getline讀取,可以讀取空格和換行
while(getline(cin,input_string)!=0)
{
if(input_string=="0")
{
continue;
}
//從字符串開頭開始遍歷,入操作數棧和運算符棧
for(int i=0 ; i<input_string.length(); )
{
c = input_string[i];
if(c =='+' || c =='-'||c =='*'||c =='/')
{
op.push(c);
i++;
}
else if(c<='9'&&c>='0')
{
while(c<='9'&&c>='0')
{
value = value*10 +(double)(c-'0');
i++;
c = input_string[i];
}
num.push(value);
value = 0;
}
else
{
i++;
}
}
while(!op.empty())
{
c = op.top();
op.pop();
switch(c)
{
case '+':
if(op.empty())
{
num.push(add());
}
else
{
t = op.top();
if(t=='+'||t=='-')
{
num.push(add());
}
else if(t=='*')
{
op.pop();
double number = num.top();
num.pop();
num.push(mul());
num.push(number);
op.push(c);
}
else if(t=='/')
{
op.pop();
double number = num.top();
num.pop();
num.push(div());
num.push(number);
op.push(c);
}
}
break;
case '-':
if(op.empty())
{
num.push(jianfa());
}
else
{
t = op.top();
if(t=='+'||t=='-')
{
num.push(jianfa());
}
else if(t=='*')
{
op.pop();
double number = num.top();
num.pop();
num.push(mul());
num.push(number);
op.push(c);
}
else if(t=='/')
{
op.pop();
double number = num.top();
num.pop();
num.push(div());
num.push(number);
op.push(c);
}
}
break;
case '*':
num.push(mul());
break;
case '/':
num.push(div());
break;
}
}
if(!num.empty())
{
cout << fixed <<setprecision(2)<<num.top()<<endl;
num.pop();
}
}
return 0;
}