以最简单的方式实现几个C语言课程设计的常见题目,适合大一或者刚学习C语言的同学学习参考。使用Code::Blocks编译器创建的纯C项目,将其中的源码粘贴进其他编译器或C++项目也可直接运行。因为部分同学没有学习过数据结构,所以尽量使用传统的数组进行存储,规避没有学习过的知识点,但鼓励大家自己改进。为了使得程序更加简单方便阅读,基本上没有进行对用户输入的容错,可以自己添加。
Code::Blocks安装和使用 https://blog.csdn.net/qq_42283621/article/details/124055391?spm=1001.2014.3001.5501
项目源码会在文章末尾给出
文章目录- 中缀表达式 vs. 后缀表达式(逆波兰表达式)
- 分割字符串 和 类型转换
- 字符串转数字
- 栈 和 队列 的实现
- 中缀表达式 转 后缀表达式
- 后缀表达式计算
- 附录——全部代码
参考文章:https://blog.csdn.net/qq_42446156/article/details/108162504
https://www.bilibili.com/video/BV1xp4y1r7rc?spm_id_from=333.337.search-card.all.click 中缀表达式 vs. 后缀表达式(逆波兰表达式)
中缀表达式: *** 作符在 *** 作数的中间,就是我们常见表达式的类型,需要括号来帮助定义计算的顺序,如果把结果去掉就会产生歧义。
1 + ( ( 2 + 3 ) × 4 ) - 5:2+3=5;5×4=20;1+20=21;21-5=16
1 + 2 + 3 × 4 - 5:3 × 4 = 12;1+ 2 = 3;3 + 12 = 15;15 - 5 = 10
后缀表达式: *** 作符在 *** 作数的后面,不需要括号,不会产生歧义。 1 2 3 + 4 × + 5 –
1 2 3 + 4 × + 5 –:2 3 + = 5;5 4 × = 20;1 20 + = 21;21 5 - =16
中缀表达式 转 后缀表达式的步骤:
初始化运算符栈s 和 结果队列q;
从左至右扫描中缀表达式:
遇到 *** 作数时,将其加入q;
遇到运算符t时:
1.s空 / s栈顶为"(" / 运算符t的优先级大于栈顶元素的优先级,运算符t入栈s;× / 优先级大于 + -
2.否则,不断将s栈顶的运算符d出并加入q中直至 s空 / s栈顶为"(" / 运算符t的优先级大于栈顶元素的优先级(t的优先级和栈顶元素优先级相同也是需要d出的),然后运算符t入栈。
遇到括号时:
1.如果是左括号“(”,则直接压入s
2.如果是右括号“)”,则依次d出s栈顶的运算符加入q直至遇到左括号"("为止,左右括号丢弃并不加入到q中
看一下上面的例子:
首先,你要求用户输入的表达式是一个字符串,你需要分割出哪些是数字,哪些是 *** 作符。下面的代码仅供参考。
#include
#include
#include
//输入字符是否是 *** 作符 + - * / ( )
//是返回1,否返回0
int isOperator(char key)
{
if (key == '+' || key == '-'
|| key == '*'|| key == '/'
|| key == '('|| key == ')')
return 1;
return 0;
}
int main()
{
//原始输入
char rawInput[50];
printf("输入中缀表达式:");
scanf("%s", rawInput);
//字符串分割后的输入
char processedInput[50][20];
//分割后包含几个项
int cnt = 0;
int index = 0;
for (int i = 0; i < strlen(rawInput); ++i)
{
//如果该字符是 *** 作符
if (isOperator(rawInput[i]))
{
//如果前一个字符不是 *** 作符,那么在当前项的末尾加一个'if'表示当前项数字结束,并将当前项设置为下一项
( 0i > && isOperator ([rawInput-i 1 ])== 0 )[
{
processedInput]cnt[]index= ';' =0
index ; ++;
}cnt//存储 *** 作符,然后将当前项设置为下一项
[
]
processedInput[cnt0]=[ ] rawInput;i[]
processedInput[cnt1]=';' ++ ;}
//如果该字符不是 *** 作符,那么把该字符添加到当前项的末尾,即当前项的数字还没有结束cntelse
[
]
[
{
processedInput]cnt=[index] ; rawInput++i;if
(index==
strlen (i ) -1rawInput) [ ][
{
processedInput]cnt=';'index++ ; }}
}cnt//输出测试
printf
(
"%d\n\n"
,
);for( cntint=
0 ;< i ; ++) i printf cnt( "%s\n"i,
[]); processedInputreturni0;}
# include#
include
字符串转数字
接下来实现,从char数组到double数字的变换
#include
#include
//字符串 转 小数double
string2Double(
char
* )double=0 key;
{
//小数点的位置,-1表示没有小数点 result int =-
1
; index for (int=
0 ;< i strlen () i ; ++)keyif( [i]
{
== '.'key)i= ; }else
{
index = i*
10
+
{
result ( result [ ] - '0'key)i; } }if(
!=
-
1 )index /= pow(10
result , strlen()- -1key) ; index return ;}int
main result(
)
char [20]
{
; tscanf("%s",
);printf( t"%lf",
string2Double()) ;returnt0;}
# include#
include
栈 和 队列 的实现
栈 先进后出,队列 先进先出。我们本实验所使用的队列只有基本的 全部入队 全部出队,所以直接使用普通的数组代替即可。下面是栈的实现。
#include
char[
50]
[ stack20];//栈顶位置,初始时没有元素int=-
1
; sTop //入栈 voidpush(
char
* )++; strcpykey(
{
[sTop]
,)stack;sTop}//出栈 keyvoidpop
(
)
-- ;}//查看栈顶元素,无元素返回NULL
{
charsTop*
top
(
)if (==-
{
1 )sTop return NULL;else
return []
;
} stackcharsTop[50
]
[ queue20];//队列中的元素个数int=0
;
int qCnt main ()
int ;char[
{
20 cmd]
; inputwhile(1)
printf("\t\t0 退出\n\t\t1 入栈\n\t\t2 出栈\n\t\t3 查看栈顶元素\n\n")
{
;scanf("%d",
&);if (cmd==0
) breakcmd ; switch(
)case
1:cmdprintf
{
( "输入元素:") ;scanf("%s", );push( input); break;inputcase2 :pop
( ); break;case3 :printf
( "栈顶元素:%s\n", top()) ;break;}} return0
;
}
# include#
include
中缀表达式 转 后缀表达式
#include
#include
char[
50]
[ stack20];//栈顶位置,初始时没有元素int=-
1
; sTop //入栈 voidpush(
char
* )++; strcpykey(
{
[sTop]
,)stack;sTop}//出栈 keyvoidpop
(
)
-- ;}//查看栈顶元素,无元素返回NULL
{
charsTop*
top
(
)if (==-
{
1 )sTop return NULL;else
return []
;
} stackcharsTop[50
]
[ queue20];//队列中的元素个数int=0
;
//字符串 转 小数 qCnt double string2Double(
char
* )double=0 key;
{
//小数点的位置,-1表示没有小数点 result int =-
1
; index for (int=
0 ;< i strlen () i ; ++)keyif( [i]
{
== '.'key)i= ; }else
{
index = i*
10
+
{
result ( result [ ] - '0'key)i; } }if(
!=
-
1 )index /= pow(10
result , strlen()- -1key) ; index return ;}//输入字符是否是 *** 作符 + - * / ( )
//是返回1,否返回0 resultint
isOperator
(
char
) if(== key'+'
{
|| ==key '-' || == key '*' ||
== key '/' ||== key '(' ||
== key ')' )return key 1 ;return
0 ;}
//运算符 a的优先级大于b的优先级返回1,否则返回0 inthighPriority
(
char
, char)if a( ( b==
{
'*' ||==a '/' ) && a ( =='+' || ==b '-' ) ) b return 1;return
0 ;}
int main(
)
//原始输入 char[50
{
]
; rawInputprintf("输入中缀表达式:")
;scanf("%s",
);//字符串分割后的输入char rawInput[50
]
[ processedInput20];//分割后包含几个项int=0
;
int cnt = 0;
for index ( int=
0 ;< i strlen () i ; ++)rawInput//如果该字符是 *** 作符if (iisOperator
{
(
[ ]))rawInput//如果前一个字符不是 *** 作符,那么在当前项的末尾加一个'if'表示当前项数字结束,并将当前项设置为下一项i(0&&
{
isOperator
( [i > - 1 ])rawInput==i 0 )[] [ ]=
{
processedInput';'cnt=0index; ++ ;}
index //存储 *** 作符,然后将当前项设置为下一项 []
[cnt0
]
=
processedInput[cnt];[] [ rawInput1i]=
processedInput';'cnt++;}//如果该字符不是 *** 作符,那么把该字符添加到当前项的末尾,即当前项的数字还没有结束 else []
[cnt]
=
[
]
{
processedInput;cnt++;indexif ( rawInput==istrlen(
)index-
1 )i [ ][rawInput] = ';'++
{
processedInput;cnt}}index} //中缀 转 后缀 for(
intcnt=
0
;
<
;
++ )// *** 作数 i if (isOperator i ( cnt[ ]i[
{
0
] )==0processedInput)istrcpy([], [ ])
{
;++queue;qCnt}// ( processedInputelseiif([
]qCnt[
0
]
== '(' )processedInputpushi([]) ; }// )
{
elseifprocessedInput(i[][
0
]
== ')' )processedInputwhilei(1)if ( top(
{
) [0]
{
== '(')pop();break ; }else
{
strcpy([]
,top
(
)
{
);queue++qCnt;pop ();}}
}qCnt// + - * /
else//将s栈顶的运算符d出并加入q中直至 s空 / s栈顶为"(" / 运算符t的优先级大于栈顶元素的优先级while(
top
(
)
!=
NULL
{
&&
top()[0 ] != '(' &&highPriority([][ 0 ] , top(processedInput)i[0])== 0)strcpy([], top ()
{
);queue++qCnt;pop ();}push
(qCnt[
]);}
}
while(processedInputtopi()!=
NULL
)
strcpy ([], top ()
{
);queue++qCnt;pop ();}//测试输出后缀表达式
forqCnt(
int=0;
<
;
++ )printf i ( "%s ", i [ qCnt] )i;
printf("\n") queue;ireturn0;
}#include#include
# include#
include
后缀表达式计算
预备一个空栈s
从左至右扫描后缀表达式:
遇到 *** 作数时,将其加入s;
遇到运算符t时:d出栈顶的两个元素,进行运算,将结果入栈
char[
50]
[20
];
//栈顶位置,初始时没有元素 stackint=-1;//入栈void
push
( sTop char *)++
;
strcpy ([] ,key)
{
;sTop}
//出栈voidstackpopsTop() key--;
}
//查看栈顶元素,无元素返回NULL
char *top(
{
)sTopif
(
==
-1 )returnNULL
{
; elsesTop return [];
} char[
50
] stack[sTop20]
;
//队列中的元素个数 queueint=0;//字符串 转 小数doublestring2Double
(
char qCnt * )double
=
0 ;//小数点的位置,-1表示没有小数点int= key-
{
1 result ; for(
int
= index 0 ;<strlen
( ); i ++ )if i ( []key=='.' )i=
{
; }keyelsei= * 10+
{
index ( i[
]
-
{
result '0' result ) ; } }keyifi( != -1)
/=
pow
( 10index , strlen()
result - -1); return;key} //输入字符是否是 *** 作符 + - * / ( ) index //是返回1,否返回0 intisOperator(
char result)
if
(
==
'+' ||=='-' key||
{
== '*'key || == '/' key || ==
'(' key || ==')' key ) return
1 key ; return0 key ; }//运算符 a的优先级大于b的优先级返回1,否则返回0
int highPriority(
char ,char
)
if
( (=='*' a|| == b'/'
{
) &&(a == '+' || a == '-') ) returnb 1 ; return b 0 ;}int
main ()
//原始输入 char[
50
] ;printf(
{
"输入中缀表达式:"
) rawInput;scanf("%s"
,);//字符串分割后的输入char
[50][ rawInput20]
;
//分割后包含几个项 processedInputint=0;int=0
;
for cnt ( int=
0 index ; <strlen
( ); i ++ )//如果该字符是 *** 作符 i if (isOperatorrawInput([ ]i)
{
)
//如果前一个字符不是 *** 作符,那么在当前项的末尾加一个'if'表示当前项数字结束,并将当前项设置为下一项 (0&&rawInputisOperatori([-
{
1
] )i > == 0 )[rawInput]i [ ]=';' = 0;
{
processedInput++cnt;}index//存储 *** 作符,然后将当前项设置为下一项 [ ][
index 0 ]=
[cnt]
;
[
processedInput]cnt[1]= ';' rawInput++i;}
processedInput//如果该字符不是 *** 作符,那么把该字符添加到当前项的末尾,即当前项的数字还没有结束cntelse[][ ] =[
]cnt;
++
;
if
{
processedInput(cnt==strlenindex( ) rawInput-i1)
[index]
[ ]i = ';'++rawInput; } }}
{
processedInput//中缀 转 后缀cntfor(indexint = 0;
<cnt;
++
)
// *** 作数
if
( isOperator( i [ ][ i 0 cnt] )i==
{
0
) strcpy([processedInput]i,[]); ++ ;}
{
// (elsequeueifqCnt([ processedInput]i[0]
==qCnt'('
)
push
( [ ]processedInput)i;}// )else if ([
{
][processedInput0i]==')'
)
while
( 1 )processedInputifi(top() [ 0]
{
== '(')pop
{
( );break;}elsestrcpy ( []
{
,top()
);
++
;
{
pop(queue)qCnt;} }}// + - * /else//将s栈顶的运算符d出并加入q中直至 s空 / s栈顶为"(" / 运算符t的优先级大于栈顶元素的优先级
whileqCnt(
top()!=
NULL
&&
top
(
)
{
[
0]!='('&& highPriority ( [ ][0],top ( ) [ 0]processedInput)i==0)strcpy( [],top()) ; ++;
{
pop(queue)qCnt;} push([])
;qCnt}
}while(top
(
)!=processedInputNULLi)strcpy(
[
]
, top()) ; ++;
{
pop(queue)qCnt;} //测试输出后缀表达式printf("后缀表达式:")
;qCntfor
(int=0
;
<
;++)printf(
"%s " ,[ i ] ); i printf qCnt( "\n"i)
;double[50 queue]i;int=
-1;//后缀表达式计算for
( doubleStackint=0;
< sDTop ; ++)if
(
isOperator ([ i ] [0 i ] qCnt) )idouble
{
= 0;doublequeue=i[];--;double
{
= result [ ];
-- tb ; doubleStackswitchsDTop([
]sDTop[
0 ta ] doubleStack)sDTopcase'+'
:sDTop=
+;queuebreaki;case'-':=
{
- ;break result ; ta case tb'*' :=
* ;break result ; ta case tb'/' :=
/ ;break result ; ta } tb++ ;[
] =; result } ta else tb++ ;[
]
=sDTopstring2Double
doubleStack(sDTop[ ] result)
;
}
{
}sDTopprintf
doubleStack(sDTop"结果:%lf\n" , [0queue]i);return
0
;
} doubleStack
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)