我是编程新手,我的功能有问题,所以您能为我提供的任何帮助将不胜感激!在不使用字符串库函数的情况下,我尝试使用 C 编写一个函数,让用户输入一个长度在一定范围内的字符串,并不断提示输入,直到它获得一个有效长度的字符串。
当我出于某种原因运行我的代码时,正在打印正确的错误消息,但仅针对所有其他不正确的字符串长度输入,它只是让用户再次输入另一个字符串。当给定一个可接受长度的字符串时,当它应该第一次接受它时再次提示输入,但在第二次输入后它接受并停止。我有一个显示此行为示例的屏幕截图,如您所见,在第三行中,在第二次输入“abc”之后和有效字符串“abcdef”之后没有打印错误消息,我必须输入它第二次退出。
这是我的代码:
#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 次。
你实际上会注意到,使用你当前的代码,如果输入字符串太大,它会正确显示错误消息,但在其他情况下,它会每隔一秒播放一次错误消息。
这是因为你输入了一个字符串,输入的结尾是
\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;
}
}
在试用您的程序时,我添加了几个“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$
尝试一下重构代码,看看它是否符合您项目的精神。