服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C/C++ - C语言实现合式公式的判断示例

C语言实现合式公式的判断示例

2022-11-03 14:38New Youg C/C++

这篇文章主要介绍了C语言实现合式公式的判断示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

前言

本文介绍通过 编程实现《离散数学》中的合式公式的判断。

合式公式

C语言实现合式公式的判断示例

很明显用递归去模拟实现判断过程相对容易。(当然利用栈,循环实现也行,毕竟递归是发生在栈区(函数栈帧),另外递归解决时要处理的细节就很多了,循环会更麻烦)。

由合式公式的定义,很明显原子公式就是我们递归的出口,确定了出口,剩下就是怎么通过递归算法,递推到这个出口

约定

联结词 代替  
 
合取(^) *(数量积)  
析取(V) +(数量和)  
蕴含(->) >  
等价 =

思路

C语言实现合式公式的判断示例

删除否定联结词

思路用一个辅助数组去占时存储非!的字符,之后拷贝到原区间,不过要对原区间进行赋值\0

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
void Del_Negation(char* str,int n)
{
 
    assert(str);
    char* tmp = (char*)calloc(n+1, sizeof(char));//多一个1,是为了放置\0,避免strcpy越界拷贝
    assert(tmp);
    int cnt = 0;
    int i = 0;
    while (i < n)//将除!的字符赋值到tmp中
    {
        if (str[i] != '!')
        {
            tmp[cnt++] = str[i];
        }
        ++i;
    }
 
    memset(str, 0, sizeof(char)*n);//对str那块内存重新赋值为\0,防止tmp拷贝到str中后,s扔有旧的数据
    strcpy(str, tmp);
    free(tmp);
    tmp = NULL;
}

删除括号

删除括号,因为是对首尾进行的删除,这里通过2次strcpy就可以完成

?
1
2
3
4
5
6
7
8
9
void Del_Bracket( char* str, int left, int right)
{
    assert(str);
    char* tmp = (char*)calloc(right - left +1+1, sizeof(char));
    assert(tmp);
    str[right] = '\0';
    strcpy(tmp, str+left+1);
    strcpy(str+left, tmp);
}

第一个联结词的下标

找寻区间中第一双目运算符:找到就返回下标,否则就返回0.

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int Find_Fist_operator( char* str, int left, int right)
{
    int ret = 0;
    while (left<right)
    {
 
        if (str[left + 1] == '+' || str[left + 1] == '*' || str[left + 1] == '>' || str[left + 1] == '=')
        {
            ret = left + 1;
            return ret;
        }
 
        ++left;
    }
    return 0;//如果ret是0,说明是非法,反之就正确
}

判断合式公式

注意区间的操作,不然很容易造成野指针的访问。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
bool Is_CombForm(char* str, int left, int right)
{
 
    if ((0 == (right - left))//区间是原子命题
        && ('A' <= str[left] || 'Z' >= str[left]))
    {
        return true;
    }
 
    if (str[left] != '(')//第一个字符是字母: A>(B)
    {
        int keyi = Find_Fist_operator(str, left, right);//找寻第一个双目运算符
        if (keyi > 0)
        {
            if (str[keyi + 1] == '(')//A<(B)
            {
                Del_Bracket(str, keyi + 1, right);
                return Is_CombForm(str, left, keyi - 1) && Is_CombForm(str, keyi + 1, right - 2);
            }
            else//A<B
            {
                return Is_CombForm(str, left, keyi - 1) && Is_CombForm(str, keyi + 1, right);
            }
        }
    }
    else//第一个是(:(A)<B
    {
        int brackt = 0;//当brackt为0,说明将双目运算符的左操作数全体找到了
        int cnt = left;
        int flag = 0;
        while (cnt<right)
        {
            if (str[cnt] == '(')
            {
                brackt++;
            }
            if (str[cnt] == ')')
            {
                brackt--;
                flag = cnt;
            }
            ++cnt;
            //[  left  , flag]  >  [flag+2,right]
            if (brackt == 0)
            {
                Del_Bracket(str, left, flag);
                if (str[flag + 2] == '(')
                {
                    Del_Bracket(str, flag + 2, right);
                    return Is_CombForm(str, left, flag - 2) && Is_CombForm(str, flag+ 2, right - 2);
                }
                else
                {
                    return Is_CombForm(str, left, flag - 2) && Is_CombForm(str, flag + 2, right);
                }  
            }
        }
    }
    return false;
}

所有代码

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include<time.h>
#include<windows.h>
 
using namespace std;
//思路用一个辅助数组去占时存储非!的字符,之后拷贝到原区间,不过要对原区间进行赋值0
void Del_Negation(char* str,int n)
{
 
    assert(str);
    char* tmp = (char*)calloc(n+1, sizeof(char));//多一个1,是为了放置\0,避免strcpy越界拷贝
    assert(tmp);
    int cnt = 0;
    int i = 0;
    while (i < n)//将除!的字符赋值到tmp中
    {
        if (str[i] != '!')
        {
            tmp[cnt++] = str[i];
        }
        ++i;
    }
 
    memset(str, 0, sizeof(char)*n);//对str那块内存重新赋值为\0,防止tmp拷贝到str中后,s扔有旧的数据
    strcpy(str, tmp);
    free(tmp);
    tmp = NULL;
}
 
//删除括号,因为是对首尾进行的删除,这里通过2次strcpy就可以完成
void Del_Bracket( char* str, int left, int right)
{
    assert(str);
    char* tmp = (char*)calloc(right - left +1+1, sizeof(char));
    assert(tmp);
    str[right] = '\0';
    strcpy(tmp, str+left+1);
    strcpy(str+left, tmp);
}
 
//判断是否为原子式
//因为去除括号的原因,当只有一个字母是原子式,否则不是
bool Is_operator(const char* str,int left,int right)
{
    assert(str);
 
    if ((0==(right-left))
        &&('A' <=str[left]||'Z'>=str[left]))
    {
    return true;
    }
    return false;
}
 
//找寻区间中第一双目运算符:找到就返回下标,否则就返回0.
int Find_Fist_operator( char* str, int left, int right)
{
    int ret = 0;
    while (left<right)
    {
 
        if (str[left + 1] == '+' || str[left + 1] == '*' || str[left + 1] == '>' || str[left + 1] == '=')
        {
            ret = left + 1;
            return ret;
        }
 
        ++left;
    }
    return 0;//如果ret是0,说明是非法,反之就正确
}
 
bool Is_CombForm(char* str, int left, int right)
{
 
    if ((0 == (right - left))//区间是原子命题
        && ('A' <= str[left] || 'Z' >= str[left]))
    {
        return true;
    }
 
    if (str[left] != '(')//第一个字符是字母: A>(B)
    {
        int keyi = Find_Fist_operator(str, left, right);//找寻第一个双目运算符
        if (keyi > 0)
        {
            if (str[keyi + 1] == '(')//A<(B)
            {
                Del_Bracket(str, keyi + 1, right);
                return Is_CombForm(str, left, keyi - 1) && Is_CombForm(str, keyi + 1, right - 2);
            }
            else//A<B
            {
                return Is_CombForm(str, left, keyi - 1) && Is_CombForm(str, keyi + 1, right);
            }
        }
    }
    else//第一个是(:(A)<B
    {
        int brackt = 0;//当brackt为0,说明将双目运算符的左操作数全体找到了
        int cnt = left;
        int flag = 0;
        while (cnt<right)
        {
            if (str[cnt] == '(')
            {
                brackt++;
            }
            if (str[cnt] == ')')
            {
                brackt--;
                flag = cnt;
            }
            ++cnt;
            //[  left  , flag]  >  [flag+2,right]
            if (brackt == 0)
            {
                Del_Bracket(str, left, flag);
                if (str[flag + 2] == '(')
                {
                    Del_Bracket(str, flag + 2, right);
                    return Is_CombForm(str, left, flag - 2) && Is_CombForm(str, flag+ 2, right - 2);
                }
                else
                {
                    return Is_CombForm(str, left, flag - 2) && Is_CombForm(str, flag + 2, right);
                }  
            }
        }
    }
    return false;
}
 
 
 
void Text(char *str)
{
    cout << str;
    int sz = strlen(str);
    Del_Negation(str, sz);
    sz = strlen(str);
 
    if (Is_CombForm(str, 0, sz-1))
    {
        printf("-------YES\n");
    }
    else
    {
        printf("----------NO\n");
    }
}
int main ()
{  
    
 
 
    char arr1[] = "P>!R";
    char  arr2[] = "!(P>Q)>!R";
    
    char arr3[] = "P>((P*R)>Q)";
 
    char arr4[] = "((P>R)*(Q*(P>R)))=R";
    char arr5[] = "((P>Q)>R)>Y";
    char arr6[] = "PQ";
    char arr7[] = "(P>RT)>Q";
    char arr8[] = "((P>Q)*(P>QT))>(R*T)";
    Text(arr1);
    Text(arr2);
    Text(arr3);
    Text(arr4);
    Text(arr5);
    Text(arr6);
    Text(arr7);
    Text(arr8);
 
 
    printf("-------------------------BY New Young\n");
 
    return 0;
}

效果

C语言实现合式公式的判断示例

总结

对于复杂的需要很多细节的递归函数,只能一个一个处理调理,不能急。

 到此这篇关于C语言实现合式公式的判断示例的文章就介绍到这了,更多相关C语言 合式公式内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://blog.csdn.net/qq_55439426/article/details/123931176

延伸 · 阅读

精彩推荐
  • C/C++深入探讨C语言中局部变量与全局变量在内存中的存放位置

    深入探讨C语言中局部变量与全局变量在内存中的存放位置

    本篇文章是对在C语言中局部变量与全局变量在内存中的存放位置进行了详细的分析介绍,需要的朋友参考下...

    C语言教程网2892020-12-08
  • C/C++C语言中递归和排列组合详解

    C语言中递归和排列组合详解

    大家好,本篇文章主要讲的是C语言中递归和排列组合详解,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下,方便下次浏览...

    布布要成为最强的人9052022-08-17
  • C/C++C++如何实现简易扫雷游戏

    C++如何实现简易扫雷游戏

    这篇文章主要为大家详细介绍了C++如何实现简易扫雷游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    XSamsara4012021-08-25
  • C/C++c语言实现简单的易语言

    c语言实现简单的易语言

    在本篇内容里小编给大家整理了一篇关于c语言实现一个简单的易语言的相关知识点,需要的朋友们参考下。...

    C语言教程网3872021-07-12
  • C/C++详解c++11以正确的姿势输出enum class的值

    详解c++11以正确的姿势输出enum class的值

    这篇文章主要介绍了详解c++11以正确的姿势输出enum class的值,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的...

    ztenv10172021-09-30
  • C/C++一元多项式加法运算

    一元多项式加法运算

    今天小编就为大家分享一篇关于一元多项式加法运算,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧...

    baiduoWang4922021-07-24
  • C/C++详解C++编程中用数组名作函数参数的方法

    详解C++编程中用数组名作函数参数的方法

    这篇文章主要介绍了详解C++编程中用数组名作函数参数的方法,是C++入门学习中的基础知识,需要的朋友可以参考下...

    C++教程网8122021-03-12
  • C/C++C语言用栈模拟实现队列问题详解

    C语言用栈模拟实现队列问题详解

    本片文章带你分析如何用两个栈,并且只使用栈的基本功能来模拟实现队列,其中同样只实现队列的基本功能,感兴趣的朋友来看看吧...

    _奇奇11592022-11-02