2016-09-25 23 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

你是如何調用編譯好的程序的? – 2016-09-25 00:23:29

+1

我使用的代碼塊ide,我在程序參數窗口中鍵入01/30/1990,我也用gcc來運行它,它說「系統不能接受你輸入的日期」。 「所需特權不由客戶持有」。 – tadm123

+2

'fopen(「01/30/1999」,「rb」)'會嘗試打開一個路徑爲'01/30/1999'的文件。顯然,不存在這樣的文件。 – 2016-09-25 00:27:36

回答

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。
  • 我刪除了關於打開文件的所有代碼。您不希望根據argv中的文件名打開文件,只想將argv[1]用作字符串。
  • 我介紹了一個檢查,看看是否存在argv[1]argc包含argv的大小,如果它是2,argv包含該程序的名稱及其第一個命令行參數。
  • 此外,您不想從文件讀取,但將命令行參數解析爲字符串,因此我將fscanf更改爲sscanf
+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的評論顯示,這不是他們想要的:」我怎樣才能從命令行獲得輸入,然後提取信息以將它們放入變量?「 – 2016-09-25 08:27:03

+0

m,d和y是變量。 –

+0

這不是重點。 OP希望從命令行*讀取輸入*,而不是從命令行*中指定的文件讀取*。 – 2016-09-25 17:44:53