C 将字符数组中的字符向右移动的最佳方法

C 将字符数组中的字符向右移动的最佳方法,c,char,shift,C,Char,Shift,我试图在Linux(Ubuntu18.04)上的C语言中将char数组的元素向右移动,并尝试为此创建一个函数。基本上,我希望将x元素的数量预先添加到数组的开头,并将其余数据移动x(向右)。如果新元素+旧有效元素超过char大小,我希望函数返回一个错误,并且不进行任何移位。我还制作了一个指向char数组的char指针,并使用结构设置char数据 这是我做的一个测试程序: #include <stdio.h> #include <unistd.h> #include <

我试图在Linux(Ubuntu18.04)上的C语言中将
char
数组的元素向右移动,并尝试为此创建一个函数。基本上,我希望将
x
元素的数量预先添加到数组的开头,并将其余数据移动
x
(向右)。如果新元素+旧有效元素超过
char
大小,我希望函数返回一个错误,并且不进行任何移位。我还制作了一个指向
char
数组的
char
指针,并使用结构设置
char
数据

这是我做的一个测试程序:

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

struct struct1
{
    char str[10];
    int myNum;
};

struct struct2
{
    char str[5];
};

int shiftChar(char *arr, int size, int length)
{

    for (int i = 0; i < length; i++)
    {
        // I know I am calculating this incorrectly. Though, not sure how I should go about checking if the new size will exceed the length of the char array.
        if (length < ((i + 1) + size))
        {
            return -1;
        }

        // If element is 0, we shouldn't shift it (usually represents garbage value?). Not sure how to detect whether an element of a char array was filled with actual data or not.
        if (arr[i] == 0)
        {
            continue;
        }

        arr[i + size] = arr[i];
        fprintf(stdout, "Replacing %c with %c at %d => %d\n\n", arr[i + size], arr[i], i, i + size);
    }

    for (int i = 0; i < size; i++)
    {
        arr[i] = 0;
    }

    return 0;
}

int main()
{
    char buffer[256];
    struct struct1 *struct1 = (struct struct1 *) (buffer);
    struct struct2 *struct2 = (struct struct2 *) (buffer + sizeof(struct struct1));

    struct1->myNum = 5;
    strncpy(struct1->str, "Hello!", 6);

    strncpy(struct2->str, "TST", 3);

    fprintf(stdout, "Buffer => ");

    for (int i = 0; i < (sizeof (struct struct1) + sizeof(struct struct2)); i++)
    {
        fprintf(stdout, "%c", buffer[i]);
    }

    fprintf(stdout, "\n\n");

    if (shiftChar(buffer, 6, 256) != 0)
    {
        fprintf(stdout, "Error shifting char array.\n");

        //exit(1);
    }

    struct1 = (struct struct1 *) (buffer + 6);
    struct2 = (struct struct2 *) (buffer + sizeof(struct struct1) + 6);

    fprintf(stdout, "struct1->str => %s\n", struct1->str);

    exit(0);
}
我知道我做得不对,但我不确定我做错了什么,或者我是否应该采取不同的做法

我的主要问题是:

  • shiftChar()
    函数有什么问题

  • 有没有更好/更简单的方法来实现我的目标

  • 是否有方法检查
    char
    数组中的元素是否有垃圾值(例如,尚未填充的值)?我想我可以使用类似于
    memset()
    的东西将缓冲区设置为所有
    0
    ,但是如果我有一个
    int
    结构指向值为“0”的缓冲区数据,会发生什么呢。如果我检查值是否等于“0”,我可以想象这将与移位一起排除

  • 我也已经对此进行了研究,但是我遇到的大多数线程是C++的,或者是向左移动元素的。我无法为我的问题找到一个可靠的解决方案。我将在我正在制作的另一个程序中使用该解决方案(如果有的话),我需要在开始时将
    struct iphdr
    的大小添加到现有的缓冲区字符中(数据已经通过
    struct iphdr
    struct udphdr
    填充),这样我就可以创建和发送IPIP数据包(网络编程)。我也知道我可以创建一个全新的字符,只需从旧的缓冲区复制数据(同时保持第一个
    sizeof(struct iphdr)
    元素的空闲),但我想,在我的情况下,这将是一个相当大的性能打击,因为我将不得不每秒执行数千次,最好只是修改现有的缓冲区
    char

    我是C编程新手。因此,我确信我遗漏了一些东西

    如果您需要任何其他信息,请让我知道,并高度感谢任何帮助


    谢谢您的时间。

    我不知道什么是最好的方式,但我想您想要这样的方式

    char *prependstr(char *str, const char *pstr)
    {
        size_t pstrlen = strlen(pstr);
        memmove(str + pstrlen, str, strlen(str) + 1);
        memcpy(str,pstr, pstrlen);
        return str;
    }
    
    int main()
    {
        char x[256] = "";
        char pstr[] = "Hello00!!";
        int i = 0;
    
        do
        {   
            sprintf(pstr, "Hello%02d!!", i++);
            printf("%s\n", prependstr(x,pstr)); 
        }while(strlen(pstr) + strlen(x) + 1 < sizeof(x));
    }
    
    char*prependstr(char*str,const char*pstr)
    {
    大小\u t pstrlen=strlen(pstr);
    memmove(str+pstrlen,str,strlen(str)+1);
    memcpy(str、pstr、pstrlen);
    返回str;
    }
    int main()
    {
    字符x[256]=“”;
    char pstr[]=“你好!!”;
    int i=0;
    做
    {   
    sprintf(pstr,“你好%02d!!”,i++);
    printf(“%s\n”,prependstr(x,pstr));
    }而(strlen(pstr)+strlen(x)+1

    我不知道什么是最好的方式,但我想你想要这样的方式

    char *prependstr(char *str, const char *pstr)
    {
        size_t pstrlen = strlen(pstr);
        memmove(str + pstrlen, str, strlen(str) + 1);
        memcpy(str,pstr, pstrlen);
        return str;
    }
    
    int main()
    {
        char x[256] = "";
        char pstr[] = "Hello00!!";
        int i = 0;
    
        do
        {   
            sprintf(pstr, "Hello%02d!!", i++);
            printf("%s\n", prependstr(x,pstr)); 
        }while(strlen(pstr) + strlen(x) + 1 < sizeof(x));
    }
    
    char*prependstr(char*str,const char*pstr)
    {
    大小\u t pstrlen=strlen(pstr);
    memmove(str+pstrlen,str,strlen(str)+1);
    memcpy(str、pstr、pstrlen);
    返回str;
    }
    int main()
    {
    字符x[256]=“”;
    char pstr[]=“你好!!”;
    int i=0;
    做
    {   
    sprintf(pstr,“你好%02d!!”,i++);
    printf(“%s\n”,prependstr(x,pstr));
    }而(strlen(pstr)+strlen(x)+1

    这是我最初发布的功能的一个修改版本,在我的案例中似乎有效:

    void shiftChar(char *arr, int size, int dataLen)
    {
        for (int i = (dataLen - 1); i >= 0; i--)
        {
            memmove(arr + i + size, arr + i, 1);
        }
    
        for (int i = 0; i < size; i++)
        {
            memcpy(arr + i, "0", 1);
        }
    }
    
    以下是输出:

    Buffer => Hello!����TST
    
    New Buffer => 000000Hello!����TST
    
    struct1->str => Hello!
    
    感谢@p_uuuj_uuu和@Lee Daniel Crocker推荐
    memmove()
    memcpy()

    如果您看到任何可以改进的地方,请随时发表评论


    谢谢。

    这是我最初发布的功能的一个修改版本,在我的案例中似乎可以使用:

    void shiftChar(char *arr, int size, int dataLen)
    {
        for (int i = (dataLen - 1); i >= 0; i--)
        {
            memmove(arr + i + size, arr + i, 1);
        }
    
        for (int i = 0; i < size; i++)
        {
            memcpy(arr + i, "0", 1);
        }
    }
    
    以下是输出:

    Buffer => Hello!����TST
    
    New Buffer => 000000Hello!����TST
    
    struct1->str => Hello!
    
    感谢@p_uuuj_uuu和@Lee Daniel Crocker推荐
    memmove()
    memcpy()

    如果您看到任何可以改进的地方,请随时发表评论


    谢谢。

    除非您将
    arr
    限制为以nul结尾的C字符串,否则您还需要进行一些检查,以确保仅将数组中的初始化字符移动不超过保留在数组中字符右侧的元素。此外,除非使用以nul结尾的C字符串,否则不能依靠
    strlen()
    获取数组中的字符数。您必须将其作为附加参数传递,否则将调用未定义的行为,将未终止的数组传递给
    strlen()

    当编写一个在有限的存储空间内操作任何东西的函数时,它通常有助于抓取铅笔和纸,画出您正在处理的内容,并标记您将需要的变量(纸和铅笔比ASCII艺术快得多)。没什么特别的,但您可以使用以下内容:

        |<--------------- size ---------------->|
        |                                       |
        +---+---+---+---+---+---+---+---+---+---+
        | a | b | c | d |   |   |   |   |   |   |
        +---+---+---+---+---+---+---+---+---+---+
        |<---- nchr --->|
        |<-------- shift ------>|
    
    int shiftchar (char *arr, size_t size, size_t nchr, size_t shift)
    {
        size_t max = size - nchr;   /* max shift is size - no. of filled chars */
    
        if (!shift) {       /* validate positive shift */
            fputs ("error: zero shift requested\n", stderr);
            return 0;       /* return failure */
        }
    
        if (shift > max) {  /* check if shift exceeds no. of chars available */
            fputs ("error: shift exceeds array bounds\n", stderr);
            return 0;       /* return failure */
        }
    
        memmove (&arr[shift], arr, shift);      /* shift chars in arr to right */
    
        return 1;   /* return success */
    }
    
    10
    元素字符数组中,循环试图在
    0
    9
    元素之间移动的一个简短示例可能是:

    #include <stdio.h>
    #include <string.h>
    
    int shiftchar (char *arr, size_t size, size_t nchr, size_t shift)
    {
        size_t max = size - nchr;   /* max shift is size - no. of filled chars */
    
        if (!shift) {       /* validate positive shift */
            fputs ("error: zero shift requested\n", stderr);
            return 0;       /* return failure */
        }
    
        if (shift > max) {  /* check if shift exceeds no. of chars available */
            fputs ("error: shift exceeds array bounds\n", stderr);
            return 0;       /* return failure */
        }
    
        memmove (&arr[shift], arr, shift);      /* shift chars in arr to right */
    
        return 1;   /* return success */
    }
    
    int main (void) {
    
        for (size_t i = 0; i < 10; i++) {
            char arr[10] = "0123456789";
            if (shiftchar (arr, 10, i, i)) {
                memset (arr, 'z', i);
                printf ("%.10s\n", arr);
            }
        }
    }
    
    将这些想法与您收到的其他答案结合起来,您应该能够编写满足所有需求的移位函数。还要记住,如果处理的不是
    char
    字符,则需要将移位的字节数乘以该数量,例如

        memmove (&arr[shift], arr, shift * sizeof *arr);      /* shift elements in arr to right */
    

    如果您还有其他问题,请告诉我。

    除非您将
    arr
    限制为以nul结尾的C字符串,否则您还需要进行一些检查,以确保只移动数组中的初始化字符,移动的长度不超过保留在字符右侧的元素