Reading both string and integer from a text file

17,093

Solution 1

If the file is in exactly that format, you can use scanf() easily. Here's some code to get you started; I haven't tested this and you need to fill in a few missing things.

#include <ctypes.h>  // for isspace()
#include <stdio.h> // for scanf(), getchar(), and EOF

char c2d[MAX_LINES][MAX_LENGTH_STRING_PER_LINE];
char *pstr;
float f2d[MAX_LINES][6]; // 6 floats per line
float *p;
int c, current_line_number;
char ch;
FILE *input;

input = fopen(...);
if (!input)
    ... handle the error

for (current_line_number = 0; ; ++current_line_number)
{
    // handle each line of input

    // first read 6 float values
    p = f2d + current_line_number;
    c = fscanf(input, "%f %f %f %f %f %f", p + 0, p + 1, p + 2, p + 3, p + 4, p + 5);
    if (c != 6)
        ... handle the error here

    // next grab string; stop at '<' or end of line or EOF
    pstr = c2d + current_line_number;
    for (;;)
    {
        ch = fgetc(input);
        if (ch == EOF || ch == '<' || ch == '\n')
        {
            *pstr = '\0';
            break;
        }
        *pstr++ = ch;
    }
    if (ch == '<')
    {
        // char was '<' so throw away rest of input line until end of line
        for (;;)
        {
            if (ch == EOF || ch == '\n')
                break;
            ch = fgetc(input);
        }
    }
    for (;;)
    {
        // eat up any white space, including blank lines in input file
        if (ch == EOF || !isspace(ch))
            break;
        ch = fgetc(input);
    }
    // once we have hit end of file we are done; break out of loop
    if (ch == EOF)
        break;
}

fclose(input);

I didn't use scanf() to read the string at the end of the line because it stops when it hits white space, and your string values have spaces in them.

If the input file isn't always six float values, you will need to write code to call scanf() one float at a time until you hit something that doesn't parse as a float, and you will need to make the array of floats wide enough to handle the largest number of floats you will permit per line.

Good luck.

Solution 2

Instead of using fscanf I would recommend using fgets to get the line. Then use sscanf on that line to get the numeric values, and search for the first alphabetic character to know where the string starts (using e.g. strspn).

Something like this:

char line[256];

while (fgets(line, sizeof(line), fp) != NULL)
{
    /* Get the numbers */
    float numbers[6];
    sscanf(line, "%f %f %f %f %f %f",
        &numbers[0], &numbers[1], &numbers[2],
        &numbers[3], &numbers[4], &numbers[5]);

    /* Where do the numbers end... */
    size_t numbers_end = strspn(line, "1234567890. \t");

    /* And get the name */
    char *name = line + numbers_end;

    /* Do something with the numbers and the name */
}
Share:
17,093
slow
Author by

slow

newbie

Updated on August 02, 2022

Comments

  • slow
    slow almost 2 years

    Let say I have a file looks like this

    51.41 52.07 52.01 51.22 50.44 49.97 Coal Diggers
    77.26 78.33 78.29 78.12 77.09 75.74 Airplane Flyers
    31.25 31.44 31.43 31.09 31.01 30.92 Oil Fracting and Pumping
    52.03 12.02 12.04 22.00 31.98 61.97 Big Bank
    44.21 44.32 44.29 43.98 43.82 43.71 Rail Container Shipping
    93.21 93.11 93.02 93.31 92.98 92.89 Gold Bugs
    

    I want to read this file word using fscanf to put the numbers in float arrays and words in an array of strings. But, after few hours of strenuous thinking, I still can't figure out how to resolve this thing.

    void dataInsert (COMPANY* company1, COMPANY* company2, COMPANY* company3, COMPANY* company4, COMPANY* company5, COMPANY* company6)
    {
    //Function Declaration
    FILE* spData;
    float number;
    char* name[20];
    
    //Statement
    if ((spData = fopen("dataFile","r")) == NULL)
    {
        fprintf(stderr, "ERROR OPENING!!");
        exit (1);
    }
    
    int i = 0;
    int numCount = 0;
    int lineCount = 0;
    while (fscanf(spData, "%f", &number) != EOF)
    {
        if(isdigit(number))
        {
            if (lineCount == 0)
            {
                company1 -> stock_price[i] = number;
            }
            else if (lineCount == 1)
            {
                company2 -> stock_price[i] = number;
            }
            else if (lineCount == 2)
            {
                company3 -> stock_price[i] = number;
            }
            else if (lineCount == 3)
            {
                company4 -> stock_price[i] = number;
            }
            else if (lineCount == 4)
            {
                company5 -> stock_price[i] = number;
            }
            else if (lineCount == 5)
            {
                company6 -> stock_price[i] = number;
            }
    
            numCount++;
            i++;
            if (numCount == 6)
            {
                lineCount++;
                numCount = 0;
                i = 0;
            }
        }
    }//while
    fclose (spData);
    }//dataInsert
    

    I don't know what to do with strings at the end of each line. I want to put those string in structure company -> name[10]. Those data are in a text file.

  • uba
    uba about 11 years
    fscanf is to be used instead of scanf, right? The input is not from stdin, it is from a file.
  • steveha
    steveha about 11 years
    Sure, and fgetc() instead of getchar(). I changed the answer.
  • slow
    slow about 11 years
    If I use scanf, does it just skip the strings at the end of each line?
  • steveha
    steveha about 11 years
    According to the man page for scanf(), the format code %s reads any sequence of characters that is non-white-space, and then stops when it hits white-space. Since the company names can have spaces in them, I thought it was easier to just loop until done rather than try to get scanf() to do what we want. When you use scanf() with the %f format code, it will return a 0 to signal that the input didn't work as a float, and you will have some nonsense value in the float... probably a 0 or garbage, I haven't checked. You can try it if you like.
  • slow
    slow about 11 years
    Thanks for the reply but, unfortunately, I can't use sscanf since this is part of a school assignment so I have to do it based on what I have learned in class.
  • Some programmer dude
    Some programmer dude about 11 years
    @ProgrammingNerd Never be afraid of "thinking outside the box"... You could do two solutions, one following the assignment to the letter, and then list possible shortcomings followed by a solution that solves the assignment but without the shortcomings.
  • Some programmer dude
    Some programmer dude about 11 years
    @ProgrammingNerd Not that I'm saying that my solution is without shortcomings in itself, all solutions have pros and cons, including mine.
  • slow
    slow about 11 years
    Yeah, I always try to solve problems in numerous ways, although it is the not best solution. That is what makes programming so interesting and fun! haha