2010-09-22 4 views
78

Supposons que vous ayez une chaîne qui n'est PAS null terminée et que vous connaissiez sa taille exacte, alors comment pouvez-vous imprimer cette chaîne avec printf en C? Je me souviens d'une telle méthode, mais je ne peux pas savoir maintenant ...Utilisation de printf avec une chaîne terminée non nulle

+6

Dans 'contexte C', toutes les chaînes sont nulles terminées. Les tableaux de char sans null dans eux ne sont pas des chaînes ... ils sont des tableaux de char :) – pmg

+3

duplication possible de [Comment imprimer une chaîne non-terminée par zéro en utilisant printf?] (Http://stackoverflow.com/ questions/2137779/how-do-i-print-a-non-terminated-string-using-printf) – Justin

+0

https://stackoverflow.com/questions/2239519/-there-a-specifier -comment-plusieurs-caractères-d'un-string-à-print-out-pri –

Répondre

129

Il y a une possibilité avec printf, il va comme ceci:

printf("%.*s", stringLength, pointerToString); 

Pas besoin de copier quoi que ce soit, pas besoin de modifier l'original chaîne ou tampon.

+9

Mais de toute façon c'est dangereux, quelqu'un va un jour imprimer cette chaîne avec% s – pmod

+0

Oui, c'est ça! – whoi

+4

@Pmod: Pas nécessairement si le tampon n'est pas exposé au monde extérieur. Il est également très utile d'imprimer simplement * parties * d'une chaîne (qui peut être terminée par un caractère nul, bien sûr). Si vous voulez vraiment voir cela en action, jetez un oeil au proxy SIP OpenSER/Kamailio où ils évitent de copier beaucoup de choses à cause de cette technique (en utilisant aussi sprintf). – DarkDust

1
#include<string.h> 
int main() 
{ 
/*suppose a string str which is not null terminated and n is its length*/ 
int i; 
for(i=0;i<n;i++) 
{ 
printf("%c",str[i]); 
} 
return 0; 
} 

Je modifié le code, voici une autre façon:

#include<stdio.h> 
int main() 
{ 
printf ("%.5s","fahaduddin");/*if 5 is the number of bytes to be printed and fahaduddin is the string.*/ 

return 0; 

} 
+0

Très mauvaise performance en raison de beaucoup de lectures d'octets inutiles (qui viennent avec une pénalité de performance si l'octet n'est pas sur une adresse alignée sur la plupart des processeurs) et que l'analyse et la mise en forme sont effectuées pour chaque caractère. Ne faites pas ça :-) Voir ma réponse pour la solution. – DarkDust

+0

Merci d'avoir mentionné –

+0

@DarkDust: seule une machine pathologique pourrait pénaliser les lectures d'octets non alignées sur les limites de mots. Pensez-vous que les lectures de mots ne sont pas alignées sur les limites des mots? Ou une ancienne merde mips ou quelque chose? –

5

printf("%.*s", length, string) ne fonctionnera pas.

Cela signifie d'imprimer une longueur d'octet OU un octet nul, selon la première éventualité. Si votre tableau-of-char non-null-terminated contient des octets NULL AVANT la longueur, printf s'arrêtera sur ceux-ci, et ne continuera pas.

+13

comment une valeur nulle peut-elle apparaître dans un tableau de caractères à terminaison non nulle? Pensez-y ... – pmg

+2

il travaillera pour lui parce qu'il sait la longueur exacte – BlackBear

+4

Et comment est-ce une réponse à la question de l'OP? – Shahbaz

12

Vous pouvez utiliser fwrite() pour stdout!

fwrite(your_string, sizeof(char), number_of_chars, stdout); 

De cette façon, vous affichera les premiers caractères (nombre défini dans la variable number_of_chars) dans un fichier, dans ce cas stdout (la sortie standard, votre écran)!

+0

Très utile lorsque vous voulez inspecter un long tampon contenant des chaînes et des zéros! – Elist

19

Voici une explication du fonctionnement de %.*s et de son emplacement.

Les spécifications de conversion dans une chaîne de modèle de printf ont la forme générale:

% [ param-no $] flags width [ . precision ] type conversion 

ou

% [ param-no $] flags width . * [ param-no $] type conversion 

La deuxième forme est pour obtenir la précision de la liste des arguments:

Vous pouvez également spécifier une précision de '*'. Cela signifie que l'argument suivant dans la liste des arguments (avant la valeur réelle à imprimer) est utilisé comme précision. La valeur doit être un int, et est ignorée si elle est négative.

- Output conversion syntax dans le manuel glibc

Pour %s la mise en forme de chaîne, la précision a une signification particulière:

Une précision peut être spécifiée pour indiquer le nombre maximal de caractères à écrire; sinon, les caractères dans la chaîne jusqu'à mais n'incluant pas le caractère null de fin sont écrits dans le flux de sortie.

- dans le manuel glibc

D'autres variantes utiles:

  • "%*.*s", maxlen, maxlen, val va droit justifier, insérer des espaces avant;
  • "%-*.*s", maxlen, maxlen, val justifie à gauche.
+0

Si je comprends bien, ce qui suit pad la sortie tout en empêchant encore un dépassement de chaîne? '"% - *. * S ", remplissage, str_view.size(), str_view.data()' – scx

1
printf("%.5s", pointerToNonNullTerminatedString); 

La longueur de la chaîne sera 5.

Questions connexes