【问题标题】:Verification with strlen in c在 c 中使用 strlen 进行验证
【发布时间】:2013-12-23 17:55:16
【问题描述】:

我正在使用这段代码来验证在结构中输入的长度,以便文件不会爆炸,但我认为我执行不正确。

    do
    {
        inputflag=0;
        printf("Passenger ID no: ");
        gets(newRes.idCard);
        if((strlen(newRes.idCard))>7)
        {
            printf("invalid input \n");
            inputflag=1;
        }
        fflush(stdin);
    } while(inputflag==0);

【问题讨论】:

  • 不要使用fflush(stdin)。这是非法的,会导致未定义的行为!
  • 当您检查输入的大小时,损坏已经造成...尝试使用 fgets 代替。
  • 如果没有 fflush(stdin) 会更糟
  • 您最好在实现标头中找到gets() 的原型并将其注释掉。它是如此卑鄙和邪恶,它已被该语言弃用,并且在未来的版本中将不再支持。请改用fgets()
  • 您的 fflush 应该在打印后出现在标准输出上。

标签: c string loops strlen


【解决方案1】:

您的gets 呼叫不安全。它可以接受比您分配的更多的字符。轰隆隆。

假设您已为 .idCard 分配了至少 8 个字节(即 7 个​​字符加上终止符)然后考虑使用:

  fgets(newRes.idCard, 7+1, stdin);

这确保您不会接受太多字符。它将根据需要截断。检查fgets 的返回值是否成功。

(man fgets)

编译此示例代码并学习。我希望你能在这里找到你想要的东西。

#include <stdio.h>
#include <string.h>

#define MAX_ID_LEN (7)

int main() {
    char idCard[MAX_ID_LEN+1];
    printf("ID: ");
    if (fgets(idCard, MAX_ID_LEN+1, stdin)) {
        char *cLast = idCard + strlen(idCard)-1;
        if (*cLast == '\n')
            *cLast = 0;  // strip newline *if* present
        printf("Success!  idCard='%s'\n", idCard);
    } else {
        printf("Failure.\n");
    }
    return 0;
}

注意这里有几行代码来检查输入是否包含换行符并将其删除。 fgets 确保换行除非用户输入超过 7 个字符的 ID。我希望这对你来说很清楚。

另外,这可能不会让您分心:(只需使用fscanf

#include <stdio.h>

int main() {
    char idCard[7+1];
    printf("ID: ");
    fscanf(stdin, "%7s", idCard);
    printf("idCard='%s'\n", idCard);
    return 0;
}

【讨论】:

  • @user3052741,请分享您尝试过的代码或sn-p。 fgets 将在换行时停止阅读。
  • ' 做 { inputflag=0; printf("旅客编号:"); fgets(newRes.idCard, 7+1, 标准输入); if((strlen(newRes.idCard))>7) { printf("无效输入\n");输入标志=1; } fflush(标准输入); }while(inputflag==0);'
  • 那是因为 fflush 没有按预期工作。看看我的回答如何刷新标准输入。
  • 我认为还需要对结果字符串强制以空值结尾 - 如果读入的字符数 > 7,则 idCard 的值不会以空值结尾。
  • @user3052741,我刚刚编辑了上面的答案以包含一个小型测试程序。我建议您编译并运行它以确认它有效。它会。请注意,如果您使用fgets,则不再需要任何strlen 检查有效长度,因为已经确保了最大长度。
【解决方案2】:

为了正确刷新标准输入,您应该执行以下操作:

int c;
while ((c = getchar()) != '\n' && c != EOF);

您应该使用fgets 而不是gets,因为您可以将字符数限制为输入缓冲区的大小。

gets 不知道长度,因此如果用户输入的长度超过缓冲区提供的长度,可能会导致缓冲区溢出。

How come fflush(stdin) function is not working?

【讨论】:

    【解决方案3】:

    检查长度 将数据读入太小的缓冲区为时已晚。首先将数据读入一个大的保存缓冲区。

    fgets() 是过时的gets() 的绝佳替代品。记得去掉可能的结尾\n

    还要避免像“7”这样的幻数。使用 sizeof(newRes.idCard) 之类的东西。

    在精心设计的代码中,fflush(stdin) 是不需要的,应该避免使用,因为它不可移植。

    int inputflag = 0;  // Not clear is OP needs this value after the while loop.
    do {
      printf("Passenger ID no: ");
      char buf[sizeof(newRes.idCard) * 2]; ' twice as big as needed.
      if (fgets(buf, sizeof buf, stdin) == NULL) {
        inputflag = 1;
        break;
      }
      size_t Len = strlen(buf);
      if (Len && buf[Len-1] == '\n') buf[--Len] = '\0';
      if(Len >= sizeof(newRes.idCard)) {
        printf("invalid input \n");
        inputflag = 1;
      }
      else {
        strcpy(newRes.idCard, buf);
      }
    } while (inputflag == 0);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-08-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-30
      • 1970-01-01
      • 1970-01-01
      • 2013-10-25
      相关资源
      最近更新 更多