首页 > 解决方案 > 使字符数组向左/向右旋转其单元格 n 次

问题描述

我在这里完全是新人,但我听说过很多关于这个网站的信息,现在我已经被接受了 7 个月的软件开发“训练营”,我正在为即将到来的测试提高我的 C 知识。

我被分配了一个关于我已经通过的测试的问题,但是我没有完成那个问题,这让我很困扰。

问题是用 C 编写一个程序,将字符(char)数组的单元格向左移动 1(对我来说,在哪个方向上并不重要,但问题是向左移动)。而且我还自己承担在执行过程中不要使用临时数组/堆栈或任何其他结构来保存整个数组数据。

所以一个 'string' 或包含 '0' '1' '2' 'A' 'B' 'C' 的字符数组将在使用后变为 '1' '2' 'A' 'B' 'C' '0'功能一次。

写这个没问题,我相信我最终得到了类似的东西:

void ArrayCharMoveLeft(char arr[], int arrsize, int times) {
    int i;
    for (i = 0; i <= arrsize ; i++) {
        ArraySwap2CellsChar(arr, i, i+1);
    }
}

如您所见,该功能有些模块化,因为它允许输入单元格需要向左移动或移动的次数。我没有实现它,但这就是我的想法。

据我所知,有3种方法可以做到这一点:

  1. 循环 ArrayCharMoveLeft 次。这本能地感觉效率低下。
  2. 在 ArrayCharMoveLeft 中使用递归。这应该类似于第一个解决方案,但我不能 100% 确定如何实现它。
  3. 这就是我试图弄清楚的方式:循环中没有循环,没有递归,没有临时数组,程序将知道如何将单元格向左/向右移动 x 次而不会出现任何问题。

问题是,在交换数组中的 N 次单元之后,剩余的数组大小 - 有时没有组织。例如:

将 ArrayCharMoveLeft 与我们上面提到的给定数组一起使用 3 作为次将产生 ABC021 而不是 ABC012 的预期值。

我为此运行了以下功能:

int i;
char* lastcell;
if (!(times % arrsize))
{
    printf("Nothing to move!\n");
    return;
}
times = times % arrsize;
// Input checking. in case user inputs multiples of the array size, auto reduce to array size reminder
for (i = 0; i < arrsize-times; i++) {
    printf("I = %d ", i);
    PrintArray(arr, arrsize);
    ArraySwap2CellsChar(arr, i, i+times);
}

如您所见,for 从 0 运行到数组大小 - 次。如果使用此函数,例如使用包含 14 个字符的数组。然后使用 times = 5 将使 for 从 0 运行到 9,因此单元格 10 - 14 不是按顺序排列的(但其余的是)。

最糟糕的是,剩余的细胞总是保持顺序,但在不同的位置。意思而不是 0123 他们可以是 3012 或 2301... 等等。

我在不同的时间值上运行了不同的数组,但没有找到特定的模式,例如“如果剩余的单元格 = 3,则在剩余的单元格上使用 ArrayCharMoveLeft,时间 = 1)。

它似乎总是 2 个选项中的 1 个:剩余的单元格按顺序排列,或者以不同的值移动。似乎与此类似:time shift+direction to allign 1 0 2 0 3 0 4 1R 5 3R 6 5R 7 3R 8 1R 数字随时间和数组的不同而变化。有人对此有想法吗?即使您在循环中使用递归或循环,我也想听听一个可能的解决方案。对此唯一坚定的规则是不要使用临时数组。

提前致谢!

标签: arrayscstringchar

解决方案


  1. 使用标准库函数memcpy,memmove等,因为它们非常适合您的平台。
  2. 使用正确的尺寸类型 -size_t不是int
char *ArrayCharMoveLeft(char *arr, const size_t arrsize, size_t ntimes) 
{
    ntimes %= arrsize;
    if(ntimes)
    {
        char temp[ntimes];
        memcpy(temp, arr, ntimes);
        memmove(arr, arr + ntimes, arrsize - ntimes);
        memcpy(arr + arrsize - ntimes, temp, ntimes);
    }
    return arr;
}

但是您希望它没有临时数组(内存效率更高,性能非常差):

char *ArrayCharMoveLeft(char *arr, size_t arrsize, size_t ntimes) 
{
    ntimes %= arrsize;
    while(ntimes--)
    {
        char temp = arr[0];
        memmove(arr, arr + 1, arrsize - 1);
        arr[arrsize -1] = temp;
    }
    return arr;
}

https://godbolt.org/z/od68dKTWq https://godbolt.org/z/noah9zdYY


推荐阅读