【问题标题】:Predict the number预测数字
【发布时间】:2010-10-12 04:30:11
【问题描述】:

我希望用户输入一个 4 位数字,程序必须告诉该 4 位数字是什么,即通过蛮力攻击生成该 4 位数字。但在下面提到的行中,编译器说无效间接。我也会想了解一下我实施它的方式,这是一个好的做法吗?

#include<stdio.h>
void BruteForceAttack(int *arr);
int main()
{
 int *arr,i;
 printf("Enter 4 digits ,press enter after entring each digit:\n");
 for(i=0;i<4;i++)
 scanf("%d",arr+i);
 BruteForceAttack(arr);
 getchar();
 return 0;
}
void BruteForceAttack(int *arr)
{
 int i,j,k,l;
 for(i=0;;i++)
 {
  for(j=0;;j++)
  {
   for(k=0;;k++)
   {
    for(l=0;;l++)
    {
      if((*(arr+0)==i)&&(*(arr+1==j))&&(*(arr+2==k))&&(*(arr+3)==l))   /*Here the compiler says invalid indirection*/
     {
      printf("The number is %d%d%d%d",i,j,k,l);
      return;
     }
    }
   }
  }
 }
}

【问题讨论】:

    标签: c arrays pointers loops brute-force


    【解决方案1】:

    总共 3 个问题:

    问题一:

    您的arr 是一个悬空指针,您在scanf 中取消对它的引用。

    你需要:

    int arr[4]; 
    

    代替

    int *arr;
    

    问题 2:

    涉及j 和k 的比较不正确:

    &&(*(arr+1==j))&&(*(arr+2==k))
    

    应该是

    &&(*(arr+1)==j)&&(*(arr+2)==k)
              ^              ^
    

    问题 3:

    即使进行了上述 2 项修复,您的程序也会运行到无限循环,因为您的 for 循环没有没有终止条件。

    由于您要求用户输入 4 位数字,因此您的所有循环都应从 0 到 9 为:

    for(i=0;i<10;i++)
            ^^^^^
    

    也为其他 3 个循环添加类似的检查。

    【讨论】:

      【解决方案2】:

      我也想要一些 cmets关于他们的方式我 实施它,这是一个好习惯吗?

      关于您问题的这个特定部分,请考虑一下您尝试实施的算法。您有可用的号码,存储在arr 中。如果用户选择号码9999,您将在到达之前遍历 10000 个号码。相反,如果您一次遍历每个数字并在找到正确数字时停止(因为它是事先知道的),那么您将迭代 40 次。

      就数学复杂性而言,您当前的算法在最坏情况下的性能为 10n,而它可以实现为 10n。

      【讨论】:

      • 我实际上想要像蛮力这样的东西来找到数字是什么,就像我们破解密码一样
      • @fahad:如果它是纯数字密码,那么您可以通过首先将密码转换为整数来实现更快的算法。除非您想实施字典攻击或类似的东西(但我想这并不是真正的“蛮力”)。例如,您可以在数字密码上相当轻松地实现binary search。
      • 我可能应该补充一点,二进制搜索还假定您有办法知道您是“大于”还是“小于”密码。如果您通过蛮力进行严格猜测(只有是/否响应),那么您的算法几乎就是您必须这样做的方式。因此,为什么暴力破解密码需要花费大量时间,以及为什么更长的密码更安全。即使有一个数字,每多一个数字也会将最差时间的性能提高 10 倍。
      • 我想知道二进制搜索算法如何使用整数密码进行单词,因为其中的数字首先按顺序排序。
      【解决方案3】:

      我发现了几个问题:

      1. 您没有为*arr 分配任何内存。也许您应该将arr 定义为

        int arr[4];
        

        然后,在 scanf 中,您可以执行以下操作:

        scanf("%d", &arr[i]);
        
      2. 您可以只在问题行上使用数组偏移表示法:

        if(arr[0] == i && arr[1] == j && arr[2] == k && arr[3] == l)
        

      【讨论】:

        【解决方案4】:

        您的括号放错了位置。 *(arr+1==j) 应该是 *(arr+1)==j 等。这将修复编译器警告,但 arr[1]==j (等)会更好。

        【讨论】:

        • 当然,如果你真的想使用指针算法——这里有点没有意义。 *(arr+b) 等价于 arr[b]。
        • @Christian:同意!但是,来自 Lisp 背景,我觉得有必要修正括号......
        • 如何交朋友和影响人:因为arr[b]相当于*(arr + b),所以也相当于*(b + arr),相当于b[arr]。因此,您可以将数组表示法编写为1[array],它的工作方式与array[1] 相同。
        【解决方案5】:

        考虑你最里面的循环

        for(l=0;;l++)
            {
              if((*(arr+0)==i)&&(*(arr+1==j))&&(*(arr+2==k))&&(*(arr+3)==l))   /*Here the compiler says invalid indirection*/
             {
              printf("The number is %d%d%d%d",i,j,k,l);
              return;
             }
            }
        

        如果用户输入的数字不是以 000 开头的数字 - 这个循环将如何终止?这会不会继续无限循环 i, j, k ==0 ?

        【讨论】:

          【解决方案6】:

          您没有为 arr 分配任何空间!使用 malloc 分配空间。

          ...
          int *arr,i;
          arr = (int *) malloc(4*sizeof(int));
          ...
          

          此外,您正在将布尔值(c 中的 int)转换为地址!错误行中的大括号是错误的。

          ...
          if((*(arr+0)==i)&&((*(arr+1)==j))&&((*(arr+2)==k))&&((*(arr+3)==l))
          ..
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-11-27
            • 2020-09-10
            • 2023-04-04
            • 1970-01-01
            • 2018-04-03
            • 2013-04-19
            相关资源
            最近更新 更多