文本行字符在c中动态计数
Text line character count dynamically in c
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 时,即使我给出更多的字符串。我很迷惑 。请帮帮我!!
一些问题:
首先,你需要一行:
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
like :
size_t tmp;
while(tmp = fread(line, sizeof(char), BUFFER_SIZE, file))
{
count += tmp;
/* do stuff on line */
}
但如果您只想获取文件的大小,请查看 this other post。
一种不让自己陷入内存分配等问题的方法是:
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 和运行时库担心缓冲——这就是它们的目的。也许不是最有效的,但有时简单是有益的。
祝你好运。
这里是一个函数 mfgets
,它将一行读入动态分配的缓冲区。它应该是合理的防弹。
喜欢 fgets
它 returns NULL
如果没有字符被读取。但是,如果在读取任何字符之前初始缓冲区分配失败,它也可以 return NULL
。
如果缓冲区分配或重新分配在任何时候失败,它会将 errno
设置为 ENOMEM
,但如果已读取任何字符,则缓冲区仍 returned。
作为奖励,第二个参数可用于获取缓冲区中字符串的长度。
可以通过调用 free
函数释放 returned 缓冲区。
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;
}
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 时,即使我给出更多的字符串。我很迷惑 。请帮帮我!!
一些问题:
首先,你需要一行:
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
like :
size_t tmp;
while(tmp = fread(line, sizeof(char), BUFFER_SIZE, file))
{
count += tmp;
/* do stuff on line */
}
但如果您只想获取文件的大小,请查看 this other post。
一种不让自己陷入内存分配等问题的方法是:
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 和运行时库担心缓冲——这就是它们的目的。也许不是最有效的,但有时简单是有益的。
祝你好运。
这里是一个函数 mfgets
,它将一行读入动态分配的缓冲区。它应该是合理的防弹。
喜欢 fgets
它 returns NULL
如果没有字符被读取。但是,如果在读取任何字符之前初始缓冲区分配失败,它也可以 return NULL
。
如果缓冲区分配或重新分配在任何时候失败,它会将 errno
设置为 ENOMEM
,但如果已读取任何字符,则缓冲区仍 returned。
作为奖励,第二个参数可用于获取缓冲区中字符串的长度。
可以通过调用 free
函数释放 returned 缓冲区。
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;
}