3
#include <stdio.h>

int main() {
    int i;  
    char arr[100];

    for (i = 0; i < 100; i++)  
        scanf("%c", &arr[i]);  
    for (i = 0; i < 100; i++) {  
        if ('a' <= arr[i] && arr[i] <= 'z')  
            arr[i] =-32;  
        else
        if ('A' <= arr[i] && arr[i] <= 'Z')  
            arr[i] =+32;  
    }  
    printf("%s", arr);  
    return 0;   
}

There was a problem:

You have been given a String consisting of uppercase and lowercase English alphabets. You need to change the case of each alphabet in this String. That is, all the uppercase letters should be converted to lowercase and all the lowercase letters should be converted to uppercase. You need to then print the resultant String to output.

What is wrong with the above code? It is compiling successfully but there is a runtime error.

chqrlie
  • 131,814
  • 10
  • 121
  • 189
Karan Singh
  • 1,114
  • 1
  • 13
  • 30
  • 1
    And what is the runtime error? What string are you entering? – Dave Costa Jan 27 '17 at 13:39
  • An *obvious* problem is that you don't terminate the string. – Some programmer dude Jan 27 '17 at 13:41
  • 1
    Turn up the warnings on your compiler. I'm sure it will give you warnings at the very least. – Mike Sherrill 'Cat Recall' Jan 27 '17 at 13:41
  • Does the string always contain exactly 100 characters? If not, you should read it with `fgets` instead of 100 `scanf("%c",..)`. This will also add the null terminator for you. – interjay Jan 27 '17 at 13:42
  • I was using an online judge and the input was 'abcdE' The output was ABCDe{@ÿÿÿÿðÿÿ¨ÑdËÀ4¢ËÈA¢Ëý@ ïÿÿ°@ which is definitely wrong – Karan Singh Jan 27 '17 at 13:42
  • The runtime error is because `%s` expects `arr` to have a terminating `'\0'`, but it doesn't. Also, in converting case your code assumes ASCII coding (or compatible) which is not actually guaranteed. Look up functions `isupper()`, `islower()`, `toupper()`, and `tolower()` which are declared in standard header `` and are guaranteed to work. – Peter Jan 27 '17 at 13:42
  • Also, please try to avoid [magic numbers](https://en.wikipedia.org/wiki/Magic_number_(programming)) (like `32` in your code), at least without documenting it. You might also take a look at the [`isupper`](http://en.cppreference.com/w/c/string/byte/isupper) and [`islower`](http://en.cppreference.com/w/c/string/byte/islower) functions, as well as [`toupper`](http://en.cppreference.com/w/c/string/byte/toupper) and [`tolower`](http://en.cppreference.com/w/c/string/byte/tolower) functions. – Some programmer dude Jan 27 '17 at 13:43
  • I also used a for loop, to print the characters one by one, The error was the same. – Karan Singh Jan 27 '17 at 13:43
  • That's because your code isn't coping with input that is anything other than 100 characters. – Peter Jan 27 '17 at 13:44
  • Lastly, if the input is only five characters, why keep reading beyond that? Maybe you should consider using [`fgets`](http://en.cppreference.com/w/c/io/fgets) instead? That will give you a nice terminated string to work with. – Some programmer dude Jan 27 '17 at 13:46
  • @Someprogrammerdude how do I terminate my string if its not 100 letters long and I still want to use scanf? – Karan Singh Jan 27 '17 at 13:49
  • BTW, you might want to use `('a'-'A')` instead of `32`... Of course, this is not guaranteed to work on every platform out there (the correct way has already been pointed out by @Peter). – barak manos Jan 27 '17 at 13:49
  • If you want to use `scanf()` and have the string terminated, use a different format string. I'll leave it as an exercise to work out what - there is a set of possibilities - and you'll learn more by doing it yourself. – Peter Jan 27 '17 at 14:07
  • `if ('a' <= arr[i] && arr[i] <= 'z') arr[i] =-32; ` -> `if (arr[i] >='a' && arr[i] <= 'z') arr[i] = toupper(arr[i]);` – Lundin Jan 27 '17 at 14:08

6 Answers6

4

There are multiple problems in your code:

  • the main issue is the away you adjust the case: arr[i] =-32; does not decrement arr[i] by 32, but stores 32 into arr[i]. The combined assignment operator is spelled -=. You have the same problem for += in the other case.

  • Converting lower case to upper case by subtracting 32 works for ASCII, but is not portable to other character sets. Similarly, comparing to 'a' and 'z' works for ASCII, but not for EBCDIC. You should use the functions from <ctype.h>.

  • you read 100 characters with scanf("%c"...) but you do not check the return value, nor do you null terminate the array. Furthermore, you should read at most one less than the size of the array to leave space for the '\0' byte. As coded, your program invokes undefined behavior at printf("%s", arr); because arr is not null terminated.

Here is a corrected version:

#include <ctype.h>
#include <stdio.h>

int main(void) {
    int c;

    while ((c = getchar()) != EOF) {
        if (isupper(c))
            c = tolower(c);
        else
        if (islower(c))
            c = toupper(c);

        putchar(c);
    }
    return 0;   
}
chqrlie
  • 131,814
  • 10
  • 121
  • 189
  • +1 Okay tbh I really like this answer. Can I unselect the previous answer and select yours as the better one? Also, why are we declaring c as an int when we will take in characters? – Karan Singh Jan 27 '17 at 14:32
  • @KaranSingh: `c` is defined as `int` to handle all values returned by `getc()`: all values of `unsigned char` plus the special value `EOF`. The type `char` cannot properly handle all cases. `EOF` will either be the same as `'\377'` (`'ÿ'` in iso-latin1) or will never match. – chqrlie Jan 27 '17 at 16:30
2

The most obvious problem is that you are not null-terminating the string, so when you call printf("%s", arr) the behavior will be unpredictable.

Dave Costa
  • 47,262
  • 8
  • 56
  • 72
2

The problem with your code is that it never terminates the string. If you read 100 characters, and then you want to print them with %s in printf, you have to add a null terminator at the end, like this:

char arr[100+1]; // See +1
... // Reading code
arr[100] = '\0';

Note that library functions islower/isupper provide a portable, and a lot more readable, approach to testing character type. Similarly, tolower/toupper provide more information about your intentions to the reader of your code than simply adding and subtracting 32. Moreover, C code that uses these standard functions will work on systems with non-ASCII character encoding.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • what if my string isn't 100 letters long and I still want to terminate it. How do I do that? and there are a few comments I made under the question. – Karan Singh Jan 27 '17 at 13:46
  • @KaranSingh If you want to terminate the string at position `n`, use `arr[n] = '\0';` Writing zero at one position after the last char is all you need to do. – Sergey Kalinichenko Jan 27 '17 at 13:49
1

In order to printf("%s", arr), you need to terminate arr with a null-character.

One way to do it is by:

  • Declaring char arr[101]
  • Setting arr[100] = 0
barak manos
  • 29,648
  • 10
  • 62
  • 114
0

Your code has serveral issues: not-null-terminated input string, unproper lower/uppercase conversion and confusion with =- / -= and =+ / += operators.

Next code is based on yours:

As an alternative to get a null-terminated string it uses fgets() instead of scanf(), just for the example.

Also uses C library functions for avoiding issues with different charsets, simplifing the conditions and for upper/lower case operations.

Edited to improve code quality, as @chqrlie suggested in a comment.

#include <stdio.h>
#include <ctype.h>

int main()
{
    int i;  
    char arr[101];

    printf("Enter string: ");
    fgets(arr, sizeof(arr), stdin);;  
    for(i=0;i<strlen(arr); i++)  
    {
        int value = (unsigned char) arr[i]; // to properly use int parameters, as expected by ctype.h next functions
        if (isupper(value))
        {
            arr[i]=tolower(value);  
        }
        else {
            if (islower(value))
            {
                arr[i]=toupper(value);
            }
        }
    }  
    printf("%s", arr);  

    return 0;
}

Test it here.

MarcM
  • 2,173
  • 22
  • 32
  • -1 for using unsafe, obsolete function `gets()`. Furthermore, you use `tolower` and `toupper`, you should also use `islower()` and `isupper()` and cast the `char` argument as `(unsigned char)`. The disclaimer is a lame excuse, use `fgets()`. – chqrlie Jan 27 '17 at 14:11
  • @chqrlie, you're right. As mentioned before I first used gets() to keep the example simple. But I agree with you regarding the (bad) use of deprecated funtions. Edited to use a currently valid alternative. – MarcM Jan 27 '17 at 14:25
  • I removed the downvote. Note also the problem with signed char arguments to `islower()`, `isupper()` etc. – chqrlie Jan 27 '17 at 16:25
0
    #include <iostream>
#include<string>
using namespace std;
int main() {
    int i;
    string str;
    cin >> str;    //Reading input from STDIN
    // cout << "Input number is " << i << endl; // Writing output to STDOUT
    for(i=0;i<str.length();i++){
        if((str[i]>='A' && str[i]<='Z')||(str[i]>='a'&& str[i]<='z')){
            if(str[i]>='A' && str[i]<='Z'){
                str[i]=str[i]+32;
                // cout<<str[i];
            }
            
            else if(str[i]>='a' && str[i]<='z'){
                str[i]=str[i]-32;
            }
                
            cout<<str[i];   
        }
    }

}
ali
  • 1