Why does `printf("%c", 5)` print a vertical bar? - c

Here is the code
#include <stdio.h>
int main()
{
printf ("\t%d\n",printf("MILAN"));
printf ("\t%c",printf("MILAN"));
}
Here is the output
$gcc -o main *.c
$main
MILAN 5
MILAN |
Now the question is
Why printf return | when we are printing characters (formatter as %c) ?
What is the relation between 5 and | here?

Your question really boils down to the behaviour of printf("%c", 5);.
The actual output is a function of the character encoding used by your platform. If it's ASCII (very common) then it will output the control character ENQ. What you actually get as an output will depend on your command shell, and a vertical bar is not an unreasonable choice.

printf returns the number of characters printed. In this case, that number is 5, as you've seen. The second print you're doing tries to typecast that int to a char, which C lets you do because it's C. On your computer, it shows up as a |. I see it rendered as a blank character. As #Bathsheba says, the integer 5 corresponds to a control character in ASCII, and the rendering for those is system-dependent.
Here's an ascii table, if you're curious about other numbers.

Related

Trying to replicate printf behaviour about variadic paramenters

I'm trying to replicate some printf functionality for education purposes, but I've encountered some printf behavior that I'm unable to understand. I'll try explaining with a simple example:
have this call:
printf(" %c %c %c", 0, 1, 2); // yes, parameters are ints not chars.
The output seems normal, only 3 spaces, numbers are ignored.
But taking printf output to a file, then using "cat -e file" does this:
^# ^A ^B
^# for 0, ^A for 1, ^B for 2 and so on.
Here is my question, what are those symbols? How they relate to the values?
Also my own printf, does this as well except for the 0 which is treated as a '\0' char...I need to mimic printf exactly so I need to understand what is going on there...
I've searched about those symbols, but can't find anything. They are not memory garbage because the results are always same.
The -e option to cat tells it to use a particular notation for printing non-printable characters. ^# represents the value 0, ^A represents the value 1, and ^B represents the value 2. Those are exactly the values you gave.
Simply cat uses caret notation to display not printable characters. ^A represents 1 and ^Z represents 26. ^# is 0 and
27 - ^[
28 - ^\
29 - ^]
30 - ^^
31 - ^_
127 - ^?
What i meant is why printf prints ^# while im getting '\0'(?)
printf("%c", 0); prints the null character to stdout. What you see when viewing the output of stdout is not part of stdout, but an implementation detail of the shell/terminal program. Print the return value of printf() to get its understanding of how many characters it printed. Perhaps on stderr to separate it from stdout.
int count = printf(" %c %c %c", 0, 1, 2);
fprintf(stderr, "<%d>\n", count);
The output seems normal, only 3 spaces, numbers are ignored.
"Seems" deserves more detail. How was only 3 determined?
But taking printf output to a file, ...
What was the length of the file? 6?
... then using "cat -e file" does this:
Refer to #dbush good answer as to why you now see " ^# ^A ^B".
I'm using memset to replace the character.
is unclear as there is no memset() in the question.
Got it solved. Thanks to the explanations here, i realized that even i was printing the resulting string with write() i was using a pointer to iterate it so never gave a chance to actually pass over that null character.
write(STDOUT_FD, delta, d_length);
Then write() does the job correcty:
make test > check.txt && cat -e check.txt
own: ^# ^A ^B$
lib: ^# ^A ^B$
Also now i know about the caret notation, thanks everyone!

Why does multiplying a character produce other seemingly random characters?

I can't understand why this code output is weird. I wrote this out of curiosity and now if I enter 55 it shows a leaf. And also many other things depending on number. I searched it in google but didn't find any possible explanation.
#include <stdio.h>
int main(){
char input='*';
int x;
scanf("%d",&x);
printf("%c",input*x);
return 0;
}
Characters are encoded as integers, usually 8-bit by default in C. Some are defined by ASCII and others depend on your OS, screen font, etc.
The * character has code 42. If you enter 55, your code computes 42*55=2310 and uses the low 8 bits of this value, which is 6, as the character to print. Character 6 is ACK which is not defined as a printable character by ASCII, but it sounds like your system is using something like the legacy IBM code page 437, in which character 6 displays as the spade symbol ♠.
Multiplying a character code by an integer is not a very useful thing to do. I'm not sure what you were expecting to accomplish with this program. If you thought it would print 55 copies of the * character, like Perl's x operator, well it doesn't. C has no built-in way to do that; you would just write a loop that prints * once per iteration, and iterates 55 times.

How does one use shift sequences to output a character from another character set

Reading about how to use shift sequences to print characters from other character sets I've arrived at the following code (of which I'm sure the escape sequence is incorrect, however I do not know why):
#include <stdio.h>
int main(int argc, char *argv[])
{
printf("\x1B\x28\x49\x0E\xB3"); /* Should print: ウ */
return 0;
}
This however is not working for me as it outputs a "?" in the terminal rather than the character "ウ". My font does indeed have support for the character. If someone could explain what I'm doing incorrectly and how I would go about correcting this(still using shift sequences), that would be greatly appreciated.
Thank you
Your are using ISO-2022-JP-3. Hence you need to write your program as follows:
int main ()
{
// switch to JIS X 0201-1976 Kana set (1 byte per character)
printf ("\x1B(I");
printf ("\x33"); /* ウ */
// mandatory switch back to ASCII before end of line
printf ("\x1B(B");
printf ("\n");
return 0;
}
Note however that it is unlikely to be the character set expected by the terminal (on linux, this is most likely UTF-8). You can use iconv to perform the conversion:
$ ./main | iconv -f ISO-2022-JP-3
Alternatively you can use iconv(3) to perform the conversion inside your program.
What happens if you do echo 'ウ' >/tmp/x && od -x /tmp/x - do you see the same hex characters as you are using in the example above? I'm betting not, and I've based this answer on that bet.
Your cat works because ウ is encoded in your source file as UTF-8.
You have your terminal set to UTF-8 (or more likely it's just defaulting to UTF-8) so UTF-8 works, but Shift-JIS does not.

How do I print the infinity symbol in C using printf [duplicate]

This question already has answers here:
Showing characters in extended ASCII code (Ubuntu)
(3 answers)
Closed 9 years ago.
I tried the following
printf ("%c", 236); //236 is the ASCII value for infinity
But I am just getting garbage output on the screen.
printf was working correctly for ASCII values less than 128. So I tried the following
printf ("%c", 236u); //unsigned int 236
Still I am just getting garbage only. So, what should I do to make printf display ASCII values from 128 to 255.
Like everyone else in the comments already mentioned, you would not be able to reliably print characters after 127 (and assuming it as ASCII) since ASCII is only defined upto 127. Also the output you see very much depends on the terminal settings (i.e. which locale it is configured to).
If you're fine using UTF-8 to print, you could give wprintf a try as shown below:
#include <stdio.h>
#include <wchar.h>
#include <locale.h>
int main()
{
setlocale( LC_ALL, "en_US.UTF-8" );
wprintf (L"%lc\n", 8734);
return 0;
}
It would produce the following output:
∞
8734 (or 0x221E) is the equivalent of the UTF-8 UNICODE character for the symbol ∞.
Standard C does not have a symbol for infinite. That's for your implementation (eg. your compiler, your operating system, your terminal and your hardware) to define. Consider that C was designed with portability for systems that use non-ASCII character sets in mind (eg. EBCDIC).

Mixing data types results in heart output

I was fooling around with one of the sample programs in the K&R, and found that this
#include <stdio.h>
main()
{
double nc;
for (nc = 0; getchar() != EOF; ++nc)
;
printf("%lf\n", nc );
putchar(nc);
}
produces output that is 3.000000 (which I totally expected) then a new line with a heart on it (which I totally did not expect). Why would it output a new line with a heart on it?
I assume it has something to do with me mixing data types.
You're calling putchar() with a double as an argument. It's going to get implicitly typecast to int, and then that character will be output. You get the heart because for some reason your character set has a heart as character number 3. If you run it and type a bunch more characters before the EOF, you'll get a different character. On my machine, your program doesn't make a heart, but if I type more characters, I can get whatever I want on that next line. ASCII character 3 is ETX, end of text, so I don't know why you would get the heart in your case - are you using some weird locale or character set? What does this program output on your machine:
#include <stdio.h>
int main(int argc, char *argv[])
{
putchar(3);
putchar('\n');
return 0;
}
Edit:
You're getting the heart because that's what's in your character set at position 3. From wikipedia:
In Code page 437, the original character set of the IBM PC, the value of 3 (hexadecimal 03) represents the heart symbol. This value is shared with the non-printing ETX control character, which overrides it in many contexts.

Resources