简体   繁体   中英

How to read next line of input file until end of file without using EOF

I have an input file (lets say 10 lines) of coordinate pairs with each line looking something like this:

(1653408W, 503223N) (1651614W, 502806N)

I am trying to put the given input into DMS format. Each line in the input file ends with a \\n character and I would like to loop through the file and stop after the final \\n . I was thinking of using something like:

while(fscanf(filename,
             "(%3d%2d%2d%c, %2d%2d%2d%c) (%3d%2d%2d%c, %2d%2d%2d%c)\n",
             &firstLonD, &firstLonM, &firstLonS, &firstLonC,
             &firstLatD, &firstLatM, &firstLatS, &firstLatC,
             &secLonD, &secLonM. &secLonS, &secLonC,
             &secLatD, &secLatM, &secLatS, &secLatC) == 16) {
//do something
}

Sorry for long loop conditional and possible poor readability. Any suggestions on how to proceed?

Spaces and newlines in the fscanf format string do NOT match spaces and newlines in the input. Instead, any whitespace character in the format means "skip over whitespace", reading and discarding whitespace until any non-whitespace character is found -- which might be the next character, so nothing is skipped. In addition, most conversion specifiers also skip whitespace, so you only want spaces in the format before literal chaarcters or %c , %[ and %n directives, which are the ones that don't skip whitespace.

So for your purposes, you want a format string like:

while(fscanf(filename,
         " (%3d%2d%2d%c ,%2d%2d%2d%c ) (%3d%2d%2d%c ,%2d%2d%2d%c )",
         &firstLonD, &firstLonM, &firstLonS, &firstLonC,
         &firstLatD, &firstLatM, &firstLatS, &firstLatC,
         &secLonD, &secLonM. &secLonS, &secLonC,
         &secLatD, &secLatM, &secLatS, &secLatC) == 16) {

Though it might also be better to read single coordinates in a loop a later pair them up:

while(fscanf(filename,
         " (%3d%2d%2d%c ,%2d%2d%2d%c )",
         &LonD, &LonM, &LonS, &LonC,
         &LatD, &LatM, &LatS, &LatC) == 8) {

It might also be better to read the latitude/longitude as a single number and later split it into degrees/minutes/seconds by div/mod by 100:

while(fscanf(file, " (%d%c ,%d%c )", &lonVal, &lonDir, &latVal, &latDir) == 4) {
    lonDeg = lonVal / 10000;
    lonMin = (lonVal % 10000) / 100;
    lonSec = lonVal % 100;

this way you can deal with longitudes < 100 degrees without requiring leading 0s to make them be exactly 7 digits...


The thing about scanf and friends is that they want to read things delimited by whitespace, and they really don't care what kind of whitespace it is. So input all on one line with just spaces (or tabs) is the "same" as multiple lines. This is an intentional "feature" of the way scanf works, so if you actually care about the difference between newlines and other whitespace, scanf is not the right tool.

#include <stdlib.h>
File *file;
size_t len = 0;
ssize_t read;
char * line = NULL;     
while ((read = getline(&line, &len, file)) != -1)
{
    printf("%s",line);
    if(sscanf(line, "....format",...)==16)){
           ..............
     }
}

It's better design to read lines from a file with a straight string-reading function (like fgets ), and then use string parsing on the string read from the file with sscanf or similar. scanf -family functions generally shouldn't be used to read from streams directly, only from strings.

Then, you should also check the return value of sscanf to ensure that each value was scanned into the intended type appropriately.

char line[200];
while(fgets(line, 200, stdin))
{
    if(sscanf(line, "<format-string-here>", ...) != 16)
    {
        // handle error
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM