Maison  >  Questions et réponses  >  le corps du texte

linux - Comment utiliser Snprintf pour imprimer le contenu original et du nouveau contenu dans un tableau?

snprintfCette fonction nécessite une longueur spécifiée et le compilateur effectuera une vérification hors limites, il faut donc s'assurer que la longueur cible est plus longue que la somme de tous les paramètres. Mais considérez les procédures suivantes :

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

#define LENGTH 1024

int main() {
    char cache[LENGTH];
    memset(cache, 0, LENGTH);
    snprintf(cache, sizeof(LENGTH), "%s/ruaruarua", cache);
    return 0;
}

Après avoir ouvert ce programme-Wall, une erreur sera signalée :

test.c: In function ‘main’:
test.c:9:44: error: ‘/ruaruarua’ directive output truncated writing 10 bytes into a region of size 4 [-Werror=format-truncation=]
     snprintf(cache, sizeof(LENGTH), "%s/ruaruarua", cache);
                                        ~~~~^~~~~~
test.c:9:5: note: ‘snprintf’ output 11 or more bytes into a destination of size 4
     snprintf(cache, sizeof(LENGTH), "%s/ruaruarua", cache);
     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cc1: all warnings being treated as errors

Cette erreur est attendue car il est effectivement possible de franchir la ligne. La question est donc : comment puis-je remplir la même fonction sans signaler d’erreur ?

Mongcc版本比较新,7.1.1, on estime que les anciennes versions du compilateur ne signaleront pas cette erreur.

仅有的幸福仅有的幸福2701 Il y a quelques jours824

répondre à tous(1)je répondrai

  • PHP中文网

    PHP中文网2017-05-27 17:46:46

    Tout d'abord, le deuxième paramètre de snprintf() représente la taille du tampon, qui devrait ici être LENGTH, sizeof(LENGTH)< / La valeur de code> est 4
    (je suppose que ce que vous voulez écrire devrait être sizeof(cache)). Alors, est-ce que tout ira bien après l'avoir changé en snprintf(cache, LENGTH, "%s/ruaruarua", cache); ? Jetons un coup d'œil à cet exemple : snprintf()的第二个参数代表的是缓冲区的大小,在这里应该是LENGTHsizeof(LENGTH)的值是4
    (我猜你想写的应该是sizeof(cache)吧)。那么,改成snprintf(cache, LENGTH, "%s/ruaruarua", cache);之后就行了吗?我们看看这个例子:

    #include <stdio.h>
    
    int main()
    {
        char buf[20] = "hello";
        snprintf(buf, 20, "%s world", buf);
        puts(buf);
        return 0;
    }

    这个例子企图给buf末尾添加一个字符串,看看输出

    
     world

    并没有达到期望的结果。这是为什么呢?snprintf()的手册里有这么一段:

    Some programs imprudently rely on code such as the following

    sprintf(buf, "%s some further text", buf);

    to append text to buf. However, the standards explicitly note that the results are undefined if source and destination buffers overlap when calling sprintf(), snprintf(), vsprintf(), and vsnprintf(). Depending on the version of gcc(1) used, and the compiler options employed, calls such as the above will not produce the expected results.

    即如果原始和目标缓冲区重叠的话,这些printf()家族的函数执行结果将是未定义的。

    那该如何如何“向一个数组中打印自己原有的内容和一些新的内容”呢?一种方式是把传给snprintf()的缓冲区设为数组中字符串的末尾:

    snprintf(buf + strlen(buf), 20, " world");

    那如何连续往缓冲区末尾添加数据呢?注意到printf()

    #include <stdio.h>
    #include <string.h>
    
    int main()
    {
        char buf[40];
        char *p = buf;
    
        p += sprintf(p, "hello %s\n", "world");
        p += sprintf(p, "hello %s", "again");
        /* and more similar calls... */
    
        puts(buf);
        return 0;
    }
    

    Cet exemple tente d'ajouter une chaîne à la fin de buf, regardez le résultat

    hello world
    hello again

    n'a pas obtenu les résultats escomptés. Pourquoi est-ce ? Il y a ce paragraphe dans le manuel de snprintf() : #🎜🎜# #🎜🎜#Certains programmes s'appuient imprudemment sur du code tel que celui-ci#🎜🎜# rrreee #🎜🎜#pour ajouter du texte à buf Cependant, les standards notent explicitement que les résultats ne sont pas définis si les tampons source et de destination se chevauchent lors de l'appel de sprintf(), . snprintf(), vsprintf() et vsnprintf() Selon la version de gcc(1) utilisée, et les options du compilateur utilisées, les appels tels que celui ci-dessus ne produiront pas les résultats attendus.#🎜🎜# #🎜🎜#C'est-à-dire que si les tampons d'origine et de destination se chevauchent, les résultats d'exécution de ces fonctions de la famille printf() ne seront pas définis. #🎜🎜# #🎜🎜#Alors, comment « imprimer votre contenu original et du nouveau contenu dans un tableau » ? Une solution consiste à définir le tampon passé à snprintf() à la fin de la chaîne dans le tableau : #🎜🎜# rrreee #🎜🎜#Alors comment ajouter continuellement des données à la fin du buffer ? Notez que la valeur de retour de la fonction de la famille printf() est le nombre de caractères imprimés (nombre de caractères imprimés), alors vous pouvez l'appeler comme ceci : #🎜🎜# rrreee #🎜🎜#Le résultat est #🎜🎜# rrreee

    répondre
    0
  • Annulerrépondre