2010-07-09 25 views
2

我想加載一個像文件()中的數組文件()在PHP中的文本文件。我想能夠訪問像array [N](它應該包含整個文件中的第N行)不同的行,然後我需要刪除每個數組元素後使用它將減少大小,直到達到0和程序將結束。我知道如何讀取文件,但我不知道如何填充字符串數組以便像我說的那樣使用。我正在使用gcc版本4.4.3(Ubuntu 4.4.3-4ubuntu5)進行編譯。將文本文件轉換爲純C中的字符串數組?

我該如何做到這一點?

回答

1

我建議你將你的文件讀入一個指向字符串的指針數組中,這將允許你按照你指定的方式索引和刪除行。使用這種方法可以考慮效率的權衡,以提前計算行數還是在讀取每行時分配/擴展數組。我會選擇前者。

  1. 讀取文件,計數你看到行終止符的數量(醚\n\r\n
  2. 由線分配該尺寸
  3. 重新讀取該文件的字符*,線的陣列,使用malloc()分配緩衝區的每個,並通過下一個數組索引指向

對於你的操作:

  • 索引僅僅是array[N]
  • 刪除剛剛釋放由array[N]索引緩衝區,並設置array[N]進入NULL

UPDATE:

通過提出的更多的內存高效的方法@r ..@ marc-van-kempen是一個優於malloc()的好方法,每次只讀一行,即將文件寫入單個緩衝區並替換所有行終止符s的'\0'

假設你這樣做,你有一個很大的緩衝區char *filebuf和行數是int num_lines那麼你可以分配你的索引數組是這樣的:

char *lines[] = (char **)malloc(num_lines + 1); // Allocates array of pointers to strings 
lines[num_lines] = NULL; // Terminate the array as another way to stop you running off the end 

char *p = filebuf; // I'm assuming the first char of the file is the start of the first line 
int n; 
for (n = 0; n < num_lines; n++) { 
    lines[i] = p; 
    while (*p++ != '\0') ; // Seek to the end of this line 
    if (n < num_lines - 1) { 
    while (*p++ == '\0') ; // Seek to the start the next line (if there is one) 
    } 
} 

有了一個緩衝接近「刪除」一行僅僅是將lines[n]設置爲NULL的一種情況。有沒有免費()

+0

或者只是在緩衝區中讀取文件,然後關閉它。使用更多的RAM,但由於僅執行一次I/O操作可能會更快 - 取決於操作系統是否爲您緩衝第一次讀取。 – 2010-07-09 01:35:14

+0

我在哪裏可以讀取一些指針數組的示例?我知道行數會定義主數組的大小,但我不知道如何管理每個數組元素。 – jahmax 2010-07-09 01:44:03

2

算法:

  1. 使用fseekftellfseek尋求結束,確定文件的長度,並尋求回到開頭。
  2. malloc一個足夠整個文件加上空終止的緩衝區。
  3. 使用fread將整個文件讀入緩衝區,然後在末尾寫入一個0字節。
  4. 以字節爲單位循環遍歷緩衝區並計算換行符。
  5. 使用malloc來分配該號碼+ 1 char *指針。
  6. 再次循環遍歷緩衝區,將第一個指針指向指向緩衝區的開始處,並將連續指針指向換行後的字節。用進程中的0(空)字節替換換行符本身。

一個優化:如果您不需要隨機訪問行(通過行號對它們進行索引),請取消指針數組,然後用0個字節替換所有換行符。然後s+=strlen(s)+1;前進到下一行。您需要添加一些檢查以確保您不會超過緩衝區的末端(或開始,如果您正在反轉)。

無論哪種方式,這種方法是非常有效的(無內存碎片),但也有一些缺點:

  • 不能逐個免費線;一旦完成,你只能釋放整個緩衝區。
  • 你必須改寫換行符。有些人更喜歡讓它們保持在內存結構中。
  • 如果文件以換行符結束,則指針數組中的最後一行將爲零長度。國際海事組織這是對文本文件的理解解釋,但有些人更喜歡考慮最後一個換行符後的空字符串爲非行,並且如果不以換行符結尾,則考慮最後一行「不完整」。
1

兩個稍微不同的方式來實現這一點,一個是更多的內存友好,另一個更友善的CPU。

I存儲器友好

  1. 打開該文件並獲得它的大小(用FSTAT()和朋友)==>大小
  2. 分配該尺寸==>炭的buf [大小]的緩衝液;
  3. 掃描緩衝區,計算'\ n'(或'\ n \ r'== DOS或'\ r'== MAC)==> N
  4. 分配數組:char * lines [N]
  5. 再次掃描緩衝區並點行[0]至& buf [0],掃描第一個'\ n'或'\ r'並將其設置爲'\ 0'(定界字符串),設置行[1]至後的第一個字符不是 '\ n' 或 '\ r' 等

II CPU友好

  1. 創建鏈接列表結構(如果你不知道如何做或不想做,可以看看'glib'(不是glibc!),它是gtk的一個實用程序伴侶。
  2. 打開文件並開始使用fgets()讀取行,隨着每行的逐行讀取malloc。
  3. 保留一行的鏈表==>列表並計算總行數
  4. 分配一個數組:char * lines [N];
  5. 瀏覽鏈表並將指向每個元素的指針指定給其對應的數組元素
  6. 釋放鏈表(不是它的元素!)
相關問題