How does calling printf() add numbers here? - c

I don't understand how this printf() call is working to add together two numbers. Does the %*c have something to do with it?
//function that returns the value of adding two number
int add(int x, int y)
{
NSLog(#"%*c",x, '\r');
NSLog(#"%*c",y, '\r');
return printf("%*c%*c", x, '\r', y, '\r'); // need to know detail view how its working
}
for calling
printf("Sum = %d", add(3, 4));
Output
Sum=7

When passed to printf (or similar functions), %*c means you're passing two parameters instead of one. The first parameter specifies a field width, and the second a character (or string, int, etc.) to write out in that width of field.
printf returns the total number of characters written to the output stream.

A number after % specifies the field width; so %5c will print 4 spaces, followed by the character argument, giving a total of 5 characters.
* specifies that the field width is provided as an argument to printf. So this will print one field of x characters, followed by another of y characters. Each field consists of spaces followed by a carriage-return ('\r'), so there shouldn't be any visible output. printf returns the total number of characters printed - in this case, x+y.

i agree with leeduhem, it is extremely clever,
printf() return the number of character it printed.
For the argument, I think it is more easy to understand with an example:(Also you can see the width trick in here:
#include <iostream>
#include<cstdio>
#include<cstdlib>
using namespace std;
int main() {
// your code goes here
int x = printf("%*c", 100, '\r');
printf("%d\n", x);
return 0;
}
x is whatever value you set to specific the width (in the eg, it's 100)
That means the width you specific is actually counted and return by the printf()
But I think this add() can only duel with positive numbers, if one of the number is <= 0, the method should fail, you may try add(-3,-4), in my own machine it still print 7...

Oh, this is clever.
return printf("%*c%*c", x, '\r', y, '\r');
On success, printf() will return how many character it printed, and "%*c", x, '\r' tell it to print x characters (x-1 spaces followed by one \r). Therefore, printf("%*c%*c", x, '\r', y, '\r') will return how many characters are printed, which is x+y.
See printf(3) for further details.
Note:
As pointed out by #shole, this int add(int x, int y) works only for both x and y are nonnegative integers. For example:
add(-1, 1) // gives 2 instead of 0
add(0, 1) // gives 2 instead of 1

Related

c integer starts with 0

How can I print the 0 value in front of integer
if user enters 05 printing 05. %d just ignores the 0
#include <stdio.h>
#include <stdlib.h>
int main()
{
int x;
x = 05;
printf("%d", x);
return 0;
}
output = 5
First of all, realize that constants with a leading 0 are interpreted as octal, not decimal. 05 and 5 are the same, but you'll have an issue with something like 09.
You can specify a minimum output field width like so:
printf( "%2d\n", x ); // minimum field width of 2, pad with blanks
or
printf( "%*d\n", 2, x ); // minimum field width of 2, pad with blanks
To pad with a leading 0, use
printf( "%02d\n", x ); // minimum field width of 2, pad with 0
or
printf( "%0*d\n", 2, x ); // minimum field width of 2, pad with 0.
Use the format specifier %02d:
#include <stdio.h>
int main(void)
{
int x;
x = 05;
printf("%02d\n", x);
return 0;
}
If a user can enter 05 or 5 and you want to distinguish between the two you need to read the input as a string instead. As mentioned by user3121023, note that integers with a leading zero are interpreted as octal numbers, for instance 010 equals 8.
Here is the full documentation of printf:
https://pubs.opengroup.org/onlinepubs/9699919799/
printf("%02d", x);
The zero represents how many digits will the zero padding be so if you wanted to do the same with 10 for example it should be 03 hope this helps.
If the user enters “05” and you read it using scanf with %d or something similar, the only result you will get from the scanf is the value five; there will be no indication whether the user entered “05” or “5”. If you need to know specifically what the user enters, you need to read the input as strings or characters.
If you use ”0” as the first digit of a constant in C source code, it introduces an octal constant, so that 010 represents eight.
If you want to print a leading “0” before a number, you can simply include it literally in the format string: printf("0%d", x);.
If you want to print the string with at least a certain number of digits, with as many leading zeros as necessary to give that many digits, you can use “0n” in the format specification, where “n” is the number of digits: printf("%02d", x);.
If you want to combine the above and print a zero in front of the number if and only if the user entered a zero in front of the number, you need to write source code that adjusts what is printed based on what was seen in input. (The easiest way to do this may be to record the characters the user types and just print those exactly.)

Confusion regarding a printf statement

So I was running this code
#include<stdio.h>
int add(int x, int y)
{
return printf("%*c%*c",x ,' ',y,' ');
}
int main()
{
printf("Sum = %d", add(3,4));
return 0;
}
And can't seem to understand how does the following statement works
return printf("%*c%*c",x ,' ',y,' ');
So I tried writing a simple code
int x=3;
printf("%*c",x);
and I got a weird special character (some spaces before it) as output
printf("%*c",x,' ');
I am getting no output. I have no idea what is happening? Please Help. Thank you.
This code
int x=3;
printf("%*c",x,'a');
makes use of the minimum character width that can be set for each input parameter to printf.
What the above does is print out the a character, but specifies that the minimum width will be x characters - so the output will be the a character preceded by 2 spaces.
The * specifier tells printf that the width of the part of the output string formed from this input parameter will be x characters minimum width where x must be passed as additional argument prior to the variable that is to be printed. The extra width (if required) is formed from blank spaces output before the variable to be printed. In this case the width is 3 and so the output string is (excluding the quotes which are just there to illustrate the spaces)
" a"
With your code here
printf("%*c",x);
you have passed the length value, but forgotten to actually pass the variable that you want printed.
So this code
return printf("%*c%*c",x ,' ',y,' ');
is basically saying to print the space character but with a minimum width of x characters (with your code x = 3), then print the space character with a minimum of y characters (in your code y = 4).
The result is that you are printing out 7 blank space characters. This length is the return value of printf (and hence your add function) which is confirmed by the output of
Sum = 7
from the printf inside main().
If you change your code to
return printf("%*c%*c",x ,'a',y,'b');
you would see the string (obviously excluding the quotes)
" a b"
printed which would make what is happening more clear.
Try to print that in the correct way. %d is for printing integer, %c is for printing char.
In your code:
int x=3;
printf("%*c",x);
The x is how much spaces the char will get, you write 3. But you didn't put the char you want to print, so it print garbage.
When you write:
printf("%*c",x,' ');
You printing space ' ' char inside 3 chars space.
Same thing when you do
printf("%*c",x, ' ',y,' '); - just 7 blank spaces. The result is correct because printf returns how many characters it writes.
Look here for extra printf formats.

Using atof() function in C with multiple input values

The goal of this program is to create a function which reads in a single string, user typed, command (ultimately for program to be used in conjunction with a robot) which consists of an unknown command word(stored and printed as command), and an unknown number of decimal parameters(the quantity is stored and printed as num, and the parameters are to be stored as float values in the array params). In the User input, the command and parameters will be separated by spaces. I believe my issue is with the atof function when I go to extract the decimal values from the string. What am I doing wrong? Thank you for the help!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void func(char *input, char *command, int *num, float *params);
int main()
{
char input[40]={};
char command[40]={};
int num;
float params[10];
printf("Please enter your command: ");
gets(input);
func(input,command,&num,params);
printf("\n\nInput: %s",input);
printf("\nCommand: %s",command);
printf("\n# of parameters: %d",num);
printf("\nParameters: %f\n\n",params);
return 0;
}
void func(char *input, char *command, int *num, float *params)
{
int i=0, k=0, j=0, l=0;
int n=0;
while(input[i]!=32)
{
command[i]=input[i];
i++;
}
for (k=0; k<40;k++)
{
if ((input[k]==32)&&(input[k-1]!=32))
{
n++;
}
}
*num=n;
while (j<n)
{
for (l=0;l<40;l++)
{
if((input[l-1]==32)&&(input[l]!=32))
{
params[j]=atof(input[l]);
j++;
}
}
}
}
A Sample Output Screen:
Please enter your command: Move 10 -10
Input: Move 10 -10
Command: Move
# of parameters: 2
Parameters: 0.000000
The Parameters output should, ideally, read "10 -10" for the output. Thanks!
Change atof(input[l]) to atof(input + l). input[l] is single char but you want to get substring from l position. See also strtod() function.
Other people have already remarked the problem in your code, but may I suggest that you have a look at strtod() instead?
While both atof() and strtod() discard spaces at the start for you (so you don't need to do it manually), strtod() will point you to the end of the number, so that you know where to continue:
while(j < MAX_PARAMS) // avoid a buffer overflow via this check
{
params[j] = strtod(ptr, &end); // `end` is where your number ends
if(ptr == end) // if end == ptr, input wasn't a number (say, if there are none left)
break;
// input was a number, so ...
ptr = end; // continue at end for next iteration
j++; // increment number of params
}
Do note that the above solution does not differentiate between invalid arguments (say, foo instead of 3.5) and missing ones (because we've hit the last argument). You can check for that by doing this: if(!str[strspn(str, " \t\v\r\n\f")]) --- this checks if we're at the end of string (but allowing trailing whitespace). See the second side-note for what it does.
SIDE-NOTES:
You can use ' ' instead of 32 to check for space; this has two advantages:
It is clearer to the reader (it's very clear that it's a whitespace, instead of "some magic number that happens to have meaning")
It works in non-ASCII encodings (and the standard allows other encodings, though ASCII is by far the most popular; one common encoding is EBCDIC)
For future reference, this trick can help you skip whitespace: ptr += strspn(ptr, " \t\v\r\n\f");. strspn returns the number of characters at the start of the string that match the set (in this case, one of " \t\v\r\n"). Check documentation for more info.
Example for strspn: strspn("abbcbaa", "ab"); returns 3 because you have aab (which match) before c (which doesn't).
you are trying to convert a char into a float,
params[j]=atof(input[l]);
you should get the entire word(substring) of the float.
Example, "12.01" a null terminated string with 5 characters and pass it to atof, atof("12.01") and it will return a double of 12.01.
so, you should first extract the string for each float parameter and pass it to atof
Avoid comparing character to ascii value, rather you could have use ' ' (space) directly.
Instead of using for loop with a fixed size, you can use strlen() or strnlen() to find the length of the input string.

Addition using printf in C [duplicate]

This question already has answers here:
Adding two numbers without using operators
(3 answers)
Closed 9 years ago.
on net: using printf to add two numbers(without using any operator) like following:
main()
{
printf("Summ = %d",add(10,20))
return 0;
}
int add(int x,int y)
{
return printf("%*d%*d",x,' ',y,' ');
}
Could anyone please explain, how this works:
return printf("%*d%*d",x,' ',y,' ');
Note: This fails when i call "sum" like following:
sum(1,1) or sum(3,-1)
There are two central concepts here:
printf() returns the number of characters printed.
The %*d format specifier causes printf() to read two integers from its arguments, and use the first to set the field width used to format the second (as a decimal number).
So in effect the values being added are used as field widths, and printf() then returns the sum.
I'm not sure about the actual d formatting of the space character, at the moment. That looks weird, I would have gone with an empty string instead:
static int sum(unsigned int a, unsigned int b)
{
return printf("%*s%*s", a, "", b, "");
}
int main(void)
{
unsigned int a = 13, b = 6;
int apb = sum(a, b);
printf("%d + %d = %d?\n", a, b, apb);
return 0;
}
The above works and properly computes the sum as 19.
printf returns the number of printed characters.
Here, it is used in the add function to generate a string only composed of 10 + 20 spaces, by using the format string.
So the printf in the add function will return 30.
Then, this result is simply printed with printf (his main purpose).
Note: it might be evident, but this printf usage has to be avoided. It's very dirty as it generates useless outputs. Imagine: add(10000,10000)...
First, printf returns the number of characters it prints.
Second, in the format specifier %*d, * means the minimum number of characters to be printed, but the width is not from the format string itself, but from the additional argument.
With all together, the job is done, but it won't work well on small numbers like 1 because of %d in the format specifier, a better solution could be :
("%*c%*c", a, ' ', b,' ');

What does the n stand for in `sscanf(s, "%d %n", &i, &n)`?

The man page states that the signature of sscanf is
sscanf(const char *restrict s, const char *restrict format, ...);
I have seen an answer on SO where a function in which sscanf is used like this to check if an input was an integer.
bool is_int(char const* s) {
int n;
int i;
return sscanf(s, "%d %n", &i, &n) == 1 && !s[n];
}
Looking at !s[n] it seems to suggest that we check if sscanf scanned the character sequence until the termination character \0. So I assume n stands for the index where sscanf will be in the string s when the function ends.
But what about the variable i? What does it mean?
Edit:
To be more explicit: I see the signature of sscanf wants a pointer of type char * as first parameter. A format specifier as seconf parameter so it knows how to parse the character sequence and as much variables as conversion specifiers as next parameters. I understand now that i is for holding the parsed integer.
Since there is only one format specifier, I tried to deduce the function of n.
Is my assumption above for n correct?
Looks like the op has his answer already, but since I bothered to look this up for myself and run the code...
From "C The Pocket Reference" (2nd Ed by Herbert Shildt) scanf() section:
%n Receives an integer of value equal to the number of characters read so far
and for the return value:
The scanf() function returns a number equal to the number of the number of fields
that were successfully assigned values
The sscanf() function works the same, it just takes it's input from the supplied buffer argument ( s in this case ). The "== 1" test makes sure that only one integer was parsed and the !s[n] makes sure the input buffer is well terminated after the parsed integer and/or that there's really only one integer in the string.
Running this code, an s value like "32" gives a "true" value ( we don't have bool defined as a type on our system ) but s as "3 2" gives a "false" value because s[n] in that case is "2" and n has the value 2 ( "3 " is parsed to create the int in that case ). If s is " 3 " this function will still return true as all that white space is ingored and n has the value of 3.
Another example input, "3m", gives a "false" value as you'd expect.
Verbatim from sscanf()'s man page:
Conversions
[...]
n
Nothing is expected; instead, the number of characters
consumed thus far from the input is stored through the next pointer,
which must be a pointer to int. This is not a
conversion, although it can be suppressed with the * assignment-suppression character. The C
standard says: "Execution of
a %n directive does not increment the assignment count returned at the completion of
execution" but the Corrigendum seems to contradict this. Probably it is wise not
to make any assumptions on the effect of %n conversions on the return value.
I would like to point out that the original code is buggy:
bool is_int(char const* s) {
int n;
int i;
return sscanf(s, "%d %n", &i, &n) == 1 && !s[n];
}
I will explain why. And I will interpret the sscanf format string.
First, buggy:
Given input "1", which is the integer one, sscanf will store 1 into i. Then, since there is no white space after, sscanf will not touch n. And n is uninitialized. Because sscanf set i to 1, the value returned by sscanf will be 1, meaning 1 field scanned. Since sscanf returns 1, the part of the expression
sscanf(s, "%d %n", &i, &n) == 1
will be true. Therefore the other part of the && expression will execute. And s[n] will access some random place in memory because n is uninitialized.
Interpreting the format:
"%d %n"
Attempts to scan a number which may be a decimal number or an integer or a scientific notation number. The number is an integer, it must be followed by at least one white space. White space would be a space, \n, \t, and certain other non-printable characters. Only if it is followed by white space will it set n to the number of characters scanned to that point, including the white space.
This code might be what is intended:
static bool is_int(char const* s)
{
int i;
int fld;
return (fld = sscanf(s, "%i", &i)) == 1;
}
int main(int argc, char * argv[])
{
bool ans = false;
ans = is_int("1");
ans = is_int("m");
return 0;
}
This code is based on, if s is an integer, then sscanf will scan it and fld will be exactly one. If s is not an integer, then fld will be zero or -1. Zero if something else is there, like a word; and -1 if nothing is there but an empty string.
variable i there means until it has read an integer vaalue.
what are you trying to ask though? Its not too clear! the code will (try to ) read an integer from the string into 'i'

Resources