简体   繁体   English

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

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

I'm trying to use sprintf() to put a string "inside itself", so I can change it to have an integer prefix. 我正在尝试使用sprintf()将字符串“放入自身”,因此可以将其更改为具有整数前缀。 I was testing this on a character array of length 12 with "Hello World" inside it already. 我已经在长度为12的字符数组中对此进行了测试,并且其中已经包含“ Hello World”。

The basic premise is that I want a prefix that denotes the amount of words within a string. 基本前提是我想要一个表示字符串中单词数量的前缀。 So I copy 11 characters into a character array of length 12. Then I try to put the integer followed by the string itself by using "%i%s" in the function. 因此,我将11个字符复制到长度为12的字符数组中。然后,我尝试通过在函数中使用"%i%s"来将整数和字符串本身放在后面。 To get past the integer (I don't just use myStr as the argument for %s ), I make sure to use myStr + snprintf(NULL, 0, "%i", wordCount) , which should be myStr + characters taken up by the integer. 要跳过整数(我不只是将myStr用作%s的参数),请确保使用myStr + snprintf(NULL, 0, "%i", wordCount) ,它应该是myStr + characters taken up by the integer.

The problem is that I'm having is that it eats the 'H' when I do this and prints "2ello World" instead of having the '2' right beside the "Hello World" 问题是我在执行此操作时会吃掉“ H”并打印“ 2ello World”,而不是在“ Hello World”旁边显示“ 2”

So far I've tried different options for getting "past the integer" in the string when I try to copy it inside itself, but nothing really seems to be the right case, as it either comes out as an empty string or just the integer prefix itself '222222222222' copied throughout the entire array. 到目前为止,当我尝试将其复制到自身中时,我已经尝试了各种不同的方法来获取字符串中的“过去的整数”,但是似乎没有什么是正确的情况,因为它要么是空字符串,要么只是整数前缀“ 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;
}

First, to insert a one-digit prefix into a string “Hello World”, you need a buffer of 13 characters—one for the prefix, eleven for the characters in “Hello World”, and one for the terminating null character. 首先,要将一位数字的前缀插入字符串“ Hello World”中,需要一个13个字符的缓冲区,一个为前缀,11个为“ Hello World”中的字符,另一个为终止的空字符。

Second, you should not pass a buffer to snprintf as both the output buffer and an input string. 其次,不应将缓冲区作为输出缓冲区和输入字符串传递给snprintf Its behavior is not defined by the C standard when objects passed to it overlap. 当传递给它的对象重叠时,C标准未定义其行为。

Below is a program that shows you how to insert a prefix by moving the string with memmove . 下面的程序向您展示如何通过使用memmove移动字符串来插入前缀。 This is largely tutorial, as it is not generally a good way to manipulate strings. 这主要是教程,因为它通常不是操纵字符串的好方法。 For short strings, where space is not an issue, most programmers would simply print the desired string into a temporary buffer, avoiding overlap issues. 对于短字符串来说,空间不是问题,大多数程序员只会将所需的字符串打印到临时缓冲区中,从而避免出现重叠问题。

#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);
}

The best way to deal with this is to create another buffer to output to, and then if you really need to copy back to the source string then copy it back once the new copy is created. 解决此问题的最佳方法是创建另一个要输出到的缓冲区,然后,如果您确实需要复制回源字符串,则在创建新副本后将其复制回。

There are other ways to "optimise" this if you really needed to, like putting your source string into the middle of the buffer so you can append and change the string pointer for the source (not recommended, unless you are running on an embedded target with limited RAM and the buffer is huge). 如果确实需要,还有其他方法可以“优化”,例如将源字符串放入缓冲区的中间,以便可以为源添加和更改字符串指针(不建议这样做,除非您在嵌入式目标上运行内存有限且缓冲区很大)。 Remember code is for people to read so best to keep it clean and easy to read. 请记住,代码是供人们阅读的,因此最好保持代码整洁且易于阅读。

#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;
}

Notes: 笔记:

  1. To be safer protecting overflows in memory you should use strncpy and snprintf. 为了更安全地防止内存溢出,您应该使用strncpy和snprintf。

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

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