#include <setjmp.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX_TRIES 3 #define PASSWORD "mypassword" jmp_buf env; int tries = 0; char* tfgets(char* str, int n, FILE* stream) { char* ret = fgets(str, n, stream); if (ret == NULL) { return ret; } // 将读入的字符串最后的换行符替换为结束符 '\0' int len = strlen(str); if (len > 0 && str[len - 1] == '\n') { str[len - 1] = '\0'; } return ret; } int main() { char str[100]; if (setjmp(env) != 0) { printf("You've been locked out\n"); return 1; } while (tries < MAX_TRIES) { printf("Enter password: "); if (tfgets(str, 100, stdin) == NULL) { break; } if (strcmp(str, PASSWORD) == 0) { printf("Access granted\n"); break; } tries++; } if (tries == MAX_TRIES) { printf("Too many tries\n"); longjmp(env, 1); } return 0; }分析一下上述代码
时间: 2024-01-30 14:02:42 浏览: 25
这段代码是一个简单的密码验证程序,其中用到了 setjmp 和 longjmp 函数来实现异常处理。
首先定义了一个 PASSWORD 常量作为正确的密码,以及一个 env 变量作为跳转的目标。然后定义了一个 tfgets 函数,其功能类似于 fgets 函数,但是会将读入的字符串最后的换行符替换为结束符 '\0'。
在 main 函数中,通过 setjmp 函数设置了一个跳转点 env。然后进入一个循环,每次循环中要求用户输入密码。如果输入成功,则输出 "Access granted" 并跳出循环。如果输入失败,则 tries 变量加一,表示尝试次数加一。如果尝试次数超过了 MAX_TRIES,则输出 "Too many tries" 并通过调用 longjmp 函数跳转到之前设置的 env 位置,输出 "You've been locked out"。
因此,这段代码的作用是:让用户输入密码,如果输入正确,则输出 "Access granted" 并结束程序;如果输入错误次数超过了 MAX_TRIES,则输出 "Too many tries" 并锁定用户,下一次运行程序时直接输出 "You've been locked out"。
相关问题
讲C语言所有头文件包装一个.h文件
将所有C语言头文件包装在一个.h文件中并不是一个好的实践,因为这样会导致包含大量的无用代码,增加编译时间和程序大小。
一般来说,我们在编写C程序时,只需要包含需要的头文件即可。如果需要一些常用的头文件,可以自己定义一个公共头文件,例如common.h,将常用的头文件包含在其中,然后在需要使用这些头文件的地方包含common.h即可。
如果你非要将所有C语言头文件包装在一个.h文件中,可以按照以下步骤操作:
1. 创建一个名为all.h的文件;
2. 将需要包含的头文件逐一添加到all.h中;
3. 在需要使用这些头文件的地方包含all.h即可。
以下是all.h文件的示例代码:
```c
#ifndef ALL_H
#define ALL_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <time.h>
#include <ctype.h>
#include <stdbool.h>
#include <errno.h>
#include <limits.h>
#include <float.h>
#include <assert.h>
#include <signal.h>
#include <setjmp.h>
#include <stdarg.h>
#include <locale.h>
#include <wchar.h>
#include <fenv.h>
#include <complex.h>
#include <iso646.h>
#include <tgmath.h>
#endif /* ALL_H */
```
需要注意的是,为了避免重复包含,我们使用了ifndef/define/endif语句。
尝试编写 fgets 函数的一个新版本 tfgets——tfgets 函数的输入与 fgets 函数一致。用户键入的信息需要与预设信息一致,即视为正确输入, 如果用户连续输错三次,则尝试使用非本地跳转,给出提示, 并不允许该用户再次尝试。请编写一段代码实现上述功能
好的,这里是一个可能的实现:
```
#include <setjmp.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_TRIES 3
#define PASSWORD "mypassword"
jmp_buf env;
int tries = 0;
char* tfgets(char* str, int n, FILE* stream) {
char* ret = fgets(str, n, stream);
if (ret == NULL) {
return ret;
}
// 将读入的字符串最后的换行符替换为结束符 '\0'
int len = strlen(str);
if (len > 0 && str[len - 1] == '\n') {
str[len - 1] = '\0';
}
return ret;
}
int main() {
char str[100];
if (setjmp(env) != 0) {
printf("You've been locked out\n");
return 1;
}
while (tries < MAX_TRIES) {
printf("Enter password: ");
if (tfgets(str, 100, stdin) == NULL) {
break;
}
if (strcmp(str, PASSWORD) == 0) {
printf("Access granted\n");
break;
}
tries++;
}
if (tries == MAX_TRIES) {
printf("Too many tries\n");
longjmp(env, 1);
}
return 0;
}
```
在这个实现中,我们定义了一个 `tfgets` 函数,它与 `fgets` 函数具有相同的参数和返回值,但是它会将读入的字符串最后的换行符替换为结束符 '\0'。在 `main` 函数中,我们使用一个循环来尝试多次输入密码,如果尝试次数超过了 `MAX_TRIES`,则会给出警告并使用 `longjmp` 函数跳转到 `env` 标记处,禁止该用户再次尝试。在循环中,我们使用 `tfgets` 函数来获取用户输入,并将其与预设的密码进行比较,如果匹配则输出 "Access granted" 并退出循环。
这个实现使用了 `setjmp` 和 `longjmp` 函数来实现非本地跳转。`setjmp` 函数保存了当前程序状态并返回一个标记,`longjmp` 函数则可以使用该标记来恢复程序状态并跳转到指定位置。在这个实现中,我们在 `main` 函数的循环中使用了 `setjmp` 函数来保存程序状态,并在循环结束后使用 `longjmp` 函数来跳转到 `env` 标记处,禁止该用户再次尝试。