42 69 13 43 -3 5 -23 62this file could be read with a simply loop:
file >> ws; while (!file.eof()) { file >> x >> y; // do something with x and y just read file >> ws; }if we know ahead of time that this is the case, we can immediately tell what is going on. however, just looking at the file contents is less obvious. especially if the data has been slightly altered:
42 69 13 43 -3 5 -23 62note how the data is exactly the same and can be read with the exact same code, but the data is now not even obvious when we know what is supposed to be in the file.
+-+-+-+-+-+--+-+-+-+-+-+--+-+-+-+-+--+-+-+-+-+-+-+ first file: |4|2| |6|9|\n|1|3| |4|3|\n|-|3| |5|\n|-|2|3| |6|2| +-+-+-+-+-+--+-+-+-+-+-+--+-+-+-+-+--+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+--+-+-+-+-+-+-+-+--+-+-+-+-+-+-+ second file: |4|2| |6|9| |1|3|\n|4|3| |-|3| |5|\n|-|2|3| |6|2| +-+-+-+-+-+-+-+-+--+-+-+-+-+-+-+-+--+-+-+-+-+-+-+again, same data, different spacing.
42 69 13 43 -3 5 -23 62or:
42 69 13 43 -3 5 -23 62or even:
42 69 13 43 -3 5 -23 62
Joe Sally Hanesh Vong Ella Soph Fresh Fresh Soph Jr 4 11 9 10 10 Valley Lane Mountain View Mountain View Valley Lane River Trailhere's the same data in a block format:
Joe Soph 4 Valley Lane Sally Fresh 11 Mountain View Hanesh Fresh 9 Mountain View Vong Soph 10 Valley Lane Ella Jr 10 River Trailnow it is easier to identify what data goes with which student. even clearer would be:
Joe Soph 4 Valley Lane Sally Fresh 11 Mountain View Hanesh Fresh 9 Mountain View Vong Soph 10 Valley Lane Ella Jr 10 River Trailbut, for some reason, blank space like that is rare in data files. I would encourage you to do such things, though!
file.peek(); while (!file.eof()) { object.read(file); // do something with object just read file.peek(); }
name = Joe class = Soph gpa = 4 branch = Valley Lane name = Sally class = Fresh gpa = 11 branch = Mountain View
file >> setw(MAX_LABEL) >> label >> sep >> setw(MAX_NAME) >> name;but this doesn't account for several things. first off, the user might re-order information within the block:
name = Joe gpa = 4 class = Soph branch = Valley Lane class = Fresh gpa = 11 name = Sally branch = Mountain Viewnote that the same data is present, the blocks have just been internally shuffled. the assumption here is that your program should be able to place the correct data in the correct variables by the context of the labels. that is a major assumption, are we ready for it? SURE!
const char known_labels[MAX_KNOWN_LABELS][MAX_LABEL] = { "name", "gpa", "class", "branch" }; file >> setw(MAX_LABEL) >> label >> sep; L = 0; while (L < MAX_KNOWN_LABELS && strcmp(label,known_labels[L]) != 0) { L++; } // L is either the index of the correct label or MAX_KNOWN_LABELSit's just a simple linear search through an array of strings! now we can switch on the label index to an appropriate action:
switch (L) { case 0: file >> setw(MAX_NAME) >> name; break; case 1: file >> gpa; break; case 2: file >> setw(MAX_CLASS) >> year; break; case 3: file.getline(branch, MAX_BRANCH); break; default: // nothing -- ignore unknown labels }easy as pie! (although it is rather a pain to make a pie, this is an old expression that means it really is easy...*shrug*) speaking of hidden pain, don't forget to watch out for the unknown label condition — when the loop above ends at MAX_KNOWN_LABELS!
name=Joe class=Soph gpa=4 branch= Valley Lane name =Sally class = Fresh GPA = 11 branch =Mountain Viewwhich our code can no longer read correctly. the capitalization problems can be side-stepped by using a case-insensitive string comparison. perhaps you could do something about that... the spacing problems are much harder to deal with. since we don't know whether they'll have or not have space preceding the separator character (an '=' above), following the separator, or even before the label itself, things are a bit more messy. however, since all labeled data has but one item per file line, we can read in the whole line and then do string processing (which we are familiar with from previous studies) to break up the pieces within our program:
file.getline(labeled_line, MAX_LINE); sep_at = search(labeled_line, '='); lcap = min(sep_at,MAX_LABEL)-1; strncpy(label, labeled_line, lcap); label[lcap] = '\0'; // copy rest into value string: value_index = 0; do { sep_at++; value[value_index++] = labeled_line[sep_at]; } while (value_index != MAX_VALUE_LEN && labeled_line[sep_at] != '\0');
char * sep_at; // make sep_at a pointer rather than an index file.getline(labeled_line, MAX_LINE); sep_at = strchr(labeled_line, '='); // use cstring library function to search *sep_at = '\0'; // split string logically in two strncpy(label, labeled_line, MAX_LABEL-1); label[MAX_LABEL-1] = '\0'; strncpy(value, sep_at+1, MAX_VALUE_LEN-1); // use pointer to second half value[MAX_VALUE_LEN-1] = '\0';
// count number of leading spaces lead_space = 0; while (isspace(str[lead_space])) { lead_space++; } // shift data over moving = 0; while (str[moving+lead_space] != '\0') { str[moving] = str[moving+lead_space]; moving++; } str[moving] = '\0'; // not entirely necessary, but good form // remove trailing spaces while (moving != 0 && isspace(str[moving-1])) { moving--; str[moving] = '\0'; }the shifting loop could be done with a call to strcpy, of course — if you are willing to suffer the pointers; I was just being obsessive... (of course repeat this process for both the label and value strings — perhaps calling a function...?)
void Class::read(istream & strm) { // known label array strm.peek(); while (!strm.eof() && !end_of_block) { // read line // split line at separator // search for label -- case-insensitively // switch to translate and store value based on label strm.peek(); } return; }
name other data here numeric sequencenow when the sequence of numbers hits either the end of the file or the next name, you'll know it is over:
peek while (!eof) { read name read other data read first of sequence while (good) // file will either eof or fail at end of sequence { process sequence item read next in sequence } clear peek }we might even want to convert this to 'hacked' form with space-based priming
Last modified 03/23/2018 01:03:42.
It is now 3/15/2025, 4:24:48 AM.
Date you last viewed this page: That's for you to know and ...well, that's for you to know.
© 1993-2025 Jason James (email — craie@acm.org — for permissions &/or details)