簡體   English   中英

如何將文件指針移動到文件中的下一行?

[英]How can I move a file pointer to the next line in a file?

我正在嘗試編寫一個函數來讀取一行,將每個字符保存到一個數組中,操作該字符數組,將結果打印到另一個文件,然后移到文件中的下一行。

一些示例輸入/輸出如下(程序的目的是找到導數 - 但那部分代碼工作正常。):

INPUT:
x
4x^4
91
sinx

OUTPUT:
1
16x^3
0
cosx

到目前為止我編寫的函數:

int main(){

    FILE *inptr = fopen("functions.txt", "r");
    FILE *outptr = fopen( "derive.txt", "w");

    if(inptr)
        derive(inptr,outptr);

    return 0;
}

void derive(FILE *inptr, FILE *outptr){
    int i;
    char in = '0';
    char array[MAX];

    while((in = fgetc(inptr)) != EOF){
        for(i = 0; in != '\n'; i++){
            fscanf(inptr, "%c", &in);
            array[i] = in;
        }
        manipulate(array, outptr); // Function that finds the derivative and prints to output file
    }
}

我的問題是:如何將文件指針 inptr 移動到下一行?

如何將文件指針移動到文件中的下一行?

文件是字節的集合,其中字節的含義取決於文件格式。

“純文本”是一組許多不同的文件格式; 用不同的方式來編碼字符(EBCDIC、ASCII、“擴展 ASCII”的許多變體、UTF-8、UCS-2、UTF-16,...)和不同的方式來表示“行尾”(“\\n” , "\\r\\n\\", "\\r")。

第一步是確定您的軟件是否將采用一種特定風格的“純文本”文件格式(並因其他所有內容而被破壞 - 例如,當有人從不同的操作系統傳輸文件時),還是支持多種文件格式並具有顯式控制(使用命令行參數/s,以便用戶可以告訴它哪種文件格式)和/或它是否會嘗試自動檢測(例如假設 UTF-8,它也適用於 ASCII,然后自動檢測什么“行尾”,可能通過接受“\\r”或“\\n”,然后檢查“\\n”是否跟在“\\r”之后或“\\r”跟在“\\n”之后)。

下一步是將字符從碰巧使用的任何文件格式轉換為某種“適合您的標准”字符集(這可能是也可能不是編譯器碰巧使用的任何字符集),同時丟棄垃圾(例如 Unicode 之類的東西) “字節順序標記”)並處理格式錯誤/損壞數據的可能性(例如,對於 UTF-8 來說是非法的字節序列,對於 ASCII 來說是非法的字節,......)並處理不需要的有效字符(NULL ,鈴,刪除,...)。

在“字符集驗證、轉換和過濾”之后,您可以立即進行“行尾檢測”(可能使用狀態機來跟蹤“前一個字符是 '\\r'”和“前一個字符是 '\\n'”;和也許計算空格字符並刪除/刪除行尾的所有尾隨空格); 並且可以將字符存儲在數組中以備后用(如果它沒有被丟棄或“行尾”)或調用“處理此行”函數(如果它是“行尾”)。 也不要忘記“文件結尾”——你可能會在你還在一行中間的時候到達文件的結尾(並且可以通過假裝文件中的最后一行以“行尾”結尾來處理這個問題“當它沒有)。

請注意fscanf(inptr, "%c", &in); 非常糟糕(您可能會在此函數中花費大部分 CPU 時間來解析格式字符串"%c" )並且您可以使用fgetc()作為“不那么糟糕”的替代方案; 並且所有這些函數( fscanf()fgetc()fgets() ,...)無論如何大部分都無法使用(除非您對“純文本”文件格式實際上是哪種文件格式做出未知的編譯器特定假設然后被破壞其他一切都是錯誤的),而且大多數這些功能都很慢。 反而; 您想考慮使用read() (以便您可以處理充滿字節的整個緩沖區並避免每個字節的 C 庫函數和/或內核 API 調用的開銷),或者mmap()

最后; 您需要確保惡意攻擊者無法(故意)提供在一行中包含過多字符的文件。 必須進行安全檢查(例如if(i >= MAX) { // Array is full, can't add the next character to the array ); 並且可以跟隨輸出錯誤消息(“行號處的行太長...”)或使用動態調整大小的數組(例如使用realloc()函數來增加數組的大小)。

while((in = fgetc(inptr)) != EOF){
    for(i = 0; in != '\n'; i++){
        fscanf(inptr, "%c", &in);
        array[i] = in;
    }
    manipulate(array, outptr); // Function that finds the derivative and prints to output file
}

在這里,您不需要增加inptr因為在 for 循環中執行fscanf()時,它的指針不斷增加,因此在下一個 while 循環中,您將在下一行。


在上面的代碼中,您缺少任何行的第一個字符。,

雖然您已經閱讀了一個字符,但您沒有使用該字符,但在下一個 for 循環中再次閱讀字符。

int main(){

    FILE *inptr = fopen("functions.txt", "r");
    FILE *outptr = fopen( "derive.txt", "w");

    if(inptr)
        derive(inptr,outptr);

    return 0;
}

void derive(FILE *inptr, FILE *outptr){
    int i;
    char in = '0';
    char array[MAX],word[MAX];
    fseek(inptr,0,SEEK_SET);
    while((in = fgetc(inptr)) != EOF){
        for(i = 0; in != '\n'; i++){
            fscanf(inptr, "%c", &in);
            array[i] = in;
            fgets(word,MAX,inptr); 
            /* this should set the cursur of inptr to the next line :D */
        }
        manipulate(array, outptr); // Function that finds the derivative and               prints to output file
    }
}

使用函數fgets()逐行讀取文件。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM