Is getchar() equivalent to scanf("%c") and putchar() equivalent to printf("%c")? - c

Is a = getchar() equivalent to scanf("%c",&a);?
Is putchar(a) equivalent to printf("%c",a); where a is a char variable?

Generally speaking yes they are the same.
But they are not in a few nitpicky ways. The function getchar is typed to return int and not char. This is done so that getchar can both all possible char values and additionally error codes.
So while the following happily compiles in most compilers you are essentially truncating away an error message
char c = getchar();
The function scanf, though, allows you to use a char type directly and separates out the error code into the return value.

They do the same thing here. However, if you know you are just doing characters then getchar and putchar will be more efficient, since the printf and scanf variants will have to parse the string each time to determine how to process your request. Plus, they may be called in a lower level library meaning you may not have to have the printf/scanf linked if they are not needed elsewhere.

Related

why does this C/C++ code helps in taking fast input

I took this code from this link https://www.codechef.com/viewsolution/1715623
and I am not able to understand how the scan() function helps in taking fast input
#define g getchar_unlocked()
int scan()//fast input output
{
int t=0;
char c;
c=g;
while(c<'0' || c>'9')
c=g;
while(c>='0' && c<='9')
{
t=(t<<3)+(t<<1)+c-'0';
c=g;
}//end fast input output
return(t);
}
User defined function scan() uses lib function getchar_unlocked() which is faster than getchar() and any other standart input methods since it's not thread safe.
Inner function loops are used to consider only numeric input (and uses shift operators instead of multiplying for extra performance gain which must be tested before used).
And this function contains possible int overflow.
I think it's basically atoi with getchar. It ignores leading non numeric characters then creates an integer of the string numerals, exiting when numeric numbers stop. Scan is probably not the right name for this, it should be Atoi(), or ScanNum()? Probably doesn't work for when the integer is big due to integer overflow issues.
I'd be surprised if this is faster than atoi() not sure why they didn't use isdigit() either.
Unlike the California University code, doesn't check for a sign, nor does it use the register keyword.

why getchar() function work different in a loop?

#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.

Calling isalpha Causing Segmentation Fault

I have the following program that causes a segmentation fault.
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int main(int argc, char *argv[])
{
printf("TEST");
for (int k=0; k<(strlen(argv[1])); k++)
{
if (!isalpha(argv[1])) {
printf("Enter only alphabets!");
return 1;
}
}
return 0;
}
I've figured out that it is this line that is causing the problem
if (!isalpha(argv[1])) {
and replacing argv[1] with argv[1][k] solves the problem.
However, I find it rather curious that the program results in a segmentation fault without even printing TEST. I also expect the isalpha function to incorrectly check if the lower byte of the char* pointer to argv[1], but this doesn't seem to be the case. I have code to check for the number of arguments but isn't shown here for brevity.
What's happening here?
In general it is rather pointless to discuss why undefined behaviour leads to this result or the other.
But maybe it doesn't harm to try to understand why something happens even if it is outside the spec.
There are implementation of isalpha which use a simple array to lookup all possible unsigned char values. In that case the value passed as parameter is used as index into the array.
While a real character is limited to 8 bits, an integer is not.
The function takes an int as parameter. This is to allow entering EOF as well which does not fit into unsigned char.
If you pass an address like 0x7239482342 into your function this is far beyond the end of the said array and when the CPU tries to read the entry with that index it falls off the rim of the world. ;)
Calling isalpha with such an address is the place where the compiler should raise some warning about converting a pointer to an integer. Which you probably ignore...
The library might contain code that checks for valid parameters but it might also just rely on the user not passing things that shall not be passed.
printf was not flushed
the implicit conversion from pointer to integer that ought to have generated at least compile-time diagnostics for constraint violation produced a number that was out of range for isalpha. isalpha being implemented as a look-up table means that your code accessed the table out of bounds, therefore undefined behaviour.
Why you didn't get diagnostics might be in one part because of how isalpha is implemented as a macro. On my computer with Glibc 2.27-3ubuntu1, isalpha is defined as
# define isalpha(c) __isctype((c), _ISalpha)
# define __isctype(c, type) \
((*__ctype_b_loc ())[(int) (c)] & (unsigned short int) type)
the macro contains an unfortunate cast to int in it, which will silence your error!
One reason why I am posting this answer after so many others is that you didn't fix the code, it still suffers from undefined behaviour given extended characters and char being signed (which happens to be generally the case on x86-32 and x86-64).
The correct argument to give to isalpha is (unsigned char)argv[1][k]! C11 7.4:
In all cases the argument is an int, the value of which shall be representable as an unsigned char or shall equal the value of the macro EOF. If the argument has any other value, the behavior is undefined.
I find it rather curious that the program results in a segmentation fault without even printing TEST
printf doesn't print instantly, but it writes to a temporal buffer. End your string with \n if you want to flush it to actual output.
and replacing argv[1] with argv[1][k] solves the problem.
isalpha is intended to work with single characters.
First of all, a conforming compiler must give you a diagnostic message here. It is not allowed to implicitly convert from a pointer to the int parameter that isalpha expects. (It is a violation of the rules of simple assignment, 6.5.16.1.)
As for why "TEST" isn't printed, it could simply be because stdout isn't flushed. You could try adding fflush(stdout); after printf and see if this solves the issue. Alternatively add a line feed \n at the end of the string.
Otherwise, the compiler is free to re-order the execution of code as long as there are no side effects. That is, it is allowed to execute the whole loop before the printf("TEST");, as long as it prints TEST before it potentially prints "Enter only alphabets!". Such optimizations are probably not likely to happen here, but in other situations they can occur.

Why are islower() and friends required to handle EOF?

Why are islower() and friends required to handle EOF, whereas putchar() and friends don't have to?
Why isn't islower() treating int as unsigned char, as it is the case in putchar()? This would make total sense, because we have to check for EOF first anyway. See also Why the argument type of putchar(), fputc(), and putc() is not char?
because we have to check for EOF first anyway.
We absolutely don't.
int c;
while(isspace(c=fgetc(fp)));
if (c==EOF) ...
This is totally legitimate code to skip whitespaces. Checking each character for EOF separately is a waste of time.
The ctype functions are made to handle EOF specifically to enable code like this.
See also this question.
None of character type functions are required to handle EOF, other than ignoring it (i.e. returning false). In fact, EOF marker is not even mentioned in <ctype.h> header documentation.
The most likely reason for character classification function signatures to use int in place of char, signed or unsigned, is to avoid implementation-defined behavior in loops like this:
int c;
while ((c =getchar()) != EOF) {
if (islower(c)) {
...
} else if (isdigi(c)) {
...
}
}
This would compile and run with islower(char) instead of islower(int), but the result would be implementation defined, which is not desirable under such basic circumstances. Essentially, int in the signature of getchar became "contagious," getting into signatures of functions only marginally related to it.

Cannot create a program which will invert string

I am using Linux.
I am trying to write a program in c that will print a string backward.
Here is my code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main (){
char string[100];
printf ("Enter string:\n");
gets (string);
int length = strlen (string)-1;
for (length = length; length>=0; length--){
puts (string[length]);
}
}
And here is the error:
a.c:10: warning: passing argument 1 of ‘puts’ makes pointer from integer without a cast
/usr/include/stdio.h:668: note: expected ‘const char *’ but argument is of type ‘char’
/tmp/cc5rpeG7.o: In function `main':
a.c:(.text+0x29): warning: the `gets' function is dangerous and should not be used.
What should I do?
Forget that the function gets() exists - it is lethal. Use fgets() instead (but note that it does not remove the newline at the end of the line).
You want to put a single character at a time: use putchar() to write it to stdout. Don't forget to add a newline to the output after the loop.
Also, for (length = length; length >= 0; length--) is not idiomatic C. Use one of:
for ( ; length >= 0; length--)
for (length = strlen(string) - 1; length >= 0; length--)
for (int length = strlen(string) - 1; length >= 0; length--)
The last alternative uses a feature added to C99 (which was available in C++ long before).
Also, we could debate whether length is the appropriate name for the variable. It would be better renamed as i or pos or something similar because, although it is initialized to the length of the input, it is actually used as an array index, not as the length of anything.
Subjective: Don't put a space between the name of a function and its parameter list. The founding fathers of C don't do that - neither should you.
Why is gets() lethal?
The first Internet worm - the Morris worm from 1988 - exploited the fingerd program that used gets() instead of fgets(). Since then, numerous programs have been crashed because they used gets() and not fgets() or another alternative.
The fundamental problem is that gets() does not know how much space is available to store the data it reads. This leads to 'buffer overflows', a term which can be searched for in your favourite search engine that will return an enormous number of entries.
If someone types 150 characters of input to the example program, then gets() will store 150 characters in the array which has length 100. This never leads to happiness - it usually leads to a core dump, but with carefully chosen inputs - often generated by a Perl or Python script - you can probably get the program to execute arbitrary other code. This really matters if the program will ever be run by a user with 'elevated privileges'.
Incidentally, gets() is likely to be removed from the Standard C library in the next release (C1x - see n1494 from WG14). It won't vanish from actual C libraries for a long time yet (20 years?), but it should be replaced with this implementation (or something similar):
#undef NDEBUG
#include <assert.h>
char *gets(char *buffer)
{
assert("Probability of using gets() safely" == 0);
}
One other minor detail, discussed in part under the comments to the main question.
The code shown is clearly for C99; the declaration of length part way through the function is invalid in C89. Given that, it is 'OK' for the main() function not to explicitly return a value, because the C99 standard follows the lead of the C++ standard and allows you to omit the return from main() and the effect is the same as return(0); or return 0; at the end.
As such, the program in this question cannot strictly be faulted for not having a return at the end. However, I regard that as one of the more peculiar standardizing decisions, and would much prefer it if the standards had left that provision out - or done something more radical like allowing the ubiquitous but erroneous void main() observing that when control returns from that, the result is that a success status is returned to the environment. It isn't worth fighting to get that aspect of the standard changed - sadly - but as a personal style decision, I don't take advantage of the licence granted to omit the final return from main(). If the code has to work with C89 compilers, it should have the explicit return 0; at the end (but then the declaration of length has to be fixed too).
You can also use recursion to do it. I think it looks nicer then when using a loop.
Just call the method with your string, and before printing the char in the method, call the method again with the same string, minus the first char.
This will print out you string in reversed order.
First:
NEVER NEVER NEVER NEVER NEVER use gets(); it will introduce a point of failure in your code. There's no way to tell gets() how big the target buffer is, so if you pass a buffer sized to hold 10 characters and there's 100 characters in the input stream, gets() will happily store those extra 90 characters in the memory beyond the end of your buffer, potentially clobbering something important. Buffer overruns are an easy malware exploit; the Morris worm specifically exploited a gets() call in sendmail.
Use fgets() instead; it allows you to specify the maximum number of characters to read from the input stream. However, unlike gets(), fgets() will save the terminating newline character to the buffer if there's room for it, so you have to account for that:
char string[100];
char *newline;
printf("Enter a string: ");
fflush(stdout);
fgets(string, sizeof string, stdin);
newline = strchr(buffer, '\n'); // search for the newline character
if (newline) // if it's present
*newline = 0; // set it to zero
Now that's out of the way...
Your error is coming from the fact that puts() expects an argument of type char *, but you're passing an argument of type char, hence the "pointer from integer without cast" message (char is an integral type). To write a single character to stdout, use putchar() or fputc().
You should use putchar instead of puts
So this loop:
for (length = length; length>=0; length--){
puts (string[length]);
}
Will be:
for (length = length; length>=0; length--){
putchar (string[length]);
}
putchar will take a single char as a parameter and print it to stdout, which is what you want. puts, on the other hand, will print the whole string to stdout. So when you pass a single char to a function that expects a whole string (char array, NULL terminated string), compiler gets confused.
Use putc or putchar, as puts is specified to take a char* and you are feeding it a char.

Resources