数组的两个练习

左移右移

假设有数组[1,2,3,4,5]

实现时应该注意

在开始编写程序前,我们先做一个简单的规划,

为此,我们可以先列出函数原型。

void print_array(int arr[], int size);
void left_shift_array(int arr[], int size);
void right_shift_array(int arr[], int size);

接下来,我们逐个函数编写程序:

void print_array(int arr[], int size)
{
    printf("[");
    for (int i = 0; i < size; i++)
        printf( i < (size - 1) ? "%d, " : "%d", arr[i]);
    printf("]\n");
}

print_array()使用条件运算符控制格式符,为每个非最后元素追加一个','分隔符,整个数组以[]包含。

void left_shift_array(int arr[], int size)
{
    // 数组只有一个元素时,不需要处理
    if (size == 1)
        return;

    // 保存第一个元素的拷贝
    int first = arr[0];

    // 将后面的元素逐个向前移动1位
    for (int i = 1; i < size; i++)
        arr[i - 1] = arr[i];

    // 第一个元素放到数组尾部
    arr[size - 1] = first;
}

左移函数left_shift_array()已经注释的很详细了,右移的编写与之类似,只需要反向进行即可。

void right_shift_array(int arr[], int size)
{
    if (size == 1)
        return;

    int last = arr[size - 1];

    for (int i = size - 1; i > 0; i--)
        arr[i] = arr[i - 1];

    arr[0] = last;
}

最后我们编写主函数,驱动我们的代码即可。

int main()
{
    int nums[] = { 1, 2, 3, 4, 5, 6 };
    print_array(nums, 6);

    printf("\nleft shift:\n");
    left_shift_array(nums, sizeof(nums) / sizeof(int));
    print_array(nums, 6);
    left_shift_array(nums, sizeof(nums) / sizeof(nums[0]));
    print_array(nums, 6);

    printf("\nright shift:\n");
    right_shift_array(nums, sizeof(nums) / sizeof(int));
    print_array(nums, 6);
    right_shift_array(nums, sizeof(nums) / sizeof(nums[5]));
    print_array(nums, 6);

    return 0;
}

glimix.com

何年何月

也许我们对今天是这一年中的第x天感兴趣,同样可以编写程序来求解。首先我们考虑一下月份天数的存储设计,数组是首选:

int days[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

下标0对应1月份的天数,这个偏差不是大问题,但如果让下标与月份一一对应,可能更优雅。这里我们为数组分配13个空间,0索引处不用,这样days[1]就与1月的天数相对应了。

int days[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

另一种设计就是,要不要存储月份天数累加值?这种策略下,查询会很简单;而使用之前的方法,则需要一个循环累加求值。

int days[13] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
days[7] + 26 = 212 + 26 = 238 // 当查询8月26日时的表达

这里,我们选择第二种方式存储月份信息。函数is_leap_year()判断传入的年份是否为闰年,这样一年的2月份会有29天。

int days_in_month(int year, int month)
{
    int days[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

    if (month == 2 && is_leap_year(year))
        return 29;
    else
        return days[month];
}

bool is_leap_year(int year)
{
    return (year % 4 == 0 && year % 100 != 0) ||
           (year % 400) == 0;
}

然后就是累加计算天数的部分:

int date_to_days(int year, int month, int day)
{
    int days = day;

    for (int m = 1; m < month; m++)
    {
        days += days_in_month(year, m);
    }

    return days;
}

最后编写主程序将它们驱动起来。

int main()
{
    printf("2000-05-02: %d\n", date_to_days(2000, 5, 2));
    printf("1956-11-30: %d\n", date_to_days(1956, 11, 30));
    printf("2021-08-26: %d\n", date_to_days(2021, 8, 26));
    return 0;
}

glimix.com

陕ICP备2025078817号-1 陕公网安备61011202001108号