C语言如何打印两个点的数字?

How to print a number with two dots in the C language?

问题是当我运行这段代码

#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;
}

如果我输入“1.000.000”,打印的输出将是“1.000000”,那么如何将输出设置为与输入相同?我用 int、float 和 double 试过了,还是一样...

问题是1.000.000是1,需要输入1000000

您可以使用函数 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. You may be able to change the behavior of these functions to suit your needs by changing the locale 将一行作为字符串读取,但是,这是特定于平台的功能,这意味着它可能适用于一种编译器,但不适用于另一种编译器。

如果 . 应该表示数字分组,并且您希望它被接受为输入,那么最可靠的解决方案可能是使用 fgets 读取一行输入,然后在尝试使用 strtol.

将字符串转换为 long int 之前,丢弃 . 数字组分隔符

如果在将数字转换为 lont int 后,您希望数字以 3 个为一组打印,并带有 . 分隔符,那么最好创建您自己的函数这样做。

这是一个执行上述所有操作的示例程序:

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

#define MAX_LINE_SIZE 100

void print_with_group_separation( long );

int main( void )
{
    char line[MAX_LINE_SIZE];
    char line_without_separators[MAX_LINE_SIZE];
    char *p, *q;

    //prompt user for input
    printf( "Please enter an integer: " );

    //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 = '[=10=]';

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

    //copy line while discard group separating characters
    p = line;
    q = line_without_separators;
    do
    {
        if ( *p != '.' )
            *q++ = *p;

    } while ( *p++ != '[=10=]' );

    //print string after removing separators
    printf( "String after removing separators: %s\n", line_without_separators );

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

    //verify that conversion was successful
    if ( p == line_without_separators )
    {
        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 );

    //print the same number with group separation
    printf( "The same number with group separation: " );
    print_with_group_separation( l );
    printf( "\n" );
}

//NOTE: This function assumes that "num" is not negative. It won't
//attempt to create more than 4 groups of digits, because ISO C
//only requires "long int" to be able to represent
//numbers up to 2,147,483,647.
void print_with_group_separation( long num )
{
    long quotient;
    long remainder;
    bool has_printed = false;

    //calculate billions
    quotient  = num / 1000000000;
    remainder = num % 1000000000;

    //print billions
    if ( quotient != 0 )
    {
        printf( "%ld.", quotient );
        has_printed = true;
    }

    //calculate millions
    quotient  = remainder / 1000000;
    remainder = remainder % 1000000;

    //print millions
    if ( has_printed || quotient != 0 )
    {
        if ( has_printed )
            printf( "%03ld.", quotient );
        else
            printf( "%ld.", quotient );

        has_printed = true;
    }

    //calculate thousands
    quotient  = remainder / 1000;
    remainder = remainder % 1000;

    //print thousands
    if ( has_printed || quotient != 0 )
    {
        if ( has_printed )
            printf( "%03ld.", quotient );
        else
            printf( "%ld.", quotient );

        has_printed = true;
    }

    //print remainder
    if ( has_printed )
        printf( "%03ld", remainder );
    else
        printf( "%ld", remainder );
}

这个程序有以下输出,使用问题的输入:

Please enter an integer: 1.000.000
You entered the string: 1.000.000
String after removing separators: 1000000
The string was successfully converted to the following integer: 1000000
The same number with group separation: 1.000.000

这个程序也适用于不同的输入:

Please enter an integer: 324.112.532
You entered the string: 324.112.532
String after removing separators: 324112532
The string was successfully converted to the following integer: 324112532
The same number with group separation: 324.112.532

不可能只有1个integer/float/double就有2个点。我建议您以字符串形式接收输入并将其分解为 integer/float/double 的部分,然后进行计算或其他任何操作,然后将它们再次组合成一个字符串并输出。例如:

#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;
}

请注意,如果你想让它在中间分配0,请使用一些loop/if-else语句来实现。

在我之前的 中,我观察到您需要很多对您有利的事情才能获得您想要的结果。

  • 您需要将语言环境设置为 "C""POSIX" 语言环境以外的语言环境。
  • 在对 setlocale() 的调用中使用空字符串作为语言环境意味着程序应使用环境中指定的语言环境。
  • 您需要一个设置 'radix character'(小数点)的语言环境。
  • 您需要一个设置 'grouping character'.
  • 的语言环境
  • 您需要一个能够识别 ' 格式修饰符的 printf() 版本。
  • 您还需要允许输入中的分组字符的 scanf() 版本,即使标准 C 和 POSIX 都不需要这样做。

所以,输入解析是非常有问题的——你需要标准 C 以外的东西 scanf() 来完成这项工作。

如果语言环境设置正确,您可以生成输出。

演示程序:

#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;
}

在 Mac 运行 macOS Catalina (10.15.7) 上,在环境中使用 LANG=en_US.UTF-8,我可以输入 1234567.89 并获得输出 1,234,567.89.直到我尝试对 /usr/share/locale 中的语言环境进行详尽测试后,我才发现一些使用 , 作为小数点并使用 . 作为分组字符的语言环境 — none of de_DE.UTF-8, fr_FR.UTF-8, es_ES.UTF-8, pt_PT.UTF-8, it_IT.UTF-8 设置分组字符。

我的测试程序叫做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
$

输入的字符串使用逗号;当基数字符为 . 时,意味着 ,89 留在输入中以供进一步处理。

你的里程会有所不同。如果 scanf() 支持输入中的分组字符,请告诉我您的操作系统和 C 库。

请注意,您不应处理 ls 的输出,因为文件名中可能出现空格、换行符和其他各种 'gotcha' 字符。但是,我在使用它之前检查过它对我来说是安全的。 YMMV!