printf에서 선행 0을 숨기는 방법
다음과 같은 결과0.23
. 간단히 출력하려면 어떻게 해야 합니까?.23
?
printf( "%8.2f" , .23 );
C 표준에는 다음과 같이 나와 있습니다.f
그리고.F
부동 소수점 형식 지정자:
소수점 문자가 나타나면 그 앞에 한 자리 이상의 숫자가 나타납니다.
소수점 앞에 0이 나타나지 않으려면 사용과 같은 작업을 해야 할 것 같습니다.snprintf()
숫자를 문자열로 포맷하고 제거합니다.0
형식이 지정된 문자열이 "0"으로 시작하는 경우(그리고 "-0"도 마찬가지).그러면 형식화된 문자열을 실제 출력으로 전달합니다.아니면 그런 비슷한 것.
를 사용해서만 할 수 있는 것은 아닙니다.printf
. 에 대한 설명서printf
다음과 같이 말합니다.
f - "double" argument is output in conventional form, i.e.
[-]mmmm.nnnnnn
The default number of digits after the decimal point is six,
but this can be changed with a precision field. If a decimal point
appears, at least one digit appears before it. The "double" value is
rounded to the correct number of decimal places.
소수점이 나타나면 그 앞에 적어도 하나의 숫자가 나타납니다.
따라서 자신의 서식을 직접 코드화해야 할 것 같습니다.
필요한 정확도를 가진 정수로 변환하기만 하면 됩니다.
double value = .12345678901; // input
int accuracy = 1000; // 3 digit after dot
printf(".%03d\n", (int)(value * accuracy) );
출력:
.123
double f = 0.23;
assert(f < 0.995 && f >= 0);
printf(".%02u\n" , (unsigned)((f + 0.005) * 100));
#include <stdio.h>
static void printNoLeadingZeros(double theValue)
{
char buffer[255] = { '\0' };
sprintf(buffer, "%.2f", theValue);
printf("%s\n", buffer + (buffer[0] == '0'));
}
int main()
{
double values[] = { 0.23, .23, 1.23, 01.23, 001.23, 101.23 };
int n = sizeof(values) / sizeof(values[0]);
int i = 0;
while(i < n)
printNoLeadingZeros(values[i++]);
return(0);
}
스탠다드 C 도서관에서는 이것을 제공하지 않기 때문에 직접 작성하셔야 합니다.이것은 드문 일회성 요구사항이 아닙니다.후행 0을 다듬고 수천 개의 구분자를 추가하려면 조만간 유사한 함수를 작성해야 합니다.따라서 원하는 출력 바이트를 얻을 수 있을 뿐만 아니라 강력한 라이브러리를 작성하는 방법을 보다 일반적으로 설명하는 것이 좋습니다.이 작업을 수행할 때는 다음 사항을 유의해야 합니다.
어떻게 부를지 생각해 보세요.이런 것은 한 번 쓰고 백만 번 전화하는 것이니, 가능한 한 쉽게 전화를 걸도록 하세요.
그런 다음 당신이 생각할 수 있는 모든 대안을 연습하는 테스트 스위트를 만듭니다.
그렇게 하는 동안 문제를 더 이상 풀어서 다시는 그 문제로 돌아가지 않도록 하세요(예: 폭, 정밀도를 하드코드하지 말고 계속해서 리딩 플러스, e-포맷 등을 위한 버전을 만들어 보세요).
스레드를 사용하지 않더라도 스레드에서 안전하게 사용할 수 있습니다(실제로 포인트 3의 특정 경우).
거꾸로 작업하기:스레드 안전을 위해서는 스택에 저장소를 할당해야 하며, 이 작업은 호출자가 수행해야 합니다.이것은 예쁘지도 않고 재미도 없지만 그냥 익숙해지세요.C 방식입니다.형식은 너비, 정밀도, 일부 플래그 및 변환 유형(f, e, g)을 가질 수 있습니다.폭과 정밀도 파라미터를 만들어 보겠습니다.퍼블릭 API를 완전히 파라미터화하는 것보다는 함수 이름에 어떤 플래그와 변환 유형을 사용하는지를 나타내는 엔트리 포인트를 여러 개 가지고 있겠습니다.
불만은 버퍼를 기능에 전달할 때 기능의 크기를 알아야 한다는 것입니다.하지만 별도의 파라미터를 만들면 1) 발신자가 작성해야 하고 2) 발신자가 틀릴 수 있기 때문에 불편합니다.그래서 저의 개인 스타일은 버퍼를 포인터가 아닌 문자 배열로 가정하고 ()의 크기를 사용하여 크기를 취하는 함수의 더 자세한 버전으로 전달하는 마스킹 매크로를 만드는 것입니다.
여기 제가 생각해낼 수 있는 가장 간단한 방법과 시험 사례가 있습니다.
(참고 COUNT()는 배열의 요소 수를 얻기 위해 수십 년 동안 매주 사용해 온 매크로입니다.표준 C, 이런 것이 있어야 합니다.)
(참고로 저는 여기서 "헝가리어 표기법"의 방언을 사용합니다."d"는 두 배입니다."a"는 "array of"입니다. "sz"는 NUL 종단 문자열 버퍼이고 "psz"는 1을 가리키는 포인터입니다.이 둘의 차이점은 "sz"가 COUNT() 또는 크기가 ()인 경우 배열 크기를 얻을 수 있는 반면 "psz"는 그렇지 않다는 것입니다."i"는 정수이고 특정 변수 "i"는 루프에 사용됩니다.
double ad[] = { 0.0, 1.0, 2.2, 0.3, 0.45, 0.666, 888.99,
-1.0, -2.2, -0.3, -0.45, -0.666, -888.99 };
char szBuf[20];
for ( int i = 0; i < COUNT( ad ); i++ )
printf( "%s\n", NoLeadingZeroF( 4, 2, ad[i], szBuf ) );
for ( int i = 0; i < COUNT( ad ); i++ )
printf( "%s\n", NoLeadingZeroPlusF( 4, 2, ad[i], szBuf ) );
이제 "f" 버전과 "+f" 버전이 매우 유사해 보이므로 둘 다 내부 함수를 부르도록 합시다.버퍼크기를 취하는 함수들과 그것을 스스로 계산하는 매크로들이 있습니다. (병렬함수는 e, g 형식의 경우에도 쓰입니다.)
char* NoLeadingZeroFN( int iWidth, int iPrecision, double d, char* szBuf, int iBufLen ) {
return NoLeadingZeroFmtN( "%*.*f", iWidth, iPrecision, d, szBuf, iBufLen );
}
char* NoLeadingZeroPlusFN( int iWidth, int iPrecision, double d, char* szBuf, int iBufLen ) {
return NoLeadingZeroFmtN( "%+*.*f", iWidth, iPrecision, d, szBuf, iBufLen );
}
#define NoLeadingZeroF( width, precision, number, buf ) \
NoLeadingZeroFN( ( width ), (precision ), ( number ), ( buf ), sizeof( buf ) )
#define NoLeadingZeroPlusF( width, precision, number, buf ) \
NoLeadingZeroPlusFN( ( width ), (precision ), ( number ), ( buf ), sizeof( buf ) )
마지막으로 일을 하는 (내부) 기능.snprintf()는 Windows에서는 미리 지정된 밑줄이 필요하지만 Unix에서는 필요하지 않습니다.
char* NoLeadingZeroFmtN( char* szFmt, int iWidth, int iPrecision, double d, char* szBuf, int iBufLen ) {
#ifdef WIN32
_snprintf( szBuf, iBufLen - 1, szFmt, iWidth, iPrecision, d );
#else
snprintf( szBuf, iBufLen - 1, szFmt, iWidth, iPrecision, d );
#endif
// Some snprintf()'s do not promise to NUL-terminate the string, so do it ourselves.
szBuf[ iBufLen - 1 ] = '\0';
// _snprintf() returns the length actually produced, IF the buffer is big enough.
// But we don't know it was, so measure what we actually got.
char* pcTerminator = strchr( szBuf, '\0' );
for ( char* pcBuf = szBuf; *pcBuf && *pcBuf != '.'; pcBuf++ )
if ( *pcBuf == '0' ) {
memmove( pcBuf, pcBuf + 1, pcTerminator - pcBuf );
break;
}
return szBuf;
}
출력은 다음과 같습니다.
.00
1.00
2.20
.30
.45
.67
888.99
-1.00
-2.20
-.30
-.45
-.67
-888.99
+.00
+1.00
+2.20
+.30
+.45
+.67
+888.99
-1.00
-2.20
-.30
-.45
-.67
-888.99
추가 테스트를 통해 기능이 너무 작은 버퍼에서 작동하는지 확인해야 합니다.
쉬운 해결책이 없어 보입니다.저는 아마 아래와 같은 코드를 사용할 것입니다.가장 빠른 방법은 아니지만 다양한 형식으로 작동해야 합니다.문자 수와 점의 위치도 보존합니다.
#include <stdio.h>
void fixprint(char *s)
{
size_t i;
i = 1;
while (s[i]=='0' || s[i]==' ' || s[i]=='+' || s[i]=='-') {
if (s[i]=='0') s[i]=' ';
i++;
}
}
int main()
{
float x = .23;
char s[14];
sprintf(s,"% 8.2f",x);
fixprint(s);
printf("%s\n",s);
}
작업은 하여 수행할 수 .printf()
그럼 어떻게 완벽하게 해낼 수 있을까요?
이것이 제 해결책입니다.
sprintf()
=>=>=float
.string
.
#include <stdio.h>
#include <string.h>
int main()
{
char result[50];
float num = 0.23;
sprintf(result, "%.2f", num);
char *str = result;
int n = strspn(str, "0" );
printf("Trimmed string is %s ", &str[n]);
return 0;
}
산출량
Trimmed string is .23
언급URL : https://stackoverflow.com/questions/2595738/how-to-hide-leading-zero-in-printf
'programing' 카테고리의 다른 글
Sping-Boot 구성:맵 채우기에 사용되는 yaml 키의 공백을 유지하는 방법 (0) | 2023.09.26 |
---|---|
jQuery에서 프로그래밍과 사용자 클릭을 구분하려면 어떻게 해야 합니까? (0) | 2023.09.26 |
Oracle의 PERCENTILE_CONT 함수의 PostgreSQL 등가물 (0) | 2023.09.26 |
MySQL 쿼리 캐싱을 비활성화하는 방법 (0) | 2023.09.26 |
길이가 있는 안전하지 않은 포인터를 Swift Array 유형으로 변환 (0) | 2023.09.26 |