读取未知大小的文本文件
Reading text file of unknown size
我正在尝试将未知大小的文本文件读入字符数组。
这是我目前所拥有的。
#include<stdio.h>
#include<string.h>
int main()
{
FILE *ptr_file;
char buf[1000];
char output[];
ptr_file =fopen("CodeSV.txt","r");
if (!ptr_file)
return 1;
while (fgets(buf,1000, ptr_file)!=NULL)
strcat(output, buf);
printf("%s",output);
fclose(ptr_file);
printf("%s",output);
return 0;
}
但我不知道如何在读取未知大小的文件时为输出数组分配大小。
此外,当我为输出输入一个大小时,比如 n=1000,我得到了分段错误。
我是一个非常没有经验的程序员任何指导表示赞赏:)
文本文件本身在技术上是一个 .csv 文件,因此内容如下所示:
“0,0,0,1,0,1,0,1,1,0,1...”
执行此操作的标准方法是使用 malloc
分配一定大小的数组,然后开始读取它,如果您 运行 在 运行 字符不足(也就是说,如果在填满数组之前没有达到 EOF
),请为数组选择更大的大小并使用 realloc
使其更大。
这是读取和分配循环的样子。我选择使用 getchar
一次读取输入一个字符(而不是使用 fgets
一次读取一行)。
int c;
int nch = 0;
int size = 10;
char *buf = malloc(size);
if(buf == NULL)
{
fprintf(stderr, "out of memory\n");
exit(1);
}
while((c = getchar()) != EOF)
{
if(nch >= size-1)
{
/* time to make it bigger */
size += 10;
buf = realloc(buf, size);
if(buf == NULL)
{
fprintf(stderr, "out of memory\n");
exit(1);
}
}
buf[nch++] = c;
}
buf[nch++] = '[=10=]';
printf("\"%s\"", buf);
关于这段代码的两个注意事项:
- 初始大小和增量的数字10太小了;在实际代码中,你会想要使用更大的东西。
- 很容易忘记确保尾随'\0'有空间;在这段代码中,我尝试使用
if(nch >= size-1)
. 中的 -1
来做到这一点
我编写了以下代码来读取未知大小的文件并将每个字符放入缓冲区(对我来说非常有效)。请阅读以下参考资料以更好地掌握文件处理:
尝试这样的事情:
char* buffer;
size_t result;
long lSize;
pFile = fopen("CodeSV.txt","r");
if (pFile==NULL) {fputs ("File error",stderr); exit (1);}
// obtain file size:
fseek (pFile , 0 , SEEK_END);
lSize = ftell (pFile);
rewind (pFile);
buffer = malloc(lSize);
// copy the file into the buffer:
result = fread (buffer,1,lSize,pFile);
if (result != lSize) {fputs ("Reading error 2",stderr); exit (3);}
/* the whole file is now loaded in the memory buffer. */
fclose (pFile);
如果您正在阅读的文件大小不是很大,那么您可以试试这个:
#include<stdio.h>
#include<string.h>
int main()
{
FILE *ptr_file;
char output[10000];
ptr_file =fopen("lol_temp.txt","r");
if (!ptr_file)
return 1;
int bytes_read = fread(output,1,10000,ptr_file);
fclose(ptr_file);
printf("%s",output);
return 0;
}
使用动态链表比使用数组更好。这里我有一个简单的喜欢列表来存储您从文件中读取的每个字符。既然你说 "ultimately I want to read the file into a string, and manipulate the string and output that modified string as a new text file" 我终于创建了一个字符串文件。我测试了它,所以我想它应该可以正常工作:)
您可以将列表的接口和实现分离到单独的文件中,甚至使用 obj。实施文件
#include <stdio.h>
#include <stdlib.h>
typedef char Titem; //just to identify it
// Interface of list
typedef struct node *Tpointer;
typedef struct node {
Titem item;
Tpointer next;
} Tnode;
typedef Tpointer Tlist;
void initialize_list(Tlist *list);
void insert_to_list_end(Tlist *list, Titem data);
void cleanup_list(Tlist *list);
// Implementation of list (only obj file is need in your application)
void initialize_list(Tlist *list) {
*list = NULL;
}
void insert_to_list_end(Tlist *list, Titem data) {
Tpointer newnode, last = *list;
newnode = (Tpointer)malloc(sizeof(Tnode));
newnode->item = data;
newnode->next = NULL;
if (last == NULL){
*list = newnode;
}//first node
else{
while (1) {
if (last->next == NULL) {
last->next = newnode;
break;
}
last = last->next;
}
}
}
void cleanup_list(Tlist *list) {
Tpointer aux1, aux2;
aux1 = *list;
while (aux1 != NULL) {
aux2 = aux1->next;
free(aux1);
printf("\nDeleted"); //for testing purposes
aux1 = aux2;
}
initialize_list(list);
}
#define file_dir "CodeSV.txt"
int main(void){
FILE *fp;
fp = fopen(file_dir, "r");
int counter = 1;
Tlist list;
if (fp) {
initialize_list(&list);
int c;
while ((c = getc(fp)) != EOF){
insert_to_list_end(&list, (char)c);
counter++;
}
fclose(fp);
}
else{ printf("file not found"); return 0; }
//creating a string with what you read
char stringFromFile[counter];
Tlist currentNode = list;
int i;
for (i = 0; i <= counter; i++) {
stringFromFile[i] = currentNode->item;
currentNode = currentNode->next;
if (currentNode == NULL) { break; }
}
printf("WHAT YOU JUST READ: %s", stringFromFile);
/*here you can manipulate the string as you wish. But remember to free the linked list (call cleanup_list) when u're done*/
cleanup_list(&list);
return 1;
}
如果 OP 想要进行文本处理和操作 行 ,而不是将整个文件读入 1 个字符串,请制作一个 行 [=15] 的链表=].
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define LINE_MAXSIZE 65536
typedef struct line_T {
struct line_T *next;
char *data;
size_t length;
} line_T;
line_T *ReadFile(FILE *istream) {
line_T head;
line_T *p = &head;
char *buf = malloc(LINE_MAXSIZE);
assert(buf);
while (fgets(buf, LINE_MAXSIZE, istream)) {
p->next = malloc(sizeof *(p->next));
assert(p->next);
p = p->next;
p->next = NULL;
p->length = strlen(buf);
assert(p->length < LINE_MAXSIZE - 1); // TBD: cope with long lines
p->data = malloc(p->length + 1);
assert(p->data);
memcpy(p->data, buf, p->length + 1);
}
free(buf);
return head.next;
}
unsigned long long CountConsumeData(line_T *p) {
unsigned long long sum = 0;
while (p) {
sum += p->length;
free(p->data);
line_T *next = p->next;
free(p);
p = next;
}
return sum;
}
int main(void) {
const char *fname = "CodeSV.txt";
FILE *istream = fopen(fname, "r");
line_T *p = ReadFile(istream);
fclose(istream);
printf("Length : %llu\n", CountConsumeData(p));
return 0;
}
如果我不在答案中添加可能是从文本文件中读取未知长度未知行的最标准方法之一,那我就是失职了。在 C 语言中,您有两种主要的字符输入方法。 (1) 面向字符 输入(即 getchar
、getc
等)和 (2) 面向行 输入(即 fgets
、getline
)。
从该函数组合中,POSIX 函数 getline
默认情况下将分配足够的 space 来读取任意长度的行(直到系统内存耗尽)。此外,当读取 行 输入时,行导向 输入通常是正确的选择。
要读取未知数量的行,一般方法是分配预期数量的指针(在 char 指针数组 中),然后根据需要重新分配如果您最终需要更多。如果您想在链表中处理将指向结构的指针串在一起的复杂性,那很好,但处理字符串数组要简单得多。 (当你有一个包含多个成员的结构而不是单行时,链表更合适)
这个过程很简单。 (1) 为一些初始数量的指针分配内存(LMAX
下面的 255
),然后在读取每一行时(2)分配内存来保存该行并将该行复制到数组(strdup
在下面使用,(a) 分配内存来保存字符串,(b) 将字符串复制到新的内存块,返回指向其地址的指针)(您将返回到字符串数组的指针分配为array[x]
)
与任何动态内存分配一样,你负责跟踪分配的内存,保留指向每个已分配内存块开始的指针(这样你就可以稍后释放它),然后在不再需要时释放内存。 (使用 valgrind
或一些类似的内存检查器来确认您没有内存错误并且已释放您创建的所有内存)
下面是一个方法示例,它简单地读取任何文本文件并将其行打印回 stdout
,然后再释放分配给保存该文件的内存。阅读所有行后(或在阅读所有行时),您可以轻松地将 csv 输入解析为单独的值。
注意:下面的,当LMAX
行被读取时,array
被重新分配以容纳两倍于之前的行,并且读取继续。 (如果你想为每一行分配一个新的指针,你可以将 LMAX
设置为 1
,但这是处理内存分配的 非常低效的 方法)选择一些合理的预期起始值,然后重新分配 2X
当前是标准的重新分配方法,但您可以自由分配您选择的任何大小的额外块。
查看代码,如果您有任何问题,请告诉我。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LMAX 255
int main (int argc, char **argv) {
if (argc < 2 ) {
fprintf (stderr, "error: insufficient input, usage: %s <filename>\n",
argv[0]);
return 1;
}
char **array = NULL; /* array of pointers to char */
char *ln = NULL; /* NULL forces getline to allocate */
size_t n = 0; /* buf size, 0 use getline default */
ssize_t nchr = 0; /* number of chars actually read */
size_t idx = 0; /* array index for number of lines */
size_t it = 0; /* general iterator variable */
size_t lmax = LMAX; /* current array pointer allocation */
FILE *fp = NULL; /* file pointer */
if (!(fp = fopen (argv[1], "r"))) { /* open file for reading */
fprintf (stderr, "error: file open failed '%s'.", argv[1]);
return 1;
}
/* allocate LMAX pointers and set to NULL. Each of the 255 pointers will
point to (hold the address of) the beginning of each string read from
the file below. This will allow access to each string with array[x].
*/
if (!(array = calloc (LMAX, sizeof *array))) {
fprintf (stderr, "error: memory allocation failed.");
return 1;
}
/* prototype - ssize_t getline (char **ln, size_t *n, FILE *fp)
above we declared: char *ln and size_t n. Why don't they match? Simple,
we will be passing the address of each to getline, so we simply precede
the variable with the urinary '&' which forces an addition level of
dereference making char* char** and size_t size_t *. Now the arguments
match the prototype.
*/
while ((nchr = getline (&ln, &n, fp)) != -1) /* read line */
{
while (nchr > 0 && (ln[nchr-1] == '\n' || ln[nchr-1] == '\r'))
ln[--nchr] = 0; /* strip newline or carriage rtn */
/* allocate & copy ln to array - this will create a block of memory
to hold each character in ln and copy the characters in ln to that
memory address. The address will then be stored in array[idx].
(idx++ just increases idx by 1 so it is ready for the next address)
There is a lot going on in that simple: array[idx++] = strdup (ln);
*/
array[idx++] = strdup (ln);
if (idx == lmax) { /* if lmax lines reached, realloc */
char **tmp = realloc (array, lmax * 2 * sizeof *array);
if (!tmp)
return -1;
array = tmp;
lmax *= 2;
}
}
if (fp) fclose (fp); /* close file */
if (ln) free (ln); /* free memory allocated to ln */
/*
process/use lines in array as needed
(simple print all lines example below)
*/
printf ("\nLines in file:\n\n"); /* print lines in file */
for (it = 0; it < idx; it++)
printf (" array [%3zu] %s\n", it, array[it]);
printf ("\n");
for (it = 0; it < idx; it++) /* free array memory */
free (array[it]);
free (array);
return 0;
}
Use/Output
$ ./bin/getline_rdfile dat/damages.txt
Lines in file:
array [ 0] Personal injury damage awards are unliquidated
array [ 1] and are not capable of certain measurement; thus, the
array [ 2] jury has broad discretion in assessing the amount of
array [ 3] damages in a personal injury case. Yet, at the same
array [ 4] time, a factual sufficiency review insures that the
array [ 5] evidence supports the jury's award; and, although
array [ 6] difficult, the law requires appellate courts to conduct
array [ 7] factual sufficiency reviews on damage awards in
array [ 8] personal injury cases. Thus, while a jury has latitude in
array [ 9] assessing intangible damages in personal injury cases,
array [ 10] a jury's damage award does not escape the scrutiny of
array [ 11] appellate review.
array [ 12]
array [ 13] Because Texas law applies no physical manifestation
array [ 14] rule to restrict wrongful death recoveries, a
array [ 15] trial court in a death case is prudent when it chooses
array [ 16] to submit the issues of mental anguish and loss of
array [ 17] society and companionship. While there is a
array [ 18] presumption of mental anguish for the wrongful death
array [ 19] beneficiary, the Texas Supreme Court has not indicated
array [ 20] that reviewing courts should presume that the mental
array [ 21] anguish is sufficient to support a large award. Testimony
array [ 22] that proves the beneficiary suffered severe mental
array [ 23] anguish or severe grief should be a significant and
array [ 24] sometimes determining factor in a factual sufficiency
array [ 25] analysis of large non-pecuniary damage awards.
内存检查
$ valgrind ./bin/getline_rdfile dat/damages.txt
==14321== Memcheck, a memory error detector
==14321== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
==14321== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==14321== Command: ./bin/getline_rdfile dat/damages.txt
==14321==
Lines in file:
array [ 0] Personal injury damage awards are unliquidated
<snip>
...
array [ 25] analysis of large non-pecuniary damage awards.
==14321==
==14321== HEAP SUMMARY:
==14321== in use at exit: 0 bytes in 0 blocks
==14321== total heap usage: 29 allocs, 29 frees, 3,997 bytes allocated
==14321==
==14321== All heap blocks were freed -- no leaks are possible
==14321==
==14321== For counts of detected and suppressed errors, rerun with: -v
==14321== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2)
int main(int argc, char** argv)
{
FILE* fpInputFile = NULL;
unsigned long ulSize = 0; // Input File size
unsigned long ulIteration = 0;
unsigned char* ucBuffer; // Buffer data
if(argc != 2)
{
printf("Enter ihe file name \n");
return -1;
}
fpInputFile = fopen(argv[1],"r"); // file open
if(!fpInputFile){
fprintf(stderr,"File opening failed");
}
fseek(fpInputFile,0,SEEK_END);
ulSize = ftell(fpInputFile); //current file position
fseek(fpInputFile,0,SEEK_SET);
ucBuffer = (unsigned char*)malloc(ulSize); // memory allocation for ucBuffer var
fread(ucBuffer,1,ulSize,fpInputFile); // Read file
fclose(fpInputFile); // close the file
}
使用 fseek 和 ftell 获取文本文件的偏移量
我正在尝试将未知大小的文本文件读入字符数组。 这是我目前所拥有的。
#include<stdio.h>
#include<string.h>
int main()
{
FILE *ptr_file;
char buf[1000];
char output[];
ptr_file =fopen("CodeSV.txt","r");
if (!ptr_file)
return 1;
while (fgets(buf,1000, ptr_file)!=NULL)
strcat(output, buf);
printf("%s",output);
fclose(ptr_file);
printf("%s",output);
return 0;
}
但我不知道如何在读取未知大小的文件时为输出数组分配大小。 此外,当我为输出输入一个大小时,比如 n=1000,我得到了分段错误。 我是一个非常没有经验的程序员任何指导表示赞赏:)
文本文件本身在技术上是一个 .csv 文件,因此内容如下所示: “0,0,0,1,0,1,0,1,1,0,1...”
执行此操作的标准方法是使用 malloc
分配一定大小的数组,然后开始读取它,如果您 运行 在 运行 字符不足(也就是说,如果在填满数组之前没有达到 EOF
),请为数组选择更大的大小并使用 realloc
使其更大。
这是读取和分配循环的样子。我选择使用 getchar
一次读取输入一个字符(而不是使用 fgets
一次读取一行)。
int c;
int nch = 0;
int size = 10;
char *buf = malloc(size);
if(buf == NULL)
{
fprintf(stderr, "out of memory\n");
exit(1);
}
while((c = getchar()) != EOF)
{
if(nch >= size-1)
{
/* time to make it bigger */
size += 10;
buf = realloc(buf, size);
if(buf == NULL)
{
fprintf(stderr, "out of memory\n");
exit(1);
}
}
buf[nch++] = c;
}
buf[nch++] = '[=10=]';
printf("\"%s\"", buf);
关于这段代码的两个注意事项:
- 初始大小和增量的数字10太小了;在实际代码中,你会想要使用更大的东西。
- 很容易忘记确保尾随'\0'有空间;在这段代码中,我尝试使用
if(nch >= size-1)
. 中的
-1
来做到这一点
我编写了以下代码来读取未知大小的文件并将每个字符放入缓冲区(对我来说非常有效)。请阅读以下参考资料以更好地掌握文件处理:
尝试这样的事情:
char* buffer;
size_t result;
long lSize;
pFile = fopen("CodeSV.txt","r");
if (pFile==NULL) {fputs ("File error",stderr); exit (1);}
// obtain file size:
fseek (pFile , 0 , SEEK_END);
lSize = ftell (pFile);
rewind (pFile);
buffer = malloc(lSize);
// copy the file into the buffer:
result = fread (buffer,1,lSize,pFile);
if (result != lSize) {fputs ("Reading error 2",stderr); exit (3);}
/* the whole file is now loaded in the memory buffer. */
fclose (pFile);
如果您正在阅读的文件大小不是很大,那么您可以试试这个:
#include<stdio.h>
#include<string.h>
int main()
{
FILE *ptr_file;
char output[10000];
ptr_file =fopen("lol_temp.txt","r");
if (!ptr_file)
return 1;
int bytes_read = fread(output,1,10000,ptr_file);
fclose(ptr_file);
printf("%s",output);
return 0;
}
使用动态链表比使用数组更好。这里我有一个简单的喜欢列表来存储您从文件中读取的每个字符。既然你说 "ultimately I want to read the file into a string, and manipulate the string and output that modified string as a new text file" 我终于创建了一个字符串文件。我测试了它,所以我想它应该可以正常工作:) 您可以将列表的接口和实现分离到单独的文件中,甚至使用 obj。实施文件
#include <stdio.h>
#include <stdlib.h>
typedef char Titem; //just to identify it
// Interface of list
typedef struct node *Tpointer;
typedef struct node {
Titem item;
Tpointer next;
} Tnode;
typedef Tpointer Tlist;
void initialize_list(Tlist *list);
void insert_to_list_end(Tlist *list, Titem data);
void cleanup_list(Tlist *list);
// Implementation of list (only obj file is need in your application)
void initialize_list(Tlist *list) {
*list = NULL;
}
void insert_to_list_end(Tlist *list, Titem data) {
Tpointer newnode, last = *list;
newnode = (Tpointer)malloc(sizeof(Tnode));
newnode->item = data;
newnode->next = NULL;
if (last == NULL){
*list = newnode;
}//first node
else{
while (1) {
if (last->next == NULL) {
last->next = newnode;
break;
}
last = last->next;
}
}
}
void cleanup_list(Tlist *list) {
Tpointer aux1, aux2;
aux1 = *list;
while (aux1 != NULL) {
aux2 = aux1->next;
free(aux1);
printf("\nDeleted"); //for testing purposes
aux1 = aux2;
}
initialize_list(list);
}
#define file_dir "CodeSV.txt"
int main(void){
FILE *fp;
fp = fopen(file_dir, "r");
int counter = 1;
Tlist list;
if (fp) {
initialize_list(&list);
int c;
while ((c = getc(fp)) != EOF){
insert_to_list_end(&list, (char)c);
counter++;
}
fclose(fp);
}
else{ printf("file not found"); return 0; }
//creating a string with what you read
char stringFromFile[counter];
Tlist currentNode = list;
int i;
for (i = 0; i <= counter; i++) {
stringFromFile[i] = currentNode->item;
currentNode = currentNode->next;
if (currentNode == NULL) { break; }
}
printf("WHAT YOU JUST READ: %s", stringFromFile);
/*here you can manipulate the string as you wish. But remember to free the linked list (call cleanup_list) when u're done*/
cleanup_list(&list);
return 1;
}
如果 OP 想要进行文本处理和操作 行 ,而不是将整个文件读入 1 个字符串,请制作一个 行 [=15] 的链表=].
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define LINE_MAXSIZE 65536
typedef struct line_T {
struct line_T *next;
char *data;
size_t length;
} line_T;
line_T *ReadFile(FILE *istream) {
line_T head;
line_T *p = &head;
char *buf = malloc(LINE_MAXSIZE);
assert(buf);
while (fgets(buf, LINE_MAXSIZE, istream)) {
p->next = malloc(sizeof *(p->next));
assert(p->next);
p = p->next;
p->next = NULL;
p->length = strlen(buf);
assert(p->length < LINE_MAXSIZE - 1); // TBD: cope with long lines
p->data = malloc(p->length + 1);
assert(p->data);
memcpy(p->data, buf, p->length + 1);
}
free(buf);
return head.next;
}
unsigned long long CountConsumeData(line_T *p) {
unsigned long long sum = 0;
while (p) {
sum += p->length;
free(p->data);
line_T *next = p->next;
free(p);
p = next;
}
return sum;
}
int main(void) {
const char *fname = "CodeSV.txt";
FILE *istream = fopen(fname, "r");
line_T *p = ReadFile(istream);
fclose(istream);
printf("Length : %llu\n", CountConsumeData(p));
return 0;
}
如果我不在答案中添加可能是从文本文件中读取未知长度未知行的最标准方法之一,那我就是失职了。在 C 语言中,您有两种主要的字符输入方法。 (1) 面向字符 输入(即 getchar
、getc
等)和 (2) 面向行 输入(即 fgets
、getline
)。
从该函数组合中,POSIX 函数 getline
默认情况下将分配足够的 space 来读取任意长度的行(直到系统内存耗尽)。此外,当读取 行 输入时,行导向 输入通常是正确的选择。
要读取未知数量的行,一般方法是分配预期数量的指针(在 char 指针数组 中),然后根据需要重新分配如果您最终需要更多。如果您想在链表中处理将指向结构的指针串在一起的复杂性,那很好,但处理字符串数组要简单得多。 (当你有一个包含多个成员的结构而不是单行时,链表更合适)
这个过程很简单。 (1) 为一些初始数量的指针分配内存(LMAX
下面的 255
),然后在读取每一行时(2)分配内存来保存该行并将该行复制到数组(strdup
在下面使用,(a) 分配内存来保存字符串,(b) 将字符串复制到新的内存块,返回指向其地址的指针)(您将返回到字符串数组的指针分配为array[x]
)
与任何动态内存分配一样,你负责跟踪分配的内存,保留指向每个已分配内存块开始的指针(这样你就可以稍后释放它),然后在不再需要时释放内存。 (使用 valgrind
或一些类似的内存检查器来确认您没有内存错误并且已释放您创建的所有内存)
下面是一个方法示例,它简单地读取任何文本文件并将其行打印回 stdout
,然后再释放分配给保存该文件的内存。阅读所有行后(或在阅读所有行时),您可以轻松地将 csv 输入解析为单独的值。
注意:下面的,当LMAX
行被读取时,array
被重新分配以容纳两倍于之前的行,并且读取继续。 (如果你想为每一行分配一个新的指针,你可以将 LMAX
设置为 1
,但这是处理内存分配的 非常低效的 方法)选择一些合理的预期起始值,然后重新分配 2X
当前是标准的重新分配方法,但您可以自由分配您选择的任何大小的额外块。
查看代码,如果您有任何问题,请告诉我。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LMAX 255
int main (int argc, char **argv) {
if (argc < 2 ) {
fprintf (stderr, "error: insufficient input, usage: %s <filename>\n",
argv[0]);
return 1;
}
char **array = NULL; /* array of pointers to char */
char *ln = NULL; /* NULL forces getline to allocate */
size_t n = 0; /* buf size, 0 use getline default */
ssize_t nchr = 0; /* number of chars actually read */
size_t idx = 0; /* array index for number of lines */
size_t it = 0; /* general iterator variable */
size_t lmax = LMAX; /* current array pointer allocation */
FILE *fp = NULL; /* file pointer */
if (!(fp = fopen (argv[1], "r"))) { /* open file for reading */
fprintf (stderr, "error: file open failed '%s'.", argv[1]);
return 1;
}
/* allocate LMAX pointers and set to NULL. Each of the 255 pointers will
point to (hold the address of) the beginning of each string read from
the file below. This will allow access to each string with array[x].
*/
if (!(array = calloc (LMAX, sizeof *array))) {
fprintf (stderr, "error: memory allocation failed.");
return 1;
}
/* prototype - ssize_t getline (char **ln, size_t *n, FILE *fp)
above we declared: char *ln and size_t n. Why don't they match? Simple,
we will be passing the address of each to getline, so we simply precede
the variable with the urinary '&' which forces an addition level of
dereference making char* char** and size_t size_t *. Now the arguments
match the prototype.
*/
while ((nchr = getline (&ln, &n, fp)) != -1) /* read line */
{
while (nchr > 0 && (ln[nchr-1] == '\n' || ln[nchr-1] == '\r'))
ln[--nchr] = 0; /* strip newline or carriage rtn */
/* allocate & copy ln to array - this will create a block of memory
to hold each character in ln and copy the characters in ln to that
memory address. The address will then be stored in array[idx].
(idx++ just increases idx by 1 so it is ready for the next address)
There is a lot going on in that simple: array[idx++] = strdup (ln);
*/
array[idx++] = strdup (ln);
if (idx == lmax) { /* if lmax lines reached, realloc */
char **tmp = realloc (array, lmax * 2 * sizeof *array);
if (!tmp)
return -1;
array = tmp;
lmax *= 2;
}
}
if (fp) fclose (fp); /* close file */
if (ln) free (ln); /* free memory allocated to ln */
/*
process/use lines in array as needed
(simple print all lines example below)
*/
printf ("\nLines in file:\n\n"); /* print lines in file */
for (it = 0; it < idx; it++)
printf (" array [%3zu] %s\n", it, array[it]);
printf ("\n");
for (it = 0; it < idx; it++) /* free array memory */
free (array[it]);
free (array);
return 0;
}
Use/Output
$ ./bin/getline_rdfile dat/damages.txt
Lines in file:
array [ 0] Personal injury damage awards are unliquidated
array [ 1] and are not capable of certain measurement; thus, the
array [ 2] jury has broad discretion in assessing the amount of
array [ 3] damages in a personal injury case. Yet, at the same
array [ 4] time, a factual sufficiency review insures that the
array [ 5] evidence supports the jury's award; and, although
array [ 6] difficult, the law requires appellate courts to conduct
array [ 7] factual sufficiency reviews on damage awards in
array [ 8] personal injury cases. Thus, while a jury has latitude in
array [ 9] assessing intangible damages in personal injury cases,
array [ 10] a jury's damage award does not escape the scrutiny of
array [ 11] appellate review.
array [ 12]
array [ 13] Because Texas law applies no physical manifestation
array [ 14] rule to restrict wrongful death recoveries, a
array [ 15] trial court in a death case is prudent when it chooses
array [ 16] to submit the issues of mental anguish and loss of
array [ 17] society and companionship. While there is a
array [ 18] presumption of mental anguish for the wrongful death
array [ 19] beneficiary, the Texas Supreme Court has not indicated
array [ 20] that reviewing courts should presume that the mental
array [ 21] anguish is sufficient to support a large award. Testimony
array [ 22] that proves the beneficiary suffered severe mental
array [ 23] anguish or severe grief should be a significant and
array [ 24] sometimes determining factor in a factual sufficiency
array [ 25] analysis of large non-pecuniary damage awards.
内存检查
$ valgrind ./bin/getline_rdfile dat/damages.txt
==14321== Memcheck, a memory error detector
==14321== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
==14321== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==14321== Command: ./bin/getline_rdfile dat/damages.txt
==14321==
Lines in file:
array [ 0] Personal injury damage awards are unliquidated
<snip>
...
array [ 25] analysis of large non-pecuniary damage awards.
==14321==
==14321== HEAP SUMMARY:
==14321== in use at exit: 0 bytes in 0 blocks
==14321== total heap usage: 29 allocs, 29 frees, 3,997 bytes allocated
==14321==
==14321== All heap blocks were freed -- no leaks are possible
==14321==
==14321== For counts of detected and suppressed errors, rerun with: -v
==14321== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2)
int main(int argc, char** argv)
{
FILE* fpInputFile = NULL;
unsigned long ulSize = 0; // Input File size
unsigned long ulIteration = 0;
unsigned char* ucBuffer; // Buffer data
if(argc != 2)
{
printf("Enter ihe file name \n");
return -1;
}
fpInputFile = fopen(argv[1],"r"); // file open
if(!fpInputFile){
fprintf(stderr,"File opening failed");
}
fseek(fpInputFile,0,SEEK_END);
ulSize = ftell(fpInputFile); //current file position
fseek(fpInputFile,0,SEEK_SET);
ucBuffer = (unsigned char*)malloc(ulSize); // memory allocation for ucBuffer var
fread(ucBuffer,1,ulSize,fpInputFile); // Read file
fclose(fpInputFile); // close the file
}
使用 fseek 和 ftell 获取文本文件的偏移量