文本行字符在c中动态计数

时间:2018-07-05 09:14:25

标签: c file-handling

   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时,我甚至会给出更多的字符串。我很困惑 。请帮帮我!!

3 个答案:

答案 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;
}