How Can I Rewrite Without Stod() [duplicate] - c++

This question already has answers here:
Easiest way to convert int to string in C++
(30 answers)
Converting Input string to float/double C++
(5 answers)
Closed 5 years ago.
How can I rewrite my readDetails function without using stod() or strtod() in C++?
The compiler I will be using doesn't have c++11 enabled and I get
'stod' was not declared in this scope error
int readDetails(SmallRestaurant sr[])
{
//Declaration
ifstream inf;
//Open file
inf.open("pop_density.txt");
//Check condition
if (!inf)
{
//Display
cout << "Input file is not found!" << endl;
//Pause
system("pause");
//Exit on failure
exit(EXIT_FAILURE);
}
//Declarations and initializations
string fLine;
int counter = 0;
int loc = -1;
//Read
getline(inf, fLine);
//Loop
while (inf)
{
//File read
loc = fLine.find('|');
sr[counter].nameInFile = fLine.substr(0, loc);
fLine = fLine.substr(loc + 1);
loc = fLine.find('|');
sr[counter].areaInFile = stod(fLine.substr(0, loc)); //line using stod
fLine = fLine.substr(loc + 1);
loc = fLine.find('|');
sr[counter].popInFile = stoi(fLine.substr(0, loc));
fLine = fLine.substr(loc + 1);
sr[counter].densityInFile = stod(fLine); //line using stod
counter++;
getline(inf, fLine);
}
//Return
return counter;
}
Below is the text I am trying to read:
Census Tract 201, Autauga County, Alabama|9.84473419420788|1808|183.651479494869
Census Tract 202, Autauga County, Alabama|3.34583234555866|2355|703.860730836106
Census Tract 203, Autauga County, Alabama|5.35750339330735|3057|570.60159846447

Use std::istringstream.
std::string number_as_text("123");
int value;
std::istringstream number_stream(number_as_text);
number_stream >> value;
Edit 2: For those pedantic people:
The example below reads a double. Very similar pattern to the above reading of an integer.
std::string number_as_text("3.14159");
double pi;
std::istringstream number_stream(number_as_text);
number_stream >> pi;
You could also use a variant of sprintf.
Edit 1: Another parsing method
You could try:
std::string tract;
std::string county;
std::string state;
double value1;
char separator;
//...
std::ifstream input("myfile.txt");
//...
std::getline(input, tract, ',');
std::getline(input, county, ',');
std::getline(input, state, '|');
input >> value1;
input >> separator;
//...
input.ignore(100000, '\n'); // Ignore any remaining characters on the line
The above doesn't require separate string to number conversion.

Related

How to assign words from csv assign to variables? [duplicate]

This question already has answers here:
How can I read and parse CSV files in C++?
(39 answers)
Closed 2 years ago.
I have a code that reads a file with a following:
word1,word2,word,3....,word8
word1,word2,word,3....,word8
word1,word2,word,3....,word8
ifstream infile;
//string path;s
infile.open("file.csv");
string line;
CourseNode *current = head;
int i=1;
if(infile.is_open()){
while(getline(infile, line)) {
if(i == 1)
cout << "1st line==> "+line << endl; // ignore first line
else { // read data
string firstname, lastname, id, a,b,c,d,t ;
stringstream sst(line);
getline(getline (sst, firstname, ','),lastname, ',');
//getline(getline(getline (sst, firstname, ','),lastname, ','),id, ',');
cout << "result==> "<< firstname<<" "<<lastname << endl;
}
i++;
}
I assume i have to work with this line and insert there my string variables but i am not sure how!
getline(getline (sst, firstname, ','),lastname, ',');
Any help will be appreciateed! Thank you!
To read a .csv file you may read the entire line and split after to load easly your data:
std::ifstream infile;
infile.open("file.csv");
std::string line;
int i = 1;
if(infile.is_open()){
while(getline(infile, line)) {
if(i == 1) {
// ignore line
continue;
} else { // read data
std::vector<std::string> value; // this is where you stock the data
value = split(line); // add your implementation of split
// here: do something with the data in value
}
i++;
}
}
You have in value every data from a line of your .cvs file. Now, you can assigne every case to a specific variable or put them in a list of object.

How to know if next getline is EOF C++

Hi i'm doing some project to read input from csv file, the value i extract from file are Day, Month, Year, Hour, Minute, Windspeed, SolarRadiation.
bool readFile(MasterMap &mastMap){
const string index = "MetData/data.txt"; //<--- container of every file name constant cant change
string temp, temp2, token; // <--temp to store filename from index,
// <-- temp2 to getline from every single line from file
// << token to store temporary data
ifstream myFile(index.c_str()); // create ifstream to read into the index file
if(myFile.is_open()){
while(getline(myFile, temp))
{
cout << temp << endl; // <--- Print out the file name (testing)
string fileName = "MetData/"+temp; // <-- filename is to contain temp
ifstream actualFile(fileName.c_str()); // <--- Open the File
if(actualFile.is_open())
{
time timeValue;
MonthsMap monthMap;
windLog wLog;
solarRadiation SR;
windSpeed WS;
string MonthYear = "";
int MY = 0;
int day = 0;
int totalCount = 0;
getline(actualFile, temp2); //remove the first line of the file.
while(**actualFile.eof()**)
{
getline(actualFile, temp2)
stringstream ss(temp2); // <-- pas line to stream
getline(ss, token,'/'); // <--Token for day;
int dayTemp = atoi(token.c_str());
getline(ss, token,'/'); // <--Token for month;
string month = token.c_str();
getline(ss, token,' '); // <--Token for year;
string year = token.c_str();
MonthYear = month + year;
if(MY == 0 && day == 0){
MY = atoi(MonthYear.c_str());
day = dayTemp;
}
if(day!=dayTemp || actualFile.eof()){
monthMap.insertWindLog(day, wLog);
wLog = windLog();
day = dayTemp;
if(MY!=atoi(MonthYear.c_str()) || actualFile.eof()){
cout << "Entered Month > " << MY << endl;
mastMap.insertData(MY, monthMap);
monthMap = MonthsMap();
MY=atoi(MonthYear.c_str());
}
getline(ss, token,':'); // <-- Token for Hour;
timeValue.setHour(atoi(token.c_str()));
getline(ss, token,','); // <-- Token for Minute;
timeValue.setMinute(atoi(token.c_str()));
for(int i = 0; i<9; i++)
getline(ss, token, ',');
getline(ss, token,','); // <-- Token for WindSpeed
WS.setTime(timeValue);
WS.setWindspeed(atof(token.c_str()));
getline(ss,token,','); // <-- Token for Solar Radiation
SR.setTime(timeValue);
SR.setSolarRadiation(atof(token.c_str()));
wLog.insertDataSR(SR);
wLog.insertDataWS(WS);
}
else{
getline(ss, token,':'); // <-- Token for Hour;
timeValue.setHour(atoi(token.c_str()));
getline(ss, token,','); // <-- Token for Minute;
timeValue.setMinute(atoi(token.c_str()));
for(int i = 0; i<9; i++)
getline(ss, token, ',');
getline(ss, token,','); // <-- Token for WindSpeed
WS.setTime(timeValue);
WS.setWindspeed(atof(token.c_str()));
getline(ss,token,','); // <-- Token for Solar Radiation
SR.setTime(timeValue);
SR.setSolarRadiation(atof(token.c_str()));
wLog.insertDataSR(SR);
wLog.insertDataWS(WS);
}
totalCount++;
}
cout << totalCount << endl;
actualFile.close();
}else
return false;
}
myFile.close();
}else
return false;}
Problem
The problem is when the line reach end-of-file, it will end the loop immediatly but what i need is check if the current line is EOF, so it can enter the last month.
**edited :: Full Code
**edited :: thanks for you input guys, i just rewrite abit of my code, i change the loop param into while(!actualFile.eof()) and for the if statement i put if(day!=dayTemp || actualFile.eof()) and the getline is after the while loop
Sorry for unclear question and title
Take a look here:
http://www.cplusplus.com/reference/istream/istream/getline/
I quote:
The function will also stop extracting characters if the end-of-file is reached. If this is reached prematurely (before either writing n characters or finding delim), the function sets the eofbit flag.
More information here:
http://www.cplusplus.com/reference/ios/ios_base/iostate/
You want to look at rdstate:
http://www.cplusplus.com/reference/ios/ios/rdstate/
And test for the flag eofbit.
That resource also shows you about eof():
http://www.cplusplus.com/reference/ios/ios/eof/
It gives an example:
// ios::eof example
#include <iostream> // std::cout
#include <fstream> // std::ifstream
int main () {
std::ifstream is("example.txt"); // open file
char c;
while (is.get(c)) // loop getting single characters
std::cout << c;
if (is.eof()) // check for EOF
std::cout << "[EoF reached]\n";
else
std::cout << "[error reading]\n";
is.close(); // close file
return 0;
}
So, use eof() to test if you have reached the end of the file. But you can also do that flag test if approrpriate in your case. I think eof() is sufficient.
You could do something like this:
Declare variable bool reach;
getline(file, line);
if(file.eof()) reach = true;

How do separate a string from a text file

I have a text file that has information format like this:
id last,first string
for example:
0 Snow,John nothing
1 Norris,Chuck everything
How do i get last name and first name stored separately?
To get information from file, I did:
#include <fstream>
int id;
string str;
string last;
string first;
int main()
{
ifstream myfile(ex.txt);
myfile >> id;
while (myfile)
{
for (int i = 0; i < 4; i++) // this is the amount of times i'll get information from 1 line
{
id = id; // its actually some_structure.id = id, omit
getline(myfile, last, ','); // i think i need to use another function as getline get the whole line
cout << id;
cout << last; // print out the whole line!
}
}
}
ifstream myfile;
string line;
while (getline(myfile, line))
{
istringstream ss(line);
int id;
ss >> id;
string fullname;
ss >> fullname;
string firstname, lastname;
{
istringstream ss2(fullname);
getline(ss2, lastname, ',');
getline(ss2, firstname);
}
}
if (std::ifstream input(filename))
{
int id;
string lastname, firstname, other_string;
while (input >> id && getline(input, lastname, ',') &&
input >> firstname >> other_string)
... do whatever you like...
if (!input.eof())
std::cerr << "error while parsing input\n";
}
else
std::cerr << "error while opening " << filename << '\n';
The code above has more error checking than the other answers I've seen, but admittedly - because it doesn't read text a line at a time then parse out the fields, it would happily accept e.g.:
10 Chuck,
Norris whatever
Would recomend something like this:
string name;
myfile >> id >> name >> str;
first = name.substr(0, name.find(","));
last = name.substr(name.find(",") + 1);
Note that your EOF checking is incorrect.
// The complete code that will do the job
// Please remove uncomment all code
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main () {
string line;
ifstream myfile ("ex.txt");
if (myfile.is_open())
{
while ( getline (myfile,line) )
{
cout << line << '\n';
string last = line.substr(line.find(" ") + 1, line.find(",") - 2);
string first = line.substr(line.find(",") + 1, line.find(",") + line.find(" ") - 1);
}
myfile.close();
}
else {
cout << "Unable to open file";
}
return 0;
}

Reading in a file with delimiter and blank lines for hashing program

How do I read in lines from a file and assign specific segments of that line to the information in structs? And how can I stop at a blank line, then continue again until end of file is reached?
Background: I am building a program that will take an input file, read in information, and use double hashing for that information to be put in the correct index of the hashtable.
Suppose I have the struct:
struct Data
{
string city;
string state;
string zipCode;
};
But the lines in the file are in the following format:
20
85086,Phoenix,Arizona
56065,Minneapolis,Minnesota
85281
56065
I cannot seem to figure this out. I am having a really hard time reading in the file. The first line is basically the size of the hash table to be constructed. The next blank line should be ignored. Then the next two lines are information that should go into the struct and be hashed into the hash table. Then another blank line should be ignored. And finally, the last two lines are input that need to be matched to see if they exist in the hash table or not. So in this case, 85281 is not found. While 56065 is found.
This is what I have and it doesn't seem to be doing what I want it to do:
int main(int argc, char *argv[])
{
string str;
//first line of file is size of hashtable
getline(cin, str);
stringstream ss(str);
int hashSize;
ss >> hashSize;
//construct hash table
Location *hashTable = new Location[hashSize];
//skip next line
getline(cin, str);
string blank = " ";
while(getline(cin, str))
{
{
//next lines are data
Location locate;
string line;
getline(cin, line);
istringstream is(line);
getline(is, locate.zipCode, ',');
getline(is, locate.city, ',');
getline(is, locate.state, ',');
insertElementIntoHash(hashTable, locate, hashSize);
}
}
dispHashTable(hashTable, hashSize);
//read third set of lines that check if the zipCodes are in the hashtable or not
while(getline(cin, str))
{
//stop reading at a blank line or in this case, end of file
stringstream is(str);
string searchZipCode;
is >> searchZipCode;
searchElementInHash(hashTable, hashSize, searchZipCode);
}
//delete hash table after use
delete []hashTable;
return 0;
}
You might read the input this way:
#include <iostream>
#include <sstream>
#include <vector>
struct Location
{
std::string city;
std::string state;
std::string zipCode;
};
int main(int argc, char *argv[]) {
std::istringstream input(
"2\n"
"\n"
"85086,Phoenix,Arizona\n"
"56065,Minneapolis,Minnesota\n"
"\n"
"85281\n"
"56065\n"
);
// Make the size unsigned, to avoid signed/unsigned compare warnings.
unsigned hashSize;
std::string line;
getline(input, line);
std::istringstream hash_line(line);
// Ignore white space.
if( ! (hash_line >> hashSize >> std::ws && hash_line.eof())) {
std::cerr << "Error: Invalid file format [1].\n" << line << '\n';
return -1;
}
else {
getline(input, line);
std::istringstream first_blank_line(line);
// Ignore white space.
first_blank_line >> std::ws;
if( ! first_blank_line.eof()) {
// Missing blank line.
std::cerr << "Error: Invalid file format [2].\n" << line << '\n';
return -2;
}
else {
// Have a local variable (No need to allocate it)
// (Is it a hash table !???)
std::vector<Location> hashTable;
hashTable.reserve(hashSize);
while(hashTable.size() < hashSize && getline(input, line)) {
std::istringstream data_line(line);
Location locate;
getline(data_line, locate.zipCode, ',');
getline(data_line, locate.city, ',');
getline(data_line, locate.state); // Note: No comma here.
if(data_line && data_line.eof()) {
// Note: The fields may have leading and/or trailing white space.
std::cout
<< "Insert the location into the hash table.\n"
<< locate.zipCode << '\n'
<< locate.city << '\n'
<< locate.state << '\n';
hashTable.push_back(locate);
}
else {
std::cerr << "Error: Invalid file format [3].\n" << line << '\n';
return -3;
}
}
if(hashTable.size() != hashSize) {
std::cerr << "Error: Invalid file format [4].\n";
return -4;
}
else {
getline(input, line);
std::istringstream second_blank_line(line);
// Ignore white space.
second_blank_line >> std::ws;
if( ! second_blank_line.eof()) {
// Missing blank line.
std::cerr << "Error: Invalid file format [5].\n";
return -5;
}
else {
std::string searchZipCode;
while(input >> searchZipCode) {
// Search element in the hash table
}
}
}
}
}
return 0;
}
Following modification should work:
//skip next line
getline(cin, str);
string blank = " ";
string line;
while(getline(cin, line) && (line != ""))
{
{
//next lines are data
Location locate;
istringstream is(line);
getline(is, locate.zipCode, ',');
getline(is, locate.city, ',');
getline(is, locate.state, ',');
insertElementIntoHash(hashTable, locate, hashSize);
}
}

how to extract out data from a txt file which is seperated by |

I am looking for a way to extract out data from a txt file which data is seperated by row and each column of data is seperaed by |
Here's an example
12|john bravo|123 kings street
15|marry jane|321 kings street
Previously i did it by separating using spaces like this
12 john kingstreet
15 marry kingstreet
But it poses a problem when I add a last name to the names/ add an address with spaces, ex: john bravo
So I decided to separate the column data using |
this is how I extract the data
struct PERSON{
int id;
string name;
string address;
};
//extract
int main(){
PERSON data[2];
ifstream uFile("people.txt");
int i = 0;
while(uFile >> data[i].id >> data[i].name >> data[i].address){
i++;
}
return 0;
}
So how do i extract if the columns are separated by | ??
Use getline() twice:
First, get each line use default seperator (new line); second, for each segment from first step, use '|' as seperator. "stringstream" class may be used to transfer data.
#edward The code below is modified from yours, and I think #P0W58 's answer is better.
#include <iostream>
#include <fstream>
#include <sstream>
using namespace std;
const int length = 2;
struct PERSON
{
int id;
string name;
string address;
};
//extract
int main()
{
PERSON data[length];
ifstream fin("people.txt");
int i = 0;
while(true)
{
string segment;
if (!getline(fin, segment))
break;
stringstream transporter;
transporter << segment;
string idString;
getline(transporter, idString, '|');
getline(transporter, data[i].name, '|');
getline(transporter, data[i].address, '|');
stringstream idStream;
idStream << idString;
idStream >> data[i].id;
i++;
}
for (i=0; i<length; i++)
cout << data[i].id << '+' << data[i].name << '+'\
<< data[i].address << endl;
return 0;
}
To read into a struct , I'd overload << and then parse the text as mentioned in one of the answer .
Something like this :
#include<sstream>
//...
struct PERSON{
int id;
std::string name;
std::string address;
friend std::istream& operator >>(std::istream& is, PERSON& p)
{
std::string s;
std::getline(is, s); //Read Line, use '\r' if your file is saved on linux
std::stringstream ss(s);
std::getline(ss, s, '|'); //id
p.id = std::atoi(s.c_str());
std::getline(ss, p.name, '|'); // name
std::getline(ss, p.address, '|'); //address
return is ;
}
};
And then you can probably do,
std::ifstream fin("input.txt");
PERSON p1;
while (fin >> p1)
//std::cout << p1.id << p1.name << std::endl ;
You can overload << too
Use boost::tokenizer or find first of like :
// code example
string s = "12|john bravo|123 kings street";
string delimiters = "|";
size_t current;
size_t next = -1;
do
{
current = next + 1;
next = s.find_first_of( delimiters, current );
cout << s.substr( current, next - current ) << endl;
}
while (next != string::npos);