2017-05-07 52 views
0

我與C.一些內置的功能的問題,基本上我試圖創建是我自己的Colpitts振盪器計算器這需要以下面的輸入作爲參數:電感值,電容值,第二電容值。與strtoll和分裂沒有返回正確的數字

輸入可以以F或H結尾,也可以使用前綴p,m,n和u來表示pico,milli,nano和micro。如果數字太大並且後綴將被附加到輸出,輸出也將被格式化。

插入調試printf語句後,我的程序出現問題,數字轉換不正確。

我已經使用的測試參數,如下面這個命令:

1p 2pF 3F 

這是我最初的輸出:

DEBUG Init proc: 1p      
DEBUG post proc: 0.000000    
DEBUG Init proc: 2p      
DEBUG post proc: 0.000000    
DEBUG Init proc: 3      
DEBUG post proc: 3.000000 

但DEBUG後PROC線除了最後一個錯誤。

我想看到的:

DEBUG Init proc: 1p      
DEBUG post proc: 0.000000000001    
DEBUG Init proc: 2p      
DEBUG post proc: 0.000000000002    
DEBUG Init proc: 3      
DEBUG post proc: 3.000000 

這是我的代碼:

#include <stdio.h> 
#include <math.h> 
#include <stdlib.h> 
int main(int argc,char* argv[]){ 
    if (argc < 4){ 
printf("Need 3 args: L, C1, C2. %d supplied\n",argc-1);return -1; 
    } 
    long double nums[4],f;long isnum; 
    int n=0; 
    for (n=1;n<4;n++){ 
//process each arg 
char *p=argv[n];while(*p != '\0'){p++;};p--; 
//strip last character if it's F, f, H, or h 
if (*p=='F' || *p=='f' || *p=='H' || *p=='h'){*p='\0';p--;} 
printf("DEBUG Init proc: %s\n",argv[n]); 
switch (*p){ 
    case '0': //do nothing if new last character is a number 
    break; 
    case 'p': //convert picounit to unit 
    *p='\0'; 
    nums[n]=strtoll(argv[n],NULL,10)/1000000000000ULL; 
    break; 
    case 'n': //convert nanounit to unit 
    *p='\0'; 
    nums[n]=strtoll(argv[n],NULL,10)/1000000000ULL; 
    break; 
    case 'u'://convert microunit to unit 
    *p='\0'; 
    nums[n]=strtoll(argv[n],NULL,10)/1000000ULL; 
    break; 
    case 'm'://convert milliunit to unit 
    *p='\0'; 
    nums[n]=strtoll(argv[n],NULL,10)/1000ULL; 
    break; 
    default: //do nothing if new last character is a number from 1 to 9 or print error if it isn't u,m,n or p. 
    isnum=strtol(p,NULL,10); 
    if (isnum < 1 || isnum > 9 || isnum=='\0'){ 
    printf("Number %d is in bad format. Use suffix of either: uH mH nH pH uF mF nF pF\n",n); 
    return -1; 
    } 
    nums[n]=strtoll(argv[n],NULL,10); 
} 
printf("DEBUG post proc: %Lf\n",nums[n]); 
    } 
    printf("Input values: %Lf,%Lf,%Lf\n",nums[1],nums[2],nums[3]); 
    //calculate frequency 
    f=1/(2*3.14159)*sqrt(nums[1]*((nums[2]*nums[3])/(nums[2]+nums[3]))); 
    char suf=' '; //prepare suffix to display frequency in user friendly format 
    if (f > 1000000){f=f/1000000;suf='M';} //convert to Mhz if f > 1000000 
    if (suf=='\0' && f > 1000){f=f/1000;suf='K';} 
    printf("Frequency = %Lf %c hz\n",f,suf); 
    return 0; 
} 

正如我只有一個32位處理器的工作,我覺得我的答案,這是有限的。我能做些什麼來糾正這個問題?

+1

你在做整數除法,因此例如'strtoll(argv [n],NULL,10)/ 1000000000000ULL'(可能)是0(一個int);將其轉換爲雙倍值,它將保持爲0.除以1000000000000.0而是強制浮點除法。 – Evert

+0

好的,我將.0添加到所有大數字中,並沒有幫助。 – Mike

+0

如果只給出'F'的參數,您的代碼將訪問出界 –

回答

2

首先 - 正如Evert所述 - 您正在做整數除法。編寫nums[n]=strtoll(argv[n],NULL,10)/(1000000000000.0);nums[n]=((double)strtoll(argv[n],NULL,10))/1000000000000ULL應該解決這個問題。

一旦你的數字是正確的,輸出可能是四捨五入到第6位小數:

C99§7.19.6.1的fprintf功能fF

表示A double說法浮點數轉換爲[−]ddd.ddd樣式的十進制表示法,其中小數點後面的位數等於精度規格。 如果精度丟失,則取爲6; ...

printf("DEBUG post proc: %1.15Lf\n",nums[n])你應該看到剩下的部分。

+0

1.15部分適合我。 – Mike

+1

在這樣的小數字的情況下,使用'e'格式化器可能更合適。 – Evert

+0

'nums [n] = strtoll(argv [n],NULL,10)/(1000000000000。0);也不是nums [n] =((double)strtoll(argv [n],NULL,10))/ 1000000000000ULL'有一個短暫來臨。商可以使用'double'數學計算,但結果存儲在'long double'中。建議'nums [n] = strtoll(argv [n],NULL,10)/ 1.0e12L'; – chux