【C语言】实现字符串的左旋

本文详细介绍了如何使用循环移动、截取拼接和逆序反转三种方法在C语言中实现字符串的左旋操作,通过实例展示了每种方法的原理和代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一.前言

本文章将使用三种思路实现字符串的左旋(循环移动,截取和拼接,逆序反转

二.题目要求

实现一个函数,可以左旋字符串中的k个字符。

例如:

ABCD左旋一个字符得到BCDA
ABCD左旋两个字符得到CDAB

三.题目分析

1 循环移动

当我们需要将字符串左旋k个字符时,一种简单的思路是通过循环移动字符的位置来实现。

具体的步骤如下:

  1. 首先获取字符串的长度,并对k进行取模操作。这是因为如果k的值大于字符串的长度,可以通过取模操作将其转换为一个等效的较小值。例如,对于字符串"ABCD",左旋5个字符相当于左旋1个字符,因为多余的4次旋转会回到原始的状态。
  2. 使用一个外层循环控制左旋的次数,执行k次循环即可完成字符的左旋操作。
  3. 在每次循环内部,使用一个内层循环将字符串中的每个字符向前移动一位。从第一个字符开始,将它后面的所有字符依次向前移动一个位置,直到倒数第二个字符。最后,将原始字符串的第一个字符放置在末尾位置,完成一次循环。
  4. 重复执行步骤3,直到完成k次循环,即完成字符串的左旋操作。

这样,我们通过循环移动字符的位置,就能够实现字符串的左旋。在给定的例子中,字符串"ABCD"左旋2个字符,首先将"A"移到末尾得到"BCDA",然后再将"B"移到末尾得到"CDAB",最终得到结果"CDAB"。

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

void leftRotate(char *str, int k)
 {
    int len = strlen(str);
    
    // 对k取模,避免多余的左旋操作
    k %= len;
       
    // 左旋k个字符
    for (int i = 0; i < k; i++) 
    {
        char temp = str[0];
        
        for (int j = 0; j < len - 1; j++) //单次平移
        {
            str[j] = str[j + 1];
        }
        
        str[len - 1] = temp;
    }
}

int main() 
{
    char str[] = "ABCD";
    int k = 0;
    printf("请输入左旋的次数 k == ");
    scanf("%d",&k);
    
    printf("原始字符串:%s\n", str);
    
    leftRotate(str, k);
    
    printf("左旋%d个字符后的字符串:%s\n", k, str);
    
    return 0;
}

示例输出
在这里插入图片描述

这种方法虽然简单,但是比较繁琐,执行次数较多,接下来将展示其他思路

2.截取和拼接

截取和拼接方法是一种简单直观的字符串左旋实现方式。其基本思路可以分为以下几个步骤:

1.对于左旋k个字符,我们需要将前k个字符截取出来。这可以使用标准库函数strncpy来实现,它接受三个参数:目标字符串、源字符串以及要复制的字符数。

strncpy函数用于将指定长度的字符串复制到字符数组中

2.将剩余的字符截取出来。由于C语言中字符串是以null字符(‘\0’)结尾的,我们可以通过直接使用源字符串的指针进行偏移来获取剩余的字符。

3.我们将两部分截取的字符串进行拼接。这可以使用标准库函数strcat来实现,它接受两个参数:目标字符串和要追加的字符串。

字符串连接函数 strcat() 可以将两个字符串连接起来。该函数从源字符串的尾部开始复制字符,直到遇到 NULL
字符。然后,它将目标字符串的 NULL 字符替换为源字符串中遇到的 NULL 字符。

4.最后,我们将修改后的字符串复制回原始的字符串变量中,这可以使用标准库函数strcpy来实现。

strcpy()函数:是将一个字符串复制到另一块空间地址中 的函数,‘\0’是停止拷贝的终止条件,同时也会将 ‘\0’ 也复制到目标空间。

代码展示如下

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

void leftRotate(char *str, int k) 
{
    int len = strlen(str);
    
    // 对k取模,避免多余的左旋操作
    k %= len;
    
    // 创建临时数组用于存储截取的前k个字符
    char temp[256];//这里使用k+1最好,因为vs中不支持变长数组,故这里初始化了一个值
    strncpy(temp, str, k);
    temp[k] = '\0';
    
    // 将剩余的字符覆盖原始字符串
    strcpy(str, str + k);
    
    // 拼接截取的前k个字符到末尾
    strcat(str, temp);
}

int main() 
{
    char str[] = "ABCD";
    int k = 0;
    printf("请输入左旋的次数 k == ");
    scanf("%d",&k);
    
    printf("原始字符串:%s\n", str);
    
    leftRotate(str, k);
    
    printf("左旋%d个字符后的字符串:%s\n", k, str);
    
    return 0;
}

3.逆序反转

除了前面提到的方法,还有一种巧妙的解法是使用字符串翻转的方式来实现字符串左旋,具体思路如下:

1.首先将字符串划分为两部分,即前k个字符和剩余的字符

2.分别对这两部分进行翻转操作:

  • 对前k个字符进行翻转
  • 对剩余的字符进行翻转

3.最后对整个字符串进行翻转操作,此时前k个字符已经在最后,完成左旋操作

举个例子,我们对“ABCD”进行两次左旋。
先将要左旋的前两个逆序(BACD),然后将后半段也逆序(BADC),最后整体逆序(CDAB)

下图为代码演示

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

void reverse(char *str, int start, int end) 
{
    while (start < end) 
    {
        char temp = str[start];
        str[start] = str[end];
        str[end] = temp;
        start++;
        end--;
    }
}

void leftRotate(char *str, int k) 
{
    int len = strlen(str);
    
    // 对k取模,避免多余的左旋操作
    k %= len;
    
    reverse(str, 0, k-1);         // 前k个字符翻转
    reverse(str, k, len-1);       // 剩余的字符翻转
    reverse(str, 0, len-1);       // 整个字符串翻转
}

int main() 
{
    char str[] = "ABCD";
    int k = 0;
    printf("请输入左旋的次数 k == ");
    scanf("%d",&k);
    
    printf("原始字符串:%s\n", str);
    
    leftRotate(str, k);
    
    printf("左旋%d个字符后的字符串:%s\n", k, str);
    
    return 0;
}

四.尾声

以上就是本文章的所有内容,如果大家有更好的方法,大家可以在评论区讨论或者私信给博主。

在C语言中,可以通过暴力移位法或者Left函数实现字符串左旋。其中,暴力移位法是通过循环移位的方式实现字符串左旋,而Left函数则是通过将字符串分为两部分,分别进行翻转,再将整个字符串翻转的方式实现字符串左旋。 以下是两种实现字符串左旋的方法: 1. 暴力移位法 ```c #include <stdio.h> #include <string.h> void left_move(char* str, int k) { int len = strlen(str); int i = 0; k %= len; // 省去多余循环步骤,多出字符串长度会导致多余的循环操作 while (k--) { // 左旋循环k次 char tmp = str[0]; // 创建tmp来存放字符串第一个字符 for (i = 0; i < len - 1; i++) { str[i] = str[i + 1]; // 后面的字符依次向前一位 } str[i] = tmp; // 在末尾放入tmp中的字符 } } int main() { char str[] = "ABCD"; left_move(str, 2); printf("%s\n", str); // 输出:CDAB return 0; } ``` 2. Left函数实现 ```c #include <stdio.h> #include <string.h> #include <assert.h> void Reverse(char *str, int start, int end) { // 翻转字符串 assert(str); while (start < end) { char tmp = str[start]; str[start] = str[end]; str[end] = tmp; start++; end--; } } void Left(char *str, int len, int n) { assert(str); // 断言str不为空 assert(len); // 断言字符串长度不为0 assert(n); // 断言输入左旋次数不为0 n %= len; // 省去多余循环步骤,多出字符串长度会导致多余的循环操作 Reverse(str, 0, n - 1); // 翻转前半部分 Reverse(str, n, len - 1); // 翻转后半部分 Reverse(str, 0, len - 1); // 整个字符串翻转 } int main() { char str[] = "ABCD"; Left(str, strlen(str), 2); printf("%s\n", str); // 输出:CDAB return 0; } ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值