雖然已經回答了這個問題的一些不同變化,但是如何去做的考慮可以使用一個段落。遇到這個問題時,無論您使用哪種庫或POSIX函數組合,該方法都是相同的。
本質上,您將動態分配合理數量的字符來保存每一行。自動爲您直到'\n'
字符閱讀如果你使用getline
POSIX getline
將做到這一點,利用fgets
你可以簡單地看一個固定的緩衝區滿字符,並追加他們(在必要時重新分配存儲)(或達到EOF
)
,那麼你必須分配內存,並複製填充的緩衝區。否則,您將覆蓋以前的每一行讀取的行,並且當您嘗試使用free
每行時,您可能會因爲您反覆嘗試釋放相同的內存塊而使用雙免費或損壞的SegFault。
您可以使用strdup
來簡單地複製緩衝區。但是,由於strdup
分配存儲空間,因此在爲您的行集合分配指向新內存塊的指針之前,應驗證成功分配。
要訪問每一行,您需要一個指向每個行的開始位置(持有每行的內存塊)。 A 通常使用指向字符指針的指針。 (例如char **lines;
)內存分配通常是通過分配一些合理數量的指針開始處理的,跟蹤你使用的數字,當你達到你分配的數字時,你的指針數量增加一倍。
與每次讀取一樣,您需要驗證每個內存分配。 (每個malloc
,calloc
或realloc
)您還需要通過內存錯誤檢查程序(例如Linux的valgrind
)來驗證程序使用您分配的內存的方式。它們使用簡單,只需valgrind yourexename
。
把這些碎片放在一起,你可以做類似於下面的事情。以下代碼將讀取作爲程序的第一個參數提供的文件名中的所有行(如果未提供參數,則默認爲stdin
),並將行號和行打印到stdout
(請記住,如果您在第50000行文件)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NPTR 8
int main (int argc, char **argv) {
size_t ndx = 0, /* line index */
nptrs = NPTR, /* initial number of pointers */
n = 0; /* line alloc size (0, getline decides) */
ssize_t nchr = 0; /* return (no. of chars read by getline) */
char *line = NULL, /* buffer to read each line */
**lines = NULL; /* pointer to pointer to each line */
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* validate file open for reading */
fprintf (stderr, "error: file open failed '%s'.\n", argv[1]);
return 1;
}
/* allocate/validate initial 'nptrs' pointers */
if (!(lines = calloc (nptrs, sizeof *lines))) {
fprintf (stderr, "error: memory exhausted - lines.\n");
return 1;
}
/* read each line with POSIX getline */
while ((nchr = getline (&line, &n, fp)) != -1) {
if (nchr && line[nchr - 1] == '\n') /* check trailing '\n' */
line[--nchr] = 0; /* overwrite with nul-char */
char *buf = strdup (line); /* allocate/copy line */
if (!buf) { /* strdup allocates, so validate */
fprintf (stderr, "error: strdup allocation failed.\n");
break;
}
lines[ndx++] = buf; /* assign start address for buf to lines */
if (ndx == nptrs) { /* if pointer limit reached, realloc */
/* always realloc to temporary pointer, to validate success */
void *tmp = realloc (lines, sizeof *lines * nptrs * 2);
if (!tmp) { /* if realloc fails, bail with lines intact */
fprintf (stderr, "read_input: memory exhausted - realloc.\n");
break;
}
lines = tmp; /* assign reallocted block to lines */
/* zero all new memory (optional) */
memset (lines + nptrs, 0, nptrs * sizeof *lines);
nptrs *= 2; /* increment number of allocated pointers */
}
}
free (line); /* free memory allocated by getline */
if (fp != stdin) fclose (fp); /* close file if not stdin */
for (size_t i = 0; i < ndx; i++) {
printf ("line[%3zu] : %s\n", i, lines[i]);
free (lines[i]); /* free memory for each line */
}
free (lines); /* free pointers */
return 0;
}
如果你沒有getline
,或strdup
這樣做,你可以很容易地實現每個。網站上有多個例子。如果你找不到,請告訴我。如果您還有其他問題,請讓我知道。
使用'malloc()'/'realloc()'有一個明智的策略(例如,當你用完時的雙倍大小)......檢查換行符以確定該行是否完整。我認爲這個問題太廣泛了...... –
[長度未知時獲取用戶輸入的最佳方法是什麼? (C)](https://stackoverflow.com/questions/46395682/best-way-to-get-user-input-when-length-is-unknown-c) –
嘗試編碼這些目標之一「未知數每行的字符數量未知「。避免使這篇文章太寬泛。 – chux