【问题标题】:circular array implementation循环数组实现
【发布时间】:2013-02-25 20:27:54
【问题描述】:

到目前为止,这是我对循环数组的实现。它应该存储最后输入的 5 个命令,通过输入第 6 个命令代替第 5 个命令并丢弃第 1 个命令。到目前为止,我所做的是能够存储 5 个命令并将它们打印出来。在第 6 个命令中,我注意到它位于 historyArray 的第二个位置 (k=1),但是在调试时,k 等于 0,这至少会将最后一个命令推到顶部。如果你能让我再次走上正轨,我将不胜感激。这是部分代码。

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

int main (int argc, char *argv[])
{
    int i=0; 
    int j=0; 
    int k=0;
    int tempIndex = 0;
    int elementCounter = 0;

    char inputString[100];
    char *result=NULL;
    char delims[] = " ";
    char historyArray[5][20] = {0};
    char tokenArray[20][20] ;
    char hCommand[1][20];

    do
    {
         j = 0;

         printf("hshell>");
         gets(inputString);

         //skip writing "history" in historyArray
         if (strcmp(inputString,"history")!= 0)
         {
             strcpy (historyArray[k], inputString);
         }

         k = (k+1) % 5;
         if (elementCounter <= 5)
             elementCounter++;

         // Break the string into parts
         result = strtok(inputString, delims);

         while (result!=NULL)
         {
             strcpy(tokenArray[j], result);
             j++;
             result= strtok(NULL, delims);                  
         }

         if (strcmp(tokenArray[0], "exit") == 0)
             return 0;

         if (strcmp(tokenArray[0], "history") ==  0)
         {
             if (j>1)
             {
                 tempIndex = atoi(tokenArray[j]);
                 puts(tempIndex);
             }
             else
             {
                 for (i=0; i<elementCounter-1;i++)
                     printf("%i. %s\n", i+1, historyArray[i]);
             }
         }
         else
         {
             printf("Command not found\n");
         }
    } while (1);
}

建议后(仍不完整):

         j = 0;
         //elementCounter = 0;
         printf("327>");
         gets(inputString);

         strcpy (historyArray[k], inputString);
         k = (k+1) % 5;

        if (elementCounter <= 5)
         {         
          elementCounter++;                
         }

【问题讨论】:

  • 这可能相关也可能不相关,但是您确信您的缓冲区足够大,可以容纳您遇到的任何字符串吗?如果没有,那么getsstrcpy 将导致溢出。您应该调查 fgetsstrncpy 作为“安全”替代品。
  • 另外,我对if (elementCounter &lt;= 5) 持怀疑态度;你为什么需要那个?
  • @OliCharlesworth 你是对的。我计划稍后修复这些。 if (elementCounter &lt;= 5) 用于对数组中的元素进行计数,我在数组中使用它来进一步打印代码。它在那里,因此它不会打印超过 5 个值。
  • 但是当elementCounter 达到6 时会发生什么?那么k 将永远不会再更新。
  • 在我看来,如果您在复制时删除条件并进行模运算,事情会更简单一些。即,您总是写信给historyArray[k % 5](每次都增加k),k + 1 总是输入的“命令”总数,MIN(k + 1, 5) 是当前数组中的作业数。

标签: c arrays circular-buffer


【解决方案1】:

您描述的错误是由于以下几行而发生的:

k = (k + 1) % 5;
elementCounter++;

我看到发生的事情:

k initial | calculation | k result  | elementCounter
0           (0 + 1) % 5   1 % 5 = 1   1
1           (1 + 1) % 5   2 % 5 = 2   2
...
4           (4 + 1) % 5   5 % 5 = 0   5
0           (0 + 1) % 5   1 % 5 = 1   5

k 的行为正如我所见。但是,当elementCounter 为 5 时,k = 1。

编辑:我看到的问题是最新命令被添加到位置 k,而不是位置 0,根据您的实现,这是输入的最新命令(基于各种 if 子句,如处理“退出”和“历史”命令的那个)。使用您当前的算法尝试这组命令。我希望 [Command List] 列的内容是您将看到的...

Command # | Command Text | [Command List]
0           (null)         []
1           Login          [Login]
2           History        [Login,History]
3           Skynet         [Login,History,Skynet]
4           ps -al         [Login,History,Skynet,ps -al]
5           Skynet         [Login,History,Skynet,ps -al,Skynet]
6           Exit           [Exit,History,Skynet,ps -al,Skynet]

您想要做的是复制元素 0-3,并将它们移动到元素 1-4。然后,在historyArray 的位置0 处插入新命令。因此,在适当调整算法后,您的历史记录应如下所示:

Command # | Command Text | [Command List]
0           (null)         []
1           Login          [Login]
2           History        [History,Login]
3           Skynet         [Skynet,History,Login]
4           ps -al         [ps -al,Skynet,History,Login]
5           Skynet         [Skynet,ps -al,Skynet,History,Login]
6           Exit           [Exit,Skynet,ps -al,Skynet,History]

【讨论】:

  • 我已经发布了完整的代码,以便您更好地了解正在发生的事情。
  • 谢谢你,这很有帮助!
  • 我删除了if 子句,它的工作原理如您的第一个表所示。不过,让我印象深刻的是抄袭。您说“复制元素 0-3,并将它们移动到元素 1-4”,但据我了解,这应该是相反的,例如,从索引 0-3 中的索引 1-4 复制值并插入索引 4(位置 5)中的新命令。您在上一张表格中显示的内容对吗?
  • 如果位置 4 将成为历史队列中的最新元素,是的。它将类似于我的第二张桌子,只是顺序会颠倒,因为新成员总是会添加到最终位置。当然,当您的数组少于五个成员时,这也会使您的实现复杂化。
  • 请在下面查看我的答案,并告诉我您的想法。
【解决方案2】:

这是我尝试过的,它似乎按预期工作:

             j = 0;
             //elementCounter = 0;
             printf("hshell>");
             gets(inputString);

             strcpy (historyArray[k], inputString);
             k = (k+1) % 5;

            if (elementCounter <= 5)
             {         
              elementCounter++;                
             }

             if (elementCounter ==6)
             {
                k = 5;
                for (i=0; i<5; i++)
                {
                    strcpy(historyArray[i], historyArray[i+1]);
                }
                 strcpy (historyArray[4], inputString);                 
             }

这基本上是检查elementCounter 是否变为6(意味着已输入第6 个命令)。如果是这样,它将设置k=5,以便在数组的最后一个位置输入命令,然后将前 4 个值向上移动一个位置,使索引 4 为空白。最后一步用命令填充位置。 它不是最优雅的代码,但似乎可以解决问题。

【讨论】:

    【解决方案3】:
    #include <assert.h>
    #include <limits.h>
    #include <math.h>
    #include <stdbool.h>
    #include <stddef.h>
    #include <stdint.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    int main()
    {
        long n; 
        long k; 
        long q; 
        scanf("%ld %ld %ld",&n,&k,&q);
        long *a = malloc(sizeof(long) * n);
        long *b = malloc(sizeof(long) * n);
        for(long a_i = 0; a_i < n; a_i++)
        {
           scanf("%ld",&a[a_i]);
        }
        for(long i = 0; i < k; i++)
        {
            b[0] = a[n-1];
            for(long a_i = 1; a_i < n; a_i++)
            {
            b[a_i] = a[a_i-1];
            }
            for(long a_i = 0; a_i < n; a_i++) 
                 a[a_i] = b[a_i];
        }
        for(long a0 = 0; a0 < q; a0++) 
       {
        long m; 
        scanf("%ld",&m);
        printf("%ld\n", b[m]);
        }
        return 0;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-02-27
      • 1970-01-01
      • 2012-01-30
      • 2017-08-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多