Reading a text file

Hello all...
Iam Avinash from India.
I wanted to know how to extract a number from a specified line in a text file using C. I know how to read a file but couldn't retrieve the number. Is there any string or numeric conversions to be done upfront.

To read a file line-by-line you could use std::getline().
http://www.cplusplus.com/reference/string/string/getline/

After you read the correct line in an std::string, use a string stream to extract the number(s).
http://www.cplusplus.com/reference/sstream/stringstream/

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
#include <sstream>
#include <string>

// ...

std::string line;
std::stringstream numbers;
int n;

std::getline(input_file, line);
numbers.str(line);
line >> n;


Edit: my mistake. I missed the "using C" part.

In C, instead of string streams you could use the strtok() + strtoX() combo.
http://www.cplusplus.com/reference/cstring/strtok/
http://www.cplusplus.com/reference/cstdlib/
http://www.cplusplus.com/reference/cstdlib/strtol/

To read a line in C you could use fgets():
http://www.cplusplus.com/reference/cstdio/fgets/
Last edited on
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <stdio.h>

int main()
{
    // read integer from a specified line in text file
    int line_number = 23 ; // first line is line number 1
    
    printf( "try to read integer from line %d of file " __FILE__ "\n", line_number ) ; 
    FILE* file = fopen( __FILE__, "r" ) ;
    
    int ch ;
    while( line_number > 1 && ( ch = fgetc(file) ) != EOF )
        if( ch == '\n' ) --line_number ; // skip till we reach the required line
        
    int number ;
    int result = fscanf( file, "%d", &number ) ;
    if( result != 0 && result != EOF ) printf( "number %d was read\n", number ) ;
}

/*
    12345
    67
    8901
    2345
    67890
    123
*/

http://coliru.stacked-crooked.com/a/209e1682fc85e774
But if a single line has more numbers delimited with space, like....
"Strain 0.000234 0.00237 0.00241 0.00089".
How to store these numbers? if we use arrays...size of the array should be defined before. But I dont know how many values are present in the line.
develaavi wrote:
But if a single line has more numbers delimited with space, like....
"Strain 0.000234 0.00237 0.00241 0.00089".
How to store these numbers? if we use arrays...size of the array should be defined before. But I dont know how many values are present in the line.

The code given by JLBorges will still work well to get you to the correct line.

After you get to the correct line, a simple approach could be to use a fixed-size char buffer to read the line into, then a fixed-size double array to read the numbers in, by using strtok() and strtod().

http://coliru.stacked-crooked.com/a/14fa4ef629520110

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void)
{
    // read integer from a specified line in text file
    int line_number = 47; // first line is line number 1

    printf("try to read integer from line %d of file " __FILE__ "\n", line_number); 
    FILE *file = fopen(__FILE__, "r");

    int ch;

    while (line_number > 1 && (ch = fgetc(file)) != EOF)
        if (ch == '\n')
            --line_number; // skip till we reach the required line

    double numbers[20];
    size_t numbers_len = 0;
    char buffer[100];
    char *result = fgets(buffer, sizeof buffer, file);

    if (result != NULL && !feof(file))
    {
        char *token = strtok(buffer, " ");

        printf("At line %d, strain name is \"%s\".\n", line_number, token);

        while ((token = strtok(NULL, " ")) != NULL)
            numbers[numbers_len++] = strtod(token, NULL);

        printf("A total number of %zu numbers were extracted.\n", numbers_len);
        printf("They are: ");

        for (size_t i=0; i < numbers_len; ++i)
            printf("%f ", numbers[i]);

        printf("\n");
    }
}

/*
    StrainOne   0.000234 0.00237 0.00241 0.00089
    StrainTwo   1.000234 1.00237 1.00241 1.00089 1.03220
    StrainThree 2.000234 2.00237 2.00241 2.00089 2.03220 2.39921
    StrainFour  3.000234 3.00237 3.00241 3.00089 3.03220 3.39921 3.90200
*/

> But if a single line has more numbers delimited with space, like....
> "Strain 0.000234 0.00237 0.00241 0.00089".

1. Get to the line
2. skip characters till we get a digit
1
2
    do ch = fgetc(file) ;
    while( !isdigit(ch) && ch != EOF ) ;

3. put back the digit ungetc( ch, file ) ;

4. fscanf( file, "%d", &number ) in a loop till it fails


> How to store these numbers?
> I dont know how many values are present in the line.

Use a dynamically sized array. The general idea is something like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
size_t sz = 20 ;
int* array = malloc( sz * sizeof(int) ) ;
if( array == NULL ) { /* handle error */ } 

size_t pos = 0 ;
int result = 0 ;

while( ( result = fscanf( file, "%d", &number ) != 0 )
{
     array[pos] = number ;

     if( pos == (sz-1) )
     {
         sz *= 2 ;
         int* temp = realloc( array, sz * sizeof(int) ) ;
         if( temp == NULL )
         {
             free(array) ;
             /* handle error */ 
         }
         else array = temp ;
     }

     ++pos ;
     result = 0 ;
}


EDIT: Hadn't seen the post by Catfish666 when I wrote this. So this post is redundant.
Leaving it in, just in case a dynamically resized array is really needed.
Last edited on
Topic archived. No new replies allowed.