2015-11-12 15 views
1

我決定開始學習C++我採取正式上課之前就可以了明年,我已經開始與一些對CodeEval和項目歐拉容易挑戰。在這個文件中,你必須輸入一個包含字符串的輸入文件,並且你必須輸出文件的一行和反轉的文字。使得與以下輸入一個文件CodeEval挑戰:反向字符串輸入文件

1:這是一條線

2:這是線上的兩個

最終將作爲

1:一條線是這

2:兩個線路是這

我寫了下面的程序做到這一點,並且除了無法正常倒車字符串,而不是完全扭轉這個詞,它那儘管編譯時沒有錯誤或警告,但仍存在錯誤。我假設我錯過了關於C++中正確的內存管理的事情,但我不確定它是什麼。那麼有人能夠啓發我關於內存管理方面的想法嗎?

#include <iostream> 
#include <fstream> 
#include <string> 
#include <vector> 
#include <sstream> 
int main(int argc, char** argv) 
{ 
    std::string filename = argv[1]; //has to be argv[1], argv[0] is program name 
    std::string output_string; //final output 
    std::string line; //Current line of file 
    std::ifstream read(filename.c_str()); 
    if(read.is_open()){ 
    while(std::getline(read,line)){ 
     std::string temp; 
     std::istringstream iss; 
     iss.str(line); 
     while(iss >> temp){ //iterates over every word 
     output_string.insert(0,temp); //insert at the start to reverse 
     output_string.insert(0," "); //insert spaces between new words 
     } 
     output_string.erase(0,1); //Removes the space at the beginning 
     output_string.insert(0,"\n"); //Next line 
    } 
    output_string.erase(0,1); //Remove final unnecessary \n character 
    read.close(); 
    } 
    else{ 
    std::cout<<"Unable to open file\n"; 
    } 
    for(unsigned int i = output_string.length(); i>=0;i--){ 
    std::cout<<output_string[i]; 
    } 
    std::cout<<"\n"; 
} 

回答

1
for(unsigned int i = output_string.length(); i>=0;i--){ 
    std::cout<<output_string[i]; 
} 

該段錯誤發生在這裏;您可能會從編譯器獲得一些警告並附加一些標誌。例如克++不產生警告與-Wall,但是產生兩個警告與-Wextra:一個約argc不被使用,而另一個瞭解這個循環永遠不會終止。

這裏的問題是雙重的:長頸鹿隊長說,你開始超出了實際長度你的字符串;而且條件i >= 0將始終爲真,因爲i是無符號的。因此,一旦它達到0,下一次遞減將導致它迴繞到最高可能值,然後你肯定得到一個超出邊界的內存訪問。

的警告報道是:

reverse.cpp:31:49: warning: comparison of unsigned expression >= 0 is always true [-Wtype-limits] 
    for(unsigned int i = output_string.length(); i>=0;i--){ 

另外,作爲隊長長頸鹿說,你扭轉了整個文件,而不僅僅是每一行。因此,您可以在每行完成後反轉每行並輸出,而不是稍後存儲整個輸出。

下面是整個程序的最小變化,以避免任何警告並獲得正確的輸出。主要變化是將output_string的所有用法移入讀取循環。

int main(int argc, char** argv) 
{ 
    if (argc != 2) 
    { 
      std::cerr << "Need a file to process!" << std::endl; 
      return 1; 
    } 
    std::string filename = argv[1]; //has to be argv[1], argv[0] is program name 
    std::string line; //Current line of file 
    std::ifstream read(filename.c_str()); 
    if(read.is_open()){ 
      while(std::getline(read,line)){ 
        std::string output_string; //final output 
        std::string temp; 
        std::istringstream iss; 
        iss.str(line); 
        while(iss >> temp){ //iterates over every word 
          output_string.insert(0,temp); //insert at the start to reverse 
          output_string.insert(0," "); //insert spaces between new words 
        } 
        output_string.erase(0,1); //Removes the space at the beginning 
        std::cout << output_string << std::endl; 
      } 
      read.close(); 
    } 
    else{ 
      std::cout<<"Unable to open file\n"; 
    } 
} 
+0

嘿,謝謝你的幫助。在另一個說明中,我一直在使用-Werror進行編譯,但是您會推薦作爲使用-Wextra和-Wall進行編譯的標準嗎? – NathanielJPerkins

+1

@Thallazar越警示越好。 '-Wextra'增加了一些'-Wall'不包括的警告。 「錯誤」將通常只是「警告」的東西轉換爲實際停止編譯的錯誤,這可能很適合在學習時使用。也許'-Wall -Wextra -Werror'可能是個好主意。 – notmyfriend

1

更改持續語句來

std::cout << output_string; 

你被最後在輸出字符串後打印字符出發輸出。這擺脫了段錯誤。現在您正試圖反轉打印反轉輸出。

現在你發現你應該扭轉每一行,而不是整個文本。您可以輕鬆地通過爲每行添加起始索引來代替插入中的。

所以不是

output_string.insert(0,temp); //insert at the start to reverse 

你可以做

output_string.insert(start_of_line, temp); //insert at the start to reverse 
+0

嗯,這確實修復了段錯誤,但如果我索引超出界限,爲什麼它打印什麼? – NathanielJPerkins

+0

當我嘗試它時沒有打印任何東西。也許你的時鐘設置爲星期一,並且段錯誤處理程序有點慢。 –

+0

奇怪的是,在我的作品中,它執行字符串的反轉,將其打印出來,然後最後一行是段錯誤。 – NathanielJPerkins