簡體   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