I just stumbled upon the idea that since printf returns the no.of characters it has printed to the output stream why not use it to find length of any variable in c?
The code goes something like this,
#include<stdio.h>
int main()
{
char *a="Length";
int i=1000;
printf("Size: %d\n",printf("%d\n",i)-1);
printf("String Size: %d",printf("%s\n",a)-1);
return 1;
}
Am I right? I am not concerned about where it is being used. just wanted to know if my understanding is right.
What do you mean by "length of any variable"? You mean the number of bytes used to store the variable (which better achieved with the sizeof and strlen functions) or the byte length of the string representation of the variables?
For the latter one, you should be careful, since you can use format options to actually modify the results. Consider the following example:
float num = 10.0f;
printf("%.10f", num); // return value should be 13
printf("%f", num); // return value depends on the implementation of printf and the float value supplied
Also you have to consider that there are other representations than the decimal one.
As others have already stated, printf has the side effect that it actually writes to stdout. If you do not want this, you can use snprintf to write to a buffer and not to stdout:
char buffer[256];
int x = 10;
snprintf(buffer, sizeof(buffer), "%d", x); // return value is '2'
"One liner to find length of a variable"
Not possible unless its builtin to your compiler, or you define a wild and hairy macro half a page long with a few enums to state your type...
For strings, (which you cannot use sizeof on...) see: https://stackoverflow.com/a/22128415/3370790
Related
I'm a noob on C and trying to use write() function to show an integer.
These is my code:
int n = 7;
write(1, &n, 4);
I want to show 7, but the program shows nothing or other strange character when I set n to a big number.
What am I missing?
Objects like int are represented in memory with various bits. The write routine transmits exactly those bits of memory to its destination.
Terminals are not designed to display arbitrary bits of memory. They do not interpret the bits to mean an int or other object and then display that interpretation. Generally, we transmit characters to terminals. More specifically, we send codes that represent characters. Terminals are designed to receive these codes and display little pictures of writing (characters, glyphs, emoji, whatever).
To make a terminal display “7”, we need to send it the code for “7”. A common code system for characters is ASCII (American Standard Code for Information Interchange). The ASCII code for “7” is 55. So, if you do this:
char x = 55;
write(1, &x, 1);
then the terminal will draw “7” on its display, if ASCII is being used.
So write is the wrong routine to use to display int values for a human to read. Instead, you normally use printf, like this:
printf("%d", n);
The f in printf stands for formatted. It examines the bits that represent the value in n and formats the represented value as characters intended for humans to read, and then it writes those characters to standard output.
If you want to use write to transmit characters to the terminal, you can use sprintf to get just the formatting part of printf without the printing part. For starters, this code will work:
char buffer[80]; // Make space for sprintf to work in.
int LengthUsed = sprintf(buffer, "%d", n); // Format n in decimal.
write(1, buffer, LengthUsed); // Write the characters.
(More sophisticated code would adapt the buffer size to what is needed for the sprintf.)
void ft_putnbr_fd(int nu, int fd)
{
long int n;
n = nu;
if (n < 0)
{
ft_putchar_fd('-', fd);
n = n * (-1);
}
if (n < 10)
{
ft_putchar_fd(n + '0', fd);
}
else
{
ft_putnbr_fd(n / 10, fd);
ft_putchar_fd(n % 10 + '0', fd);
}
}
When you want to print it out on the command prompt only use printf() instead:
int n = 7;
printf("%i",n);
Is there a special intention for using the write() function?
If so, please add more of your code.
When you say something like
int n = 7;
write(fd, &n, sizeof(int));
you are taking the individual bytes corresponding to the integer n and writing them out to the file descriptor fd.
And that works just fine, unless what you wanted was a human readable representation of the integer n. That's the representation you'd get if you had instead written
printf("%d\n", n);
It's printf's job, when you use a format specifier like %d, to create a human-readable string of characters corresponding to a data object.
So if you want to print an int in a human-readable way, printf is definitely your best bet. If for some reason you can't use printf, you can use sprintf to create an in-memory string, then use write to write that out:
char tmpbuf[30];
sprintf(tmpbuf, "%d", n);
write(fd, tmpbuf, strlen(tmpbuf));
If for some reason you can't use sprintf, you might be able to use itoa:
char tmpbuf[30];
itoa(n, tmpbuf, 10);
write(fd, tmpbuf, strlen(tmpbuf));
However, the itoa function is not standard. If you don't have it or can't use it, your last resort would be to convert an integer to its string representation yourself, by hand. That's such a common question that I'm not going to provide Yet Another answer to it here, but see the linked question, or this one.
You didn't ask, but if there's ever the related problem of printing a floating point number using write, there are some hints in the comments at this question.
Write function is a system call. It is used to write the content of a buffer to a declared output or to a stream. You should not use write.
Instead, you must be using printf(" ", ...). In your case:
printf("%d", n);
or
print("%d\n",n);
if you want to write it on a line and do an end line(jump the next).
For more information about printf see: printf
I'm a noob on C and trying to use write() function to show an integer.
These is my code:
int n = 7;
write(1, &n, 4);
I want to show 7, but the program shows nothing or other strange character when I set n to a big number.
What am I missing?
Objects like int are represented in memory with various bits. The write routine transmits exactly those bits of memory to its destination.
Terminals are not designed to display arbitrary bits of memory. They do not interpret the bits to mean an int or other object and then display that interpretation. Generally, we transmit characters to terminals. More specifically, we send codes that represent characters. Terminals are designed to receive these codes and display little pictures of writing (characters, glyphs, emoji, whatever).
To make a terminal display “7”, we need to send it the code for “7”. A common code system for characters is ASCII (American Standard Code for Information Interchange). The ASCII code for “7” is 55. So, if you do this:
char x = 55;
write(1, &x, 1);
then the terminal will draw “7” on its display, if ASCII is being used.
So write is the wrong routine to use to display int values for a human to read. Instead, you normally use printf, like this:
printf("%d", n);
The f in printf stands for formatted. It examines the bits that represent the value in n and formats the represented value as characters intended for humans to read, and then it writes those characters to standard output.
If you want to use write to transmit characters to the terminal, you can use sprintf to get just the formatting part of printf without the printing part. For starters, this code will work:
char buffer[80]; // Make space for sprintf to work in.
int LengthUsed = sprintf(buffer, "%d", n); // Format n in decimal.
write(1, buffer, LengthUsed); // Write the characters.
(More sophisticated code would adapt the buffer size to what is needed for the sprintf.)
void ft_putnbr_fd(int nu, int fd)
{
long int n;
n = nu;
if (n < 0)
{
ft_putchar_fd('-', fd);
n = n * (-1);
}
if (n < 10)
{
ft_putchar_fd(n + '0', fd);
}
else
{
ft_putnbr_fd(n / 10, fd);
ft_putchar_fd(n % 10 + '0', fd);
}
}
When you want to print it out on the command prompt only use printf() instead:
int n = 7;
printf("%i",n);
Is there a special intention for using the write() function?
If so, please add more of your code.
When you say something like
int n = 7;
write(fd, &n, sizeof(int));
you are taking the individual bytes corresponding to the integer n and writing them out to the file descriptor fd.
And that works just fine, unless what you wanted was a human readable representation of the integer n. That's the representation you'd get if you had instead written
printf("%d\n", n);
It's printf's job, when you use a format specifier like %d, to create a human-readable string of characters corresponding to a data object.
So if you want to print an int in a human-readable way, printf is definitely your best bet. If for some reason you can't use printf, you can use sprintf to create an in-memory string, then use write to write that out:
char tmpbuf[30];
sprintf(tmpbuf, "%d", n);
write(fd, tmpbuf, strlen(tmpbuf));
If for some reason you can't use sprintf, you might be able to use itoa:
char tmpbuf[30];
itoa(n, tmpbuf, 10);
write(fd, tmpbuf, strlen(tmpbuf));
However, the itoa function is not standard. If you don't have it or can't use it, your last resort would be to convert an integer to its string representation yourself, by hand. That's such a common question that I'm not going to provide Yet Another answer to it here, but see the linked question, or this one.
You didn't ask, but if there's ever the related problem of printing a floating point number using write, there are some hints in the comments at this question.
Write function is a system call. It is used to write the content of a buffer to a declared output or to a stream. You should not use write.
Instead, you must be using printf(" ", ...). In your case:
printf("%d", n);
or
print("%d\n",n);
if you want to write it on a line and do an end line(jump the next).
For more information about printf see: printf
I have done the reading from a file and is stored as hex values(say the first value be D4 C3). This is then stored to a buffer of char datatype. But whenever i print the buffer i am getting a value likebuff[0]=ffffffD4; buff[1]=ffffffC3 and so on.
How can I store the actual value to the buffer without any added bytes?
Attaching the snippet along with this
ic= (char *)malloc(1);
temp = ic;
int i=0;
char buff[1000];
while ((c = fgetc(pFile)) != EOF)
{
printf("%x",c);
ic++;
buff[i]=c;
i++;
}
printf("\n\nNo. of bytes written: %d", i);
ic = temp;
int k;
printf("\nBuffer value is : ");
for(k=0;k<i;k++)
{
printf("%x",buff[k]);
}
The problem is a combination of two things:
First is that when you pass a smaller type to a variable argument function like printf it's converted to an int, which might include sign extension.
The second is that the format "%x" you are using expects the corresponding argument to be an unsigned int and treat it as such
If you want to print a hexadecimal character, then use the prefix hh, as in "%hhx".
See e.g. this printf (and family) reference for more information.
Finally, if you only want to treat the data you read as binary data, then you should consider using int8_t (or possibly uint8_t) for the buffer. On any platform with 8-bit char they are the same, but gives more information to the reader of the code (saying "this is binary data and not a string").
By default, char is signed on many platforms (standards doesn't dictate its signedness). When passing to variable argument list, standard expansions like char -> int are invoked. If char is unsigned, 0xd3 remains integer 0xd3. If char is signed, 0xd3 becomes 0xffffffd3 (for 32-bit integer) because this is the same integer value -45.
NB if you weren't aware of this, you should recheck the entire program, because such errors are very subtle. I've dealed once with a tool which properly worked only with forced -funsigned-char into make's CFLAGS. OTOH this flag, if available to you, could be a quick-and-dirty solution to this issue (but I suggest avoiding it for any longer appoaching).
The approach I'm constantly using is passing to printf()-like functions a value not c, but 0xff & c, it's visually easy to understand and stable for multiple versions. You can consider using hh modifier (UPD: as #JoachimPileborg have already suggested) but I'm unsure it's supported in all real C flavors, including MS and embedded ones. (MSDN doesn't list it at all.)
You did store the actual values in the buffer without the added bytes. You're just outputting the signed numbers with more digits. It's like you have "-1" in your buffer but you're outputting it as "-01". The value is the same, it's just you're choosing to sign extend it in the output code.
What is the use of the %n format specifier in C? Could anyone explain with an example?
Most of these answers explain what %n does (which is to print nothing and to write the number of characters printed thus far to an int variable), but so far no one has really given an example of what use it has. Here is one:
int n;
printf("%s: %nFoo\n", "hello", &n);
printf("%*sBar\n", n, "");
will print:
hello: Foo
Bar
with Foo and Bar aligned. (It's trivial to do that without using %n for this particular example, and in general one always could break up that first printf call:
int n = printf("%s: ", "hello");
printf("Foo\n");
printf("%*sBar\n", n, "");
Whether the slightly added convenience is worth using something esoteric like %n (and possibly introducing errors) is open to debate.)
Nothing printed. The argument must be a pointer to a signed int, where the number of characters written so far is stored.
#include <stdio.h>
int main()
{
int val;
printf("blah %n blah\n", &val);
printf("val = %d\n", val);
return 0;
}
The previous code prints:
blah blah
val = 5
I haven't really seen many practical real world uses of the %n specifier, but I remember that it was used in oldschool printf vulnerabilities with a format string attack quite a while back.
Something that went like this
void authorizeUser( char * username, char * password){
...code here setting authorized to false...
printf(username);
if ( authorized ) {
giveControl(username);
}
}
where a malicious user could take advantage of the username parameter getting passed into printf as the format string and use a combination of %d, %c or w/e to go through the call stack and then modify the variable authorized to a true value.
Yeah it's an esoteric use, but always useful to know when writing a daemon to avoid security holes? :D
From here we see that it stores the number of characters printed so far.
n The argument shall be a pointer to an integer into which is written the number of bytes written to the output so far by this call to one of the fprintf() functions. No argument is converted.
An example usage would be:
int n_chars = 0;
printf("Hello, World%n", &n_chars);
n_chars would then have a value of 12.
So far all the answers are about that %n does, but not why anyone would want it in the first place. I find it's somewhat useful with sprintf/snprintf, when you might need to later break up or modify the resulting string, since the value stored is an array index into the resulting string. This application is a lot more useful, however, with sscanf, especially since functions in the scanf family don't return the number of chars processed but the number of fields.
Another really hackish use is getting a pseudo-log10 for free at the same time while printing a number as part of another operation.
The argument associated with the %n will be treated as an int* and is filled with the number of total characters printed at that point in the printf.
The other day I found myself in a situation where %n would nicely solve my problem. Unlike my earlier answer, in this case, I cannot devise a good alternative.
I have a GUI control that displays some specified text. This control can display part of that text in bold (or in italics, or underlined, etc.), and I can specify which part by specifying starting and ending character indices.
In my case, I am generating the text to the control with snprintf, and I'd like one of the substitutions to be made bold. Finding the starting and ending indices to this substitution is non-trivial because:
The string contains multiple substitutions, and one of the substitutions is arbitrary, user-specified text. This means that doing a textual search for the substitution I care about is potentially ambiguous.
The format string might be localized, and it might use the $ POSIX extension for positional format specifiers. Therefore searching the original format string for the format specifiers themselves is non-trivial.
The localization aspect also means that I cannot easily break up the format string into multiple calls to snprintf.
Therefore the most straightforward way to find the indices around a particular substitution would be to do:
char buf[256];
int start;
int end;
snprintf(buf, sizeof buf,
"blah blah %s %f yada yada %n%s%n yakety yak",
someUserSpecifiedString,
someFloat,
&start, boldString, &end);
control->set_text(buf);
control->set_bold(start, end);
It doesn't print anything. It is used to figure out how many characters got printed before %n appeared in the format string, and output that to the provided int:
#include <stdio.h>
int main(int argc, char* argv[])
{
int resultOfNSpecifier = 0;
_set_printf_count_output(1); /* Required in visual studio */
printf("Some format string%n\n", &resultOfNSpecifier);
printf("Count of chars before the %%n: %d\n", resultOfNSpecifier);
return 0;
}
(Documentation for _set_printf_count_output)
It will store value of number of characters printed so far in that printf() function.
Example:
int a;
printf("Hello World %n \n", &a);
printf("Characters printed so far = %d",a);
The output of this program will be
Hello World
Characters printed so far = 12
Those who want to use %n Format Specifier may want to look at this:
Do Not Use the "%n" Format String Specifier
In C, use of the "%n" format specification in printf() and sprintf()
type functions can change memory values. Inappropriate
design/implementation of these formats can lead to a vulnerability
generated by changes in memory content. Many format vulnerabilities,
particularly those with specifiers other than "%n", lead to
traditional failures such as segmentation fault. The "%n" specifier
has generated more damaging vulnerabilities. The "%n" vulnerabilities
may have secondary impacts, since they can also be a significant
consumer of computing and networking resources because large
guantities of data may have to be transferred to generate the desired
pointer value for the exploit. Avoid using the "%n" format
specifier. Use other means to accomplish your purpose.
Source: link
In my opinion, %n in 1st argument of print function simply record the number of character it prints on the screen before it reach the the %n format code including white spaces and new line character.`
#include <stdio.h>
int main()
{
int i;
printf("%d %f\n%n", 100, 123.23, &i);
printf("%d'th characters printed on the screen before '%%n'", i);
}
output:
100 123.230000
15'th characters printed on the screen before '%n'(with new character).
We can assign the of i in an another way...
As we know the argument of print function:-
int printf(char *control-string, ...);
So, it returns the number the number of characters output. We can assign that return value to i.
#include <stdio.h>
int main()
{
int i;
i = printf("%d %f\n", 100, 123.23);
printf("%d'th characters printed on the screen.", i);
}
%n is C99, works not with VC++.
Is it possible to use toString operator, or how to convert numbers to char arrays.
int myNumber = 27; /* or what have you */
char myBuffer[100];
snprintf(myBuffer, 100, "%d", myNumber);
There are several considerations for you to think about here. Who provides the memory to hold the string? How long do you need it for, etc? (Above it's a stack buffer of 100 bytes, which is way bigger than necessary for any integer value being printed.)
Best answer: start using Java. Or Javascript, or C#, or for the love of God almost anything but C. Only tigers lie this way.
Use the sprintf() function.
sprintf() is considered unsafe because it can lead to a buffer overflow. If it's available (and on many platforms it is), you should use snprintf() instead.
Consider the following code:
#include <stdio.h>
int main()
{
int i = 12345;
char buf[4];
sprintf(buf, "%d", i);
}
This leads to a buffer overflow. So, you have to over-allocate a buffer to the maximum size (as a string) of an int, even if you require fewer characters, since you have the possibility of an overflow. Instead, if you used snprintf(), you could specify the number of characters to write, and any more than that number would simply be truncated.
#include <stdio.h>
int main()
{
int i = 12345;
char buf[4];
snprintf(buf, 4, "%d", i);
//truncates the string to 123
}
Note that in either case, you should take care to allocate enough buffer space for any valid output. It's just that snprintf() provides you with a safety net in case you haven't considered that one edge case where your buffer would otherwise overflow.