Win Key
Win Key

Reputation: 49

Passing C string to a function that returns C string pointer

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

Answers (2)

chqrlie
chqrlie

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

0___________
0___________

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

Related Questions