I run into a code:
printf("\tout:\t%-14.14s\n", (sprintf(tmpbuf[0], "[%s]", mystring), tmpbuf[0]));
What does those sentence in () with sprintf mean?
It is an expression involving the comma operator, to put the following into a single line:
sprintf(tmpbuf[0], "[%s]", mystring);
printf("\tout:\t%-14.14s\n", tmpbuf[0]);
The comma operator evaluates both arguments and returns its right argument, i.e. tmpbuf[0].
Related
This question already has answers here:
What does the comma operator , do?
(8 answers)
Closed 6 years ago.
I am checking a student's homework.
The assignment is to print the amount of English letters to the console.
For some reason, what he did works (7th line):
int main(void)
{
char first = 'A';
char last = 'Z';
int amount = 0;
amount = ("%d - %d", last - first + 1);
printf("The amount of letters in the English alphabet is %d\n", amount);
return(0);
}
After seeing it, I tried putting other things in the brackets instead of "%d - %d". No matter what I put there and how many commas were there, it'd only take what's after the last comma (which is the correct sentence).
What is actually happening there?
This is one of the examples of usage of comma operator. In case of
("%d - %d", last - first + 1);
the LHS operand of the comma operator ("%d - %d") is evaluated, result is discarded, then RHS (last - first + 1) is evaluated and returned as the result. The result, is then assigned to amount and thus, you have the amount holding the result of the operation last - first + 1.
Quoting C11, chapter ยง6.5.17, comma operator
The left operand of a comma operator is evaluated as a void expression; there is a
sequence point between its evaluation and that of the right operand. Then the right
operand is evaluated; the result has its type and value.
FWIW, in this case, "%d - %d" is just another string literal, it does not carry any special meaning.
This question already has answers here:
What does the comma operator , do?
(8 answers)
How does the Comma Operator work
(9 answers)
Closed 6 years ago.
I have these lines in my program:
printf("%-29s\n",("%s, Capital", CO));
printf("%-29s\n",("%s, Drawing",CO));
and when I run the program, it only shows the %s equivalent (CO) instead of "%s, Drawing"
Please help?
You used the comma operator and the behavior is normal.
An expression with comma operator A, B means that first evaluate A, ignore its result, then evaluate B and the result of comma operator will be its value.
If you want to show "%s, Drawing", print it.
printf("%-29s\n","%s, Drawing");
As MikeCAT has already stated, you have used the comma operator. If you want to left-align the compound string, you can achieve it by first printing to a temporary buffer with snprintf:
char tmp[30];
snprintf(tmp, sizeof(tmp), "%s, Capital", CO);
printf("|%-29s|", tmp);
snprintf(tmp, sizeof(tmp), "%s, Drawing", CO);
printf("|%-29s|", tmp);
Of course, given that you print a newline directly after the string (and the justification is therefore somewhat pointless), you might as well just print the desired format directly:
printf("%s, Capital\n", CO);
printf("%s, Drawing\n",CO);
After reading this I started thinking that I have learned a loot about printf(). Suddenly I found following code snippet from this book:
int main()
{
char str[]="Hello";
int i=5,j=10;
printf(i>j?"%50s":"%s",str); //unable to understand this
return 0;
}
Surprisingly above code is running without errors and it prints Hello.
As per my knowledge following is syntax of printf():
int printf(const char *format,argument_list);
So according to this syntax, printf() should start with format string. But as you can see in above code printf() is starting with i>j.
Does it mean I am wrong in interpreting syntax of printf()?
Does placing ternary operator inside printf() is a special case?
EDIT
I know about ternary operator I am asking about first argument of printf() which should be const char* which I seem not in my example.
The conditional operator:
i>j?"%50s":"%s"
is an expression and it has to be evaluated before the function call itself can be evaluated. We can see this by going to the draft C99 standard section 6.5.2.2 Function calls which says:
An argument may be an expression of any object type. In preparing for
the call to a function, the arguments are evaluated, and each
parameter is assigned the value of the corresponding argument.81)
So what is the result of the evaluation of the conditional operator? If we go to section 6.5.15 Conditional operator it says (emphasis mine):
The first operand is evaluated; there is a sequence point after its
evaluation. The second operand is evaluated only if the first compares
unequal to 0; the third operand is evaluated only if the first
compares equal to 0; the result is the value of the second or third
operand (whichever is evaluated), converted to the type described
below.95
so in either case the result is a string literal which will decay to pointer to char which satisfies the requirement for the first argument to printf.
This code is normal and is not any special case. The requirement for printf is that the first argument should be of the type const char*, but it does not necessarily mean that it needs to be a string literal like "%s". All it means that you need to pass as the first argument an expression of the type const char*. And i>j?"%50s":"%s" fulfils this requirement.
I think you well understood the printf syntax but i think you are missing something about C syntax.
It exist a form of "compact IF like" statement formatted like that : ( condition ? true : false )
For example you can do :
int a=5;
int b=(a==5 ? 128 : 256);
int c=(a!=5 ? 8 : 9);
In this case, b=128 and c=9.
An other example :
int flag=1;
printf("The value is: %s", (flag!=0 ? "true" : "false) );
In this case you can see : The value is true
On your example :
printf(i>j?"%50s":"%s",str);
if i is upper than j you use "%50s" format and, if i is lower you use "%s" format
It can be view like :
if (i>j)
printf("%50s",str);
else
printf("%s",str);
You can see the advantage of compact test.
It is a ternary operator and in this the condition i>j is false so %s will be passed as parameter to printf which will print the value of character array which is hello.
Does it mean I am wrong in interpreting syntax of printf()?
No you are not interpreting it wrong.
Does placing ternary operator inside printf() is a special case?
In C, you can say that its an expression instead of a statement
Your code is equivalent to:
if (i > j)
printf("%50s", str);
else
printf("%s", str);
The ternary operator is simply an inline if that's used as an expression (while a regular if is used to create a block). Your line is equal to this:
if (i > j)
printf("%50s", str);
else
printf("%s", str);
if(i>j)
printf("%50s",str);
else
printf("%s",str);
Therefore, Hello gets printed in both situations
Q: Does it mean I am wrong in interpreting syntax of printf()?
A: No, just need to expand what is allowable.
Q: Does placing ternary operator inside printf() is a special case?
A: No ?: is not special, but sometimes confusing at first glance.
The format supplied to printf() does not need to be a literal. It may be any string variable.
int main() {
char str[]="Hello";
char *format;
int i,j;
i = 5; j = 10;
format = i > j ? "%50s" : "%s";
printf(format, str);
i = 10; j = 5;
format = i > j ? "%50s" : "%s";
printf(format, str);
return 0;
}
There is a statement of the form: condition?consequent:alternative.
The condition is checked, and if it's true you'll get the consequent. otherwise you'll get the alternative.
For example:
5>3 ? 10 : 5
5>3 is true, so you'll get 10.
Whenever I send in a number from the command line it errors and gives me a wrong number
edgeWidth=*argv[2];
printf("Border of %d pixels\n", edgeWidth);
fileLocation=3;
./hw3 -e 100 baboon.ascii.pgm is what I send in through the command line and when I print the number to the screen I get 49 as the number
int edgeWidth is defined at the beginning of the program.
Why is it not giving me 100?
argv contains an array of strings. So argv[1] is a string, you need to convert it to an integer:
edgeWidth = atoi(argv[1]);
The problem is that by doing
edgeWidth = *argv[2];
you're assigning the first character of "100" to edgeWidth. 49 happens to be the ASCII value for '1'.
If you want 100, you need to use something like atoi or strtol to parse the string into an int.
Addendum: Regarding numeric promotion, part two of 6.5.16.1 in the C99 spec states:
In simple assignment (=), the value of the right operand is converted
to the type of the assignment expression and replaces the value stored
in the object designated by the left operand.
so it does appear that numeric promotion happens here.
Because command line arguments are by default as char* (or may be char** somewhere) not int. you need proper conversion like atoi() to use it as int.
You should use edgeWidth = atoi(argv[2]) to get expected output.
I have the following code:
int i=1;
printf((i==1)?" ":" " "hello");
printf(" " "hello");
And I am astonished to see that the first printf only gives a space as output and the second printf outputs a space followed by the string hello. I was expecting output like second one in case of first one. But is there something here I am missing. Please help me with this ...
String literal joining is a lexical feature, which means this:
(i==1) ? " " : " " "hello"
is the same as this:
(i==1) ? " " : " hello"
It should now be pretty obvious why you get the result you get.
i == 1 is true, so the ternary operator evaluates to the first of the two options, " ". Not at all surprising.
C automatically combines two adjacent string literals together.
So your parameter to the second printf: " " "hello" gets joined together to become " hello", which is then printed out normally.
Other answers have explained why your first printf works the way it does, which should be pretty obvious.
Since the condition tested in the ternary operator (i==1) evaluates to true, it returns the expression right after the ?.
The semantics of the ternary operator are something like this:
test_something?if_true:not_true
Your printf statement works as it should.
The source of your confusion is the misunderstanding of when the concatenation is performed. Joining two consecutive string literals is done by the compiler at compile time, not by your program at run time. Therefore there is only one way to parse the first printf: both string literals belong to the "else" branch of the expression. You can test it by setting i to zero and observing the output.