Most of the time I use C++ to deal with URI Online problems, but this time I need to use C.
I have solved the computational part, but URI keeps giving me the classical “Presentation error problem”.
I know I have to break the line at the end, but neither \n or \r\n nor anything else seems to fix this problem.
Here's my code:
int main () {
double R,PI,a;
PI = 3.14159;
scanf("%lf", &R);
a = PI * (pow(R,2));
printf ("A=%0.4f", a, "\n");
return 0;
}
You misunderstood how printf works. It does not concatenate all the stuff you throw into it like you're used to from std::cout << … << …; but instead mostly prints the first argument, the format string. The latter arguments only come into play when the format string requests them, as you do with the %0.4f for the second argument. However, the third is unused. You could fix it like this:
printf("A=%0.4f%s", a, "\n");
Or, more idiomatically, like this:
printf("A=%0.4f\n", a);
By the way, at least my gcc warns me:
main.c: In function ‘main’:
main.c:…: warning: too many arguments for format [-Wformat-extra-args]
printf ("A=%0.4f", a, "\n");
Related
I'm testing conversion specifiers both for printf() and scanf() function. I hadn't problem with %a format specifier for floating point hexadecimal number used in printf() function. It displayed what I expected. But I encountered problem when I wanted to input hexadecimal float using
scanf("%a", &var);
I'm using the following code:
#include <stdio.h>
int main()
{
float var;
printf("Enter variable:\n");
scanf("%a", &var);
printf("var = %f\n", var);
printf("var = %e\n", var);
printf("var = %a\n", var);
return 0;
}
When I enter a sample value, e.g. 0x1.205b0cp-11 that is 5.5e-4 it gives me that result:
Enter variable: 0x1.205bc0p-11
var = 0.000000 var = 0.000000e+000 var = 0x0.000000p+0
Whatever number I enter it always gives me 0. What's the reason or solution for that problem. I have no idea what I'm making wrong.
That code works on my system(a), producing the expected result:
pax> ./prog
Enter variable: 0x1.205bc0p-11
var = 0.000550
var = 5.500000e-04
var = 0x1.205bcp-11
Keep in mind that hexadecimal floating point constants (and the %a conversion specifier) were introduced in C99, so you should make sure you're using a compiler that handles that. Most modern ones will, but some people may be locked in to a certain level if the vendor isn't keen on keeping up to date(b).
Keep in mind that the scanf family, conversion specifiers a, e, g, and f (and their upper-case variants) are all the same - they each handle every format that strtod handles. The (likely) reason that they all exist is to mirror the printf conversion specifiers where it makes a difference to how the value is output.
It's possibly worth testing with a variety of inputs less advanced than hex floating point, and work your way up to there. For example, the sequence { 0, 3, 3.1, 3.14159. 9e2, 6e-2, ... }. That would at least let you know where the input is failing.
Also, it's a good idea to test the conversion to ensure it works (this is true of all calls where failure can adversely affect future program behaviour). In other words, something like this in place of your scanf statement:
if (scanf("%a", &var) != 1) {
fprintf(stderr, "Something went horribly wrong!\n");
return 1;
}
(a) My system, by the way, is gcc 9.4.0 (from gcc --version) running on Ubuntu 20.04.2 (from cat /etc/lsb_release). It's often a good idea to include that sort of information in questions, it can help us figure out issues more quickly.
(b) Possibly a good reason to consider changing vendors though, of course, subject to normal cost/benefit analysis.
Try computing somehow like with printf("var = %e\n", var/7.0 + var *var);. Sometimes simple code without doing any math does not link in the math library needed by printf().
When I run this:
#include <stdio.h>
int main() {
int x = 1;
printf(x, "\n");
return 0;
}
It gives me these errors:
Thread 1: EXC_BAD_ACCESS (code=1, address=0x1)
Format string is not a string literal (potentially insecure)
Treat the string as an argument to avoid this
Incompatible integer to pointer conversion passing 'int' to parameter of type 'const char *'
And it outputs:
(lldb)
However, when I change it to:
printf("%s", x);
It works perfectly fine. (outputs "1", as expected)
Why are the conversion characters (e.g. %s, %d, etc...) needed?
They're needed to tell the printf function what the types (and number) of the parameters are that you are passing.
The language has no mechanism to allow a function to determine this dynamically, so the format string gives it the clues to decode them.
The format string is always the first parameter, because the called function can always access that in the same place. Functions like printf are still written in C typically, so can only use those functions that the language provides.
They parameters are not "conversion characters". I think your confusion comes from the fact that you think printf simply prints all its arguments and automatically deduces how to print each. However, printf cannot work like that because C does not have support for overloading.
Concretely, the first argument is not like the rest. It is not something to print, but a format string. You can see easily what it means by trying this:
printf("My friend %s has %d coins!", "John", 123);
which will print:
My friend John has 123 coins!
%s here specifies the first argument (after the format string) will be interpreted as a string, and %d means the second argument (again, after the format string) will be understood as an integer. Both will be replaced with the actual value from the argument.
Say I have a printf with many parameters:
printf("%d %d %d %d", A, B, C, D);
For some reason I would like one parameter to no longer be printed, but still be listed in the parameter list (for instance for visual reason, or maybe it's a function call with a necessary side effect, etc).
Can I replace %d with a conversion letter with no output ? I don't recall such a conversion letter. Or maybe playing with the flags...?
[Edit] I just noticed that scanf has something similar (but the reverse): an assignment suppression flag '*'. for instance sscanf("123 345 678", "%i %*i %i", &a, &b) will lead to a=123 b=678
If you for some reason must change these on the fly, then keep things simple:
printf("%d ", A);
printf("%d ", B);
if(c)
printf("%d ", C);
printf("%d ", D);
You can suppress Strings (char*) arguments by specifying zero-width.
However, I know of no way to suppress numeric (int and float) values.
int main(void) {
int a=1;
char* b="hello"; // Gets Suppressed
int c=3;
printf("%d %.0s %d\n", a, b, c); // .0 means "zero-width"
return 0;
}
First of all, I agree with Radosław Cybulski's comment: Relying on side-effects is a dangerous thing. So please don't do that.
As for suppressing the printing of a parameter I think there is no built-in placeholder for that and it would probably be better to just comment out the whole printf statement and add the version without the suppressed parameter below it.
With that said there are two(not very elegant) solutions I could come up with that does something similar to what you'd like to achieve:
Method1
You could create a macro like this:
#define SUPPRESS_PRINT(x) "\0"/*x*/
This will replace the parameter with a null terminator character.
Then you can use it in your printf statement like this:
printf("%d %d %s %d", A, B, SUPPRESS_PRINT(C), D);
Notice that the placeholder for C (i.e. the suppressed parameter) had to be changed to %s that is a null terminated string in order for this "trick" to yield the desired result.
Correction:
I've enhanced the above solution thanks to jhx's awesome suggestion in the comments. Using sequential evaluation possible side-effects won't be omitted. The revised macro would look like this:
#define SUPPRESS_PRINTF_ARG(x) ((x), "")
Usage would stay the same as described above.
Method2
There is yet another, possibly simpler, solution. It is a POSIX feature not a C99 one but it would work in most scenarios I assume. It is to use a parameter field in each format placeholder. Something like this:
printf("%1$d %2$d %3$d %4$d", A, B, C, D);
Then if you'd want to omit let's say parameter C from being printed you could just delete %3$d from the format string. Thus getting this:
printf("%1$d %2$d %4$d", A, B, C, D);
This might be the simplest way to go about it.
Working principle: The parameter field ties the format placeholder to a given parameter using its ordinal number. Thus even if you remove one the rest will still print correctly.
Note: As far as my testing goes this method does not omit side-effects!
i am learning now c and i come up with this example, where i can print a text using pointers.
#include <stdio.h>
main ()
{
char *quotes = "One good thing about music, when it hits you, you feel no pain. \"Bob Marley\"\n";
printf(quotes);
}
I get a warning from the compiler "format not a string literal and no format arguments" and when I execute the program it runs successfully.I read some other questions here that they had the same warning from the compiler but I didn't find an answer that fits me. I understood the reason why i get this message:
This warning is gcc's way of telling you that it cannot verify the format string argument to the printf style function (printf, fprintf... etc). This warning is generated when the compiler can't manually peek into the string and ensure that everything will go as you intend during runtime...
Case 3. Now this is somewhat your case. You are taking a string generated at runtime and trying to print it. The warning you are getting is the compiler warning you that there could be a format specifier in the string. Say for eg "bad%sdata". In this case, the runtime will try to access a non-existent argument to match the %s. Even worse, this could be a user trying to exploit your program (causing it to read data that is not safe to read).
(See the answer)
but what i have to add in my case to in order to have not warnings from the compiler?
Change it to printf("%s", quotes); which adds the specifier that quotes is a 'string', or array of char.
You need to tell printf what is it that you are printing. %s descriptor will tell printf that you are printing a string.
Format of printf = ("descriptor of what type of data you are printing",variable holding the data);
descriptor for strings is %s, for characters %c, for int %d
Change printf to:
printf("%s",quotes);
You have to specify format string - in simplest form:
char *quotes = "One good thing about music(...)\n";
printf("%s", quotes);
or, you can use format string to decorate output:
char *quotes = "One good thing about music(...)"; // no newline
printf("%s\n", quotes); // newline added here
or, if you don't want to mess with format strings:
char *quotes = "One good thing about music(...)"; // no newline
puts(quotes); // puts() adds newline
or
char *quotes = "One good thing about music(...)\n";
fputs(quotes,stdout);
This warning is gcc's way of telling you that it cannot verify the format string argument to the printf style function (printf, fprintf... etc). This warning is generated when the compiler can't manually peek into the string and ensure that everything will go as you intend during runtime. Lets look at a couple of examples.
So as other suggested explicitly use format specifier to tell the compiler...i.e.
printf("%s",quotes);
You are getting the warning because it is dangerous when the string you are printing contains '%'. In this line it makes no sense for percents but when you want to print this for instance:
int main ()
{
int percent = 10;
char *s = "%discount: %d\n";
printf(s, percent);
return 0;
}
your program will likely crash when printf encounters the second percent and it tries to pop a value from the stack from printf.
When you want to print a percent sign use: "%%discount:"
Try this:
#include <stdio.h>
main ()
{
char *quotes = "One good thing about music, when it hits you, you feel no pain. \"Bob Marley\"\n";
puts(quotes); //Either
printf("%s",quotes);//or
return 0;
}
I have a function call in a program that I'm maintaining has 28 arguments for a printf call. It's printing a lot of data in a CSV file. I have problems following finding where what goes and I have some mismatches in the parameters types. I enabled -Wall in gcc and I get warnings like:
n.c:495: warning: int format, pointer arg (arg 15)
n.c:495: warning: format argument is not a pointer (arg 16)
n.c:495: warning: double format, pointer arg (arg 23)
The function is like this:
fprintf (ConvFilePtr, "\"FORMAT3\"%s%04d%s%04d%s%s%s%d%s%c%s%d%c%s%s%s%s%s%s%s%11.lf%s%11.lf%s%11.lf%s%d\n", some_28_arguments_go_here);
I would like to know if there is a vim plugin that highlights the printf format specifier when i go with the cursor over a variable.
Other solutions? How to better reformat the code to make it more readable?
Not sure I know a good vim trick off the top of my head, but I know a good C macro to make it a little easier:
#define last( f, a, ft, ... ) f ft, a, __VA_ARGS__
#define pair( f, a, ftat ) last( f, a, ftat )
// ...
printf( pair( "%s", "hello",
pair( "%s", "world",
pair( "%c", '\n',
last( "%4x", 0xfeed,
"%f\n", 3.14159 )))));
split the format string and the call into several fprintf calls
From the warning you know the argument number in question, e.g. 15. In normal mode:
Go to the start of the line.
Type '15f%' to find the 15. occurrence of '%' inside the format string.
You can split it up and keeping only one fprintfcall. I do often something like that:
fprintf (ConvFilePtr,"\"FORMAT3"
"%s"
"%04d%s"
"%04d"
"%s%s%s"
"%d"
"%s%c"
"%s%d%d"
"%c%s"
"%s%s%s"
"%s%s"
"%s%11.lf"
"%s%11.lf"
"%s%11.lf"
"%s%d\n", str1,
int1, str2,
int2,
etc...);
You get the point, you still have only one call (which is important as I/O is often order of magnitude slower than pushing varaibles on the stack), and you can arrange your variables so that they are grouped logically, making it easier to spot a problem.