题目:
实现一个函数,可以左旋字符串中的k个字符。
例如:
ABCD左旋一个字符得到BCDA
ABCD左旋两个字符得到CDAB
法一(用两个循环):
//实现一个函数,可以左旋字符串中的k个字符。
#include<stdio.h>
void reverse(char arr[4], int k)
{
while (k--)
{
char start = arr[0]; //先保存最后一个字符
for(int i = 0; i <4 ; i++)
{
arr[i] = arr[i +1]; //每个字符往后移一位
}
arr[3] = start; //最后一个字符移到第一个位置
}
}
int main()
{
char arr[4] = {'A', 'B', 'C', 'D'};
int k = 0;
printf("请输入要左旋的字符数:\n");
scanf("%d", &k);
reverse(arr, k);
for (int i = 0; i < 4; i++)
{
printf("%c ", arr[i]);
}
return 0;
}
法二(建一个新的数组):
//实现一个函数,可以左旋字符串中的k个字符。
#include<stdio.h>
void reverse(char* arr, int k)
{
char newarr[4] = { 0 };
for(int i=0;i<4;i++)
{
newarr[i] = arr[(i + k) % 4];
}
for (int i = 0; i < 4; i++)
{
arr[i] = newarr[i];
printf("%c ", arr[i]);
}
}
int main()
{
char arr[4] = {'A','B','C','D'};
int k = 0;
printf("请输入要左旋的字符数:\n");
scanf("%d", &k);
reverse(arr, k);
return 0;
}
改进:
但是仍然有一个小问题。在 reverse 函数中,固定了新数组的长度为4,这意味着这个函数只能处理长度为4的字符串。为了使函数更通用,应该传递字符串的长度作为参数。
另外,代码中没有处理当 k 大于字符串长度的情况。在这种情况下,我们应该将 k 对字符串长度取模,以确保 k 在正确的范围内。
修改如下:
#include <stdio.h>
#include <string.h>
void reverse(char* arr, int n, int k)
{
k = k % n; // 如果k大于n,只旋转k%n个字符
char newarr[n]; // 这里还是有问题,[]中应该是常量表达式,而不是变量
for (int i = 0; i < n; i++)
{
newarr[i] = arr[(i + k) % 4];
}
for (int i = 0; i < n; i++)
{
arr[i] = newarr[i];
}
}
int main()
{
char arr[] = {'A', 'B', 'C', 'D'}; // 不再固定长度为4
int k;
printf("请输入要左旋的字符数: \n");
if (scanf("%d", &k) != 1)
{
printf("输入错误,请输入一个整数。\n");
return 1;
}
int n = sizeof(arr) / sizeof(arr[0]); // 计算数组长度
reverse(arr, n, k); // 传递数组、数组的实际长度和k
// 打印旋转后的数组
for (int i = 0; i < n; i++)
{
printf("%c ", arr[i]);
}
printf("\n");
return 0;
}
但是程序报错。
在C语言中,数组的大小必须在编译时是一个已知常量。这意味着我们不能使用一个变量来定义数组的长度,除非我们使用动态内存分配。
在上面那个代码中, char newarr[n] 这行代码想在栈上创建一个大小为 n 的数组,其中 n 是一个变量。这在 C 语言中是不合法的,因为数组的大小必须是一个常量表达式。
为了解决这个问题,我们可以使用 malloc 或 calloc来动态地分配内存,这样就可以在运行时确定数组的大小。
1. 下面是一个使用 malloc 的例子:
#include <stdio.h>
#include <stdlib.h> // calloc和free要包含这个头文件
void reverse(char* arr, int n, int k)
{
k = k % n; // 如果k大于n,只旋转k%n个字符
char* newarr = (char*) malloc(n * sizeof(char)); // 动态分配内存
if (newarr == NULL)
{
// 分配失败,处理错误
printf("内存分配失败\n");
return;
}
for (int i = 0; i < n; i++)
{
newarr[i] = arr[(i + k) % 4];
}
for (int i = 0; i < n; i++)
{
arr[i] = newarr[i];
}
free(newarr); // 释放内存
newarr = NULL; // 将指针置为 NULL
}
int main()
{
char arr[] = {'A', 'B', 'C', 'D'};
int k;
printf("请输入要左旋的字符数: \n");
if (scanf("%d", &k) != 1)
{
printf("输入错误,请输入一个整数。\n");
return 1;
}
int n = sizeof(arr) / sizeof(arr[0]); // 计算数组长度
reverse(arr, n, k); // 传递数组、数组的实际长度和k
// 打印旋转后的数组
for (int i = 0; i < n; i++)
{
printf("%c ", arr[i]);
}
printf("\n");
return 0;
}
使用 malloc 来动态地分配一个大小为 n 的数组 newarr 。使用 malloc 返回的指针来访问分配的内存。在reveerse 函数的最后,我们使用 free 来释放 newarr 所指向的内存,以避免内存泄漏。
2. 下面是一个使用 calloc 的例子:
calloc 需要两个参数:要分配的元素数量和每个元素的大小。
#include <stdio.h>
#include <stdlib.h> // calloc和free要包含这个头文件
void reverse(char* arr, int n, int k)
{
k = k % n; // 如果k大于n,只旋转k%n个字符
char* newarr = (char*) calloc(n, sizeof(char)); // 动态分配内存并初始化为0
if (newarr == NULL)
{
// 分配失败,处理错误
printf("内存分配失败\n");
return;
}
for (int i = 0; i < n; i++)
{
newarr[i] = arr[(i + k) % 4];
}
for (int i = 0; i < n; i++)
{
arr[i] = newarr[i];
}
free(newarr); // 释放内存
newarr = NULL; // 将指针置为 NULL
}
int main()
{
char arr[] = {'A', 'B', 'C', 'D'};
int k;
printf("请输入要左旋的字符数:\n");
if (scanf("%d", &k) != 1)
{
printf("输入错误,请输入一个整数。\n");
return 1;
}
int n = sizeof(arr) / sizeof(arr[0]); // 计算数组长度
reverse(arr, n, k); // 传递数组、数组的实际长度和k
// 打印旋转后的数组
for (int i = 0; i < n; i++)
{
printf("%c ", arr[i]);
}
printf("\n");
return 0;
}
我们使用 calloc 来替代 malloc 分配 newarr 数组。 calloc 的第一个参数是元素的数量,第二个参数是每个元素的大小,这里是 sizeof(char) 。这样 calloc 会分配 n 个字符大小的内存,并将其全部初始化为 0。
在其他方面,使用 calloc 的代码与使用 malloc 的代码相同。我们仍然需要在操作完成后使用 free 来释放内存,以避免内存泄漏。
宝子们,动动你们发财的小手点点赞吧