Reputation: 49
I am trying to pass a C string (char*)
to a function lower(char *)
(as in the prototype) that returns a C string char *lower()
to main()
. But I am not getting the desired output. Point out my mistakes and suggest some techniques for getting the result.
(Note : <string.h>
functions are not allowed & the task must be done with pointers). Here is my code,
#include <stdio.h>
#include <stdlib.h>
char *lower(char *);
void main() {
char pass[10], *pass1;
printf("Enter a password\n");
scanf("%s", pass);
pass1 = lower(pass);
printf("Lower case ");
int i = 0;
while (*pass1 != '\0') {
printf("%c", *(pass1 + i));
i++;
}
}
char *lower(char *p) {
while (*p != '\0') {
if (*p >= 'A' && *p <= 'Z') {
*p = *p + 32;
}
p++;
}
return p;
}
Upvotes: 1
Views: 761
Reputation: 144695
There are multiple problems in your code:
main
should have the prototype int main(void)
a for good style have a return 0;
statement at the end of the body.
scanf()
should protect the destination array from overflow by specifying the maximum number of characters to read into it: scanf("%9s", pass);
and you should check its return value for successful conversion.
you should use pass1[i]
instead of *(pass1 + i)
. Both expressions are equivalent but the first is more readable. Incidentally, another equivalent but surprising alternative is i[pass1]
, don't use it unless you want to confuse the reader, which might be advisable in a password handling routine.
printing individual characters with printf("%c", pass1[i])
does not seem mandated by the rules posted: use a single printf
statement.
Furthermore, the loop test is constant: while (*pass1 != '\0')
as you only increment i
in the loop. Hence an infinite loop and undefined behavior when you access elements of pass
beyond its end.
as you pass the return value to printf()
, function lower()
should return the original pointer, not the pointer to the end of the argument string.
you should not hard-code the difference between lowercase and uppercase characters, 32
only works for ASCII, not EBCDIC. *p += 'a' - 'A';
would be both more portable and more readable. It works for both ASCII and EBCDIC, but might not for other less common character sets and the test if (*p >= 'A' && *p <= 'Z')
is not precise enough for EBCDIC as the uppercase letters do not form a contiguous set. Use the macros from <ctype.h>
for a portable solution.
Here is a corrected version:
#include <stdio.h>
#include <ctype.h>
char *lower(char *);
int main(void) {
char pass[80];
printf("Enter a password\n");
if (scanf("%79s", pass) == 1) {
printf("Lower case: %s\n", lower(pass));
}
return 0;
}
char *lower(char *s) {
for (char *p = s; *p != '\0'; p++) {
*p = tolower((unsigned char)*p);
}
return s;
}
If you cannot use <ctype.h>
, use this less portable version:
char *lower(char *s) {
for (char *p = s; *p != '\0'; p++) {
if (*p >= 'A' && *p <= 'Z')
*p += 'a' - 'A';
}
return s;
}
Upvotes: 5
Reputation: 67476
char *lower(char *p){
char *ptr = p;
while(*p != '\0'){
if( *p>='A' && *p<='Z' ){
*p = *p + 32;
}
p++;
}
return ptr;
}
why sometimes is good to return something like converted char pointer - to use it in other operations - for example as a parameter in another function call.
Upvotes: 3