網站首頁 編程語言 正文
題目內容
內容:
1.設計掃描器的自動機;
2.設計翻譯、生成Token的算法;
3.編寫代碼并上機調試運行通過。
要求:
掃描器可識別的單詞包括:關鍵字、界符、標識符和常整型數。
其中關鍵字表、界符表、標識符表、常整數表如下:
關鍵字表K(1int 2void 3break 4float 5while 6do 7struct 8coust 9case 10for 11return 12if 13default 14else)
界符表 P(1 - 2 / 3 ( 4 ) 5 -- 6<= 7< 8+ 9* 10> 11= 12, 13; 14++ 15 { 16 } 17 ' 18 " )
標識符表I (1 2 3 4 5 6 7 8 9 10 11 12 13 14)
常整數表C(1 2 3 4 5 6 7 8 9 10 11 12 13 14)
【輸入形式】
源程序文件。
【輸出形式】
(1)相應單詞的Token序列;
(2)標識符表,常數表。
【測試用例1】
輸入:x10=x+y1*120+10;
輸出:
Token序列:(I 1)(P 11)等等
標識符表:x10 x y1
常數表:120 10
思路
題目中的輸出形式是:(1)相應單詞的Token序列;(2)標識符表,常數表。因此,我們可以在上述代碼中調整輸出的格式。
對于 Token 序列的輸出,我們可以將其格式化為如下形式:
Token序列:(<單詞種類>, <單詞內容>)
例如:(KEYWORD, int)(IDENTIFIER, x)(DELIMITER, =)(INTEGER, 10)
對于標識符表和常整數表的輸出,我們可以將其格式化為如下形式:
標識符表: x y
常整數表: 10 20
為了實現這種輸出格式,我們可以在輸出 Token 序列之后,再輸出標識符表和常整數表。
代碼
#include <stdio.h>
#include <string.h>
#include <ctype.h>
// 定義單詞種類
typedef enum {
KEYWORD, // 關鍵字
DELIMITER, // 界符
IDENTIFIER,// 標識符
INTEGER // 常整型數
} TokenType;
// 關鍵字表
char *keywords[] = {
"int", "void", "break", "float", "while", "do",
"struct", "const", "case", "for", "return", "if",
"default", "else"
};
// 界符表
char delimiters[] = {
'-', '/', '(', ')', '--', '<=', '<', '+', '*', '>',
'=', ',', ';', '++', '{', '}', '\'', '"'
};
// 標識符表
char *identifiers[100];
int identifier_count = 0;
// 常整數表
int integers[100];
int integer_count = 0;
// Token 序列
struct Token {
TokenType type; // 單詞種類
char *lexeme; // 單詞內容
int value; // 單詞值
} tokens[100];
int token_count = 0;
// 讀入的源程序
char source[100];
int source_pos = 0;
// 讀入下一個字符
char get_char() {
return source[source_pos++];
}
// 跳過空白符
void skip_space() {
while (isspace(source[source_pos])) source_pos++;
}
// 讀入單詞
void get_token() {
skip_space();
char ch = get_char();
// 如果是字母,則讀入單詞
if (isalpha(ch)) {
int lexeme_pos = 0;
char lexeme[100];
while (isalpha(ch) || isdigit(ch)) {
lexeme[lexeme_pos++] = ch;
ch = get_char();
}
lexeme[lexeme_pos] = '\0';
source_pos--; // 將最后讀入的非字母或數字字符放回去
// 判斷是否為關鍵字
for (int i = 0; i < 14; i++) {
if (strcmp(keywords[i], lexeme) == 0) {
tokens[token_count].type = KEYWORD;
tokens[token_count].lexeme = lexeme;
token_count++;
return;
}
}
// 如果不是關鍵字,則加入標識符表
identifiers[identifier_count] = lexeme;
tokens[token_count].type = IDENTIFIER;
tokens[token_count].lexeme = lexeme;
tokens[token_count].value = identifier_count;
identifier_count++;
token_count++;
return;
}
// 如果是數字,則讀入常整數
if (isdigit(ch)) {
int value = 0;
while (isdigit(ch)) {
value = value * 10 + (ch - '0');
ch = get_char();
}
source_pos--; // 將最后讀入的非數字字符放回去
// 加入常整數表
integers[integer_count] = value;
tokens[token_count].type = INTEGER;
tokens[token_count].value = value;
integer_count++;
token_count++;
return;
}
// 如果是界符,則讀入界符
for (int i = 0; i < 18; i++) {
if (delimiters[i] == ch) {
// 加入 Token 序列
tokens[token_count].type = DELIMITER;
tokens[token_count].lexeme = ch;
token_count++;
return;
}
}
}
int main() {
// 讀入源程序
scanf("%s", source);
// 讀入 Token 序列
while (source_pos < strlen(source)) {
get_token();
}
// 輸出 Token 序列
for (int i = 0; i < token_count; i++) {
if (tokens[i].type == KEYWORD) {
printf("(KEYWORD, %s)\n", tokens[i].lexeme);
} else if (tokens[i].type == IDENTIFIER) {
printf("(IDENTIFIER, %s)\n", tokens[i].lexeme);
} else if (tokens[i].type == INTEGER) {
printf("(INTEGER, %d)\n", tokens[i].value);
} else if (tokens[i].type == DELIMITER) {
printf("(DELIMITER, %c)\n", tokens[i].lexeme);
}
}
// 輸出標識符表
printf("\nIdentifier Table:\n");
for (int i = 0; i < identifier_count; i++) {
printf("%s\n", identifiers[i]);
}
// 輸出常整數表
printf("\nInteger Table:\n");
for (int i = 0; i < integer_count; i++) {
printf("%d\n", integers[i]);
}
return 0;
}
原文鏈接:https://juejin.cn/post/7181998174955896869
相關推薦
- 2023-03-13 ViewModel中StateFlow和SharedFlow單元測試使用詳解_Android
- 2022-06-24 使用Python獲取字典鍵對應值的兩種方法_python
- 2021-12-01 docker網絡配置過程詳解介紹_Android
- 2022-02-11 g2繪制點圖,鼠標移入點上出現tooltip,對應的label消失
- 2022-12-02 C語言實現三子棋小游戲的示例代碼_C 語言
- 2022-04-12 C++中菱形繼承的解釋與處理詳解_C 語言
- 2022-07-18 linux引導和計劃任務
- 2022-08-04 Python使用RPC例子_python
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支