繁体   English   中英

C-使用sprintf()在字符串中放置前缀

[英]C - Using sprintf() to put a prefix inside of a string

我正在尝试使用sprintf()将字符串“放入自身”,因此可以将其更改为具有整数前缀。 我已经在长度为12的字符数组中对此进行了测试,并且其中已经包含“ Hello World”。

基本前提是我想要一个表示字符串中单词数量的前缀。 因此,我将11个字符复制到长度为12的字符数组中。然后,我尝试通过在函数中使用"%i%s"来将整数和字符串本身放在后面。 要跳过整数(我不只是将myStr用作%s的参数),请确保使用myStr + snprintf(NULL, 0, "%i", wordCount) ,它应该是myStr + characters taken up by the integer.

问题是我在执行此操作时会吃掉“ H”并打印“ 2ello World”,而不是在“ Hello World”旁边显示“ 2”

到目前为止,当我尝试将其复制到自身中时,我已经尝试了各种不同的方法来获取字符串中的“过去的整数”,但是似乎没有什么是正确的情况,因为它要么是空字符串,要么只是整数前缀“ 222222222222”本身会复制到整个数组中。

int main() {
    char myStr[12];
    strcpy(myStr, "Hello World");//11 Characters in length
    int wordCount = 2;

    //Put the integer wordCount followed by the string myStr (past whatever amount of characters the integer would take up) inside of myStr
    sprintf(myStr, "%i%s", wordCount, myStr + snprintf(NULL, 0, "%i", wordCount));
    printf("\nChanged myStr '%s'\n", myStr);//Prints '2ello World'
    return 0;
}

首先,要将一位数字的前缀插入字符串“ Hello World”中,需要一个13个字符的缓冲区,一个为前缀,11个为“ Hello World”中的字符,另一个为终止的空字符。

其次,不应将缓冲区作为输出缓冲区和输入字符串传递给snprintf 当传递给它的对象重叠时,C标准未定义其行为。

下面的程序向您展示如何通过使用memmove移动字符串来插入前缀。 这主要是教程,因为它通常不是操纵字符串的好方法。 对于短字符串来说,空间不是问题,大多数程序员只会将所需的字符串打印到临时缓冲区中,从而避免出现重叠问题。

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


/*  Insert a decimal numeral for Prefix into the beginning of String.
    Length specifies the total number of bytes available at String.
*/
static void InsertPrefix(char *String, size_t Length, int Prefix)
{
    //  Find out how many characters the numeral needs.
    int CharactersNeeded = snprintf(NULL, 0, "%i", Prefix);

    //  Find the current string length.
    size_t Current = strlen(String);

    /*  Test whether there is enough space for the prefix, the current string,
        and the terminating null character.
    */
    if (Length < CharactersNeeded + Current + 1)
    {
        fprintf(stderr,
            "Error, not enough space in string to insert prefix.\n");
        exit(EXIT_FAILURE);
    }

    //  Move the string to make room for the prefix.
    memmove(String + CharactersNeeded, String, Current + 1);

    /*  Remember the first character, because snprintf will overwrite it with a
        null character.
    */
    char Temporary = String[0];

    //  Write the prefix, including a terminating null character.
    snprintf(String, CharactersNeeded + 1, "%i", Prefix);

    //  Restore the first character of the original string.
    String[CharactersNeeded] = Temporary;
}

int main(void)
{
    char MyString[13] = "Hello World";

    InsertPrefix(MyString, sizeof MyString, 2);

    printf("Result = \"%s\".\n", MyString);
}

解决此问题的最佳方法是创建另一个要输出到的缓冲区,然后,如果您确实需要复制回源字符串,则在创建新副本后将其复制回。

如果确实需要,还有其他方法可以“优化”,例如将源字符串放入缓冲区的中间,以便可以为源添加和更改字符串指针(不建议这样做,除非您在嵌入式目标上运行内存有限且缓冲区很大)。 请记住,代码是供人们阅读的,因此最好保持代码整洁且易于阅读。

#define MAX_BUFFER_SIZE  128

int main() {
    char srcString[MAX_BUFFER_SIZE];
    char destString[MAX_BUFFER_SIZE];

    strncpy(srcString, "Hello World", MAX_BUFFER_SIZE);
    int wordCount = 2;

    snprintf(destString, MAX_BUFFER_SIZE, "%i%s", wordCount, srcString);
    printf("Changed string '%s'\n", destString);

    // Or if you really want the string put back into srcString then:
    strncpy(srcString, destString, MAX_BUFFER_SIZE);
    printf("Changed string in source '%s'\n", srcString);

    return 0;
}

笔记:

  1. 为了更安全地防止内存溢出,您应该使用strncpy和snprintf。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM