【问题标题】:How do loops and char arrays work in C ?循环和字符数组如何在 C 中工作?
【发布时间】:2016-02-14 12:22:02
【问题描述】:

我有一个完全按照我想要的方式运行的程序:

#define BUF_SIZE 15

void passwordCheck (int digit)
{
static char buf[BUF_SIZE] ;
  static int  i = 0;
  char pw[]="1234" ;
  int pw_size = sizeof(pw)-1 ;
  int ret ;

  if (digit == 13)
  {
    for(i=0;i<BUF_SIZE;i++){                     //why do I need this? 
    }
    ret = memcmp(buf, pw, 4) ;                      //compares the array with the pw
      if (ret == 0 && buf[pw_size] == 0) 
      {
      printf("Access granted\n") ;
      }
      else
      {
      printf("Access denied\n") ;
      }
  }

  else {
     if (i > ((int)sizeof(buf) - 2))          //sets all values to 0 ?  
     {
        i = 0;
        memset(buf, 0, sizeof(buf)) ;
     }
     buf[i] = digit ;                  //stores a value
     buf[i++] = digit ;                //stores a values at the next stage   
  }
}

它检查用户是否输入了正确的密码,如果是,则授予访问权限,如果没有拒绝访问。这是Demo

但是我在理解上遇到了问题。

所以使用static int i,这样每次调用passwordCheck 时我就不会变成0

所以如果用户不按13passwordCheck 通过这两行将所有值存储在一个数组中

buf[i] = digit ; 
buf[i++] = digit ;

如果函数第一次被调用,这个 if 语句将数组中的所有值设置为 0:

 if (i > ((int)sizeof(buf) - 2))
     {
        i = 0;
        memset(buf, 0, sizeof(buf)) ;
     }

然后,当用户按下13 时,将检查数组的内容并通过 memcmp 如果匹配,则授予访问权限,否则拒绝访问。

但在这里,我特别想知道为什么我需要这个 for 循环:

 for(i=0;i<BUF_SIZE;i++){
        }

如果我将其注释掉,程序只会给我一次访问权限,然后再也不会。所以我假设它的作用是将区域中的所有值重置为NULL,所以和memset(buf, 0, sizeof(buf)) ;一样吗?如果是这样,为什么,它不只是一个循环?

提前致谢

【问题讨论】:

    标签: c arrays for-loop


    【解决方案1】:

    由于您的 for 循环是空的,它唯一的副作用是(您可以将其替换为):

    i = BUF_SIZE;
    

    附带说明,编译器/优化器很可能已经在输出中生成该代码,并且拥有(不需要的)for 不会产生任何开销。

    仅在您发送密码终止符13 时调用。之后,在下一次调用(输入另一个密码)时,该函数将再次采用 else 主分支,并且因为之前将 i 设置为 BUF_SIZE,将执行此操作,重置您的计数器:

        i = 0;
        memset(buf, 0, sizeof(buf)) ;
    

    您的主要if 可以简化,并且工作方式相同:

      if (digit == 13)
      {
        ret = memcmp(buf, pw, pw_size) ;   //compares the array with the pw
          if (ret == 0 && i == pw_size) 
          {
          printf("Access granted\n") ;
          }
          else
          {
          printf("Access denied\n") ;
          }
        i = 0; // Reset for next password input
      }
    
      else {
         buf[i++] = digit ; //store the value on current position and after increment the pos
      }
    

    【讨论】:

    • 好的,然后会发生什么?如果我给 i 一个值,这意味着它再次从数组的开头开始?
    • 我在答案中添加了一些细节。
    • +1 @nnn - 你的答案几乎是完美的。请在i=0; 之前或之后添加memset(buf, 0 sizeof(buf));。没有它,如果之前的密码超过4个字符,密码就会失效。
    • 请忽略我之前的留言。我刚刚意识到您正在检查i 的值。
    • 它不应该失败。我还在检查 i 值(实际 buf 大小)。 OP 正在检查 buf 中的字符,需要的是他的情况。编辑:好的,我看到你的评论晚了。
    【解决方案2】:

    如果没有这个 for 循环,您将无法检查 else 语句,直到您的 buf 已满或大小为 15。因为当 digit 为 13 时,您可以通过检查 @ 中的 i 的值来重置缓冲区987654325@ 语句是 15 使用 for 循环。这只是浪费时间。所以你可以写i=15//max size of buffer

    【讨论】:

      【解决方案3】:

      代码是一个单词解析器,一次消化一个字符。它在解析完整的单词后重置。完整的单词以回车符\rascii(13) 结尾。

      如果没有显示函数调用方式的主代码,函数本身就毫无意义。

      让我们消化代码中的每个块。

      if (digit == 13)

      这会检查它是否是密码\r 的结尾。在此块中,它将i 重置为大于buf - 2 的大小。这是使用for 循环完成的,但它可以简单地设置i = 15。这是必要的,因此下一次重试代码知道它是一个新的新密码。您会注意到,在这段代码中,它将buf 的前4 个字节与pw 的前4 个字节进行比较,并确保buf\0 终止。如果它没有检查终止,那么12345 将通过。

      else 条件处理buf 的初始化以及传递给它的字符的存储。

      在此块中,您会注意到它检查i 是否大于sizeof (buf) -2。这是他们用来表示buf 需要重置为0s 的条件。因此,上一个块中的for 循环可以通过使用赋值表达式i = 15 设置i 的值来简化。

      将数字存储到buf 的第二行与前一行做同样的事情,此外它增加了 i。上一行变得不必要了。

      静态存储的使用使得i 的值在每个函数调用中都保持不变。最后,这不是线程安全的。

      【讨论】:

      • 问题中有一个链接,有主代码和程序输出。
      • 是的,我阅读了代码,这就是我能够提出这个答案的原因。当您的演示代码被删除时,这个问题的未来读者将会迷失方向。我还在这里coliru.stacked-crooked.com/a/3cd1052290aefd24 编写了您的代码的缩短版本
      • 我意识到你不是 OP。我一直把问题和代码称为你的。
      • 没有。一点也不。线程安全的可重入代码不使用静态变量。为了使其线程安全可重入,您可以修改函数以接收额外的参数,这些参数将取代bufi 的角色。
      猜你喜欢
      • 1970-01-01
      • 2014-02-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多