C中验证字符串长度是否在特定长度范围内的函数存在问题

fv2wmkja  于 2023-04-05  发布在  其他
关注(0)|答案(2)|浏览(173)

我是一个编程新手,我的函数有问题,所以你能提供任何帮助我会非常感激!没有使用字符串库函数,我试图用C写一个函数,让用户输入一个长度在一定范围内的字符串,并不断提示输入,直到它得到一个有效长度的字符串。
当我出于某种原因运行代码时,正确的错误消息正在打印,但只针对每一个其他不正确的字符串长度输入,它只是让用户再次输入另一个字符串。它也是当给定一个长度可接受的字符串时,当它第一次应该接受它时,它会提示再次输入,但在输入第二次后,它接受它并停止。我有一个屏幕截图显示了这种行为的一个例子,正如你所看到的,在第三行,在第二次输入“abc”和有效字符串“abcdef”之后没有打印错误消息,我必须在第二次输入它才能退出。Ex 1
下面是我的代码:

#include <stdio.h>
void clrIBuff(void)
{
    while (getchar() != '\n')
    {
        ;
    }
}
void inputStr(char* str, int lengthMin, int lengthMax) {
    int i, length, flag = 0, valid = 0;
    do {
        flag = 0;
        for (i = 0; !flag && i < lengthMax + 1; i++) {
            str[i] = getchar();  // read one char at a time
            if (str[i] == '\n') {
                flag = 1;  // stop reading if newline is found
            }
        }
        length = i;
        if (str[length - 1] == '\n') {
            str[length - 1] = '\0';  // remove newline from input
            length--;
        }
        if ((lengthMin == lengthMax) && (length != lengthMax)) {
            printf("ERROR: String length must be exactly %d: ", lengthMax);
        clrIBuff();
        }
        else if (length < lengthMin) {
            printf("ERROR: String length must be between %d and %d: ", lengthMin, lengthMax);
        clrIBuff();
        }
        else if (length > lengthMax) {
            printf("ERROR: String length must be no more than %d: ", lengthMax);
        clrIBuff();
        }
        else {
            valid = 1;
        }
    } while (!valid);
}
int main()
{
    char testStr[7] = { '\0' };
    inputStr(testStr, 6, 6);
    inputStr(testStr, 4, 6);
    return 0;
}

我认为这可能与在每个if语句中调用的清除输入缓冲区的函数有关,但删除它也会导致问题,只是与上面不同。当我这样做时,每次都打印错误消息,但当长度超出可接受范围时,错误消息打印多次,并且由于某种原因,在我尝试的最后一个无效字符串中打印了3次。Ex 2

ycggw6v2

ycggw6v21#

您实际上会注意到,对于当前代码,如果输入字符串太大,它将正确显示错误消息,但在其他情况下,它将每隔一次播放错误消息。
这是因为你输入了一个字符串,输入的结尾是\n。然后你的clrIBuff函数正在等待另一个\n,这会吃掉你的整个其他输入。我建议只运行clrIBuff,如果提供的输入大于最大长度。

if ((lengthMin == lengthMax) && (length != lengthMax)) {
            printf("ERROR: String length must be exactly %d: ", lengthMax);
            if (length > lengthMax) clrIBuff();
        }
        else if (length < lengthMin) {
            printf("ERROR: String length must be between %d and %d: ", lengthMin, lengthMax);
        }
        else if (length > lengthMax) {
            printf("ERROR: String length must be no more than %d: ", lengthMax);
            clrIBuff();
        }
        else {
            valid = 1;
        }

我还重构了您提供的代码,使其更具可读性,希望这对您也有用。

#include <stdio.h>

void inputStr(char* str, int lengthMin, int lengthMax);

int main()
{
    char in1[7], in2[7];
    inputStr(in1, 6, 6);
    inputStr(in2, 4, 6);

    printf("Input 1: %s\nInput 2: %s\n", in1, in2);

    return 0;
}

void inputStr(char* str, int lengthMin, int lengthMax) {
    int i, length, valid = 0;
    // Ask the user for input
    while (1) {
        // Add each char 1 by 1 into str until \n found
        for (i = 0; i < lengthMax + 1; i++) {
            char in = getchar();
            if (in == '\n') {
                str[i] = '\0'; // End the string
                break; // Exit the loop once \n is found
            } else {
                str[i] = in;
            }
        }

        // Store the length
        length = i;

        // Error checking
        if (lengthMin == lengthMax && length != lengthMax) {
            printf("ERROR: String length must be exactly %d: ", lengthMax);
            while (length > lengthMax && getchar() != '\n'); // clear the previous input if input was bigger
        } else if (length < lengthMin || length > lengthMax) {
            printf("ERROR: String length must be between %d and %d: ", lengthMin, lengthMax);
            while (length > lengthMax && getchar() != '\n'); // clear the previous input if input was bigger
        } else break;
    }
}
abithluo

abithluo2#

在试用你的程序时,我添加了几个“printf”语句,以帮助零化问题似乎发生的地方。
下面是一些测试输出,显示了您所描述的症状。

@Vera:~/C_Programs/Console/CheckString/bin/Release$ ./CheckString 
Test #1: abc
ERROR: String length must be exactly 6: abcdef
abcdef
Test #2: abc    
ERROR: String length must be between 4 and 6: abcdd
abc  
ERROR: String length must be between 4 and 6: abcdd
abcdd
@Vera:~/C_Programs/Console/CheckString/bin/Release$

当用不同长度的字符串测试程序时,很明显,自定义缓冲区刷新函数实际上创建了第二个输入提示符,这可能是您不希望看到的。

void clrIBuff(void)
{
    while (getchar() != '\n')
    {
        ;
    }
}

显然,您的目的是删除任何剩余的字符,直到检测到换行符;然而,在用于确定字符串长度的“for”循环中已经完成了该位。因此,该函数实际上执行了另一个用户输入提示。
只是为了简化重构,一个简单的“fflush”用于替换函数体。

void clrIBuff(void)
{
    /*while (getchar() != '\n')
    {
        ;
    }*/
    fflush(stdin);
}

实际上,这里什么也没有发生,但是这使程序通过并重试用户输入。通过这一点重构,下面是终端上的一些测试输出(包括一点打印输出,以指示正在执行的测试)。

@Vera:~/C_Programs/Console/CheckString/bin/Release$ ./CheckString 
Test #1: abc
ERROR: String length must be exactly 6: abcdef
Test #2: ab
ERROR: String length must be between 4 and 6: abc
ERROR: String length must be between 4 and 6: abcd
@Vera:~/C_Programs/Console/CheckString/bin/Release$

给予一下重构后的代码,看看它是否符合项目的精神。

相关问题