2017-05-07 11 views
0

私はCの組み込み関数に問題があります。基本的に私が作成しようとしているのは、次の入力を引数として順番に取る独自のcolpitts発振器です:コンデンサ値、第2のコンデンサ値。strtollとdivisionが正しい数値を返さない

入力はFまたはHで終わることができ、pico、milli、nano、およびmicroを表す接頭辞p、m、n、およびuを持つこともできます。数値が大きすぎて接尾辞が追加されると、出力もフォーマットされます。

デバッグ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

[OK]を、すべての大きな数値に.0を追加し、それが役立たない。 – Mike

+0

'F'の引数が与えられた場合、あなたのコードは範囲外にアクセスします –

答えて

2

まず、Evertが述べたように、整数分割をしています。 nums[n]=strtoll(argv[n],NULL,10)/(1000000000000.0);またはnums[n]=((double)strtoll(argv[n],NULL,10))/1000000000000ULLと書くと、このトピックが解決されます。

あなたの数字が正しいならば、出力はおそらく第六小数点第2位を四捨五入します

C99§7.19.6.1fprintf機能fF

表すdouble引数浮動小数点数はスタイル[−]ddd.dddの10進表記に変換されます。小数点文字の後の桁数は精度指定と等しくなります。 精度が不足している場合は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'には短い時間があります。商は「二重」算術を用いて計算することができるが、結果は「長い二倍」に記憶される。 'nums [n] = strtoll(argv [n]、NULL、10)/ 1.0e12L'を提案してください。 – chux

関連する問題