char *line = NULL;
int count=0;
line = (char*)malloc(sizeof(char));
while(fgets(line,sizeof(line),file)){
line = realloc(line,sizeof(char*)); // dynamically increase allocate memory
count++;
}
printf("count number :%d\n",count);
free(line);
我正在尝试在阅读文本的每一行中计数字符,但现在尝试在一行中进行计数。每次计数为4时,我甚至会给出更多的字符串。我很困惑 。请帮帮我!!
答案 0 :(得分:2)
一些问题:
首先,您需要一行:
line = (char*)malloc(sizeof(char));
这等效于分配一个字节-sizeof(char)
-并将其地址存储到line
。也许您想获取一个更大的缓冲区以从文件中获取一些字符。
一种方法是定义一个恒定大小:
#define BUFFER_SIZE 256
line = (char *)malloc(sizeof(char) * BUFFER_SIZE);
之后,您运行计数器。
while(fgets(line,sizeof(line),file))
也是错误的,因为您最多要读取sizeof(line)
个字节,这等效于sizeof(char *)
。它是32位还是64位,具体取决于您的系统架构。
您最多要读取缓冲区的大小,这意味着您最多要读取BUFFER_SIZE
个字符。所以最好这样做:
while(fgets(line,sizeof(char) * BUFFER_SIZE, file))
{
/* do stuff */
}
这是一个警告:fgets
的使用是dangerous。如果您想从文件中获取字节并进行计数,可以使用fread
:
size_t tmp;
while(tmp = fread(line, sizeof(char), BUFFER_SIZE, file))
{
count += tmp;
/* do stuff on line */
}
但是,如果您只想获取文件的大小,请检查this other post。
答案 1 :(得分:0)
做到这一点而又不会在内存分配等方面陷入束缚的一种方法是:
FILE *f;
int n;
char c;
int line_number = 1;
int line_length = 0;
f = fopen("whatever", "r");
while (n = fread(&c, 1, 1, f))
{
if (c != '\n')
line_length += 1;
else
{
printf("Length of line %d = %d\n", line_number , line_length);
line_number += 1;
line_length = 0;
}
}
fclose(f);
即一次读取一个字符,并随即计算字符数。让OS和运行时库担心缓冲-这就是它们的作用。也许不是最有效的方法,但有时简单是有益的。
好运。
答案 2 :(得分:0)
这是一个函数mfgets
,它将一行读取到动态分配的缓冲区中。应该合理地防弹。
像fgets
一样,如果未读取任何字符,它将返回NULL
。但是,如果在读取任何字符之前初始缓冲区分配失败,它也会返回NULL
。
如果缓冲区分配或重新分配在任何时候失败,但是它将errno
设置为ENOMEM
,但是如果已读取任何字符,则仍然返回缓冲区。
作为奖励,第二个参数可用于获取缓冲区中字符串的长度。
可以通过调用free
函数来释放返回的缓冲区。
mfgets.h :
#ifndef MFGETS_H__INCLUDED__
#define MFGETS_H__INCLUDED__
#include <stdio.h>
char *mfgets(FILE *stream, size_t *stringlen);
#endif
mfgets.c :
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <limits.h>
#include <errno.h>
#include "mfgets.h"
/**
* Read a line into allocated memory.
*
* Reads a line from a stream into memory allocated by \b malloc() or
* \b realloc() until an \b EOF or a newline is read. If a newline is
* read, it is stored into the memory. A terminating null byte is
* stored after the last character in the memory. The memory can be
* freed with \b free().
*
* \param stream The stream pointer.
* \param[out] stringlen If non-null, set to length of string read.
*
* \return A pointer to the memory if at least one character was read,
* otherwise \c NULL.
*
* \remark \c errno is set to \c ENOMEM on failure to allocate memory
* of sufficient size to store the whole line. If the line has been
* partially read, memory is still returned even if \c errno is set to
* \c ENOMEM.
*/
char *mfgets(FILE *stream, size_t *stringlen)
{
size_t buflen = 256; /* initial allocation size */
size_t slen = 0; /* string length */
int err = 0; /* new error */
int olderr = errno; /* old error propagation */
char *buf; /* allocated buffer */
char *newbuf; /* reallocated buffer */
/* allocate initial buffer */
buf = malloc(buflen);
if (!buf) {
err = ENOMEM;
} else {
/* read remainder of line into new part of buffer */
while (fgets(buf + slen, buflen - slen, stream)) {
/* update string length */
slen += strlen(buf + slen);
if (slen < buflen - 1 || buf[slen - 1] == '\n') {
/* fgets() did not run out of space */
break;
}
/* need to increase buffer size */
if (buflen == SIZE_MAX) {
/* cannot increase buffer size */
err = ENOMEM;
break;
}
if (SIZE_MAX - buflen >= buflen && buflen <= INT_MAX) {
/* double buffer size */
buflen *= 2;
} else if (SIZE_MAX - buflen > INT_MAX) {
/* increase buffer size by maximum amount
* that can be passed to fgets() */
buflen += INT_MAX;
} else {
/* increase buffer size to maximum amount */
buflen = SIZE_MAX;
}
/* reallocate buffer with new size */
newbuf = realloc(buf, buflen);
if (!newbuf) {
err = ENOMEM;
break;
}
buf = newbuf;
}
/* finished reading line (or reached EOF or stream error) */
if (slen) {
/* reallocate buffer to actual string size */
newbuf = realloc(buf, slen + 1);
if (newbuf) {
buf = newbuf;
}
} else {
/* no characters read, so do not return a buffer */
free(buf);
buf = NULL;
}
}
if (stringlen) {
/* caller wants actual length of string */
*stringlen = slen;
}
/* set new error or propagate old error */
errno = err ? err : olderr;
/* return buffer or NULL */
return buf;
}
测试程序:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include "mfgets.h"
int main(void)
{
size_t slen;
char *line;
errno = 0;
while ((line = mfgets(stdin, &slen)) != NULL) {
printf("(%zu) %s", slen, line);
free(line);
errno = 0;
}
if (errno) {
perror("");
}
return 0;
}