开发者

C++, reading a serial output text file backwards

I'm using a serial terminal (hyperterminal) to read inputs that are continuously written from a microcontroller and dumped to a text file. I'm trying to make a C++ program that will read the integers from the text file into declared variables. The numbers that I'm interested in are at th开发者_C百科e bottom of the text file so I have to read it backwards. Also, when this function is called, it can be anywhere in the process of writing to the text file. For example, the last three lines of the text file could be something like:

987 1002 856 751 454 875

1024 1000 987 998 945 667

465 454 15

And from there I'd want to assign each number in the second last line to its own variable.

Some approaches I've been thinking of are:

Using fseek to point to the end, however I wouldn't know what offset to use because of the randomness of the last line.

Read in a block of three lines, identify the middle line by its line break "\n" and read 6 values from there. (Not sure how I would go about doing this, create a buffer and put it into a string? Can I do that from the bottom up?) I could even put an identifier character, like an "A" or something, at the end of each line, if that helps to search through it.

Any help is appreciated!

Thanks for the help, here's how we ended up doing it, we went backwards and used flags to bound relevant data (100 and 200, but they could have been anything) because the buffer was kinda overkill for the 6 values we needed to grab:


You can use fseek: just start a bit before the end of the file - more-than-enough bytes for any two lines while making sure you don't try to read from before the start of file - and read into a buffer (you can safely round this up significantly without degrading performance much - e.g. 1k). Scan backwards from the last character read for a newline character: that indicates the line preceding it is complete (if you can't find one then it indicates the first line's still being written so abort). Continue scanning backwards until you either find another newline character (then advance forwards past it to the start of the line) OR you are at the start of the buffer, in which case if you read from the start of the file then you know this line is complete, otherwise abort. All this is most easily accomplished with a const char* and a few ifs and while loops, then use sscanf to parse out your six numbers.

If you want to use a C++ istream, the logic is similar but you can use >> to parse the integer values out.

FILE* f = fopen(filename, "r");
if (!f) return false;
bool read_from_start_of_file;
if (read_from_start_of_file = (fseek(f, -1024, SEEK_END) != 0))
    rewind(f);
char buffer[1024];
size_t num_bytes_read = fread(f, 1, sizeof buffer, f);
if (num_bytes_read < 1)
    return false;
const char* p = buffer + num_bytes_read - 1;
// find end of last complete line...
for (; *p != '\n'; --p)
    if (p == buffer)
        return false; // line incredibly long or first line incomplete
// find start of previous line...
while (*--p != '\n')
    if (p == buffer)
        if (read_from_start_of_file)
            break;
        else
            return false;
if (*p == '\n') ++p; // skip forward to first actual character...
int a, b, c, d, e, f; // you can use an array if more convenient...
if (sscanf(p, "%d %d %d %d %d %d", &a, &b, &c, &d, &e, &f) != 6)
    return false;

// process your input...
...
return true; // it worked!
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜