符号配对(C 语言)

请编写程序检查C语言源程序中下列符号是否配对:/**/()[]{}

输入格式:

输入为一个C语言源程序。当读到某一行中只有一个句点 .和一个回车的时候,标志着输入结束。程序中需要检查配对的符号不超过100个。

输出格式:

首先,如果所有符号配对正确,则在第一行中输出YES,否则输出NO。然后在第二行中指出第一个不配对的符号:如果缺少左符号,则输出?-右符号;如果缺少右符号,则输出左符号-?

输入样例1:

void test()
{
    int i, A[10];
    for (i=0; i<10; i++) /*/
        A[i] = i;
}
.

输出样例1:

NO
/*-?

输入样例2:

void test()
{
    int i, A[10];
    for (i=0; i<10; i++) /**/
        A[i] = i;
}]
.

输出样例2:

NO
?-]

输入样例3:

void test()
{
    int i
    double A[10];
    for (i=0; i<10; i++) /**/
        A[i] = 0.1*i;
}
.

输出样例3:

YES

思路:

每一对符号配对的前提是其中间的所有符号都配对了,因此先出现的符号要想配对,首先需要后出现的符号都配对了。这就有点类似于栈的思想,思路就是遍历所有字符,遇到左符号进栈,遇到右符号配对。配对时有几种可能的情况:

  • 栈为空,栈中没有左符号。说明右符号缺少对应的左符号,输出 “?-右符号”,退出程序。
  • 栈不为空,栈顶符号与右符号配对成功,栈顶符号出栈。
  • 栈不为空,但栈顶符号与右符号配对失败。此时应该是栈顶符号缺少对应的右符号,需要输出 “左符号-?”。

经验:

  • 在遍历的过程中,将 /**/ 转换成 <> 处理更加方便,所以也要单独拎出来进行判断。
  • scanf 会默认跳过空格和回车的,如果字符串只读取了一个空格,会判断成文件输入结束(EOF)。
  • 只要不是输入纯回车或者只有一个 “.” 就需要继续读取输入。也可以用 gets(str); 来读取字符串,用 if (ch[0] == '.' && ch[1] == '\0') break; 标志结束也是可以的
  • exit 是在调用处强行终止程序。它需要头文件 #include <stdlib.h>,其中 exit(1) 是异常退出,exit(0) 是正常退出。
#include <stdio.h>
#include <stdlib.h>
#define MAX 200

char match[MAX];            // 左符号栈
int top = -1, flag = 0;     // top 表示栈顶

// 该函数检查当前右符号和栈顶符号是否匹配
void IfMatch(char left, char right)
{   
    if (top == -1)                                  // 栈为空,缺少左符配对,打印 “?-右符号”,退出程序。
    {
        if (right == '>') printf("NO\n?-*/");     // 右符号是 /* 时要输出 */ 而不是 >
        else printf("NO\n?-%c", right);           // 右符号不是 /* 时,正常输出即可
        exit(0);                                    // 退出程序
    }
    else if (match[top] == left) --top;             // 栈不为空且配对成功,栈顶符号出栈
    else                                            // 栈不为空且配对失败
    {
        if (match[top] == '<')
            printf("NO\n/*-?");
        else printf("NO\n%c-?", match[top]);     // 栈顶符号缺少配对的右符号,打印 “左符号-?
        exit(0);                                   // 退出程序
    }
}

int main()
{
    char str[MAX];
    while (scanf("%s", str) != EOF && str[0] != '.')
    {   // 遍历所有输入字符串的所有字符,将左符号全压入到符号栈中,右符号则进行判断
        for (int i = 0; i < strlen(str); ++i)
        {
            if (str[i] == '(' || str[i] == '[' || str[i] == '{')
                match[++top] = str[i];                              // 左符号入栈
            else if (str[i] == '/' && str[i + 1] == '*')            // 注释符换成 < 入栈
            {
                match[++top] = '<';
                ++i;
            }
            else if (str[i] == ')') IfMatch('(', str[i]);      // 遍历到右符号,进行配对
            else if (str[i] == ']') IfMatch('[', str[i]);
            else if (str[i] == '}') IfMatch('{', str[i]);
            else if (str[i] == '*' && str[i + 1] == '/')
            {
                IfMatch('<', '>');
                ++i;
            }
        }
    }

    if (top == -1) printf("YES");   // 栈不为空,所有配对都完成,输出
    else printf("NO\n%c-?", match[top]);

    return 0;
}

自己试着不要看把代码码出来哦,测试样例可以直接复制,加油小伙汁小改改,为了更美好的未来呢~~~

### 回答1: 可以使用栈来实现符号配对检查。具体步骤如下: 1. 定义一个栈,用于存储左符号; 2. 从源程序中逐个读取字符,如果是左符号,则将其入栈; 3. 如果是右符号,则从栈顶取出一个左符号进行匹配,如果匹配成功,则继续读取下一个字符;如果匹配失败,则说明符号配对,程序结束; 4. 如果读取完整个源程序后,栈为空,则说明所有符号配对,程序结束;否则说明还有左符号未匹配,程序结束。 下面是具体实现的代码: #include <stdio.h> #include <stdlib.h> #define MAX_SIZE 100 typedef struct { char data[MAX_SIZE]; int top; } Stack; void init(Stack *s) { s->top = -1; } void push(Stack *s, char c) { if (s->top == MAX_SIZE - 1) { printf("Stack overflow!\n"); exit(1); } s->data[++s->top] = c; } char pop(Stack *s) { if (s->top == -1) { printf("Stack underflow!\n"); exit(1); } return s->data[s->top--]; } int is_empty(Stack *s) { return s->top == -1; } int is_match(char left, char right) { return (left == '(' && right == ')') || (left == '[' && right == ']') || (left == '{' && right == '}') || (left == '/' && right == '*'); } int check_symbols(char *source) { Stack s; init(&s); char c; while ((c = *source++) != '\') { if (c == '(' || c == '[' || c == '{' || c == '/') { push(&s, c); } else if (c == ')' || c == ']' || c == '}' || c == '*') { char left = pop(&s); if (!is_match(left, c)) { return ; } } } return is_empty(&s); } int main() { char source[] = "int main() {\n" " int a[10];\n" " /* This is a comment. */\n" " for (int i = ; i < 10; i++) {\n" " a[i] = i;\n" " }\n" " return ;\n" "}"; if (check_symbols(source)) { printf("All symbols match!\n"); } else { printf("Symbols do not match!\n"); } return ; } ### 回答2: 要编写程序来检查C语言源程序中的符号配对是否正确,首先需要一个数据结构来存储这些符号。这个数据结构可以是一个栈,每遇到一个左符号,就将其入栈,每遇到一个右符号,就将栈顶元素弹出并比较是否与该右符号匹配。如果不匹配,则说明符号配对不正确,程序需要输出错误信息并结束运行。 具体步骤如下: 1. 首先读入C语言源程序,并将每个字符逐个处理。 2. 对于遇到的每个符号,都判断其是否为左符号。如果是左符号,则将其压入栈中。 3. 如果是右符号,则从栈顶弹出一个符号并比较。如果不匹配,则输出错误信息并结束程序。 4. 如果一直到程序结束时栈中仍有符号未匹配,则也输出错误信息并结束程序。 下面是代码实现: #include <stdio.h> #include <stdlib.h> #include <string.h> #define STACK_SIZE 1000 typedef struct { char data[STACK_SIZE]; int top; } Stack; void init(Stack *s); void push(Stack *s, char c); char pop(Stack *s); int is_empty(Stack *s); int main() { Stack s; init(&s); char c; while ((c = getchar()) != EOF) { if (c == '/' && getchar() == '*') // 遇到 /* 左符号 { push(&s, c); push(&s, '*'); } else if (c == '(' || c == '[' || c == '{') // 遇到左符号 { push(&s, c); } else if (c == ')') // 遇到右符号 { if (pop(&s) != '(') { printf("Error: '(' and ')' do not match!\n"); return 1; } } else if (c == ']') { if (pop(&s) != '[') { printf("Error: '[' and ']' do not match!\n"); return 1; } } else if (c == '}') { if (pop(&s) != '{') { printf("Error: '{' and '}' do not match!\n"); return 1; } } else if (c == '*' && getchar() == '/') // 遇到右符号 */ { if (pop(&s) != '*') { printf("Error: '/*' and '*/' do not match!\n"); return 1; } if (pop(&s) != '/') // 检查到这里时栈顶应该是 '/' { printf("Error: '/*' and '*/' do not match!\n"); return 1; } } } if (!is_empty(&s)) // 程序结束时栈中应该为空 { printf("Error: Some symbols are not matched!\n"); return 1; } printf("All symbols are matched!\n"); return 0; } void init(Stack *s) { s->top = -1; } void push(Stack *s, char c) { s->data[++s->top] = c; } char pop(Stack *s) { return s->data[s->top--]; } int is_empty(Stack *s) { return s->top == -1; } 在上面的代码中,我们用 init 函数来初始化栈,用 push 和 pop 函数来压入和弹出栈中的元素,用 is_empty 函数来判断栈是否为空。当遇到左符号时,我们就把它压入栈中;当遇到右符号时,我们就从栈顶弹出一个元素,并判断是否与该右符号匹配。遇到 /* 和 */ 符号时需要单独处理,因为它们不是单个字符。最后,程序结束时如果栈中还有元素,则说明有一些符号没有匹配,需要输出错误信息。 总之,这个程序的原理就是用栈来实现对符号配对的检测。可以看到,这个程序非常简单易懂,适合初学者练习。 ### 回答3: 在C语言中,注释、括号和大括号是非常重要的语法符号,缺少或者不配对会导致程序无法正常编译或者运行。因此,在编写C语言程序时,我们需要经常检查这些符号是否配对,以确保程序的正确性。下面,我将介绍如何编写程序来检查C语言源程序中的这些符号是否配对。 一、算法思路 我们可以使用栈(Stack)来实现括号的匹配检查,具体算法思路如下: 1. 创建一个栈,用来存储左括号; 2. 依次读入源程序中的字符,如果是左括号(即‘(’、‘[’、‘{’),则将其压入栈中; 3. 如果是右括号(即‘)’、‘]’、‘}’),则弹出栈顶元素,判断是否和当前字符匹配; 4. 如果匹配,则继续读入字符; 5. 如果不匹配,则表明程序中存在未配对的括号,中止程序并提示错误信息。 二、代码实现 以下是使用C语言实现上述算法的示例代码: ```c #include <stdio.h> #include <stdlib.h> /* 定义栈的结构体 */ typedef struct Stack { char data; struct Stack* next; } Stack; /* 初始化栈 */ void initStack(Stack** p) { *p = NULL; } /* 入栈 */ void push(Stack** p, char c) { Stack* new_node = (Stack*)malloc(sizeof(Stack)); new_node->data = c; new_node->next = *p; *p = new_node; } /* 出栈 */ char pop(Stack** p) { if (*p == NULL) { printf("Stack underflow.\n"); exit(EXIT_FAILURE); } char c = (*p)->data; Stack* temp = *p; *p = (*p)->next; free(temp); return c; } /* 检查括号是否配对 */ void checkPair(char* s) { Stack* p; initStack(&p); // 初始化栈 int i = 0; while (s[i] != '\0') { if (s[i] == '(' || s[i] == '[' || s[i] == '{') { push(&p, s[i]); // 左括号入栈 } else if (s[i] == ')' || s[i] == ']' || s[i] == '}') { char c = pop(&p); if (s[i] == ')' && c != '(' || s[i] == ']' && c != '[' || s[i] == '}' && c != '{') { printf("Error: unpaired brackets.\n"); exit(EXIT_FAILURE); } } i++; } if (p != NULL) { printf("Error: unpaired brackets.\n"); exit(EXIT_FAILURE); } printf("All brackets are paired.\n"); } /* 测试检查括号是否配对 */ int main() { char s[] = "int main() { return 0; }"; checkPair(s); return 0; } ``` 以上代码只是检查括号是否配对的示例,如果需要检查注释是否配对,可以使用类似的算法,并对注释的开始和结束位置进行判断。
评论 32
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值