2016-04-20 41 views
1

好吧,夥計們,我在使用我的文件指針穿過循環遍歷文件時遇到了一些麻煩。我將在我的文本文件中有一個字符串列表,每行一個,我正在測試它們之間的相似性。所以我的方法是有兩個文件指針來遍歷和比較。例如:FILE* fp1將在第一行開始設置。 FILE* fp2將設置在第二行開始。在循環時使用文件指針

我要穿越這種方式:

Line 1 <-> Line 2
Line 1 <-> Line 3
Line 1 <-> Line 4
Line 1 <-> Line 5

(我在這裏讀通過FP1的下一行去2號線,我也試圖FP2設定爲FP1之後讀取下一行)

Line 2 <-> Line 3
Line 2 <-> Line 4
Line 2 <-> Line 5

等...

這裏是代碼... FILE* fp被傳遞給函數爲(FILE* fp)

FILE* nextfp; 
for(i = 1; i <= numStr; i++){ 
    fscanf(fp, "%s", str1); 
    nextfp = fp; 
    double str1len = (double)(strlen(str1)); 
    for(j = i + 1; j <= numStr; j++){ 
     fscanf(nextfp, "%s", str2); 
     double str2len = (double)(strlen(str2)); 

     if((str1len >= str2len) && ((str2len/str1len) >= 0.90000) && (lcsLen(str1, str2)/(double)str2len >= 0.80000)) 
      sim[i][j] = 'H'; 
     else if ((str2len >= str1len) && ((str1len/str2len) >= 0.90000) && (lcsLen(str2, str1)/(double)str1len >= 0.80000)) 
      sim[i][j] = 'H'; 
    } 
} 

int numStr是線與弦總數
lcsLen(char*, char*)返回最長公共子序列的長度

sim[][]陣列是我在哪裏標記我的相似性的水平。到目前爲止,我只編寫了標記高度相似性的字符串。

我的結果是不完整的,這是由於我的fp不會去下一行,只是留在同一個字符串,並且,我的內部循環保持nextfp指向最後一個字符串,而不是它應該到達的地方到我的nextfp = fp一行。

任何幫助的讚賞!非常感謝你!

+0

根據文件的大小,我建議你在內存中讀入數組而不是讀取文件。然後它是一個簡單的嵌套循環數組索引。 –

+0

這將是任意大小。我正在接近這種方式,所以我不必擔心記憶。 – HotShot51015

+1

爲什麼你使用浮點類型的字符串長度?什麼時候每個字符串的長度都是非整數?在劃分時你可以投到浮點。 –

回答

0

第一次內層循環之後,文件流已經到達文件結尾。之後,您不能使用fp從文件流中讀取數據。記住你正在閱讀流,流不回去。閱讀man 3 fseek,你可以手動設置文件偏移量到某個地方,但這不能解決你的問題。你應該閱讀所有的數組,這更容易和更快。

1

您不能像FILE *一樣指向內存,它是指向FILE類型的對象的指針,該對象又保存與文件I/O相關聯的狀態。

複製FILE *沒什麼意義,當然也不會創建狀態的副本。

該狀態的一部分是文件中的當前位置,這不會因爲您複製指針而發生更改。

你應該研究內存映射文件,它會給你你期望的訪問類型,或者只讀整個文件一次到一個字符串數組,然後你可以以任何方式迭代你喜歡。

0

由於其他答案的狀態,你應該考慮只讀整個文件到數組中。如果您的文件大小超過幾百MB,那麼您的方法可能是正確的選擇。

在讀完第一行之後使用ftell保存當前偏移量,並在循環遍歷其餘行之後使用fseek將文件描述符設置回該偏移量。

FILE* nextfp; 
size_t offset; 
for(i = 1; i <= numStr; i++){ 
    fscanf(fp, "%s", str1); 
    offset = ftell(fp); // save the current position 
    double str1len = (double)(strlen(str1)); 
    for(j = i + 1; j <= numStr; j++){ 
     fscanf(nextfp, "%s", str2); 
     double str2len = (double)(strlen(str2)); 

     if((str1len >= str2len) && ((str2len/str1len) >= 0.90000) && (lcsLen(str1, str2)/(double)str2len >= 0.80000)) 
      sim[i][j] = 'H'; 
     else if ((str2len >= str1len) && ((str1len/str2len) >= 0.90000) && (lcsLen(str2, str1)/(double)str1len >= 0.80000)) 
      sim[i][j] = 'H'; 
    } 
    fseek(fp, offset, SEEK_SET); // set the file descriptor back to the previous position 
}