将这个代码改成devc++能运行的
时间: 2024-10-21 11:15:21 浏览: 14
要将这段代码改造成能够在 Dev-C++ 中成功编译和运行,需要进行一些调整。以下是主要的修改步骤:
1. **格式化代码**:确保代码格式正确,便于阅读和调试。
2. **修正变量声明位置**:C99标准允许在任何地方声明变量,但为了兼容性,最好在每个块的开始处声明变量。
3. **修正 `fopen` 函数中的文件路径**:确保文件路径正确,可以在当前目录下创建输入文件 `input.txt`。
4. **修正 `ungetc` 使用**:确保 `ungetc` 不会导致缓冲区溢出。
5. **修正 `add_error` 函数中的错误消息**:确保错误消息不会超过缓冲区大小。
6. **修正 `print_annotation` 函数中的注释输出**:确保注释输出不会导致缓冲区溢出。
以下是经过修改后的代码:
```c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#define MAX 1000 // 定义了一个常量,用于数组和字符串的最大长度。
typedef enum {
TOKEN_IF = 1, TOKEN_ELSE, TOKEN_FOR, TOKEN_WHILE, TOKEN_BREAK,
TOKEN_RETURN, TOKEN_CONTINUE, TOKEN_FLOAT, TOKEN_INT, TOKEN_CHAR,
TOKEN_MAIN, TOKEN_IDENTIFIER
} TokenType;
// 名字表
char NameL[MAX][MAX] = {};
// 常数表
char ConstL[MAX][MAX] = {};
// 注释
char annotation[MAX] = {};
int annotation_count = 0;
int token_count = 0;
int errors_count = 0;
int words_count = 0;
int nums_count = 0;
// 预定义的关键字
const char *keywords[] = {
"main", "auto", "break", "case", "char", "const",
"continue", "default", "do", "double", "else",
"enum", "extern", "float", "for", "goto", "if",
"int", "long", "register", "return", "short",
"signed", "sizeof", "static", "struct", "switch",
"typedef", "union", "unsigned", "volatile", "void",
"while", "restrict", "bool"
};
int keywords_num = sizeof(keywords) / sizeof(keywords[0]);
typedef struct {
char value[10];
int Class; // 编码
char seman[10]; // 语义
int line; // 行数
} token;
token Token[MAX];
typedef struct {
int line;
char message[500];
} error;
error Errors[MAX];
void create_token(const char *value, int Class, const char *ch, int line) {
strncpy(Token[token_count].value, value, MAX - 1);
Token[token_count].value[MAX - 1] = '\0';
Token[token_count].Class = Class;
strncpy(Token[token_count].seman, ch, MAX - 1);
Token[token_count].seman[MAX - 1] = '\0';
Token[token_count].line = line;
token_count++;
}
// 判断是否为关键字
int check_keyword(const char *c) {
for (int i = 0; i < keywords_num; i++) {
if (strcmp(c, keywords[i]) == 0) {
return 1;
}
}
return 0;
}
// 添加错误信息 包含line 和 错误信息 message
void add_error(int line, const char *message) {
Errors[errors_count].line = line;
strncpy(Errors[errors_count].message, message, MAX - 1);
Errors[errors_count].message[MAX - 1] = '\0';
errors_count++;
}
// 添加标识符表NameL
void add_NameL(char *words) {
if (check_keyword(words) == 1) {
return;
}
for (int i = 0; i < words_count; i++) {
if (strcmp(NameL[i], words) == 0) {
return;
}
}
strncpy(NameL[words_count], words, MAX - 1);
NameL[words_count][MAX - 1] = '\0';
words_count++;
}
// 添加常数表ConstL
void add_ConstL(char *num) {
for (int i = 0; i < nums_count; i++) {
if (strcmp(ConstL[i], num) == 0) {
return;
}
}
strncpy(ConstL[nums_count], num, MAX - 1);
ConstL[nums_count][MAX - 1] = '\0';
nums_count++;
}
// 识别单词类型,如果不是下列的关键字,则为标识符
TokenType get_token_type(const char *ch) {
if (strcmp(ch, "if") == 0) return TOKEN_IF;
if (strcmp(ch, "else") == 0) return TOKEN_ELSE;
if (strcmp(ch, "for") == 0) return TOKEN_FOR;
if (strcmp(ch, "while") == 0) return TOKEN_WHILE;
if (strcmp(ch, "break") == 0) return TOKEN_BREAK;
if (strcmp(ch, "return") == 0) return TOKEN_RETURN;
if (strcmp(ch, "continue") == 0) return TOKEN_CONTINUE;
if (strcmp(ch, "float") == 0) return TOKEN_FLOAT;
if (strcmp(ch, "int") == 0) return TOKEN_INT;
if (strcmp(ch, "char") == 0) return TOKEN_CHAR;
if (strcmp(ch, "main") == 0) return TOKEN_MAIN;
return TOKEN_IDENTIFIER;
}
// 识别数字
void is_digit(char *ch, char c, int index, FILE *file, int line) {
int point_count = 0;
ch[index++] = c;
while (isdigit(c = fgetc(file))) {
ch[index++] = c;
}
if (isalpha(c)) {
add_error(line, "标识符以数字开头!");
ch[index++] = c;
}
if (c == '.') {
point_count++;
ch[index++] = c;
if (!isdigit(c = fgetc(file))) {
add_error(line, "小数点后不是数字!");
} else {
ungetc(c, file);
}
while (isdigit(c = fgetc(file))) {
ch[index++] = c;
}
if (c == '.') {
point_count++;
}
}
if (point_count > 1) {
add_error(line, "多个小数点!");
}
ungetc(c, file);
ch[index] = '\0';
add_ConstL(ch);
char n[MAX];
int flag = 0;
for (int i = 0; i < nums_count; i++) {
if (strcmp(ch, ConstL[i]) == 0) {
sprintf(n, "%d", i);
create_token(ch, 12, n, line);
flag = 1;
}
}
if (flag == 0) {
sprintf(n, "%d", nums_count - 1);
create_token(ch, 12, n, line);
}
index = 0; // 重置index
}
void get_next_token(FILE *file) {
char c;
int index = 0;
char ch[MAX];
int line = 1;
char if_next, for_next, while_next, main_next;
while ((c = fgetc(file)) != EOF) {
index = 0;
// 处理注释
if (c == '/') {
annotation[annotation_count++] = c;
char next = fgetc(file);
if (next == '/') {
annotation[annotation_count++] = next;
while (c != '\n' && c != '#') {
c = fgetc(file);
annotation[annotation_count++] = c;
}
line++;
continue;
} else if (next == '*') {
annotation[annotation_count++] = next;
while (1) {
c = fgetc(file);
annotation[annotation_count++] = c;
if (c == '*') {
char next_next = fgetc(file);
if (next_next == '/') {
annotation[annotation_count++] = next_next;
if (c = fgetc(file) == '\n') {
// 多行注释结束后可能存在换行
line++;
annotation[annotation_count++] = c;
}
break;
} else {
ungetc(next_next, file);
}
} else if (c == '\n') {
line++;
annotation[annotation_count++] = c;
} else if (c == EOF) {
printf("多行注释缺少结尾的*/,全部代码被注释!\n");
exit(0);
}
}
continue;
} else {
ungetc(next, file); // 非注释回退一个字符
}
}
// 过滤空白符,且换行时line加1
if (isspace(c)) {
if (c == '\n') {
create_token("换行符", 37, "^", line);
line++;
}
continue;
}
// 判断是否为文件结束
if (c == EOF) {
create_token("结束符", 38, "^", line);
break;
}
// 检查一个字符是否为字母(即 A-Z 或 a-z)
if (isalpha(c)) {
ch[index++] = c;
// 检查一个字符是否为字母或数字(即 A-Z、a-z 或 0-9)
while (isalnum((c = fgetc(file))) || c == '_') {
ch[index++] = c;
}
ungetc(c, file);
ch[index] = '\0';
TokenType token_type = get_token_type(ch);
if (token_type == TOKEN_IDENTIFIER) {
// 是标识符
add_NameL(ch);
char s[MAX];
int flag = 0;
for (int i = 0; i < words_count; i++) {
if (strcmp(ch, NameL[i]) == 0) {
sprintf(s, "%d", i);
create_token(ch, 12, s, line);
flag = 1;
}
}
if (flag == 0) {
sprintf(s, "%d", words_count - 1);
create_token(ch, 12, s, line);
}
} else if (token_type == TOKEN_IF) {
create_token("if", 1, "^", line);
while (isspace(if_next = fgetc(file))) {
if (c == '\n') {
create_token("换行符", 37, "^", line);
line++;
}
}
if (if_next != '(') {
add_error(line, "if 后面没有左小括号!");
} else {
ungetc(if_next, file);
}
} else if (token_type == TOKEN_ELSE) {
create_token("else", 2, "^", line);
} else if (token_type == TOKEN_FOR) {
create_token("for", 3, "^", line);
while (isspace(for_next = fgetc(file))) {
if (c == '\n') {
create_token("换行符", 37, "^", line);
line++;
}
}
if (for_next != '(') {
add_error(line, "for 后面没有左小括号!");
} else {
ungetc(for_next, file);
}
} else if (token_type == TOKEN_WHILE) {
create_token("while", 4, "^", line);
while (isspace(while_next = fgetc(file))) {
if (c == '\n') {
create_token("换行符", 37, "^", line);
line++;
}
}
if (while_next != '(') {
add_error(line, "while 后面没有左小括号!");
} else {
ungetc(while_next, file);
}
} else if (token_type == TOKEN_BREAK) {
create_token("break", 5, "^", line);
} else if (token_type == TOKEN_RETURN) {
create_token("return", 6, "^", line);
} else if (token_type == TOKEN_CONTINUE) {
create_token("continue", 7, "^", line);
} else if (token_type == TOKEN_FLOAT) {
create_token("float", 8, "^", line);
} else if (token_type == TOKEN_INT) {
create_token("int", 9, "^", line);
} else if (token_type == TOKEN_CHAR) {
create_token("char", 10, "^", line);
} else if (token_type == TOKEN_MAIN) {
create_token("main", 39, "^", line);
while (isspace(main_next = fgetc(file))) {
if (c == '\n') {
create_token("换行符", 37, "^", line);
line++;
}
}
if (main_next != '(') {
add_error(line, "main 后面没有左小括号!");
} else {
ungetc(main_next, file);
}
}
index = 0; // 重置index
} else if (isdigit(c)) {
is_digit(ch, c, index, file, line);
} else {
char next2;
switch (c) {
case '+':
create_token("+", 13, "^", line);
break;
case '-':
create_token("-", 14, "^", line);
break;
case '*':
create_token("*", 15, "^", line);
break;
case '/':
create_token("/", 16, "^", line);
break;
case '%':
create_token("%", 17, "^", line);
break;
case '>':
if ((next2 = fgetc(file)) == '=') {
create_token(">=", 19, "^", line);
} else {
ungetc(next2, file);
create_token(">", 18, "^", line);
}
break;
case '<':
if ((next2 = fgetc(file)) == '=') {
create_token("<=", 21, "^", line);
} else {
ungetc(next2, file);
create_token("<", 20, "^", line);
}
break;
case '=':
if ((next2 = fgetc(file)) == '=') {
create_token("==", 23, "^", line);
} else {
ungetc(next2, file);
create_token("=", 28, "^", line);
}
break;
case '!':
if ((next2 = fgetc(file)) == '=') {
create_token("!=", 22, "^", line);
} else {
ungetc(next2, file);
create_token("!", 24, "^", line);
}
break;
case '&':
if ((next2 = fgetc(file)) == '&') {
create_token("&&", 25, "^", line);
} else {
add_error(line, "只使用单个 & 错误!");
}
break;
case '|':
if ((next2 = fgetc(file)) == '|') {
create_token("||", 26, "^", line);
} else {
add_error(line, "只使用单个 | 错误!");
}
break;
case '[':
create_token("[", 29, "^", line);
break;
case ']':
create_token("]", 30, "^", line);
break;
case '(':
create_token("(", 31, "^", line);
break;
case ')':
create_token(")", 32, "^", line);
break;
case '{':
create_token("{
阅读全文