2016-11-16 25 views
0

問題があります。私はtool.cの機能を必要とする回数だけループする必要があります。それは入力全体をループした後停止します。私の先生は2番目の議論に合格しなければならないと言ったが、授業は終わったし、どのように見えるべきかわからない。例えばループ回数を設定する

main.cの

#include <stdio.h> 
#include <stdlib.h> 
#include "tools.h" 

int main(int argc, char *argv[]) { 
    int count[256] = { 0 }; 
    int c; 
    while ((c=getchar())!=EOF){ 
     count[c]++; 
    } 
    switch (argc > 1 && argv[1][1]) { 
    case 'm': case 'M': 
     mostOften(count); 
     break; 
    case 'l': case 'L': 
     leastOften(count); 
     break; 
    default: 
     mostOften(count); 
     break; 
    } 
    return 0; 
} 

tools.c

#include <stdio.h> 
#include <stdlib.h> 
#include <limits.h> 
#include "tools.h" 

void mostOften(int *s) { 
    int j, a = 0; 
    int max=0, cha; 
    for(j=32; j<126; j++){ 
     if(s[j]>max) { 
       max=s[j]; 
       cha=j; 
     } 
    a++; 
    } 
    printf("char %c: %d times\n", cha, max); 
} 

void leastOften(int *s) { 
    int j, a = 0; 
    int min=INT_MAX, cha; 
    for(j=32; j<126; j++){ 
     if(s[j] && s[j]<=min) { 
       min=s[j]; 
       cha=j; 
     } 
    a++; 
    } 
    printf("char %c: %d times\n", cha, min); 
} 

I入力

段落

01もし

私は基本的に私は

+3

ケース 'm':ケース 'M': 'を別の行に入れてください。 –

+2

'switch(argc> 1 && argv [1] [1]){'は(argc> 1)switch(argv [1] [1]){' – BLUEPIXY

+0

を編集してください。入力と期待される出力。 –

答えて

0

あなたの主なプログラムは、まず、ほとんどのいずれかのためにそれを検索し、入力中に表示される文字のヒストグラムを作成し、ループを停止するなステートメント場合は、いくつかを設定する必要があり、ループにのみ9回それをしたいです頻繁または最低頻度の印刷可能な文字。

この2番目のループ(検索フェーズ)を回避するには、文字が読み込まれるたびに、最も頻繁にまたは最も頻繁な文字のインデックスを徐々に更新する必要があります。ここで

は一例です:

#include <ctype.h> 
#include <limits.h> 
#include <stdio.h> 
#include <stdlib.h> 

int main() 
{ 
    int count[256] = { 0 }; 
    int c; 
    int index_min = -1; 
    int min = INT_MAX; 
    int index_max = -1; 
    int max = INT_MIN; 

    while ((c = getchar()) != EOF) { 
     if (isprint (c)) { 
      count[c]++; 

      // update min 
      if (count[c] < min) { 
       min = count[c]; 
       index_min = c; 
      } 

      // update max 
      if (count[c] > max) { 
       max = count[c]; 
       index_max = c; 
      } 
     } 
    } 

    printf ("least common printable char: "); 
    if (index_min != -1) { 
     printf ("`%c` (%d times)\n", index_min, min); 
    } 
    else { 
     printf ("N/A\n"); 
    } 

    printf ("most common printable char: "); 
    if (index_max != -1) { 
     printf ("`%c` (%d times)\n", index_max, max); 
    } 
    else { 
     printf ("N/A\n"); 
    } 

    return 0; 
} 
+0

'int count [256] = {0};の配列の初期化には何も問題はありません;' for'ループで置き換えることは効果がありません(ただし、 –

0

あなたは問題のセットアップを持っているかを見てから、あなたが入力の一部である文字、および周波数を保持する配列上の反復が混乱しているように見えます読み込まれた文字の

コードを読みやすくするために、コードにマジックナンバーを使用しないでください。 32および126。代わりに、表示しようとしている文字を使用してください。 スペース)および~チルド)である。

for(j=32; j<126; j++){ 
あなたが使用することができ

を::

for(j = ' '; j < '~'; j++){ 

あまりにもそれが落とし穴だ持っていることたとえば、代わりに使用します。どうして?文字をループしたくない場合は、実際には各文字が入力に出現する頻度を保持する配列countの要素をループします。言い換えれば、あなたの入力に各文字が出現する頻度を保持する最小の95の整数を保持する配列が必要です。文字がどのようになるかを知っているので、32126の後ろに隠してはいけません。tools.hに配列サイズの定数(ARSZなど)を宣言してください。

#define ARSZ 95 

は、その後、あなたの入力を読み取り、count配列を充填した後、それはmostoftenまたはleastoftenいずれかの番号を取得するには、一度count配列を反復処理するだけです。さらに、countの要素数の定数があるため、countのサイズをmostoftenleastoftenに渡す必要はありません。存在する要素の数はすでに知っています(95)。

(配列のサイズが一定でない場合(のヌル終了文字列のようなセンチネルを持つ配列を渡さない場合)または数値コンパイル時に配列のサイズを渡す必要があります。

(また、Cは一般的に変数名にすべて小文字を使用しますが、通常は表示されませんMixedCaseまたはcamelCase Cの変数名はC++のままにしてください)

次に、コマンドライン引数の処理にgetoptを使用する必要がありますが、問題の引数の2番目の文字を確認するのは簡単ですが、チェックするには少なくとも1つの引数があることを検証する必要があります。引数が空文字列ではありません。基本的には、チェックしたい:

if (argc > 1 && *argv[1]) /* check argc & not empty-string */ 
    switch (argv[1][1]) { 
     case 'm': 
      mostoften (count); 
      break; 
     case 'M': 
      mostoften (count); 
      break; 
     case 'l': 
      leastoften (count); 
      break; 
     case 'L': 
      leastoften (count); 
      break; 
     default: 
      fprintf (stderr, "warning: unrecognized option, using 'mostoften'.\n"); 
      mostoften (count); 
    } 
else { 
    fprintf (stderr, "warning: no option given using 'mostoften'.\n"); 
    mostoften (count); 
} 

ノートを:あなたは、任意の単一の場合のために2つの一定の条件を置くことができないあなたのswitch(いくつかのコンパイラは非標準の拡張機能を提供)。また、defaultの場合にはbreakは必要ありません。フォールスルーはありません。

あなたが書くことができ、完全にそれを置くあなたのtools.h類似した:

#include <stdio.h> 
#include <limits.h> 

#define ARSZ 95 

int mostoften (int *a); 
int leastoften (int *a); 

あなたtools.cとして:

#include "tools.h" 

int mostoften (int *a) { 

    int i, max = INT_MIN, cha = '0'; 

    for (i = 0; i < ARSZ; i++) 
     if (a[i] > max) { 
      max = a[i]; 
      cha = i + ' '; 
     } 

    printf ("char '%c' : %d times\n", cha, max); 

    return max; 
} 

int leastoften (int *a) { 

    int i, min = INT_MAX, cha = '0'; 

    for (i = 0; i < ARSZ; i++) 
     if (a[i] < min) { 
      min = a[i]; 
      cha = i + ' '; 
     } 

    printf ("char '%c' : %d times\n", cha, min); 

    return min; 
} 

あなたは知っているmaxまたはminは、2種類の文字のために同じである場合最初の文字を選択し、leastoftenの場合は、常に0の周波数の最初の文字を選択します。この問題を解決するには、入力に存在する文字を追跡し、その文字の頻度のみを考慮する2番目の配列(または2次元配列または構造体)を保持する必要があります。

最後に、あなたのmain.cのようなものに書くことができますがあり、このタスクを達成するためにさまざまな方法がありますが、あなたの最初のコードを考えると、これはあなたの意図のように見えるものに保つ

#include "tools.h" 

int main (int argc, char **argv) { 

    int c = 0, count[ARSZ] = {0}; 

    while ((c = getchar()) != EOF) 
     if (' ' <= c && c <= '~') 
      count[c - ' ']++; 

    if (argc > 1 && *argv[1]) /* check argc & not empty-string */ 
     switch (argv[1][1]) { 
      case 'm': 
       mostoften (count); 
       break; 
      case 'M': 
       mostoften (count); 
       break; 
      case 'l': 
       leastoften (count); 
       break; 
      case 'L': 
       leastoften (count); 
       break; 
      default: 
       fprintf (stderr, "warning: unrecognized option, using " 
           "'mostoften'.\n"); 
       mostoften (count); 
     } 
    else { 
     fprintf (stderr, "warning: no option given using 'mostoften'.\n"); 
     mostoften (count); 
    } 

    return 0; 
} 

を。あなたが何か質問がある場合はそれを見て、私に知らせてください。構造体を使用せずに入力内の文字を追跡する最も簡単な方法をご希望の場合は、countcount[ARSZ][2]と単純に宣言し、追加要素を使用して文字が存在することを示します。 (配列に関数int a[][2]またはint (*a)[2]として渡すことができます)幸運。

関連する問題