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

I am trying to count character in every line reading text , but for now trying to one line . Every time count number is 4 even i give more character string . I am confused . Please help me !!

claymorehack
  • 78
  • 10

3 Answers3

2

Some issues :

First, you want a line :

line = (char*)malloc(sizeof(char));

This is equivalent to allocate one byte - sizeof(char) - and store its address to line. Maybe you want to get a larger buffer to get some characters from a file. One of the way to do that is to define a constant size :

#define BUFFER_SIZE 256
line = (char *)malloc(sizeof(char) * BUFFER_SIZE);

After, you run the counter while.

while(fgets(line,sizeof(line),file))

is also wrong, because you want to read at most sizeof(line) bytes, which is equivalent to sizeof(char *). It's 32 or 64 bits depending on your system architecture.

You want to read as most the size of your buffer, which means you want to read at most BUFFER_SIZE characters. So it's better to do :

while(fgets(line,sizeof(char) * BUFFER_SIZE, file))
{
      /* do stuff */
}

It's a warning : the use of fgets is dangerous. If you want to get bytes from file and also to count them you can use fread like :

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

But if you only want to get the size of your file, go check this other post.

Paul Ankman
  • 190
  • 9
  • Is this any way doing it without define buffer size? if i need more than 256 bit memory , when what i do? – claymorehack Jul 05 '18 at 10:28
  • @claymorehack In general you don't need to keep all of your file's data in memory. It's pointless and too big. You keep only few bytes and compute them. Then you get some more. I just test and it works well, did you open your `FILE *` in binary mode to use `fread` ? – Paul Ankman Jul 05 '18 at 12:18
0

One way to do this without tying yourself in knots over memory allocation, etc, is:

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

i.e. read the file one character at a time, counting characters as you go. Let the OS and the runtime library worry about buffering - that's what they're there for. Perhaps not the most efficient, but sometimes simplicity is beneficial.

Best of luck.

0

Here is a function mfgets that reads a line into a dynamically allocated buffer. It should be reasonably bomb-proof.

Like fgets it returns NULL if no characters were read. However, it can also return NULL if the initial buffer allocation failed before any characters were read.

It sets errno to ENOMEM if a buffer allocation or reallocation failed at any point, but if any characters have been read, then a buffer is still returned.

As a bonus, the second parameter can be used to obtain the length of the string in the buffer.

The returned buffer can be freed by calling the free function.

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

Test program:

#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;
}
Ian Abbott
  • 15,083
  • 19
  • 33
  • /tmp/cc7tRlyN.o: In function `log_in': main.c:(.text+0x2aa): undefined reference to `mfgets' collect2: error: ld returned 1 exit status your code is getting error like this – claymorehack Jul 05 '18 at 16:48
  • @claymorehack Well, you need to compile and link it. I assume you know how to compile and link C programs comprised of more than one .c file? – Ian Abbott Jul 09 '18 at 11:00