遍历数组并将元素移至数组末尾

时间:2018-12-14 20:59:48

标签: c pointers

我正在尝试实现一个简单的游戏,其中数组表示人站成一个圈,在游戏开始时绘制一个整数。每次迭代都是整数的大小,并将人们从游戏中移除。

因此,如果array [] = {a,b,c,d}和integer = 3; c是第一个被删除的。然后是b,然后是d。获胜者是。 最后,我需要按删除顺序打印结果数组。所以打印数组应该是:a,d,b,c。 我试图仅通过使用没有其他数组的指针来实现此目的。

这就是我得到的,问题是我正在尝试从正确的索引重新启动for循环,并遍历尚未丢失并无法正确解决的其余玩家:

char *names[] = {"Tyrion Lannister","Daenerys Targaryen","Jon Snow","Arya Stark","Theon Greyjoy", "Joffrey Baratheon","Khal Drogo","Ted Mosby","Marshall Eriksen","Robin Scherbatsky","Barney Stinson", "Lily Aldrin", "Tracy McConnell", "Ted Mosby", "Leonard Hofstadter","Sheldon Cooper", "Penny", "Howard Wolowitz", "Raj Koothrappali", "Bernadette Rostenkowski-Wolowitz","Amy Farrah Fowler", "Gregory House", "Lisa Cuddy", "James Wilson","Eric Foreman", "Allison Cameron", "Robert Chase" ,"Lawrence Kutner", "Chris Taub","Remy 13 Hadley", "Amber Volakis"};
int Length = 31;
int number = 10;
char *tmp;
int i = 0, j;
int boom = number;
for (int i = number - 1; i < Length; i += boom - 1)
{

    tmp = *(names + i);

    for (int index = i; index < Length - 1; index++)
    {
        *(names + index) = *(names + index + 1);
    }

    *(names + Length - 1) = tmp;


    Length--;
    if (((number - 1) + i) >= Length)
    {
        int tempIndex = i;
        i = tempIndex - Length;
        printf("tmep index is %d, i is %d, Length is %d\n", tempIndex, i, Length);
    }
}
for (i = 0; i < 31; i++)
    printf("%s\n", names[i]);

我还尝试了%运算符的另一种方法,但还不能完全解决问题。帮助将不胜感激:

for (int i = number - 1; i < Length * (number - 1); i += boom - 1)  
{
    int t = i % Length;
    printf("%d\n", t);
    if (t < size)
    {
        counter++;
        tmp = *(names + t);
        // tmptwo = *(names + 31 - j);
        for (int index = t; index < size - 1; index++)
        {
            *(names + index) = *(names + index + 1);
        }

        *(names + size - 1) = tmp;
        size--;
        printf("size %d\n", size);
    }
}

2 个答案:

答案 0 :(得分:1)

您正在按照正确的思路进行思考,但是在这种情况下,声明并定义一个简单的函数即可将数组内的元素向下移位,从而将丢失索引移至末尾,从而简化了您的生活。通过这种方式,您在代码正文中唯一要做的就是提供失败的索引,并通过简单的计数器来跟踪剩余的玩家实时人数。

将给定索引移动到给定大小的最后一个索引的函数的实现可能类似于以下内容,其中a是要重新排序的数组,elem_idx是要重新排列的元素索引移至sz元素内的最后一个元素:

void element_to_last (int *a, int elem_idx, int sz)
{
    if (elem_idx > sz - 1) {    /* valdate index in range */
        fprintf (stderr, "error: index %d out of range for size %d\n",
                elem_idx, sz);
        return;
    }

    int i = elem_idx,   /* declare, initialize i, tmp */
        tmp = *(a + i);

    if (elem_idx == sz - 1)     /* elem_idx is last index */
        return;     /* no-swap */

    for (; i < sz - 1; i++)     /* loop shifting elements down */
        *(a + i) = *(a + i + 1);

    *(a + i) = tmp;     /* set last to tmp */
}

注意:,您将需要验证元素索引移动到末尾是否在索引的有效范围内,并且如果丢失的索引已经是索引,则无需执行交换。最后一个)。

一个简短的工作示例,其中WRAP常数在打印结果时仅控制每行不超过WRAP个值的输出,并且添加的DEBUG定义允许输出显示每个信息的附加信息如果编译字符串中包含-DDEBUG,例如

#include <stdio.h>

#ifndef WRAP
 #define WRAP 10
#endif

void element_to_last (int *a, int elem_idx, int sz)
{
    if (elem_idx > sz - 1) {    /* valdate index in range */
        fprintf (stderr, "error: index %d out of range for size %d\n",
                elem_idx, sz);
        return;
    }

    int i = elem_idx,   /* declare, initialize i, tmp */
        tmp = *(a + i);

    if (elem_idx == sz - 1) {   /* elem_idx is last index */
#ifdef DEBUG
        fprintf (stderr, " index %d (%d) is last index %d - no swap.\n",
                elem_idx, tmp, sz - 1);
#endif
        return;     /* no-swap */
    }

#ifdef DEBUG
    printf (" index %d (%d) to end %d\n", elem_idx, tmp, sz - 1);
#endif

    for (; i < sz - 1; i++)     /* loop shifting elements down */
        *(a + i) = *(a + i + 1);

    *(a + i) = tmp;     /* set last to tmp */
}

void prn_array (int *a, int sz, int wrap)
{
    for (int i = 0; i < sz; i++) {
        if (i && i % wrap == 0)
            putchar ('\n');
        printf (" %2d", *(a + i));
    }
    putchar ('\n');
}

int main (void) {

    int a[] = {0,1,2,3,4,5,6,7,8,9},    /* original array order */
        sz = sizeof a/sizeof *a,        /* nelem in original */
        n = sz,                         /* n tracks remaining size */
        loser[] = {2,0,7,3,2,3,2,1,1},  /* order of losing indexes */
        lsz = sizeof loser/sizeof *loser;   /* nelem in loser array */

    puts ("before:");
    prn_array (a, sz, WRAP);

    puts ("\nelimination\n(remove indexes 2,0,7,3,2,3,2,1,1):");
    for (int i = 0; i < lsz; i++) {
        element_to_last (a, loser[i], n > 0 ? n-- : n);
        prn_array (a, sz, WRAP);
    }

    puts ("\nafter:");
    prn_array (a, sz, WRAP);
}

注意:剩余的玩家,例如,用n跟踪元素的剩余数量,而sz保留整个数组的原始大小。{{1} }用于lsz数组的大小)

使用/输出示例

在未定义loser的情况下,输出仅显示失败者移至其余玩家的末尾后的数组状态:

DEBUG

调试输出

在定义了$ ./bin/array_rotate before: 0 1 2 3 4 5 6 7 8 9 elimination (remove indexes 2,0,7,3,2,3,2,1,1): 0 1 3 4 5 6 7 8 9 2 1 3 4 5 6 7 8 9 0 2 1 3 4 5 6 7 8 9 0 2 1 3 4 6 7 8 5 9 0 2 1 3 6 7 8 4 5 9 0 2 1 3 6 8 7 4 5 9 0 2 1 3 8 6 7 4 5 9 0 2 1 8 3 6 7 4 5 9 0 2 1 8 3 6 7 4 5 9 0 2 after: 1 8 3 6 7 4 5 9 0 2 的情况下,显示DEBUGindex中的每个(value)的附加信息已显示到结束索引,并附带说明在这种情况下{{ 1}}的尝试:

"no-swap"

仔细检查一下,如果还有其他问题,请告诉我。

答案 1 :(得分:0)

此代码应使用模来解决问题。

int size = 31;
int inc = 10;

for (int i = 0; i < size; i++)
{
    int t = ((i + 1) * inc) % (size - i);
    int *tmp = *(names + t);
    printf("%d\n", t);

    for (int j = t; j < (size - 1); j++)
    {
        *(names + j) = *(names + j + 1);
    }

    *(names + size - 1) = tmp;
}