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.
Related
I am trying to read in an essay from a file which I then need to change each beginning letter of a sentence to an upper case letter and then send the corrected essay back to a file called correct.txt. The essay is stored in essay.txt.
So far I am just working with understanding the conversions from files to string in order for me to proceed with the rest of the question. So far, I have a string variable which which holds the essay with the words separated by a single space. I noticed that when I was trying to work with the size of my new string, it was not giving me the correct answer and I cannot figure out why. If you have any suggestions on how I can get it to notice the correct amount of characters, I would really appreciate it.
One more question while you're here, I know that moving forward, in order to change the beginning letters of the sentence to upper case, I need to first find the periods. Once I have this position, I can use pos+2 (including the preceding whitespace after the period) for the character that needs to become upper case. Is this the correct way of going about this and do you have any other tips on how to go forward with this?
Here is my code so far:
#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>
using namespace std;
int main(){
//declaring variables and creating objects
ifstream inputFile;
ofstream outputFile;
char inputFileName[20], outFileName[20];
cout << "Enter name of the file you want to open: " << endl;
cin >> inputFileName;
inputFile.open(inputFileName);
if (inputFile.fail()) {
cout << "Input file opening failed.\n";
exit(1);
}
cout << "Enter name of the file you want to send the output to: " << endl;
cin >> outFileName;
outputFile.open(outFileName);
if (outputFile.fail()) {
cout << "Output file opening failed.\n";
exit(1);
}
//while the file is open, it sends the contents to the string variable "essay"
string essay;
inputFile >> essay;
while (!inputFile.eof()) {
cout << essay << " ";
inputFile >> essay;
}
//this is to check for the correct size of the string "essay" before moving on to the rest of the code
int size = essay.size();
cout << size << endl;
return 0;
}
Your understanding of how the input stream works is incorrect.
The core of your code is this loop:
string essay;
inputFile >> essay;
while (!inputFile.eof()) {
cout << essay << " ";
inputFile >> essay;
}
What this does is that it reads the first word into essay, then, as long as the eof marker is not set on the stream it echoes back the word just read, and then reads another word, overwriting the previous one.
Here's the correct code. Note that checking for eof in a loop condition is a bad idea, because it doesn't quite do what you want, and would also get you stuck in an infinite loop if the stream instead entered an error condition.
string word;
while (inputFile >> word) { // read a word and stop if this fails for any reason
essay += word;
essay += " ";
}
Though I'm not sure why you read the file word by word instead of all at once.
Also, I feel the need to repeat what M.M. said in a comment: your use of raw character arrays on input is unsafe and unnecessary. Just use string. You need to then write inputFile.open(inputFileName.c_str()) unless your standard library is new enough to have the string overloads of these functions, but that is fine. The other way of doing it is dangerous and a very bad habit to get into.
Try include cstring on top of string as well.
String is considered char array which is a more 'unique' way of storing data. You can try the code listed below.
int size = essay.length();
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];
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.
I've been working on a program that creates and stores information onto files. My only problem that is keeping me from going any farther is the files name. I can manually name the file but I can't use a variable (any would do: number, character anything) for the files name, and for the contents of the file. Here's the 4 lines of code that have driven me up walls for a while now:
ofstream file;
file.open ("txt.txt"); \\I can manually create names, but that's not what I'm after
file.write >> fill; \\I attempted to use a 'char' for this but it gives errors based on the "<<"
file.close();
This is my first time using this site. Sorry in advance.
You may use variables of type strings and ask the user for keyboard input to name your file and fill in contents.
#include <iostream>
#include <fstream>
using namespace std;
int main(int argc, char** argv) {
string fileName;
string contents;
cout << "What would you like the file name be? : ";
cin >> fileName;
cout << "\nPlease write the contents of the file: ";
cin >> contents;
ofstream file;
file.open(fileName.c_str()); // provide the string input as the file name
if(file.is_open()){ // always check if the program sucessfully opened the file
file << contents << endl; // write the contents into the file
file.close(); // always close the file!
}
return 0;
}
Note that this program will read input from user for contents until it reaches a newline character '\n' or white space ' '. So if you write HELLO WORLD! as the input for contents, it will only read HELLO.
I'll leave how to read the entire line including whitespaces as exercise for you. I also suggest you grab a C++ book and study file input/output.
It really depends? C++11 or C++03?
First create a string:
std::string fname = "test.txt";
In C++11, you can just do:
file.open(fname);
However in C++03, you must:
file.open(fname.c_str());
I'm reading info from one text file, then outputting it to a bin file. I got the name to write properly, but the integer and doubles do not work properly. Disregard the system("pause"), they are so I can check my outputs.
#include <iostream>
#include <fstream>
#include <cstdlib>
using namespace std;
struct SaleSlip{
char name[20];
int prodID;
double value;
};
void main(){
fstream slips, binslip;
SaleSlip sales[17];
binslip.open("SaleSlips.bin", ios::out | ios::binary | ios::trunc);
slips.open("SaleSlips.txt", ios::in);
if(slips.eof()){
cout << "Cannot open file - SaleSlips.txt"<< endl;
system("pause");
exit(2);
}
int i = 0;
while(!slips.eof()){
slips >> sales[i].name;
slips.ignore(80, ' ');
slips >> sales[i].prodID;
slips.ignore(80, ' ');
slips >> sales[i].value;
slips.ignore(80, '\n');
cout << sales[i].name;
cout << sales[i].prodID;
cout << sales[i].value << endl;
binslip.write((const char *)&sales[i].name, sizeof(sales[i].name));
binslip.write((const char *)&sales[i].prodID, sizeof(sales[i].prodID));
binslip.write((const char *)&sales[i].value, sizeof(sales[i].value));
i++;
}
slips.close();
binslip.close();
system("pause");
}
SaleSlips.txt has one line per item of the array so "Ryan 2 1400.52" is one line. Ryan is interpreted correctly, but when I read back in from the binary it isn't right, nor is it when I check it in textpad.
binslip.write is an UnformattedOutputFunction. There is formatted and unformatted input/output. When you use unformatted output, you are writing raw bytes to the file. There is no interpretation as to what the bytes actually represent.
When you wrote to SalesSlips.bin, you wrote characters followed by numbers (rather, what you thought would be numbers). When you tried to examine SalesSlips.bin, the computer read text characters, and was expecting the rest of the file to be text, but it wasn't. Numbers are represented differently then characters. Even if you were to just deal with numbers alone, integral and floating point values are represented differently in binary. It may be a bit much for you to absorb right now, but the gist of it is you need to use a FormattedOutputFunction. This will perform the internal conversions necessary for you to output your data properly.
Imagine you have a number, lets say, 50. That number is meaningless without units that describe what 50 represents. 50 seconds? 50 feet? 50 states? You can think of binslip.write as just writing 50, and when you try to read the file later, all you see is 50, and you don't understand what it was supposed to represent, which is why it looks like gibberish to you.
To fix your code you need to replace the binslip.write lines with this:
binslip << sales[i].name << sales[i].prodID << sales[i].value;
In this case, operator<< behaves as a FormattedOutputFunction, so when you write SaleSlips.bin, you can open it in a text editor and view Ryan 2 1400.52 like you expected.
While reading and writing in BINARY mode, you are not expected to read the data in any text editor. It simply serves no purpose. If you want to read it in a text editor, recommendation is to use NORMAL mode.
Anyways, if you don't bother about viewing your BINARY data in a text editor, you could use the following lines to Read and write binary file:
while(!slips.eof())
{
slips >> sales[i].name;
slips.ignore(80, ' ');
slips >> sales[i].prodID;
slips.ignore(80, ' ');
slips >> sales[i].value;
slips.ignore(80, '\n');
cout << sales[i].name;
cout << sales[i].prodID;
cout << sales[i].value << endl;
//// WRITE THE STRUCTURE AT ONCE
binslip.write((const char *)&sales[i], sizeof(sales[i]));
i++;
}
binslip.flush();
binslip.close();
//// OPEN UP THE FILE IN READ MODE
binslip.open("SaleSlips.bin", ios::in | ios::binary );
SaleSlip sale;
//// READ UP THE COMPLETE STRUCTURE
binslip.read((char *)&sale, sizeof(sale));
//// PRINT IT.
cout<<sale.name;
cout<<sale.prodID;
cout<<sale.value;