Line by line I need to get the whole content in a line from a file. I have looked at fgetc, fgets. According to fgets, I need to specify max number of characters to read.

If I have file content like this:

1235690,9087657788888770000,89977553223456789\n

I wouldn't know how max characters in the file, is there a way to tell C to just read until \n?

Recommended Answers

All 11 Replies

Line by line I need to get the whole content in a line from a file. I have looked at fgetc, fgets. According to fgets, I need to specify max number of characters to read.

If I have file content like this:

1235690,9087657788888770000,89977553223456789\n

I wouldn't know how max characters in the file, is there a way to tell C to just read until \n?

I do not meet that command .
You can use for small files < 3.2MB;
char *t;
FILE *fp;
fgets( t, 32767, fp);


I wouldn't know how max characters in the file, is there a way to tell C to just read until \n?

Yes there's a way in C to just read until the '\n'. Nevertheless, that will not help you in what you want to do.
Create a buffer with an extra long capability; say buffer[255]. Use fgets() to read the line.
Then, remove the '\n' from buffer[ strlen ( buffer) - 1 ] if it is there.

I rather listen the tips.

remove it with

len = strlen( buffer);
if( buffer[len-1]  == '\n')
 buffer[len-1] =  '\0';

I do not meet that command .
You can use for small files < 3.2MB;
char *t;
FILE *fp;
fgets( t, 32767, fp);

How did you come up with 32767? If your files are smaller than 3.2MB, you still have to account for up to 3.2MB, which is 3355443, not 32767. And this still doesn't solve the problem because you're wasting oodles of memory[1].

>I wouldn't know how max characters in the file, is there a way to tell C to just read until \n?
You can guess at the size or use a "big enough" size for your array, but both of those are wasteful assumptions that can fail. So there's no way to do it safely without writing your own function:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/**
  <summary>Read an arbitrarily long line from input</summary>
  <param name="in">in The input stream to read from</param>
  <returns>
  On success, a pointer to the new line is returned. If memory
  allocation fails, end-of-file is reached, or a read error occurs
  before storing any characters, a null pointer is returned.
  </returns>
  <remarks>
  jsw_getline returns a pointer that must be freed
  </remarks>
*/
char *jsw_getline ( FILE *in )
{
    char buffer[BUFSIZ]; /* Buffer for partial lines */
    char *result = NULL; /* Buffer for the complete line */
    size_t size = 0;     /* Amount of memory assigned to result */

    /* In the average case, this should only run once */
    while ( fgets ( buffer, sizeof buffer, in ) != NULL ) {
        size_t len = strlen ( buffer );
        char *save = realloc ( result, size + len + 1 );

        /* If allocation fails, take what we've got */
        if ( save == NULL )
            break;

        /* Update the result buffer */
        strcpy ( save + size, buffer );
        result = save;
        size += len;

        /* Finish up if we found a newline */
        if ( result[size - 1] == '\n' ) {
            result[size - 1] = '\0';
            break;
        }
    }

    return result;
}

[1] That's assuming you simply omitted t's memory allocation for brevity. If you think that you can use a pointer without pointing it to memory that you own then your entire example is severely broken.

Narue ,can you be so nice and explain me why do you think that this code read will until '\0'.
I am a noob .

>Narue ,can you be so nice
You must be new here.

>explain me why do you think that this code read will until '\0'
I don't think it reads until '\0' because that's not what it does. If you bothered to read the comments I so nicely placed in the code then you would know exactly what I think it does. It reads an arbitrarily long line (ie. up to '\n' or end-of-file if there isn't a newline) and returns a pointer to the dynamically allocated memory where the line is stored, or a null pointer if an error occurs.

Concerning:

/* jsw_getline returns a pointer that must be freed */

If the pointer returned by jsw_getline function is used as

printf( "%s\n", jsw_getline( fp ) );

the ability of freeing that memory is lost. Correct? Is that what constitute a memory leak?

If a pointer is initialized to the function return

fjpt = jsw_getline ( fp );

does

free( fjpt );

take care of freeing that originally allocated dynamic memory?

Concerning:

/* jsw_getline returns a pointer that must be freed */

If the pointer returned by jsw_getline function is used as

printf( "%s\n", jsw_getline( fp ) );

the ability of freeing that memory is lost. Correct? Is that what constitute a memory leak?

Correct.

If a pointer is initialized to the function return

fjpt = jsw_getline ( fp );

does

free( fjpt );

take care of freeing that originally allocated dynamic memory?

Yes, that's it exactly. Personally I hate that kind of interface because it's not obvious that the memory needs to be freed, and because of that the function is more likely to be used in such a way that memory leaks show up. This is where garbage collection or destructors are ideal. You can keep the interface simple but still avoid resource leaks.

I think you can try this:
I tried this in gcc compilers, since 'a' optional argument will be present in gcc.

main()
{
char *no;
printf ("Enter a really large number: ");
fscanf (stdin, "%s[0-9,]", &no);
printf ("The number you typed: %s", no);
free (no);
}

This program will also take ',' in between. you can remove then and use other library functions to convert from string format to integer format. Note this will not take floating point, you need to makeup the string such that it takes the floating point number.

If you want to read complete line till \n then here is th code:

main()
{
char *str;
printf ("Enter a string: ");
fscanf (stdin, "%a[^\n]", &str);
printf ("The string is : %s\n", str);
free (str);
}

This is tested with gcc compiler on SLES10 (Suse enterprise Linux).

>I think you can try this:
Let's start with the fact that this thread is nearly a year old. :icon_rolleyes:

>main()
While this will still work, as C99 compilers become more prevalent your code will quickly become a liability as C99 removed the implicit int feature. Now you must specify a return type. You can return any type you want, as long as it's int.

>printf ("Enter a really large number: ");
It's a good idea to add an fflush call for stdout so that this prompt is visible before fscanf starts blocking for input.

>char *no;
>fscanf (stdin, "%s[0-9,]", &no);
Use of an uninitialized pointer is the height of stupidity. I don't care what compiler options you use, this code is wrong.

>free (no);
I'm shocked that you managed to compile and run your code without any problems. Trying to free a pointer that wasn't returned by malloc (or calloc, or realloc) is extremely likely to fail miserably.

>Note this will not take floating point, you need to makeup
>the string such that it takes the floating point number.
Which isn't possible, as the valid formatting for a floating-point number is unsurprisingly complex. You can't boil all of the rules down to a single scanf format string and expect it to cover all of the valid cases while still disallowing all of the invalid cases.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.