Home > Software engineering >  How to print a number with two dots in the C language?
How to print a number with two dots in the C language?

Time:12-28

The problem is when I run this code

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

int main()
{
    double motorcyclePrice;

    scanf("%f", &motorcyclePrice);

    printf("The motorcycle of the brand %s it's %lf.", motorcycleBrand, motorcyclePrice);

    return 0;
}

The output of the print if I put "1.000.000" it will be "1.000000", so how can I set the output to be the same as input? I tried it with int, float and double and still the same...

CodePudding user response:

the problem is that 1.000.000 is 1, you need to type 1000000

CodePudding user response:

You can read a line as a string, using the function fgets. Afterwards, you can convert it to a long int using the function strtol, or to a double using the function strtod. However, the function strtod will interpret a . in the number as a decimal point, not as digit grouping. The function strtol will treat such a character as an invalid character, and will stop trying to match a number.

Here is an example which uses the fgets to read one line of input as a string, and uses strtol to try to convert that string to an integer:

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

int main( void )
{
    char line[100], *p;

    //attempt to read one line of input
    if ( fgets( line, sizeof line, stdin ) == NULL )
    {
        printf( "input error!\n" );
        exit( EXIT_FAILURE );
    }

    //attempt to find newline character
    if ( (p=strchr(line,'\n')) == NULL )
    {
        printf( "line was too long\n" );
        exit( EXIT_FAILURE );
    }

    //remove newline character
    *p = '\0';

    //print back string to user
    printf( "You entered: %s\n", line );

    //attempt to convert string to "long int"
    long l = strtol( line, &p, 10 );

    //verify that conversion was successful
    if ( p == line )
    {
        printf( "unable to convert string to integer!\n" );
        exit( EXIT_FAILURE );
    }

    //print converted result
    printf( "The string was successfully converted to the following integer: %ld\n", l );
}

CodePudding user response:

In my earlier comment, I observed that you need a lot of things working in your favour to get the result you desire.

  • You need to set the locale to a locale other than the "C" or "POSIX" locale.
  • Using the empty string as the locale in a call to setlocale() means that the program should use the locale specified in the environment.
  • You need a locale that sets the 'radix character' (decimal point).
  • You need a locale that sets the 'grouping character'.
  • You need a version of printf() that recognizes the ' format modifier.
  • You also need a version of scanf() that permits the grouping character in the input, even though neither Standard C nor POSIX requires this.

So, the input parsing is extremely problematic — you need something other than Standard C scanf() to do that job.

You can generate the output if the locale is set up correctly.

Demo program:

#include <locale.h>
#include <stdio.h>

int main(void)
{
    double price;
    setlocale(LC_ALL, "");
    if (scanf("%lf", &price) != 1)
        return 1;
    printf("%'.2f\n", price);
    return 0;
}

On a Mac running macOS Catalina (10.15.7), with LANG=en_US.UTF-8 in the environment, I can enter 1234567.89 and get the output 1,234,567.89. It wasn't until I tried an exhaustive test of the locales in /usr/share/locale that I found some locales that use , as the decimal point and . as the grouping character — none of de_DE.UTF-8, fr_FR.UTF-8, es_ES.UTF-8, pt_PT.UTF-8, it_IT.UTF-8 set the grouping character.

My test program is called pr17.

$ for locale in $(cd /usr/share/locale; ls -d *.UTF-8)
> do echo "$locale: $(LANG=$locale ./pr17 <<< '1234567,89')"
> done
af_ZA.UTF-8: 1.234.567,89
am_ET.UTF-8: 1,234,567.00
be_BY.UTF-8: 1 234 567,89
bg_BG.UTF-8: 1 234 567,89
ca_ES.UTF-8: 1234567,89
cs_CZ.UTF-8: 1 234 567,89
da_DK.UTF-8: 1.234.567,89
de_AT.UTF-8: 1234567,89
de_CH.UTF-8: 1234567,89
de_DE.UTF-8: 1234567,89
el_GR.UTF-8: 1.234.567,89
en_AU.UTF-8: 1,234,567.00
en_CA.UTF-8: 1,234,567.00
en_GB.UTF-8: 1,234,567.00
en_IE.UTF-8: 1,234,567.00
en_NZ.UTF-8: 1,234,567.00
en_US.UTF-8: 1,234,567.00
es_ES.UTF-8: 1234567,89
et_EE.UTF-8: 1 234 567,89
eu_ES.UTF-8: 1234567,89
fi_FI.UTF-8: 1.234.567,89
fr_BE.UTF-8: 1234567,89
fr_CA.UTF-8: 1234567,89
fr_CH.UTF-8: 1234567,89
fr_FR.UTF-8: 1234567,89
he_IL.UTF-8: 1,234,567.00
hr_HR.UTF-8: 1234567,89
hu_HU.UTF-8: 1 234 567,89
hy_AM.UTF-8: 1 234 567,89
is_IS.UTF-8: 1 234 567,89
it_CH.UTF-8: 1234567,89
it_IT.UTF-8: 1234567,89
ja_JP.UTF-8: 1,234,567.00
kk_KZ.UTF-8: 1 234 567,89
ko_KR.UTF-8: 1,234,567.00
lt_LT.UTF-8: 1 234 567,89
nl_BE.UTF-8: 1234567,89
nl_NL.UTF-8: 1234567,89
no_NO.UTF-8: 1.234.567,89
pl_PL.UTF-8: 1 234 567,89
pt_BR.UTF-8: 1.234.567,89
pt_PT.UTF-8: 1234567,89
ro_RO.UTF-8: 1 234 567,89
ru_RU.UTF-8: 1 234 567,89
sk_SK.UTF-8: 1 234 567,89
sl_SI.UTF-8: 1234567,89
sr_YU.UTF-8: 1 234 567,89
sv_SE.UTF-8: 1 234 567,89
tr_TR.UTF-8: 1234567,89
uk_UA.UTF-8: 1 234 567,89
zh_CN.UTF-8: 1,234,567.00
zh_HK.UTF-8: 1,234,567.00
zh_TW.UTF-8: 1,234,567.00
$

The input string uses a comma; when the radix character is ., it means that the ,89 is left in the input for further processing.

Your mileage will vary. Let me know your operating system and C library if scanf() supports the grouping character in the input.

Note that you're not supposed to process the output of ls because of possible spaces, newlines and assorted other 'gotcha' characters that can appear in file names. However, I checked that it would be safe for me before using it. YMMV!

CodePudding user response:

It is not possible to have only 1 integer/float/double to have 2 dots. I recommend you to receive the input as a string and break it down into parts of integer/float/double then do your calculation or whatever then combine them together again into a string and output it. For example:

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

int main()
{
    char string[15];
    //get input
   scanf("%s", string); //type in 1.000.000
   //"." indicate the break
   char * token = strtok(string, ".");
   char partOfNumber[3][15];
   int i = 0;
   while( token != NULL ) {
      //assign parts to string separately
      strcpy(partOfNumber[i],token);
      token = strtok(NULL, ".");
      i  ;
   }
    //turn part into integer
    int number1 = atoi(partOfNumber[0]);
    int number2 = atoi(partOfNumber[1]);
    int number3 = atoi(partOfNumber[2]);
   //do calculation with the number or whatever...
   
   //now we combine them together again...
   return 0;
}

Do notice if you want it to assign 0 in the middle please use some loop/if-else statement to achieve.

  • Related