为什么我输入字符个数超出98字符之后按下回车,出现了莫名其妙的问题?


/*宏定义*/
#define _CRT_SECURE_NO_WARNINGS

/*头文件*/
#include<stdio.h>
#include<stdlib.h>

/*函数声明*/
void clearInputBuffer(); // 输入缓冲区清除函数的声明
int Str_Num_Judgement(int l, char* str); // 字符串字符数判断函数声明

/*外函数部分(自定义函数部分)*/
void clearInputBuffer() { // 用于清除缓冲区当中多余字符的函数工具
    int c;
    while ((c = getchar()) != '\n') {};
};

int Str_Num_Judgement(int l, char* str) { // 字符串判断函数
    while (1) {
        if (l > 98) {
            printf("您输入的字符个数已经超过了溢出保护限制的字符数98个字符,请您重新输入\n");
            clearInputBuffer(); // 清空输入缓冲区当中的字符
            for (int i = 0; i < 100; i++) {
                str[i] = '\0'; // 若超出了字符个数要求则全部进行空字符初始化
            };
            fgets(str, sizeof(str), stdin); // 重新输入需要加密的明文字符串
        }
        else
            return 0; // 判断结束(由于输入字符数满足相应要求)
    }; // 反复执行判断,直到字符数满足<=98字符即可执行下一个程序

};

/*主函数部分*/
int main() {  // 8.3.5字符串加密与解密
    int k = 0;
    int command_num = 0; // 主程序命令符参量
    char mw_str[100] = { 0 }; // 需要进行加密操作的明文
    printf("请输入要加密的明文:\n");
    fgets(mw_str, sizeof(mw_str), stdin); // 输入明文(其输入的非回车符的字符数不能超过98字符)
    k = strlen(mw_str) - 1;
    Str_Num_Judgement(k, mw_str); // 调用字符串判断函数(当字符个数满足<=98时,则该函数执行完毕)
    printf("加密后的密文是:\n");
    for (int i = 0; i <= strlen(mw_str) - 2; i++) { // 对明文进行加密
        printf("%c", mw_str[i] + i + 5); // 加密之后并输出
    }
    printf("\n");
    while (1) {
        printf("输入1加密新的明文,输入2对刚加密的密文进行解密,输入3退出系统:\n");
        printf("请输入命令符:\n");
        scanf("%d", &command_num); // 请输入命令符(1、2、3)
        clearInputBuffer(); // 清除输入缓冲区字符
        switch (command_num) {
            
            case 1: // 加密新的明文
                for (int i = 0; i < sizeof(mw_str); i++) {
                    mw_str[i]='\0';// 将明文顺序表(明文字符数组和密文字符数组)初始化            
                };
                printf("请输入要加密的明文:\n");
                fgets(mw_str, sizeof(mw_str), stdin); // 输入明文(其输入的非回车符的字符数不能超过98字符)
                Str_Num_Judgement(k, mw_str); // 调用字符串判断函数(当字符个数满足<=98时,则该函数执行完毕)
                printf("加密后的密文是:\n");
                for (int i = 0; i <= strlen(mw_str) - 2; i++) { // 对明文进行加密
                    printf("%c", mw_str[i] + i + 5); // 加密之后并输出
                }
                printf("\n");
                break;
            
            case 2: // 对刚加密的明文进行解密
                printf("解密后的明文是:");
                for (int i = 0; i < strlen(mw_str); i++)
                    printf("%c",mw_str[i]);
                break;
            
            case 3: // 系统结束
                return 0;
        }
    }
}


遇到了问题,具体问题是:
1.在执行fgets函数时即第一次执行调用Str_Num_Judgement函数之前,我输入的字符是超过了98字符,输入完后按下回车之后,程序没有给我执行Str_Num_Judgement函数当中if条件判断里的printf("您输入的字符个数已经超过了溢出保护限制的字符数98个字符,请您重新输入\n");
对于这个Str_Num_Judgement函数当中if条件判断语句中printf函数之后的代码不知道有没有执行?

2.程序执行时莫名其妙还把:
输入1加密新的明文,输入2对刚加密的密文进行解密,输入3退出系统:
请输入命令符:

执行了两次,不清楚是怎么一回事?

3.关于我的溢出保护机制的函数Str_Num_Judgement是完全没有起到作用吗?

具体的程序运行状况如下:
请输入要加密的明文:
iudshafdsaesaidlsaudsasdhhdsafuidshafjudsaifhdsuiahfdsfhdkhsafudsuafuidsafilujdsahfjhdsafjkahdsfuihdskjlfhlskdjfhlkfh
加密后的密文是:
n{k{qkqp€ot價{w€坵寍寋巰厗儞倛槏墮弶彅爯爮槚櫀Ι灄煘澀·々Сⅷ辅富ó境讣萍非毒铰辆谓萌柿善质谙
输入1加密新的明文,输入2对刚加密的密文进行解密,输入3退出系统:
请输入命令符:
输入1加密新的明文,输入2对刚加密的密文进行解密,输入3退出系统:
请输入命令符:

int Str_Num_Judgement(int l, char* str) 函数里是死循环,进去就回不来了。
问题1:因为字符串读入用fgets()函数,能读取的字符串最大长度为sizeof(mw_str) -1 ,即 100 - 1 = 99 ,当输入的字符串长度超过这个值时,它也只截取前99个,用 strlen(mw_str) 得到的值也为 99, 所以 k = strlen(mw_str) - 1; ,这里 k = 98 , 把 k 传递给 int Str_Num_Judgement()函数形参 l = 98 , if (l > 98) 这个条件不会满足,所以 条件判断语句中printf函数之后的代码不会被执行。
问题2:因为前面读取字符串的过程中,有像回车换行符 等多余的字符残留在输入缓冲区里,调用执行 Str_Num_Judgement(k, mw_str); 函数时,输入缓冲区清除函数 clearInputBuffer(); 未被执行到,所以进入 while(1) 循环时,出现了误动作。
问题3:上面问题1的原因,溢出保护机制的函数Str_Num_Judgement()是没有起到作用。

@ada 请回答下这个问题

你在 保护函数里的 sizeof 不能那样用 数组在作为参数进入被调用函数中会退化为一级指针。

也就是 Str_Num_Judgement 里 sizeof Str 要么是 4 要么是 8 取决于你是x86 还是 x64的应用,不会get更多的字符

fgets 正常情况下输入 n-1个字符 或遇到 换行符会结束。应该无法输入到 超过 99个字符

你不如在 main函数里写个do while

do{
memset(str,100, '\0');
fgets(str, sizeof(str)-1, stdin);
}
while (strlen(str) > 98);

这样预防溢出