So I currently have a working programme which successfully finds and displays all the characters in an text file. I now want to be able to read whole words instead of characters and then want to store each word into an array but I have no idea how to even read whole words.
My current code for characters
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
ifstream infile("input.txt");
if (!infile)
{
cout << "ERROR: ";
cout << "Can't open input file\n";
}
infile >> noskipws;
while (!infile.eof())
{
char ch;
infile >> ch;
// Useful to check that the read isn't the end of file
// - this stops an extra character being output at the end of the loop
if (!infile.eof())
{
cout << ch << endl;
}
}
system("pause");
}
I now want to be able to read whole words instead of characters and then want to store each word into an array but I have no idea how to even read whole words
std::string word;
infile >> word;
Change the type of ch to std::string so >> will read words.
Use,
std::string word;
infile >> word;
Instead of,
char ch;
infile >> ch;
Related
I have this file with information from the periodic table in a .txt file and Im trying to write a program that allows the user to input the element symbol then read through the file until it finds that symbol and spits out information about that element. At first I got the program to output the cout statement with no information, and now its completely skipping this section after the symbol is entered and going right to the next. Here is my code.
ifstream fin;
ofstream myfile;
string line;
myfile.open("txt file");
fin.open("txt file", ios::app);
while (std::getline(fin, line)) {
fin >> element >> symbol >> atomic_number >> atomic_mass >> physical_state >> density >> melting_point >> boiling_point >> created >> chemical_group >> electronegativity;
if (line == symbol)
{
cout << "information from above"
break;
}
fin.close();
myfile.close();
}
Trying to read a .txt file and pull out a specific line based off of a letter entered by user.
Here is a sample code:
#include <iostream>
#include"string"
#include <fstream>
using namespace std;
int main(void)
{
ifstream fi("1.txt", ofstream::in);
ofstream fo("2.txt", ofstream::out);
string buf;
string s1;
cin >> s1;
while (fi >> buf)
{
if (buf.find(s1) != string::npos) break;
}
fo << buf << endl;
fi.close();
fo.close();
return 0;
}
1.txt is the file you are trying to read. Save the pull out specific line to 2.txt. "s1" is the string entered by the user.
Hope this code is helpful to you.
I am trying to read lines of a file (cityName, hiTemp, loTemp) into a struct array. I was able to use >> to read the first several lines until I hit a city with a space in it's name.
I then tried using getline() to read the lines, but then my while loop stopped working.
I have no clue why this would happen.
int LoadData()
{
int count = 0;
string path;
cout << "Specify the input file path: ";
ifstream inFile;
cin >> path;
inFile.open(path.c_str());
if (!inFile.is_open())
{
cout << "Error - could not open file: " << path;
return (-1);
}
else
{
while (!inFile.eof())
{
cities[count].city = "";
getline(inFile, cities[count].city);
if (cities[count].city.length() == 0)
{
break;
}
char comma;
inFile >> (cities[count].high) >> comma >> cities[count].low;
cout << cities[count].city << " " << cities[count].high << " " << cities[count].low << endl;
count++;
}
inFile.close();
inFile.clear(std::ios_base::goodbit);
return count;
}
}
while (!inFile.eof())
For getting every line in the file, you should use:
while(getline(inFile, cities[count].city)) {
// ...
This works and is recommended over using the .eof() method.
You can also use this in your if-statement:
if (!getline(inFile, str))
break;
As an aside, you can read this site:
Why is “while ( !feof (file) )” always wrong? - StackOverflow post
It gives insight into why using the .eof() is not the preferred method to use in a while loop to check whether the end-of-file has been reached.
Use getline as loop condition. You can also replace the second read with a getline too and use a stringstream to parse it.
#include <sstream>
// ...
while(getline(inFile, cities[count].city)) {
if (cities[count].city.empty()) break;
// read next line with high and low values
string str;
if (!getline(inFile, str)) break; // error in file format
stringstream ss(str);
char comma;
ss >> cities[count].high >> comma >> cities[count].low; // parse it
}
I have a problem regarding reading input lines from a file. Which is quite a simple task I can manage but the problem is input file lines can consist of words and numbers which then I have to read them seperately and store them in different variables. Let me give an example(italics):
BOOK 100
PENCIL 45
LAPTOP 49
SPOON 34
The reading operation would work regardless of how many spaces there between the Word and the numbers.
I have written this piece of code to read lines directly. But I do not know how to parse them according to the information I gave up.
string fileName;
cout << "Enter the name of the file: ";
cin >> fileName;
ifstream file;
file.open(fileName);
while(file.fail())
{
cout << "enter file name correctly:";
cin >> fileName;
file.open(fileName);
}
string line;
int points;
while(!file.eof())
{
getline(file, line);
stringstream ss(line);
*I do not know what to do here :)*
}
But I do not know how to parse them according to the information I gave up.
Thats quite simple, see below example:
std::stringstream ss("SPOON 34");
std::string s;
int n;
if (ss >> s >> n) {
std::cout << s <<"\n";
std::cout << n <<"\n";
}
outputs:
SPOON
34
You can use sscanf.
char name[100];
int number;
sscanf(line, "%s %d", name, &number);
printf("%s, %d", name, number);
Now I am not sure if this really C++ish. The alternative being using stringstreams like you have started.
I have a .csv file that has 3 rows and 5 columns with values of 0,1,2,3,50, or 100. I saved it from an excel sheet to a .csv file. I am trying to use C++ to read in a .csv file and output the first two column values in the .csv file into a text file based on the last three column values. I am assuming the .csv file looks like
1,1,value,value,value
1,2,value,value,value
1,3,value,value,value
But I couldn't find a whole lot of documentation on the format of .csv files.
I looked at Reading Values from fields in a .csv file? and used some of the code from there.
Here is my code:
#include <iostream>
#include <fstream>
using namespace std;
char separator;
int test_var;
struct Spaxel {
int array1;
int array2;
int red;
int blue_o2;
int blue_o3;
};
Spaxel whole_list [3];
int main()
{
// Reading in the file
ifstream myfile("sample.csv");
Spaxel data;
int n = 0;
cout << data.array1<< endl;
myfile >> data.array1; // using as a test to see if it is working
cout << data.array1<< endl;
while (myfile >> data.array1)
{
// Storing the 5 variable and getting rid of commas
cout<<"here?"<< endl;
// Skip the separator, e.g. comma (',')
myfile >> separator;
// Read in next value.
myfile >> data.array2;
// Skip the separator
myfile >> separator;
// Read in next value.
myfile >> data.red;
// Skip the separator, e.g. comma (',')
myfile >> separator;
// Read in next value.
myfile >> data.blue_o2;
// Skip the separator
myfile >> separator;
// Read in next value.
myfile >> data.blue_o3;
// Ignore the newline, as it is still in the buffer.
myfile.ignore(10000, '\n');
// Storing values in an array to be printed out later into another file
whole_list[n] = data;
cout << whole_list[n].red << endl;
n++;
}
myfile.close();
// Putting contents of whole_list in an output file
//whole_list[0].red = whole_list[0].array1 = whole_list[0].array2 = 1; this was a test and it didn't work
ofstream output("sample_out.txt");
for (int n=0; n<3; n++) {
if (whole_list[n].red == 1)
output << whole_list[n].array1 <<","<< whole_list[n].array2<< endl;
}
return 0;
}
When I run it in Xcode it prints three 0's (from the cout << data.array1<< endl; and cout << data.array1<< endl; in the beginning of the main() and from the return 0) but does not output any file. Apparently the .csv file isn't getting read in correctly and the output file is not getting written correctly. Any suggestions?
Thanks for your time!
There are a couple of problem areas in the code you presented:
Hard coded filename. Running your program in a directory that doesn't have "sample.csv" could cause the ifstream failure you're seeing.
No checking whether myfile opened successfully or not.
Loop can access an out-of-bound index in whole_list if "sample.csv" has more lines.
The refactored code below, while not completely foolproof, corrects many of the issues mentioned. It should get you most of the way there.
#include <iostream>
#include <vector>
#include <fstream>
#include <sstream>
using namespace std;
struct Spaxel
{
int array1;
int array2;
int red;
int blue_o2;
int blue_o3;
};
ostream& operator << (ostream &os, const Spaxel &rhs)
{
os << rhs.array1
<< ','
<< rhs.array2
<< ','
<< rhs.red
<< ','
<< rhs.blue_o2
<< ','
<< rhs.blue_o3;
return os;
}
istream& operator >> (istream &is, Spaxel &rhs)
{
char delim;
is >> rhs.array1
>> delim
>> rhs.array2
>> delim
>> rhs.red
>> delim
>> rhs.blue_o2
>> delim
>> rhs.blue_o3;
return is;
}
int main(int argc, const char *argv[])
{
if(argc < 2)
{
cout << "Usage: " << argv[0] << " filename\n";
return 1;
}
const char *infilename = argv[argc - 1];
// Reading in the file
ifstream myfile(infilename);
if(!myfile)
{
cerr << "Couldn't open file " << infilename;
return 1;
}
vector<Spaxel> whole_list;
string line;
while( getline(myfile, line) )
{
Spaxel data;
stringstream linestr (line);
linestr >> data;
whole_list.push_back(data);
cout << data << '\n';
}
}
Edit: Just to help clarify some things from the comment.
As you know main is the entry point of your program so it isn't something called by your own code. The extra optional parameters int argc, const char *argv[], is how options and parameters get passed in when you run your program with arguments. First parameter argc indicates how many arguments were passed in. The second argv is an array of char * with each element being the argument passed. The first argument argv[0] is your program name and so argc is always >= 1.
Say you execute your sample program from the shell:
./sample sample.csv
then argc and argv will have the following:
argc = 2;
argv[0] = "sample"
argv[1] = "sample.csv"
So const char *infilename = argv[argc - 1]; gets the last argument passed in which should be the filename to read in.
Sorry i am not doing it within struct but i hope you will got it and resolve your problem.
char separator;
int value1;
int value2;
int value3;
while (myfile >> value1)
{
// Skip the separator, e.g. comma (',')
myfile >> separator;
// Read in next value.
myfile >> value2;
// Skip the separator, e.g. comma (',')
myfile >> separator;
// Read in next value.
myfile >> value3;
// Ignore the newline, as it is still in the buffer.
myfile.ignore(10000, '\n');
}
The above code fragment is not robust but demonstrates the concept of reading from a file, skipping non-numeric separators and processing the end of the line. The code is optimized either.
This is my problem: I read some lines from a txt. This txt is like this:
Ciao: 2000
Kulo: 5000
Aereo: 7000
ecc. I have to assign every word before(':') to a string and then to a map; and the numbers to a int and then to a map. The problem is that beginning from the second line, my string become ("\nKulo") ecc! I don't want this! What can I do?
This is the code:
#include <iostream>
#include <fstream>
#include <string>
#include <map>
using namespace std;
int main()
{
map <string, int> record;
string nome, input;
int valore;
ifstream file("punteggi.txt");
while (file.good()) {
getline(file, nome, ':');
// nome.erase(0,2); //Elimina lo spazio iniziale
file >> valore;
record[nome] = valore;
cout << nome;
}
file.close();
cout << "\nNome: ";
cin >> input;
cout << input << ": " << record[input] << "\n";
cout << "\n\n";
return 0;
}
The issue you have is that std::getline() is an unformatted input function and as such doesn't skip leading whitespace. From the looks of it, you want to skip leading whitespace:
while (std::getline(in >> std::ws, nome, ':') >> valore) {
...
}
Alternatively, if there are leading spaces, you can ignore() all characters up to the end of line after reading a value.
BTW, since I saw someone over here recommending the use of std::endl: do not use std::endl unless you really intend to flush the buffer. It is a frequent major performance problem when writing files.
Use the standard line reading idiom:
for (std::string line; std::getline(file, line); )
{
std::string key;
int n;
std::istringstream iss(line);
if (!(iss >> key >> n) || key.back() != ':') { /* format error */ }
m.insert(std::make_pair(std::string(key.cbegin(), std::prev(key.cend()),
n));
}
(Instead of the temporary string-from-iterators, you can also use key.substr(0, key.length() - 1), although I imagine that my version may be a bit more efficient. Or add a key.pop_back(); before inserting the data into the map.)