這可能是一個愚蠢的問題,但是......我試圖實作printf,但由于某種原因,我得到的輸出并不完全符合我的預期。知道它可能是什么嗎?我會很感激一些幫助。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdarg.h>
static int print(const char *restrict fmt, ...);
static int getfloat(float *);
static char *itoa(int, char *, int);
static void _strrev(char *);
int
main(void)
{
float i1 = 0.0, i2 = 0.0, noi1 = 0.0, noi2 = 0.0, res = 0.0;
print("weight - item 1: ");
getfloat(&i1);
print("no. of item 1: ");
getfloat(&noi1);
print("weight - item 2: ");
getfloat(&i2);
print("no. of item 2: ");
getfloat(&noi2);
res = ((i1 * noi1) (i2 * noi2)) / (noi1 noi2);
print("%f\n", res);
exit(EXIT_SUCCESS);
}
static int
print(const char *restrict fmt, ...)
{
va_list ap;
char buf[BUFSIZ] = {0}, tmp[20] = {0};
char *str_arg;
int i = 0, j = 0;
va_start(ap, fmt);
while (fmt[i] != '\0') {
if (fmt[i] == '%') {
i ;
switch (fmt[i]) {
case 'c':
buf[j] = (char)va_arg(ap, int);
j ;
break;
case 'd':
itoa(va_arg(ap, int), tmp, 10);
strcpy(&buf[j], tmp);
j = strlen(tmp);
break;
case 'f':
gcvt(va_arg(ap, double), 10, tmp);
strcpy(&buf[j], tmp);
j = strlen(tmp);
break;
case 's':
str_arg = va_arg(ap, char *);
strcpy(&buf[j], str_arg);
j = strlen(str_arg);
break;
default:
break;
}
} else { buf[j ] = fmt[i]; }
i;
}
fwrite(buf, j, 1, stdout);
va_end(ap);
return (j);
}
static int
getfloat(float *p)
{
int c, sign = 0;
float pwr = 0.0;
while (c = getc(stdin), c == ' ' || c == '\t' || c == '\n')
; /* ignore white spaces */
sign = 1; /* record sign */
if (c == ' ' || c == '-') {
sign = (c == ' ') ? 1 : -1;
c = getc(stdin);
}
for (*p = 0.0; isdigit(c); c = getc(stdin))
*p = 10.0 * *p c - '0';
if (c == '.') { c = getc(stdin); }
for (pwr = 1.0; isdigit(c); c = getc(stdin)) {
*p = 10.0 * *p c - '0';
pwr *= 10.0;
}
*p *= sign / pwr;
if (c != EOF)
ungetc(c, stdout);
return (float)c;
}
static char *
itoa(int n, char *strout, int base)
{
int i, sign;
if ((sign = n) < 0)
n -= n;
i = 0;
do {
strout[i ] = n % base '0';
} while ((n /= base) != 0);
if (sign < 0) { strout[i ] = '-'; }
strout[i] = '\0';
_strrev(strout);
return (strout);
}
static void
_strrev(char *str)
{
int i = 0, j = strlen(str) - 1;
for ( ; i < j; i, --j) {
int tmp = str[i];
str[i] = str[j];
str[j] = tmp;
}
}
這是我得到的輸出:19.44444466
這是我期望的輸出:(或者我至少希望收到的輸出,這本身就是我使用 printf 時得到的輸出)
19.444445
uj5u.com熱心網友回復:
f, F The double argument is rounded and converted to decimal notation in the style [-]ddd.ddd, where the number of digits after the decimal-point character is equal to the precision specification. If the precision is missing, it is taken as 6;
https://man7.org/linux/man-pages/man3/printf.3.html
的默認精度為%f六,因此printf()將結果四舍五入到小數點后六位。
您需要使用有效數字總數(小數點之前和之后)的ndigit引數。gcvt()您正在傳遞,10因此您的答案在小數點前有兩位數,在這個特定數字后有八位。
uj5u.com熱心網友回復:
至少對于您的編譯器,似乎gcvt()并沒有完全做到這一點。用具有相同值printf()的“真實”檢查它。printf
由于您沒有提供用于測驗的數字(避免getfloat()并直接初始化i1,和在您的問題i2中使用所需的常量),我無法運行它并告訴您確切的原因 - 或者它甚至發生在我自己的編譯器中.noi1noi2
通常,源代碼printf至少比你的大兩倍,所以你可能錯過了一些惡性子案例。如果我沒記錯的話,printf有代碼可以直接解碼 IEEE-754 并且不依賴gcvt.
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/448211.html
標籤:C
