2016-09-25 9 views
1

このプログラムに問題がありますが、stdinを使用すると完全に動作しますが、コマンドラインから文字を取得するために変更すると完全に動作します。私は何か間違っているのは分かっていますが、何が助けになるのか分かりません。C、argv []をコマンドライン引数として使用

説明とコード:

/* Program prints the date in this form: September 13, 2010 
    allow the user to enter date in either 9-13-2010 or 9/13/2010 
    format, otherwise print 'error' */ 

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

char *month(int m) 
{ 
    char *months[]={"January","February","March","April","May", 
       "June", "July","August","September","October", 
       "November","December"}; 
    return months[m-1]; 
} 

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

    int m=0,d=0,y=0; 

    FILE *fp; 

    if((fp=fopen(argv[1],"rb")) == NULL) 
    { 
     fprintf(stderr,"Couldn't open the file. "); 
     exit(EXIT_FAILURE); 
    } 


    printf("Type a date (mm-dd-yyyy) or (mm/dd/yyyy): \n"); 

    if(fscanf(fp,"%d%*[/-]%d%*[/-]%d",&m,&d,&y) != 3) //store characters in variables 
     { 
      fprintf(stderr, "Not properly formatted."); 
      exit(EXIT_FAILURE); 
     } 

    printf("%s %2d, %4d",month(m),d,y); 

    return 0; 
} 

を入力:

01/30/1990 

出力:

Couldn't open the file. 
+0

コンパイルされたプログラムをどのように呼び出すのですか? –

+1

私はCode Blocks IDEを使用して、プログラムの引数ウィンドウに01/30/1990とタイプしました。私もgccを使って実行しました。そして、 "システムはあなたが入力した日付を受け入れることができません"と言います。 "必要な特権はクライアントによって保持されていません"。 – tadm123

+2

'fopen(" 01/30/1999 "、" rb ")'は '01/30/1999'のパスでファイルを開こうとします。明らかに、そのようなファイルは存在しません。 –

答えて

2

は、私はあなたが持った(といくつか未定義の動作を修正するために、略して「UB」)問題を修正するようにプログラムを変更しますが、それだけで:変更

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

const char *month(int m) { 
    const char const *months[] = { 
     "January", "February", "March", "April", 
     "May", "June", "July", "August", 
     "September", "October", "November", "December", 
    }; 

    if (1 <= m && m <= 12) { 
     return months[m - 1]; 
    } else { 
     return NULL; 
    } 
} 

int main(int argc, char *argv[]) { 
    int m = 0, d = 0, y = 0; 

    if (argc == 2) { 
     if (sscanf(argv[1], "%d%*[/-]%d%*[/-]%d", &m, &d, &y) != 3) { 
      fprintf(stderr, "Not properly formatted."); 
      exit(EXIT_FAILURE); 
     } 

     printf("%s %2d, %4d", month(m), d, y); 
    } else { 
     fprintf(stderr, "Please provide one date argument to the program, formatted as mm-dd-yyyy or mm/dd/yyyy\n"); 
     exit(EXIT_FAILURE); 
    } 

    return 0; 
} 

何?

  • 返品タイプをmonth()に変更しました。その配列は文字列リテラルによってサポートされているので、将来のバージョンのプログラムで誤ってUBを修正することはできません。
  • month()に範囲チェックを導入しました。 mが小さすぎる場合(たとえば0/0/0)、大きすぎる場合(たとえば25/09/2016)、いくつかのUBを防止するときにnullポインタを返します。
  • ファイルのオープンに関するすべてのコードを削除しました。ファイル名に基づくファイルをargvに開くことを望まない場合は、argv[1]を文字列として使用したいだけです。
  • argv[1]が存在するかどうかをチェックしました。 argcのサイズはargvで、2の場合、argvにはプログラムの名前と最初のコマンドライン引数が含まれています。
  • ファイルから読み込むのではなく、コマンドライン引数を文字列として解析するので、fscanfsscanfに変更しました。
+0

これは素晴らしいです、ありがとう! – tadm123

0

ここでは、一般的な解決策を持っています。日付は、ファイル(fscanf)、コマンドライン(sscanf)または型付き(scanf)で渡すことができます。

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

char* month(int m) 
{ 
    char* months[] = { "January", "February", "March", "April", "May", 
     "June", "July", "August", "September", "October", 
     "November", "December" }; 
    return months[m - 1]; 
} 

int main(int argc, char* argv[]) 
{ 
    int m = 0, d = 0, y = 0; 

    FILE* fp; 

    int wrongFormat = 0; 

    if (argc > 1) 
    { 
     if ((fp = fopen(argv[1], "rb")) == NULL) 
     { 
      if (sscanf(argv[1], "%d%*[/-]%d%*[/-]%d", &m, &d, &y) != 3) 
       wrongFormat = 1; 
     } 
     else 
     { 
      if (fscanf(fp, "%d%*[/-]%d%*[/-]%d", &m, &d, &y) != 3) 
       wrongFormat = 1; 
     } 
    } 
    else 
    { 
     printf("Type a date (mm-dd-yyyy) or (mm/dd/yyyy): \n"); 
     if (scanf("%d%*[/-]%d%*[/-]%d", &m, &d, &y) != 3) 
      wrongFormat = 1; 
    } 

    if (wrongFormat) 
    { 
     fprintf(stderr, "Not properly formatted."); 
     exit(EXIT_FAILURE); 
    } 

    printf("%s %2d, %4d\n", month(m), d, y); 

    return 0; 
} 
+0

OPのコメントは、これが望むものではないことを示しています。「コマンドラインから入力を取得し、その情報を抽出して変数に入れるにはどうすればよいですか? –

+0

m、dおよびyは変数である。 –

+0

それはポイントではないです。 OPはコマンドライン*で指定されたファイルから*の代わりに*をコマンドラインから読み込みたい*。 –

関連する問題