How to change input method of this program? - c++

Hello I'm a BME student and don't have so much information on programming. I found a simple program on the internet that I could perfectly use to run my data but it only accepts input by hand. I want to make it automated with the data files I have as it takes so much time entering all the values one by one. Could you please help me to integrate some module to make that possible? I did not want to put the entire program as the code is very long, but the input part is below:
int m;
cout << "Enter the MRI number" << endl;
cin >> m;
cout << "Enter the extensions one by one" << endl;
for (i=1; i<=m; i++)
cin >> a[i];
So the main logic of the program is:
1) Enter the total number of MRI extensions >> 4
2) Enter the MRI extensions >> 12131415 12131411 12131419 12131421
3) Run the algorithm and get the output
And my data file will be like this:
4
12131415
12131411
12131419
12131421
Roughly this is the process, but my data files contain around 70-75 extensions each but not 4 as it is in the example above.
Any kind of help will be much appreciated. Thanks!
p/s if my question somehow violates the rules of asking question, I am really sorry. I read that my question should be including some work done by me, but I really do not know how to handle this.

Basically how it works it is accepting the input stream (cin and cout) you need to do one of two things. Automate it when calling the program (use program which will feed the information for the console), depending on what system you are using for linux something like cat "input file" | your executable. The second possibility is to change the input stream to be file stream. In this case instead of using cin and cout you need to use your own declared file streams exactly the same way.
Here is the example from cplusplus.com:
#include <iostream> // std::cout
#include <fstream> // std::ifstream
int main () {
std::ifstream ifs ("test.txt", std::ifstream::in);
char c = ifs.get();
while (ifs.good()) {
std::cout << c;
c = ifs.get();
}
ifs.close();
return 0;
}
First lines include the input and output stream.
Then this line:
std::ifstream ifs ("test.txt", std::ifstream::in);
constructs the actual stream, rest is the usage of stream.
int m;
std::ifstream myinputfile ("file you want to read", std::ifstream::in);
myinputfile >> m;
for (i=1; i<=m; i++)
myinputfile >> a[i];

Related

C++ question regarding how ifstream reads lines and columns

I was reading some old codes of mine and I realize that I don`t know exactly how ifstream works. The following code should just read a file, save its contents into an object and create another file with exactly same data, which is written as:
#include <iostream>
#include <fstream>
using namespace std;
class grade {
public:
float grade1;
float grade2;
float grade3;
};
void read_file(grade data[]){
ifstream myfile("data.txt");
int i=0;
while(myfile >> data[i].grade1){
myfile >> data[i].grade2 >> data[i].grade3;
i=i+1; }
myfile.close();
myfile.clear();
}
void write_file(grade data[]){
ofstream myfile("data_out.txt");
for(int i=0; i<3; i++){
myfile << data[i].grade1 << "\t" << data[i].grade2 << "\t" << data[i].grade3 << endl;
}
myfile.close();
myfile.clear();
}
int main()
{
grade data[3];
read_file(data);
write_file(data);
return 0;
}
With "data.txt" having:
23.5 10.1 11.6
14.3 8.2 9.3
6.5 6.7 5.3
The code works just fine, but I don't get how the ifstream "knows" which line or column it should be at a given moment, since the variable i is not used to control myfile. I am assuming that by default ifstream has two internal variables, one for line and the other for column, that each time a myfile >> xxx command is identified, the column variable is incremented and every time that a loop repeats the line variable is incremented.
It is something like that? Not actually controlling what line or column the code is at a given moment is quite confusing to me.
Lets say, for instance, that in this example I would like to read only the data on the second line and column. Could I access directly it using some explicit expression like 'myfile[1][1] >> xxx'? I guess that getlinecould be used, but since it is used for strings I really don't know.
In read_file() the reading occurs in this loop:
int i=0;
while(myfile >> data[i].grade1){
myfile >> data[i].grade2 >> data[i].grade3;
i=i+1; }
First, this assumes that data[] was already allocated with sufficient number of elements. It's strange since the file was not yet read, so how to know how many records are to be read in advance?
Then, this reading algorithm assumes that the data is in an ordinary text file, in which data elements are space separated:
The myfile >> data[i].grade1 reads the first grade of a new sequence. If it reaches the end of file, the result will be evaluated to false and the loop will end.
Then for every first grade read, the loops reads the next grades of the record: myfile >> data[i].grade2 >> data[i].grade3;
This logic reads in fact one number after the other. The only constraint is that there are one or several spaces between the numbers. The stream therefore doesn't care about columns: it's just the next item to be read.
The following input file would work equally well:
23.5
10.1
11.6
14.3 8.2
9.3 6.5 6.7 5.3
This being said, no need to close and clear the stream at the end of the function: when the function will return, its local objets will be destroyed. This includes the stream object, and the destruction ensures that everything ends right.
Remark: incomplete records are not handled well: if the first grade is present but one of the remaining is missing, the stream will be in an error state, and the grade2 or grade3 elements will be left uninitialized.

How do I correctly use "getline(cin, input);"

I am writing a program that is to convert text that a user gives. I have tried this method by itself in a test program and it works perfectly; however when I try to implement it into the larger program, the user cannot give the program an input to store. The relevant code is as follows:
int main()
{
string str = "NULL";
int mappings = 0;
readMappings(mappings);
receiveInput(str);
displayInput(mappings, str);
return 0;
}
void readMappings(int &count)
{
ifstream readMappings; // Creates the function "readMappings"
string filename; // Generates the filename variable to search for mapping document
cout << "Enter the filename of the mapping document: ";
cin >> filename; // User enters filename
readMappings.open(filename); // "readMappings" function opens the given mappings document
while (!readMappings.is_open())
{
cout << "Unsble to open file. Please enter a valid filename: "; // If the user enters an invaled filename, the program will ask again
cin >> filename;
readMappings.open(filename);
}
if (readMappings.good()) // Mapping document is successfully opened
{
readMappings >> count; // Reads first line
}
readMappings.close(); // If everything fails in this function, the document will close
}
void receiveInput(string &input)
{
char correctness;
do {
cout << "\nPlease enter the text you would like to be converted to NATO:\n";
getline(cin, input);
cout << "You are about to convert: \"" << input << "\".\nIs this correct? (Y/N)" << endl;
cin >> correctness;
} while (correctness == 'N' || correctness =='n');
}
I thought it may have been the program waiting for another input from the user so I added a variable I assumed it would already fill, but it did not fix my solution. In my opinion, the problem is in the receiveInput function, but I could be wrong. Thanks in advance for any assistance.
Also, I am using function prototypes with correct reference variables.
I see two problems:
1) You're not checking for an EOF condition, after invoking std::getline().
2) You are mixing together both std::getline and the >> operator. Now, there's actually nothing technically wrong with that, but both std::getline and the >> operator have very nuanced semantics, when it comes to error checking and input consuming, that you need to get 100% right, in order to correctly use them together.
Just replace your usage of the >> operator with std::getline, so you're using std::getline exclusively, and make sure to check for fail() or eof(). You will find plenty of examples of how to correctly check for end of file and failure conditions, with std::getline, here on stackoverflow.com.

Trying to write a class in C++ that only reads in the first column of data and skips to the next line

This may be a very simplistic question, but I have not found any examples to guide me. I am trying to write class in C++ that can read a text file where columns of data (float, char, int, etc...) are separated by spaces. I would like the class to be able to ignore some columns and read in specified columns. For now I am experimenting with one and two column formats and progressing from there. A brief example of a test input file is listed below.
103.816
43.984
2214.5
321.5
615.8
8.186
37.6
My first attempt at writing a code to read in one column of data is trivial and looks like this.
void Read_Columnar_File::Read_File(const std::string& file_name)
{
int i;
std::ifstream inp(file_name,std::ios::in | std::ios::binary);
if(inp.is_open()) {
std::istream_iterator<float> start((inp)), end;
std::vector<float> values(start,end);
for(i=0; i < 7; i++) std::cout << values[i] << std::endl;
}
else std::cout << "Cannot Open " << file_name << std::endl;
inp.close();
}
In my next attempt I am trying to read in only one column of a two column format like the input shown below. The numbers are just made up for this example
103.816 34.18
43.984 21.564
2214.5 18.5
321.5 1.00
615.8 4.28
8.186 1.69
37.6 35.48
I modified the code format slightly to look like the example below. I am using a brief but of pseudocode after the inp >> statement to illustrate that I am trying to get the code to skip to the next line after reading in the first column. my question is "How do I get the code to just read the first column and then skip to the next line where again it just reads the first column of data and make it keep doing this until the end of file?" And thank you in advance for any advice that you can give.
void Read_Columnar_File::Read_File(const std::string& file_name)
{
int i;
float input;
std::vector<float> values;
std::ifstream inp(file_name,std::ios::in | std::ios::binary);
if(inp.is_open()) {
for(i=0; i < 7; i++) {
inp >> input >> \\ - At this point I want the code to skip to the next
\\ line of the input file to only read the first column
\\ of data
values.push_back(input);
}
for(i=0; i < 7; i++) std::cout << values[i] << std::endl;
}
else std::cout << "Cannot Open " << file_name << std::endl;
inp.close();
}
You can use the member function ignore() to discard all the characters until the next line. I would also fix up your code to use a for() loop predicated on the success of the extraction so your code will work for any number of columns, not just 7:
for (float input; inp >> input; values.push_back(input))
{
inp.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
When you want to read only part of a line, and skip the rest of that line, one easy starting point is to:
read the entire line into a string
put the whole string into an istringstream
Parse out the parts you care about
Repeat
As a rule, I generally find this easier to generalize than ones that alternate between reading and ignoring data as it's being read from the file.

File Handling not working in while loop

Code:
#include<iostream.h>
#include<fstream.h>
#include<string.h>
int n = 0, flag = 0,i;
struct bac
{
char name[10];
char amt[5];
} s;
void main()
{
ofstream f("C:\\TC\\1.dat");
for(i=0;i<10;i++)
{
cout << "\nenter the details ";
cin >> s.name >> s.amt;
f.write((char *)&s, sizeof(bac));
}
}
sometimes the code works fine
but at the other times , when i look at the output file,it is empty , the problem has come up many times , and i ant to know whether there is a precaution regarding loops with file handling
for eg. in other program
.....
while(ch!=4)
{
cout << "\nBANK MANAGEMENT SYSTEM \n";
cout << "enter choice ";
cout << "\n1.add\n2.search\n3.delete and overwrite ";
cin >> ch;
if (ch == 1)
{
cout << "\nenter the details ";
cin >> s.name >> s.amt;
f.write((char *)&s, sizeof(bac));
}
.....
the file is empty
I guess you may have used a very old compiler older than gcc 4.5.3.
I tried your code and it has no problem.
#include <iostream> //use header file without using deprecated iostream.h
#include <fstream> //same reason as above
#include <string>
using namespace std;
int n = 0, flag = 0,i;
struct bac
{
char name[10];
char amt[5];
} s;
int main() //usually main returns int. void was kind of old now
{
ofstream f("test.txt");
for(i=0;i<10;i++)
{
cout << "\nenter the details ";
cin >> s.name >> s.amt;
f.write((char *)&s, sizeof(bac));
}
f.flush();
f.close();
return 0;
}
I compiled the code in gcc 4.5.3 and ran it. the file has all the stuff I entered.
However, it will be better to use the << operator when you use file i/o stream to write to file.
You can find more information about and from top of this link:
http://members.gamedev.net/sicrane/articles/iostream.html
Another point, wen you have done writing to a file, remember to flush and close the file handle, otherwise, sometimes it will cause some annoying problems.
The code doesn't seem very C++-like to me...
To answer the last question, there aren't any gotchas about fstreams in loops specifically, no.
I suggest first trying to do f.write with the members name and amt themselves—compilers might add padding between name and amt, creating unwanted garbage output.
Are you sure you have write permission to the filepath all the time? Try opening a local file, as in the path being simply "1.dat".
Also try opening the file as f("/* file name */", ofstream::out | ofstream::app). "out" sets it as an output stream, and "app" makes it add to the end of the file. www.cplusplus.com/ofstream details more flags.
since you are using c++, I suggest you use a formal way to use ofstream, in your code, it should be f << s.name << s.amt.
remember, you are using c++, so keep using i/o stream.

Reading text file into C++

I was writing a program which could read inputs directly from a text
file into a C++ file. However, the contents of the file come in
different formats, for example time. The input file looks like this:
Time(1) Price(1)
8:56:18 1250.00
9:00:25 1250.25
9:21:36 1250.50
9:23:32 1249.75
Time(2)
8:55:28
9:02:14
9:20:23
9:21:37
Price(2)
1680.50
1681.00
1680.50
1681.50
My program to read the file is as follows:
int main()
{
string file;
cout << "Enter a file name to read input: ";
cin >> file;
ifstream file_name(file.c_str());
while(!file_name.eof())
{
double input;
file_name >> input;
cout << input << endl;
}
}
But when I executed the program, I get stuck in an infinite loop and
all I see are 0s written on the screen. Is this being caused due the
formatting of the time?
The default behavior of file_name >> input is type safe therefore file_name byte offset pointer never increments for inputs like Time(1) or 8:56:18. You may use string input; instead of double input; to retrieve the values, then later you may check their types by using following standard c library.
#include <cstdlib>
.
.
.
atof()
atoi()
.
Here is the documentation.