Reading a ";" delimited file into a character array structure - c++

I am trying to read a set of values from a text file into an array of structures of arrays. The entries are each separated by a '\n', and each entry consists of 3 values, separated by a ';'.
The problem is that after correctly reading the first line of file data the program reads the first value from the second line, then seems to fail to read the remaining values. Can you point out the error in my syntax or logic?
The test data appears below.
CS162;Finish Lab 2;9/26/2009
CS201;Take Quiz 1;9/28/2009
After reading in the test data my program's output is below.
Your tasks are:
Finish Lab 2 for CS162 is due 9/26/2009
CS201
for is due
The loops that read the file into the array and outputs the array contents are below. My complete code will be at the end of the question.
for ( ; InputFile.peek() != EOF; ListSize++ )
{
InputFile.get(TaskList[ListSize].Course, BUFFERSIZE, ';');
InputFile.ignore(BUFFERSIZE, ';');
InputFile.get(TaskList[ListSize].Assignment, BUFFERSIZE, ';');
InputFile.ignore(BUFFERSIZE, ';');
InputFile.get(TaskList[ListSize].DueDate, BUFFERSIZE, ';');
InputFile.ignore(BUFFERSIZE, '\n');
}
cout << "Your tasks are:" << endl;
for ( int Iteration = 0; Iteration <= ListSize; Iteration++ )
{
cout << TaskList[Iteration].Assignment << " for " << TaskList[Iteration].Course << " is due " << TaskList[Iteration].DueDate << endl;
}
Full disclosure, this is for a computer science class. This is why I am not asking for complete code solutions, just help with logic or syntax errors. If I am doing this in completely the wrong way, please point me to documentation to help me. But this does put limitations on my code. The program must use character arrays, not strings.

Perhaps the last get should be:
InputFile.get(TaskList[ListSize].DueDate, BUFFERSIZE, '\n');
instead of
InputFile.get(TaskList[ListSize].DueDate, BUFFERSIZE, ';');
Your last field (due date) does not have a semicolon at the end, only a newline.
Update: I suggest you also look into using getline instead of get. They have similar functionality, but getline will consume the delimiter also, meaning that you won't need to use the ignore().

Without thinking about the code you have written, I'll just say that my normal pattern for this type of problem is:
while (readline) { processline; }
Incremental file processing is more likely to run into problems if you don't have everything exactly correct.

Related

Issue in Loop with Reading and Writing from File c++

The problem I'm having is that in the following loop, I'm attempting to read sentences one by one from the input file (inSentences) and output it into another file (outMatch), if it contains a certain word. I am not allowed to use any string functions except for .at() and .size().
The problem lies in that I'm trying to output the sentence first into a intermediary file and then use the extraction operator to get the word one by one to see if it has the word. If it does, it outputs the sentence into the outMatch file. While debugging I found that the sentence variable receives all of the sentences one by one, but the sentMore variable is always extracting out the first sentence of the file, so it's not able to test the rest of the sentences. I can't seem to fix this bug. Help would be greatly appreciated.
P.S. I don't really want the answer fleshed out, just a nudge or a clue in the right direction.
outMatch.open("match");
outTemp.open("temp");
while(getline(inSentences, sentence, '.')){
outTemp << sentence;
outTemp.close();
inTemp.open("temp");
while(inTemp >> sentMore){
if(sentMore == word){
cout << sentence << "." << endl;
inTemp.close();
sentCount++;
}
}
}
You should use string streams! Your issue right now appears to be that you never reopen outTemp, so after the first loop you're trying to write to it after you've closed it. But you can avoid all these problems by switching to stringstreams!
Since you don't want a full solution, an example may look like:
string line_of_text, word;
istringstream strm(line_of_text);
while(strm >> word) {
cout << word << ' ';
}

Formatting Output c++

Wanting to do some fancy formatting. I have several lines that I want to interact with each other. Get the first two lines. Print out the character in the second line times the integer in the first line. Seperate them all with a asterisk character. No asterisk after the final character is printed. Move onto the next integer and character. Print them on a separate line. Do this for the whole list. The problem I am having is printing them on separate lines. Example:
5
!
2
?
3
#
Desired output:
!*!*!*!*!
?*?
#*#*#
My output:
!*!*!*!*!*?*?*#*#*#*
Below is my code. Another thing to mention is that I am reading the data about the characters and numbers from a separate text file. So I am using the getline function.
Here is a chunk of the code:
ifstream File
File.open("NumbersAndCharacters.txt")
string Number;
string Character;
while(!File.eof(){
getline(File, Number);
getline(File, Character);
//a few lines of stringstream action
for (int i=0; i<=Number; i++){
cout<<Character<<"*";}//end for. I think this is where
//the problem is.
}//end while
File.close();
return 0;
Where is the error? Is it the loop? Or do I not understand getline?
It should be printing an "endl" or "\n" after each multiplication of the character is done.
Thanks to everyone for the responses!
You have not shown your code yet, but what seems to be the issue here is that you simply forgot to add a new line every time you print your characters. For example, you probably have done:
std::cout << "!";
Well, in this context you forgot to add the new line ('\n'), so you have two options here: first insert the new line yourself:
std::cout << "! \n";
Or std::endl;
std::cout << "!" << std::endl;
For comparison of the two, see here and here. Without further description, or more importantly your code that doesn't seem to work properly, we can't make suggestions or solve your problem.

C++ reading a file into a struct

Using fstreams I have a file opened that contains numerous lines. Each contiguos set of 4 lines are such that: the first line is an int, the second and third are strings and fourth is a double. This sequence continues till EOF.
I'm attempting to load these lines into a struct array:
struct Library {
int id;
string title;
string artist;
double price;
};
and the code I'm trying to implement to load data into the struct is this:
const int LIMIT = 10
Library database[LIMIT];
ifstream file;
file.open("list.txt");
if(file) {
while(!(file.eof()) && counter < LIMIT) {
file >> database[counter].id;
getline(file, database[counter].title;
getline(file, database[counter].artist;
file >> database[counter].price;
}
} else {
...
}
// Using the following to debug output
for(int i = 0; i < counter; i++) {
cout << "ID: " << database[i].id << endl
<< "Title: " << database[i].title << endl
<< "Artist: " << database[i].artist << endl
<< "Price: " << database[i].price << endl
<< "-----------------------" << endl;
}
The file I'm trying to throw at this thing is
1234
Never Gonna Give You Up
Rick Astley
4.5
42
Thriller
Michael Jackson
32.1
The problem I'm having here is that between reading the id and title using file >> ... and getline(...) is that somewhere a newline bite is being introduced screwing up the output, which displays this monstrosity...
ID: 1234
Title:
Artist: Never Gonna Give You Up
Price: 0
--------------------
ID: 0
Title:
Artist:
Price: 0
--------------------
The solution is probably the most basic of solutions, but mainly because I can't figure out exactly what is going on with the newline bite I can't combobulate a phrase to shove into google and do my stuff there, and I'm at the stage where I've been looking at a problem so long, basic knowledge isn't working properly - such as how to handle basic input streams.
Any form of help would be much appreciated! Thanks in advance :)
This happens because the >> operator for the input stream only grabs part of a line, and does not always grab the newline character at the end of the line. When followed by a call to getline, the getline will grab the rest of the line previously parsed, not the line after it. There are a few ways to solve this: you can clear the buffer from the input stream after each read, or you can simply get all your input from getline and just parse the resulting strings into an integer or a double when you need to with calls to stoi or stod.
As a side note, you don't want to detect the end of your file the way you presently are. See why is eof considered wrong inside a loop condition?
You can solve this problem by adding:
fflush(file);
everytime before you use getline(file, ...). Basically this will clear the input buffer before you use the getline() function. And fflush() is declared in the cstdio library.
file >> database[counter].id;
will read, in this case, a whitespace separated sequence of characters that is interpreted as an int. The newline is considered whitespace. You should now be sitting on that newline character, thus the getline() will read nothing -- successfully -- and increment the file position just past that.
You may be better off using getline() for each line and then separately interpreting the lines from the reading. For example, the first line read could be interpreted with a subsequent std::stoi() to get the integer representation from the string.

How to extract specific substring from getline function in C++?

I'm fairly new to C++ so please forgive me if my terminology or methodology isn't correct.
I'm trying to write a simple program that:
Opens two input files ("infileicd" and "infilesel").
Opens a single output file "list.txt".
Compares "infilesel" to "infileicd" line by line.
If a line from "infilesel" is found in "infileicd", it writes that line from "infileicd" to "list.txt", effectively making a separate log file.
I am using the getline() function to do this but have run into trouble when trying to compare each file line. I think it might be easier if I could use only the substring of interest to use as a comparison.
The problem is that there are multiple words within the entire getline string and I am only really interested in the second one. Here are two examples:
"1529 nic1_mau_op_mode_3 "8664afm007-01" "1" OUTPUT 1 0 LOGICAL 4 4136"
"1523 pilot_mfd_only_sel "8664afm003-02" "1" OUTPUT 1 0 LOGICAL 4 4112"
"nic1_mau_op_mode_3" and "pilot_mfd_only_sel" are the only substrings of interest.
It would make it a lot easier if I could only use that second substring to compare but I don't know how to extract it specifically from the getline() function. I haven't found anything suggesting it is impossible to do this, but if it is impossible, what would be an alternative method for extracting that substring?
This is a personal project so I'm under no time contstraints.
Any assistance is greatly apprecated in advance. Here is my code (so far):
int main()
{
//Open the file to write the selected variables to.
ofstream writer("list.txt");
//Open the selected variabels file to be read.
ifstream infilesel;
infilesel.open("varsel.txt");
//Open the icd file to be read.
ifstream infileicd;
infileicd.open("aic_fdk_host.txt");
//Check icd file for errors.
if (infileicd.fail()){
cerr << "Error opening icd.\n" << endl;
return 1;
}
else {
cout << "The icd file has been opened.\n";
}
//Check selected variables file for errors.
if (infilesel.fail()){
cerr << "Error opening selection file.\n" << endl;
return 1;
}
else {
cout << "The selection file has been opened.\n";
}
//Read each infile and copy contents of icd file to the list file.
string namesel;
string nameicd;
while(!infileicd.eof()){
getline(infileicd, nameicd);
getline(infilesel, namesel);
if (nameicd != namesel){ //This is where I would like to extract and compare the two specific strings
infileicd; //Skip to next line if not the same
} else {
writer << nameicd << namesel << endl;
}
}
writer.close();
infilesel.close();
infileicd.close();
return 0;
}
So, based on what we discussed in the comments, you just need to toss the stuff you don't want. So try this:
string namesel;
string nameicd;
string junk;
while(!infileicd.eof()){
// Get the first section, which we'll ignore
getline(infileicd, junk, ' ');
getline(infilesel, junk, ' ');
// Get the real data
getline(infileicd, nameicd, ' ');
getline(infilesel, namesel, ' ');
// Get the rest of the line, which we'll ignore
getline(infileicd, junk);
getline(infilesel, junk);
Basically, getline takes a delimiter, which by default is a newline. By setting it as a space the first time, you get rid of the first junk section, using the same method, you get the part you want, and then the final portion goes to the end of the line, also ignoring it.

c++ while loops, using getline function

Ok so to start because people like to know, this is homework....
I am writing a C++ Program to convert a text file to XML (this is not where I need help)
I am having this issue.
I am writing a while loop to cycle through the companies in the txt file (up to 15) and at the end of each group it is marked with the words --END_MANAGER_DATA--. I am trying to write a while loop that will loop through the company's and finish looping when it reaches --END_MANAGER_DATA--. below is an example of the txt file
19936 WALKER KOLTON PORTLAND TN
HARMAN INTERNATIONAL INDUSTRIES INC
LUCENT TECHNOLOGIES INC
COMPUTER SCIENCES CORP
COMMUNICATIONS CORPORATION
--END_MANAGER_DATA--
this is the code I am trying to use.....
getline(inFile,company);
inFile.ignore();
while(company != "--END_MANAGER_DATA--"|| !inFile.eof())
{
outputfile <<"\t\t\t <company> "<<company << "</company>"<<endl;
getline(inFile,company);
inFile.ignore();
}
this is not working....it just stays in the loop.... can someone offer advice as to a route I can take. I am not asking for you to finish my homework....just need a nudge in the right direction
The idiomatic way to read data is to put the std::getline() into the while loop's test condition rather like this:
std::string line;
while(std::getline(inFile, line) && line != "--END_MANAGER_DATA--")
{
std::cout << "\t\t\t<company>" << line << "</company>" << '\n';
}
This works because the while will only proceed if there were no errors reading the line. Testing for eof() doesn't work because eof() doesn't happen until after the read has taken place and the read will only take place if no error condition already exists.
In your code you ignore() the first character of each line which is why, I think, you can never match "--END_MANAGER_DATA--".
Try this:
string company = "";
while(company.compare("--END_MANAGER_DATA--") != 0 && !inFile.eof()) {
getline(inFile, company);
outFile << "\t\t\t <company> "<< company << "</company>" << endl;
inFile.ignore();
}