Comparing Char with == and single quote gives warning

76 Views Asked by At

I am writing a program to calculate cosines and I should read the user input for angles given in degree (°) or radians (r). If the angle were to be given in degrees, it should be converted into radians (hence I used the if-else statement). However, when I compare char with == and single quote I get the following warning:

warning: multi-character character constant [-Wmultichar]
if((unit != '°') && (unit != 'r'))

This is my full code:

#include<stdio.h>
#include<stdlib.h>
#include<math.h>

// Prototype
void calc_cos(double, char);

int main (void)
{
    double angle;
    char unit;
    printf("PLease give an angle and its unit in degrees (°) or radians (r) for cosinus calculation\n");
    if((unit != '°') && (unit != 'r'))
    {
        printf("ERROR. Unit is not in '°' or 'r'. Aborting...\n");
        return 0;
    }
    else
    {
    scanf("%lf %c", &angle, &unit);
    calc_cos(angle, unit);
    }
    return 0;
}

void calc_cos(double angle, char unit)
{
    double results=0;
    if(unit == '°')
    {
        angle = angle*M_PI/180;
    }
    else if(unit == 'r')
    {
        angle = angle;
    }
    results = cos(angle);
    printf("cos(%lf rad) = %lf\n", angle, results);
}
2

There are 2 best solutions below

0
On BEST ANSWER

As others have indicated in the comments, the degree (°) character is not encoded as a single byte in the ASCII system; rather, it is interpreted by the compiler as a sequence of (probably) two bytes.

There are various ways around this. One would be to use the wchar_t type for your unit variable, and the corresponding wide literals for the comparisons (L'°' and L'r', in place of '°' and 'r'); however, this would require changing (at least) your scanf call to use the %lc format specifier, but you would almost certainly be better of, in that case, using the wprintf and wscanf "wide-character" versions of the standard I/O functions.

However, even with such changes, you are likely to encounter problems reading the ° character in a console application, as there are numerous different encoding systems that can be used. So, in my opinion, you would be better off using a simple letter d to specify units of degrees.

Also, even with any of these fixes, there are some other issues in your code. The most notable is that you are testing the unit variable before it has been given. Code with this corrected, plus a few other suggested improvements (and using the d for degrees) is shown below:

#include <stdio.h>
#include <stdlib.h>
#define _USE_MATH_DEFINES /// Many compilers require this to give the "M_PI" definition
#include <math.h>

// Prototype
void calc_cos(double, char);

int main(void)
{
    double angle;
    char unit;
    printf("Please give an angle and its unit in degrees (d) or radians (r) for cosinus calculation\n");
    scanf("%lf %c", &angle, &unit); /// MUST read "unit" BEFORE testing it!
    if ((unit != 'd') && (unit != 'r')) {
        printf("ERROR. Unit is not in 'd' or 'r'. Aborting...\n");
        return 0;
    }
    calc_cos(angle, unit);
    return 0;
}

void calc_cos(double angle, char unit)
{
    double results = 0;
    if (unit == 'd') {
        angle = angle * M_PI / 180;
    }
//  else if (unit == 'r') { /// This block is unnecessary
//      angle = angle;
//  }
    results = cos(angle);
    printf("cos(%lf rad) = %lf\n", angle, results);
}

Please feel free to ask for any further clarification and/or explanation.

0
On

In C a char is one byte but the degrees sign typically needs more than one byte, at least in the UTF-8 character encoding. One solution is to store the unit in a character array instead, like this:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void)
{
    char unit[4 + 1];
    int count;

    count = scanf("%4s", unit);
    if (count == 1) {
        if (strcmp(unit, "°") == 0) {
            puts("degrees chosen");
        } else if (strcmp(unit, "r") == 0) {
            puts("radians chosen");
        } else {
            fprintf(stderr, "invalid unit: %s\n", unit);
            exit(EXIT_FAILURE);
        }
    }
    return 0;
}

A UTF-8 character is one to four bytes long and the format specifier %4s makes sure that at most four bytes are read.

However, a simpler approach is to instead use the letter "d" for degrees.