2015-02-08 62 views
0

我一直在爲學校編寫一個C++代碼項目,它希望我從命令行參數中讀取文本文件,並輸出它,並添加命令中聲明的形容詞在任何文章之後行[a,an,the]。這是我第一次爲任何項目使用命令行。在C++程序中讀取命令行參數時出現內存錯誤

我已經設法從命令行讀取文本文件,但我的問題是當我想要獲取字符串作爲函數isArticle()的參數時,我一直在UNIX shell中收到以下消息:

./test-program1[38]: eval: line 1: 7704: Memory fault 
0a1,4 

我不懷疑問題出在isArticle()功能,但在這裏它是:

bool isArticle(string n) 
{ 
    string article[]={"a","an","the","A","An","aN","AN","The","tHe","thE","THe","tHE","ThE","THE"}; 

    for(int i=0;i<sizeof(article);i++) 
    { 
     if(n.compare(article[i])==0) 
      return true; 
    } 

    return false; 
} 

雖然它不是完整的,下面是我用它來查看是否isArticle一些測試代碼()函數正在工作:

int main(int argc, char *argv[]) 
{ 
    istream *br; 
    ifstream file; 

    if(argc == 1) 
     br = &cin; 
    else if(argc==3) 
    { 
     file.open(argv[2]); 
     if(file.is_open())//put work here 
     { 
      br=&file; 
      string word; 
      string output[sizeof(file)]; 
      while(file>>word) 
      { 
       if(isArticle(word)==true) 
       { 
        cout<<word; 
       } 
      } 
     } 
     else 
     { 
      usage(argv[2],"Cannot open "+string(argv[2])); 
      return 1; 
     } 
    } 
    else 
    { 
     usage(argv[1], "More than one filename was given"); 
     return 1; 
    } 
    return 0; 
} 
+2

你應該檢查'sizeof(article)'和'sizeof(file)'do(不是你想象的那樣)。 – juanchopanza 2015-02-08 17:47:29

+0

爲了擴大juanchopanza的說法,'sizeof(article)'將會是相當大的比14大很多,但這就是數組中定義了多少個字符串。這是一個很好的東西,你包括'isArticle()'函數,因爲這是麻煩的根源 - 所以感謝你包括它。當像這樣的函數中有數組定義時,數組中元素的數量爲'sizeof(article)/ sizeof(article [0])''。這對陣列參數不起作用;那麼調用代碼需要明確傳遞大小。 – 2015-02-08 17:53:16

+0

如果將字符串轉換爲全部小寫或全部大寫,則不需要進行多次比較。搜索「C++ transform tolower toupper」 – 2015-02-08 17:54:50

回答

0

sizeof運算符不返回數組中元素的數量。它返回數組佔用的內存空間。 char的數組將具有與int的數組不同的sizeof

爲了您的數組,你可以決定在編譯時元素的個數:

const unsigned int elements_in_array = 
    sizeof(article)/sizeof(article[0]); 
+0

使用sizeof(array)/ sizeof(array [0])時要非常小心';這很危險。如果數組衰減到指針,它仍然會編譯,但它不會做你想要的。 C++ 11爲此擁有'std :: begin'和'std :: end';在C++ 11之前,當然,我們在工具箱中都有相同的東西。 – 2015-02-08 19:07:47

1

正如其他人已經指出,sizeof給數組中元素的個數 ;這樣做的慣用方式是使用 std::end(article) - std::begin(article)。在pre-C++ 11中,大多數 經驗豐富的C++程序員都會這樣做,使用工具包中的 beginend版本。

整個isArticle函數是非常單一的。在C++ 11中, 整個功能將是一個單一的庫調用:

bool 
isArticle(std::string const& word) 
{ 
    static std::string const articles[] = { 
     "a", "an", "the", "A", "An", "aN", "AN", 
     "The", "tHe", "thE", "THe", "tHE", "ThE", "THE", 
    }; 
    return std::any_of(
      std::begin(articles), std::end(articles), 
      [=](std::string const& target) { return word == target; }); 
} 

在早期的C++中,我們就已經寫:

return std::find(begin(articles), end(articles), word) 
     != end(articles); 

(與beginend從我們平時的工具包)。如果我們想(爲 教學的原因)寫的循環自己,那將是什麼 這樣的:

沒有真正涉及到你的眼前的問題
std::string::const_iterator current = std::begin(articles); 
std::string::const_iterator end = std::end(articles); 
while (current != end && *current != word) { 
    ++ current; 
} 
return current != end; 

有幾點可能 值得mentionning:

  • 類的類型通常是通過引用const來傳遞的,而不是通過 的值。這可以說是不成熟的優化,但它無處不在,其他任何事情都讓人想知道爲什麼。未在功能改變

  • 值應被宣佈const static

  • std::string支持==!=;如果你正在尋找平等, 這就是你應該使用的。 compare函數實際上應該只用於詞典排序。

  • 從循環的中間返回是你一般想要避免的東西 。當然,當功能這麼簡單時,它確實不是 的問題,但這是一個不好的習慣。

這只是關心的功能問題。在main,你也 有問題sizeof。在這種情況下,它看起來像是 試圖使用它來確定文件中單詞的數量。 不能在沒有實際讀取文件的情況下完成。這裏你需要的是 std::vector<std::string>,而不是C風格的數組(其大小必須是編譯時已知的 )。

當然:if所需的類型是boolisArticle 返回bool,所以沒有其他需要。寫作 isArtile(word) == true強烈建議您不知道什麼類型是 bool類型。 (提示:表達 isArtile(word) == true的類型也bool

而且最後一個建議:如果沒有參數的程序,你 沒有做任何事情。我不認爲這是意圖。命令行通常 解決方案的Unix下的進程(和它的也很普遍 Windows下)就是把所有的實際工作中的功能,並寫 類似:

int 
main(int argc, char** argv) 
{ 
    if (argc == 1) { 
     process(std::cin); 
    } else { 
     for (int i = 1; i != argc; ++ i) { 
      std::ifstream in(argv[i]); 
      if (! in) { 
       // Output error message and set global flag for 
       // return value... 
      } else { 
       process(in); 
      } 
     } 
    } 
    return globalFlagWithReturnValue; 
} 

功能process需要一個std::istream&作爲參數,其中 允許其讀取std::cin或打開的std::istream

+0

我不明白。你發佈的代碼有'ostream'派生,然後後面的句子談論'istream'。這是什麼? – 2015-02-08 19:17:21

+0

@ThomasMatthews我不知道我在想什麼。顯然應該是'istream'派生'std :: cin'和'std :: ifstream'(因爲這些是輸入)。我修復了它。謝謝。 – 2015-02-08 19:26:01