自制C语言解释器无法存储读取变量问题求助
问题排查与修复:自定义语言解释器变量存储失败
问题根源
你的测试脚本中console:read->"Enter your name: "->name这类命令,当前代码仅处理了读取用户输入的环节,完全未实现将输入内容存储到指定变量name的逻辑;同时fgets读取的输入会包含换行符,若不清理会导致变量值带多余格式。
具体问题点:
interpretCommand的console:read->分支里,读取userInput后无后续处理,既没提取命令末尾的变量名,也没将输入写入变量数组。- 原代码的变量赋值逻辑仅在「非console命令」的else分支触发,但你的read命令属于console命令范畴,因此这部分逻辑不会执行。
修复步骤
- 在
console:read->分支中提取目标变量名:读取用户输入后,从命令行中解析->name部分的变量名,调用变量存储逻辑。 - 清理用户输入的换行符:用
strcspn移除userInput末尾的\n和\r,避免变量值带多余换行。 - 复用变量存储逻辑:将变量创建/赋值的逻辑抽为独立函数,减少重复代码,同时方便在read分支调用。
修改后的完整代码
#include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX_VARIABLES 10 // Structure to store variables struct Variable { char name[50]; char value[256]; }; // Array to store variables struct Variable variables[MAX_VARIABLES]; int variableCount = 0; // Function to find a variable by name struct Variable *findVariable(const char *name) { for (int i = 0; i < variableCount; ++i) { if (strcmp(variables[i].name, name) == 0) { return &variables[i]; } } return NULL; // Variable not found } // 独立的变量赋值函数,复用逻辑 int setVariable(const char *name, const char *value) { struct Variable *variable = findVariable(name); if (variable == NULL) { if (variableCount >= MAX_VARIABLES) { printf("Maximum number of variables reached\n"); return 0; } strncpy(variables[variableCount].name, name, sizeof(variables[variableCount].name)-1); variables[variableCount].name[sizeof(variables[variableCount].name)-1] = '\0'; variable = &variables[variableCount++]; } strncpy(variable->value, value, sizeof(variable->value)-1); variable->value[sizeof(variable->value)-1] = '\0'; return 1; } // Function to interpret commands void interpretCommand(const char *command) { if (strncmp(command, "console:write->", 15) == 0) { // Extract the message within double quotes const char *messageStart = strchr(command, '"'); const char *messageEnd = strrchr(command, '"'); if (messageStart != NULL && messageEnd != NULL && messageStart < messageEnd) { // Print the message, replacing variables if present for (const char *p = messageStart + 1; p < messageEnd; ++p) { if (*p == '*') { ++p; // Move past '*' const char *varStart = p; while (*p != '*' && p < messageEnd) { ++p; } char varName[50]; strncpy(varName, varStart, p - varStart); varName[p - varStart] = '\0'; struct Variable *variable = findVariable(varName); if (variable != NULL) { printf("%s", variable->value); } else { printf("Undefined variable: %s", varName); } } else { putchar(*p); } } putchar('\n'); } else { printf("Invalid message format\n"); } } else if (strncmp(command, "console:read->", 14) == 0) { // Extract the prompt within double quotes const char *promptStart = strchr(command, '"'); const char *promptEnd = strrchr(command, '"'); if (promptStart != NULL && promptEnd != NULL && promptStart < promptEnd) { // Print the prompt printf("%.*s", (int)(promptEnd - promptStart - 1), promptStart + 1); // Read user input char userInput[256]; if (fgets(userInput, sizeof(userInput), stdin) == NULL) { printf("Failed to read input\n"); return; } // 去掉输入末尾的换行符和回车符 userInput[strcspn(userInput, "\n\r")] = '\0'; // 提取后面的变量名(->varName部分) const char *varArrow = strstr(promptEnd + 1, "->"); if (varArrow != NULL) { const char *varName = varArrow + 2; // 调用赋值函数存储变量 setVariable(varName, userInput); } else { printf("No variable specified to store input\n"); } } else { printf("Invalid prompt format\n"); } } else { // Check if the command starts with "variableName->" char *arrow = strstr((char*)command, "->"); if (arrow != NULL) { *arrow = '\0'; // Separate variable name and value setVariable(command, arrow + 2); } else { printf("Unknown command\n"); } } } int main() { // Open the file FILE *file = fopen("King.roar", "r"); if (file == NULL) { perror("Error opening file"); return 1; } char line[256]; // Assuming a maximum line length of 255 characters // Read and interpret each line from the file while (fgets(line, sizeof(line), file) != NULL) { // Remove newline character if present size_t len = strlen(line); if (len > 0 && line[len - 1] == '\n') { line[len - 1] = '\0'; } // Interpret the command interpretCommand(line); } // Close the file fclose(file); return 0; }
关键修改说明
- 新增
setVariable函数,将变量查找、创建、赋值的逻辑抽离,让read分支和普通赋值分支均可复用,减少冗余代码。 - 在
console:read->分支中,读取输入后用strcspn清理换行符,再从命令中提取->后的变量名,调用setVariable存储输入内容。 - 普通赋值分支直接调用
setVariable,简化代码逻辑。
测试验证
运行修改后的代码,执行King.roar脚本,输出示例:
Enter your name: Alice Enter your age: 30 Hello Alice! You are 30 years old!
此时变量可正常存储和读取,不会再出现Undefined variable错误。
内容的提问来源于stack exchange,提问作者Hatchy
相关产品推荐
相关产品推荐

