【问题标题】:String terminator in character array in CC中字符数组中的字符串终止符
【发布时间】:2015-01-22 23:07:45
【问题描述】:

我正在尝试编写一个程序来根据一组规则确定密码的有效性。

这是我所拥有的:

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <math.h>

int main()
{
  int uppercase = 0;
  int length = 0;
  int numbers = 0;
  int others = 0;
  char password[13];
  char yesOrNo;
  printf("Your password must be 8-12 characters long.\n"
         "It must contain at least one symbol, uppercase letter, and number.\n\n");
 COMEBACK:
  printf("Please enter your password:");
  scanf(" %s", &password);
  while (password != 'NULL') { // Tried 0 here, tried '\0', but to no avail.
    if (isalpha(password)) {
      length += 1;
      if (isupper(password)) {
        uppercase += 1;
      }
    }
    else if (isdigit(password)) {
      numbers += 1;
      length += 1;
    }
    else {
      length += 1;
    }
    // This is just a test, to see if it was working.
    printf("%d - %d - %d - %d --- %s",
           uppercase, length, numbers, others, password);
  }
  if ((uppercase > 0) && (numbers > 0)
      && (length >= 8) && (length <= 12) && (others > 0)) {
    printf("Good job, you've done your password correctly.");
  } else {
    printf("%d - %d - %d - %d --- %s \t Incorrect..",
           uppercase, length, numbers, others, password); // Same thing here.
    scanf("%s", &yesOrNo);
    switch (yesOrNo) {
    case 'y':
      goto COMEBACK;
      break;
    case 'n':
      printf("Sorry you're dumb man..");
      break;
    default:
      printf("Please enter a valid password.");
    }
  }
  return 0;
}

我遇到的问题是,while 循环永远不会结束,因为它似乎无法为我的密码数组找到终止符。我输入了“\0”以及“0”。但我还是想不通。任何帮助表示赞赏。谢谢。

【问题讨论】:

  • 除非绝对必要,否则您应该永远使用gotocs.utexas.edu/users/EWD/ewd02xx/EWD215.PDF
  • 使用你的调试器。跳到“COMEBACK”标签真的很可怕......
  • @Numbers,'goto' 在 C 语言中有很多有效的用途。请参阅最新 Linux 内核中的 >100k 示例以获取一些示例。
  • @BrianMcFarland:此代码不是正确使用 goto 的示例。
  • @JonathanLeffler 不想争论它是。事实上,这是一个非常丑陋的例子。我只是希望这么多人引用 EWD 并试图吓跑新开发人员远离它不是一种本能反应。

标签: c arrays terminator


【解决方案1】:

这段代码:

while (password != 'NULL') { 

应该会生成大量编译器警告。多字符文字是不可移植的,不应与指针进行比较。

您可能需要:

char *ptr = password;
while (*ptr != '\0') {
    ...
    ptr++;
}

或(C99 或更高版本):

for (char *ptr = password; *ptr != '\0'; ptr++)
{
    ...
}

并使用*ptr 来识别字符(或者,通常是(unsigned char)*ptr,因为普通的char 通常是有符号的,而isalpha() 等需要正值或EOF 作为输入值)。如果没有C99,可以在循环外声明char *ptr;,在循环控件内去掉char *

你有:

if (isalpha(password)) {

由于 password 是一个数组,因此您将一个固定指针传递给一个需要非指针 (int) 值的函数。我可能会在循环中添加:

{
    unsigned char uc = *ptr;
    if (isalpha(uc))
        ...

请注意,对于所有情况,您可能只需要一个 length++;

另外请注意,任何密码都不会满足“至少一个符号”标准,因为您永远不会增加 others

goto 可以替换为while() 循环,该循环也可以检测 EOF:

while (scanf("%12s", password) == 1)
{
    length = others = uppercase = numbers = 0;  // Ignore previous attempts
    for (char *ptr = password; *ptr != '\0'; ptr++)
    {
        unsigned char uc = *ptr;
        length++;
        ...character testing code...
    }
    ...validity checking code...
}

在学习 C 时,假设编译器警告是可靠的错误。它比你现阶段更了解 C。

【讨论】:

    【解决方案2】:

    password 是一个数组。它永远不会是NULL。但它可以包含一个空终止符,这可能是你所追求的。只需检查password[0] == '\0'

    【讨论】:

    • 比较的是'NULL',而不仅仅是NULL。不过,您是对的,比较是错误的。 (而不是我的反对票。)
    • @JonathanLeffler 呃,在评论 OP 中提到尝试了 0 和 '\0'。他可能不是在检测到密码字面上是“NULL”之后。
    • 我认为您假设 OP 正在尝试检查整个密码字符串是否为 NULL,而我认为 OP 正在尝试检查每个字符并查看它是否通过标准。为什么这个假设 -> 他正在使用像 isalpha 这样的函数。 (而不是我的反对票)。乔纳森答对了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-02
    • 2012-01-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-12
    相关资源
    最近更新 更多