C - Использование sprintf (), чтобы поместить префикс внутри строки - PullRequest
0 голосов
/ 06 июля 2019

Я пытаюсь использовать 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" вместо того, чтобы иметь "2" рядом с "Hello World"

До сих пор я пробовал разные варианты пропуска "целого числа" в строке, когда я пытался скопировать его внутрь себя, но на самом деле ничто не является правильным случаем, так как он либо выглядит как пустая строка, либо только сам целочисленный префикс «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;
}

Ответы [ 2 ]

1 голос
/ 06 июля 2019

Во-первых, чтобы вставить однозначный префикс в строку «Hello World», вам необходим буфер из 13 символов - один для префикса, одиннадцать для символов в «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);
}
0 голосов
/ 07 июля 2019

Лучший способ справиться с этим - создать еще один буфер для вывода, а затем, если вам действительно нужно скопировать обратно в исходную строку, скопировать его обратно после создания новой копии.

Таместь и другие способы «оптимизировать» это, если вам действительно нужно, например, поместить исходную строку в середину буфера, чтобы вы могли добавить и изменить указатель строки для источника (не рекомендуется, если вы не работаете со встроенной целью сОЗУ ограничено и буфер огромен).Помните, что код предназначен для чтения людьми, поэтому лучше держать его в чистоте и легко читать.

#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.
...