2013-08-22 51 views
1

我有我格式化這樣的城市列表:C/C++讀取和寫入長字符串的文件

{town, ...}, 
{...}, 
... 

閱讀並建立每個鄉鎮和創建town1,town2,工程.... 問題是當我輸出它時,第一行工作{鎮,...},但第二行崩潰。 任何想法爲什麼?

我有[地區] [城鎮](excel表)。

因此,每個區域重複有多少個城鎮。 每個文件每行有1個區域/城鎮。

judete包含每個區域重複1次。

AB 
SD 
PC 
.... 

orase包含城鎮列表。

town1 
town2 
.... 

orase指數包含每個鎮

AB 
AB 
AB 
AB 
SD 
SD 
SD 
PC 
PC 
... 

我想這樣{ 「town1」, 「town2」,...}每行輸出的區域(第5行)包含屬於同一行judete的地區的城鎮(第5行)。

這裏是我的代碼:

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

char judet[100][100]; 
char orase[50][900000]; 
char oras[100], ceva[100]; 

void main() 
{ 

    int i=0, nr; 
    FILE *judete, *index, *ORASE, *output; 
    judete = fopen("judete.txt", "rt"); 
    index = fopen("orase-index.txt", "rt"); 
    ORASE = fopen("orase.txt", "rt"); 
    output = fopen("output.txt", "wt"); 

    while(!feof(judete)) 
    { 
     fgets(judet[i], 100, judete); 
     i++; 
    } 

    nr = i; 
    char tmp[100]; 
    int where=0; 

    for(i=0;i<nr;i++) 
     strcpy(orase[i],""); 

    while(!feof(index)) 
    { 
     fgets(tmp, 100, index); 
     for(i=0;i<nr;i++) 
     { 
      if(strstr(judet[i], tmp)) 
      { 
       fgets(oras, 100, ORASE); 
       strcat(ceva, "\""); 
       oras[strlen(oras)-1]='\0'; 
       strcat(ceva, oras); 
       strcat(ceva, "\", "); 
       strcat(orase[i], ceva); 
       break; 
      } 

     } 
    } 


    char out[900000]; 

    for(i=0;i<nr;i++) 
    { 
     strcpy(out, ""); 
     strcat(out, "{"); 
     strcat(out, orase[i]); //fails here 
     fprintf(output, "%s},\n", out); 
    } 

} 

結果我從運行代碼得到的是:

未處理的異常在0x00D4F7A9(msvcr110d.dll)在orase-judete.exe:0000005:訪問違規寫入地址0x00A90000。

+0

它是如何崩潰的?如果通過'gdb'運行它,會發生什麼? 另外,不要使用strcat/strcpy。使用'n'版本('strncpy'等) –

+0

你可以給一個judete.txt的小樣本嗎? –

+1

@OliverMatthews'strncpy()'不比'strcpy()'更好,它只是有一個不同的謬誤。 – 2013-08-22 13:46:15

回答

4

不要清除orase陣列,東陽你的循環

for(i-0;i<nr;i++) 
    strcpy(orase[i],""); 

錯誤( ' - ' 而不是 '=')執行0次。

+0

orase我沒有清理它,因爲我沒有在那條線上放任何東西,我只是用「」來初始化它以防萬一。 –

+1

@MihaiBratulescu:仔細閱讀這一行。我懷疑它是(甚至接近)唯一的問題,但他指出的是一個真正的問題。 –

+0

好吧,我以爲你拼錯 - 不是我反正相同的效果,它崩潰 –

3

我認爲無論您是在編寫C還是C++,您都需要下定決心。你已經用這兩個標記了這個,但是代碼看起來像是純C的。雖然C++編譯器會接受大多數C,但結果並不是大多數人認爲的理想C++。

由於您已將其標記爲C++,因此我將假設您實際上想要(或完全正確)C++代碼。編寫良好的C++代碼將與您當前的C代碼有足夠的差異,從頭開始可能比嘗試逐行重寫代碼更容易。

然而,我看到這樣做的直接問題是,你沒有真正指定你想要的輸出。目前,我假定您希望每行輸出都是這樣的:"{" <town> "," <town> "}"

如果是這樣的話,我會首先注意到輸出看起來完全不依賴於您的judete文件。 oraseorase-index似乎完全足夠。爲此,我們的代碼可以是這個樣子:

#include <iostream> 
#include <string> 
#include <iterator> 
#include <fstream> 
#include <vector> 

// a class that overloads `operator>>` to read a line at a time: 
class line { 
    std::string data; 
public: 
    friend std::istream &operator>>(std::istream &is, line &l) { 
     return std::getline(is, l.data); 
    } 
    operator std::string() const { return data; } 
}; 

int main() { 
    // open the input files: 
    std::ifstream town_input("orase.txt"); 
    std::ifstream region_input("orase-index.txt"); 

    // create istream_iterator's to read from the input files. Note 
    // that these iterate over `line`s, (i.e., objects of the type 
    // above, so they use its `operator>>` to read each data item). 
    // 
    std::istream_iterator<line> regions(region_input), 
           towns(town_input), 
           end; 

    // read in the lists of towns and regions: 
    std::vector<std::string> town_list {towns, end}; 
    std::vector<std::string> region_list {regions, end}; 

    // write out the file of town-name, region-name: 
    std::ofstream result("output.txt"); 
    for (int i=0; i<town_list.size(); i++) 
     result << "{" << town_list[i] << "," << region_list[i] << "}\n"; 
} 

野老,由於這是C++,您通常需要將源保存爲something.cpp而不是something.c編譯器要正確識別它。

編輯:根據您的評論已經給了新的要求,顯然你想要的東西更接近這個:

#include <iostream> 
#include <string> 
#include <iterator> 
#include <fstream> 
#include <vector> 
#include <map> 

// a class that overloads `operator>>` to read a line at a time: 
class line { 
    std::string data; 
public: 
    friend std::istream &operator>>(std::istream &is, line &l) { 
     return std::getline(is, l.data); 
    } 
    operator std::string() const { return data; } 
}; 

int main() { 
    // open the input files: 
    std::ifstream town_input("orase.txt"); 
    std::ifstream region_input("orase-index.txt"); 

    // create istream_iterator's to read from the input files. Note 
    // that these iterate over `line`s, (i.e., objects of the type 
    // above, so they use its `operator>>` to read each data item). 
    // 
    std::istream_iterator<line> regions(region_input), 
           towns(town_input), 
           end; 

    // read in the lists of towns and regions: 
    std::vector<std::string> town_list (towns, end); 
    std::vector<std::string> region_list (regions, end); 

    // consolidate towns per region: 
    std::map<std::string, std::vector<std::string> > consolidated; 
    for (int i = 0; i < town_list.size(); i++) 
     consolidated[region_list[i]].push_back(town_list[i]); 

    // write out towns by region 
    std::ofstream output("output.txt"); 
    for (auto pos = consolidated.begin(); pos != consolidated.end(); ++pos) { 
     std::cout << pos->first << ": "; 
     std::copy(pos->second.begin(), pos->second.end(), 
      std::ostream_iterator<std::string>(output, "\t")); 
     std::cout << "\n"; 
    }  
} 
+0

我有一個C++項目(只是因爲),但你的代碼包含錯誤,我不知道很多(如果有的話)C + +糾正它們,也關於judete文件我需要它,因爲我希望每行(第5行)包含屬於該行的城鎮(第5行) –

+0

我將它標記爲C++,因爲我的C++編程人員也可以幫助我。 –

+3

@MihaiBratulescu:如果您在嘗試編譯上面的代碼時遇到錯誤,那麼很可能您的編譯器太舊了。上面的代碼用g ++和VC++的當前版本乾淨地編譯。如果你要求C++程序員來幫助你,他們很有可能會像我一樣做,並試圖幫助你編寫C++ ... –

1

注意ceva永遠不會初始化。

而不是使用strcpy初始化字符串,我會建議使用靜態初始化:

char ceva[100]="";