C语言移动字符串问题

问题描述:
在这个题目中
输入一个字符串和一个整数 n,一行使用空格隔开,将 1 至 n 个字符,平移到字符串的最后,输出移动后的字符串。

输入格式
一个字符串和一个整数。

输出格式
一个字符串。
在我写的代码中出现了长的字符串移动错误的情况,短的却可以。
相关代码

#include<stdio.h>
void movechars(char *s,int n)
{
    for(char *p=s,*q=s+n;*q;p++,q++)
    {
        char temp=*p;
        *p=*q;
        *q=temp;
    }
}
int main(void)
{
    int n;
    char str[100];
    scanf("%s",str);
    scanf("%d",&n);
    movechars(str,n);
    printf("%s",str);
    return 0;
}

运行结果
实际输入:
qwe子qwe字qwe自retertgfgdhfdjxhdfhdfhfxhb 8
实际输出:
eretertgfgdhfdjxhdfhdfhfxhbqweqwqwe
预期输出:
eretertgfgdhfdjxhdfhdfhfxhbqwe紫qwe资qw
(实际字符串之间没有汉字,提问要求不能有重复字符)
实际输出与预期输出不同。
我的初步解决思路:
我用的双指针法实现的,并没有逻辑错误,也没有语法错误,不知道为什么错了。
#操作环境、软件版本等相关信息
头歌上的题目,操作环境,版本现版本。

遇到bug要会测试,你输入的全是重复的字符,排列到底对不对全靠猜
我输入:1234 3
输出:4231
因为你算法本身就不对
你是p和q一直在交换,但是q到结尾交换就结束了
你要把前n个字符先存起来,后n个字符往前挪,再把前n个字符追加到后面

void movechars(char *s, int n){
    int len = strlen(s);
    n = n % len;  // 获得有效的移动次数
    for (char *p = s, *q = s + n; *q; p++, q++){
        char temp = *p;
        *p = *q;
        *q = temp;
    }
}

为什么平移相对位置还会变

可采纳

void move(char *s,int m)
 {
     int i,j;
     char temp;
     for(i=1;i<=m;i++)//m是平移字符的个数 
     {
         temp=*s;//temp临时变量每次记录字符串的第一个字符 
         for(j=1;*(s+j)!='\0';j++)//内层循环 每次除了第一个字符的其他位置字符向左平移一位,m个字符向左平移m次 
         *(s+j-1)=*(s+j);
         *(s+j-1)=temp;
         *(s+j)='\0';
     }
 }


  • 这个问题的回答你可以参考下: https://ask.csdn.net/questions/722213
  • 除此之外, 这篇博客: C语言实现八大排序算法详解及其性能之间的中的 我们老师给我们花了100个星星的重要,那就是非常重要,快速排序。名字就很嚣张。。。言归正传,快排采用了分治算法。把大问题,分解成小问题。首先我们先找一个基准值,基准值的寻找法,有很多,这里我先用一个取边上值得方法,找到基准值以后呢拿着这个基准值和所有数组比较,使这个数组中比基准值小的都放左边,比基准值大的都放到右边,然后就把原来数组分成三块,中间基准值,左边都是比它小的,右边都是比它大的。然后这两个数组,继续分,一直分。直到他的终止条件,也就是小数组有序了就停止,那么什么时候有序停止呢?小区间长度为1或者长度为0的时候,就是有序了。所有小数组都有序了,那么就是整个数组有序了。只是原理,那么问题,又来了,怎么放左放右呢?我目前会三种。 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:
  • 算法思想

  • 以下回答由chatgpt基于相关博客总结生成:

    更新问题描述: 我正在做一个C语言程序,需要实现将输入的一个字符串中的前N个字符移动到字符串末尾的功能。我的代码实现了双指针交换的方法。但测试时,长字符串无法移动,而短字符串却能正常移动。以下是输入输出与我的预期不符的情况:

    实际输入:qwe子qwe字qwe自retertgfgdhfdjxhdfhdfhfxhb 8 实际输出:eretertgfgdhfdjxhdfhdfhfxhbqweqwqwe 预期输出:eretertgfgdhfdjxhdfhdfhfxhbqwe紫qwe资qw

    问题分析: 根据给出的参考资料没有与这个问题直接相关的内容。在分析这个问题时,可以先看一下代码实现,分析是否漏掉了某些细节问题。而一般情况下,字符串操作出现问题,可能是由于指针未初始化或移动过程中指针越界导致的。

    解决方案: 进一步分析给出的测试数据,我们可以看到出现问题的字符串的长度长达30多个字符。此时,如果采用双指针交换字符来实现移动的话,效率可能较低,同时,如果采用指针越界的方式来移动字符串,可能会出现意想不到的结果。因此,我们可以考虑采用较为简单的方式来实现字符串移动,比如先把前N个字符存到另一个字符串,然后再把剩下的字符放在新字符串的末尾,最后将之前存储的前N个字符追加在新字符串末尾即可。具体实现如下:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    void move(char* str, int n){
        char temp[n+1];
        strncpy(temp, str, n); // 把前N个字符存到临时字符串
        temp[n] = '\0';
        memmove(str, str+n, strlen(str)-n); // 向前移动剩下的字符串
        strcat(str, temp); // 在最后追加之前存储的前N个字符
    }
    
    int main(){
        char str[1000];
        int n;
        printf("请输入字符串和需要前移的字符数(用空格分隔):");
        scanf("%[^\n]%d", str, &n); // 同时输入字符串和数字
        move(str, n);
        printf("移动后字符串为:%s", str);
        return 0;
    }
    

    这里我们采用了C标准库函数 strncpy() 来将源字符串中的前n个字符复制到temp临时字符串中,并在temp字符串末尾补字符 '\0'。之后我们使用 memmove() 将源字符串中的剩余字符向前移动n个位置,并使用 strcat() 在移动后的字符串末尾添加temp临时字符串,实现整个字符串的前移。值得注意的是strcat() 前需要保证把'\0'添加在目标字符串的末尾,否则它会在不确定的位置添加。

    代码中,使用了字符串的头文件 string.h 中的三个函数。但快速阅读后,没有发现指针的越界问题。此时问题可能来自编译环境。如果是早期编译环境,字符串的内存分配是在栈区,如果字符串长度过长,就可能出现了栈空间不足的问题。这导致了程序的崩溃或其他非预期情况。可以采取的解决方案之一就是尽量不要用字符串的栈空间,而改用堆空间。

    更新后的代码,尽量使用了动态分配内存,可以在编译较早的版本上使用:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    void move(char* str, int n){
        char* temp = (char*)malloc((n+1)*sizeof(char)); // 使用动态分配内存
        strncpy(temp, str, n);
        temp[n] = '\0';
        memmove(str, str+n, strlen(str)-n);
        strcat(str, temp);
        free(temp); // 释放动态分配的内存
    }
    
    int main(){
        char* str = (char*)malloc(1000*sizeof(char)); // 同样使用动态分配内存
        int n;
        printf("请输入字符串和需要前移的字符数(用空格分隔):");
        scanf("%[^\n]%d", str, &n);
        move(str, n);
        printf("移动后字符串为:%s", str);
        free(str); // 释放动态分配的内存
        return 0;
    }
    

    在实现完代码后,我们可以多测试几个字符串长度,判断是否还会出现类似的问题。

    参考资料: 1. C语言中字符串的用法,见https://www.runoob.com/cprogramming/c-strings.html
    2. 何时需要使用指向堆的指针,见https://blog.csdn.net/lele12/article/details/76181443
    3. 栈空间和堆空间的区别,见https://www.guru99.com/cpp-stack-vs-heap.html