Символ строки текста рассчитывается динамически в c - PullRequest
0 голосов
/ 05 июля 2018
   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 голосов
/ 05 июля 2018

Один из способов сделать это, не связывая себя узлами в распределении памяти и т. Д., Это:

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);

т.е. читать файл по одному символу за раз, считая символы по ходу дела. Пусть ОС и библиотека времени выполнения беспокоятся о буферизации - вот для чего они нужны. Возможно, не самый эффективный, но иногда простота выгодна.

Удачи.

0 голосов
/ 05 июля 2018

Вот функция 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;
}
0 голосов
/ 05 июля 2018

Некоторые проблемы:

Сначала вы хотите строку:

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 опасно . Если вы хотите получить байты из файла, а также посчитать их, вы можете использовать fread, например:

size_t tmp;
while(tmp = fread(line, sizeof(char), BUFFER_SIZE, file))
{
    count += tmp;
    /* do stuff on line */
}

Но если вы хотите узнать только размер вашего файла, проверьте этот другой пост .

...