"The function returns the character written as an unsigned char cast to an int or EOF on error": see Putchar.
In order to do practice, I produced this program:
#include<stdio.h>
int main(void){
for(putchar('1'); putchar('2'); putchar('3'))
putchar('4');
return 0;
}
It results in an infinite loop whit output ...432432432432432....
I cannot get the reason behind such a result. I expected the loop to print just the same number over and over. I am referring to the value of putchar('4'), where the character '4' should be promoted to the int 52. Why such promotion is not behaving as I expected?
In your case, as per the loop policy,
putchar('1') is executed once.
putchar('2') is evaluated, is found TRUTHY, putchar('4'); is executed, and then putchar('3'); is executed.
back to previous step unless the putchar('2') is FALSY (which never happens).
Hence infinite loop, and every loop iteration includes three putchar statements.
Related to the question "....where the character '4' should be promoted to the int 52" , quoting C11, ยง7.21.7, (emphasis mine)
The fputc function writes the character specified by c (converted to an unsigned
char) to the output stream pointed to by stream, [...]
and
The putchar function is equivalent to putc with the second argument stdout.
So, it's the character representation which will be printed, and the character representation of '4' is, well, 4.
It does print 124324324324....because putchar(1) is executed at the beginning of the loop and never again.
Putchar prints char on the standard output, and return the same char casted to int. It does not print the char casted to int to the standard output. If you say: putchar('z'), it will print 'z'
putchar(2) at the beginning of each iteration and return the int value of the char '2' which happens to be non zero. This also means that the loop never ends.
putchar('3') is executed at the end of each iteration.
putchar('4') between the beginning and the end of each iteration.
That is why you get that output.
Because putchar ('2') is always != 0 and you execute putchar('4') then action in for which is putchar('3) then condition check putchar('2') which always true and you go to the beginning of this loop
Related
I want to input an integer number and a character with scanf funtion, but it didn't work as I want.
The codes are as follows.
#include <stdio.h>
int main()
{
int a;
char c;
scanf("%d",&a);
scanf("%2c",&c);
printf("%d%c",a,c);
return 0;
}
I tried to input 12a (there is a space after a) from the terminal, but the output is not "12a" but "32a".
I also tried to run the code above step by step and found that when it run into the first "scanf", the value of "a" is 12, but when run into second "scanf", the value of "a" turned 32.
I want to figure out why the second scanf changes the value of a, which is not presented.
The problem is that the compiler has put variable a just behind variable c. When you do the second scanf() you specify to read two characters into a variable that has space only for one. You have incurred in a buffer overflow, and have overwritten memory past the variable c (and a happens to be there). The space has been written into a and this is the reason that you get 32 output (a has been stored the value of an ASCII SPACE, wich is 32).
What has happened is known as Undefined Behaviour, and it's common when you make this kind of mistakes. You can solve this by definning an array of char cells with at least two cells for reading the two characters . and then use something like:
#include <stdio.h>
int main()
{
int a;
char c[2];
scanf("%d", &a);
scanf("%2c", c); /* now c is a char array so don't use & */
printf("%d%.2s", a, c); /* use %.2s format instead */
return 0;
}
Note:
the use of %.2s format specifier is due to the fact that c is an array of two chars that has been filled completely (without allowing space to include a \0 string end delimiter) this would cause undefined behaviour if we don't ensure that the formatting will end at the second character (or before, in case a true \0 is found in the first or the second array positions)
Quoting C11, chapter 7.21.6.2, The fscanf function (emphasis mine)
c
[...]If an l length modifier is present, the input shall be a sequence of multibyte characters that begins in the initial shift state. Each multibyte character in the sequence is converted to a wide character as if by a call to the mbrtowc function, with the conversion state described by an mbstate_t object initialized to zero before the first multibyte character is converted. The corresponding argument shall be a pointer to the initial element of an array of wchar_t large enough to accept the resulting sequence of wide characters. [...]
and you're supplying a char *. The supplied argument does not match the expected type of argument, so this is undefined behavior.
Therefore the outcome cannot be justified.
To hold an input like "a ", you'll need a (long enough) char array, a char variable is not sufficient.
#include <stdio.h>
int main()
{
char c;
while ((c=getchar()) != EOF)
putchar(c);
}
why when i input text such as for example "omar"put char print "omar" back .Isn't it supposed to print 'o' repeatedly since getchar will take first character only.I know that I am wrong about something probably because i don't know how exactly getchar or putchar works ,so can somebody please explain how they works.Another question why getchar and putchar work normally without a while loop but inside while loop behavior is something different.
why getchar() function work different in a loop?
I take you to be asking why getchar() works differently than you expect, as opposed to differently than in other contexts. If you in fact meant the latter then the answer would be "it doesn't."
But of course reading a character from a stream, whether via getchar() or some other I/O function, removes it from the stream. getchar() would not be very useful if it did not do that. Therefore, if you call it repeatedly, you read (and remove) each character in turn until and unless all available characters are consumed. You can test this by replacing the loop in your program with several getchar() calls in row.
And, of course, your loop does call it repeatedly. The loop-control expression, (c=getchar()) != EOF, is evaluated before each iteration of the loop, and that involves calling getchar() (as opposed to using a value previously returned by that function).
On a completely separate note, do be aware that getchar() returns a result of type int, exactly so that it can return at least one value, EOF, that is outside the range of type unsigned char. If you convert the result to type char then either there is one real input value that you will mistake for EOF, or you will never detect EOF, depending on whether char is signed or unsigned. To reliably and portably detect the end of the file, you must handle that return value as an int, not a char.
I know this has been discussed before, but I want to make sure I understand correctly, what is happening in this program, and why. On page 20 of Dennis Ritchie's textbook, The C Programming Language, we see this program:
#include <stdio.h>
int main()
{
int c;
c = getchar();
while(c != EOF){
putchar(c);
c = getchar();
}
return 0;
}
When executed, the program reads each character keyed in and prints them out in the same order after the user hits enter. This process is repeated indefinitely unless the user manually exits out of the console. The sequence of events is as follows:
The getchar() function reads the first character keyed in and assigns its value to c.
Because c is an integer type, the character value that getchar() passed to c is promoted to it's corresponding ASCII integer value.
Now that c has been initialized to some integer value, the while loop can test to see if that value equals the End-Of-File character. Because the EOF character has a macro value of -1, and because none of the characters that are possible to key in have a negative decimal ASCII value, the condition of the while loop will always be true.
Once the program verifies that c != EOF is true, the putchar() function is called, which outputs the character value contained in c.
The getchar() is called again so it reads the next input character and passes its value back to the start of the while loop. If the user only keys in one character before execution, then the program reads the <return> value as the next character and prints a new line and waits for the next input to be keyed in.
Is any of this remotely correct?
Yes, you've basically got it. But it's even simpler: getchar and putchar return and accept int types respectively already. So there's no type promotion happening. You're just taking in characters and sending them out in a loop until you see EOF.
Your intuition about why those should be int and not some char form is likely correct: the int type allows for a sentinel EOF value that is outside the value range of any possible character value.
(The K&R stdio functions are very old at this point, they don't know about Unicode and etc, and some of the underlying design rationales are if not murky, just not relevant. Not a lot of practical code these days would use these functions. That book is excellent for a lot of things but the code examples are fairly archaic.)
(Also, fwiw, your question title refers to "copying a file", which you still can do this way, but there are more canonical ways)
Well, it is correct in idea, but not in details, and that's where the devil is in.
The getchar() function reads the first character from standard input and returns it as an unsigned char promoted to int (or the special EOF value if no character was read)
The return value is assigned into c, which is of type int (as it should, as if it were a char strange things could happen)
Now that c has been assigned some integer value, the while loop can test to see if that value equals the value of the EOF macro.
Because the EOF macro has an implementation-specified negative value, and because the characters were converted to unsigned char and promoted to int, none of them have a negative value (at least not in any systems that you'd meet a a novice), the condition of the while loop will always be true until the End-of-File condition happens or an error happens when reading standard input.
Once the program verifies that c != EOF is true, the putchar() function is called, which outputs the character value contained in c.
The getchar() is called again so it reads the next input character and passes its value back to the start of the while loop.
The standard input, if it is connected to a terminal device, is usually line-buffered, meaning that the program does not receive any of the characters on the line until the user has completed the line and hit the Enter key.
Instead of ASCII, we speak of the execution character set, which nowadays might often be individual bytes of UTF-8 encoded Unicode characters. EOF is negative in binary too, we do not need to think about "its decimal value". The char and unsigned char types are numbers too, and the character constants are of type int - i.e. on systems where the execution character set is compatible with ASCII, writing ' ' will be the same thing as writing 32, though of course clearer to those who don't remember ASCII codes.
Finally, C is very strict about the meaning of initialization. It is the setting of the initial value into a variable when it is declared.
int c = getchar();
has an initialization.
int c;
c = getchar();
has c uninitialized, and then assigned a value. Knowing the distinction makes it easier to understand compiler error messages when they refer to initialization or assignment.
I am writing a simple code to print the content of the file to stdout.
When i use this :
while((c=fgetc(fp))!=EOF)putchar(c);
It works like it should but i wanna to merge putchar and fgetc. So i wrote
while(putchar(fgetc(fp))!=EOF);
But it doesn't seem to work. So i check the return value of putchar
RETURN VALUE
fputc(), putc() and putchar() return the character written as an
unsigned char cast to an int or EOF on error.
So why it doesn't work?
getchar returns one of the following:
A character, represented as an unsigned char value (e.g. typically between 0 and 255, inclusive of those values), converted to an int. Thus, there are typically one of 256 (UCHAR_MAX+1, technically) values that fall into this category.
A non-character, EOF, which has a negative value, typically -1.
Thus, getchar may typically return one of 257 (not 256) values. If you attempt to convert that value straight to char or unsigned char (e.g. by calling putchar), you'll be losing the EOF information.
For this reason you need to store the return value of getchar into an int before you convert it to an unsigned char or char.
I'm trying to run a basic code on my Dev C++ IDE, but it gives an expected output-
printf("%d", printf("stackoverflow1"));
printf("%d", puts("stackoverflow2"));
puts(printf("stackoverflow3"));
the expected output should be:
stackoverflow114stackoverflow2
14stackoverflow314
but the output I'm getting is:
stackoverflow114stackoverflow2
0stackoverflow3
Can someone explain the inconsistency in the output ? I know that puts return a non negative number but why I'm getting a '0' everytime. Also in the last statement why is puts not printing the no of characters printed by printf ?
puts(), as you mentioned, only has to return a non-negative number on success. This means the compiler you are using gets to decide what is returned, as long as it follows this. Your compiler appears to have chosen 0.
as 2501 mentioned, passing puts(const char * p ) an int is illegal, your compiler should have complained about it. puts() is supposed to print starting from p until it reaches a '\0' char, so the input has to be a pointer to a '\0' terminated string
You have undefined behavior. puts() takes a const char* argument yet you pass it an int.
puts(printf("stackoverflow3"));
Enable warnings on your compiler and your code won't even compile.
printf("%d", printf("stackoverflow1"));
Printf returns an int (how much chars are printed = 14). Because the arguments of the outer printf have to be evaluated before the outer one can be evaluated, the string printed will bee "stackoverflow114"
printf("%d", puts("stackoverflow2"));
puts returns a "nonnegative value" (this is the only guarantee, the standard gives to you). In your case the nonnegative value is the int 14. The string "stackoverflow2\n" is printed by puts and the 14 is printed by printf.
puts(printf("stackoverflow3"));
puts takes an const char* as an argument and printf returns the number of chars printed (which is 14, again). Since puts takes a pointer, it may interpret the memory at address 14 as a string and output it (it might cancel compilation, too - most compilers will be 'glad' and cast this for you, along with a warning). This string seems to be empty (this might be sort of random). This line thus only prints "stackoverflow3" (in your case) and the outer puts only prints a random string (in your case "").