How do you read in a double from a file in C++?
For ints I know you can use the getline() and then atoi, but I am not finding an array to double function. What is available for reading in doubles, or converting a char array to a double?
You can use stream extraction:
std::ifstream ifs(...);
double d;
ifs >> d;
This work provided that other then whitespace, the next data in the stream should be a double in textual representation.
After the extraction, you can check the state of the stream to see if there were errors:
ifs >> d;
if (!ifs)
{
// the double extraction failed
}
Do not consider using atof(), or any of the ato.. functions, as they do not allow you to diagnose errors. Take a look at strtod and strtol. Or use the stream extraction operators.
I'm wondering, does one need to be careful about locale settings (e.g. a locale could use comma instead of dot to separate the decimal part) or do stringstreams always default to some standard "C locale" notation?
You can leverage istringstream For example, here are toDouble and toInt:
double toDouble(string s) {
double r = 0;
istringstream ss(s);
ss >> r;
return r;
}
int toInt(string s) {
int r=0;
istringstream ss(s);
ss >> r;
return r;
}
Related
I've attempted to use atof() (which I think is way off) and stringstream. I feel like stringstream is the answer, but I'm so unfamiliar with it. Based on some Google searches, YouTube videos, and some time at cplusplus.com, my syntax looks like below. I'm pulling data from a .csv file and attempting to put it into a std::vector<double>:
while (file.good() )
{
getline(file,line,',');
stringstream convert (line);
convert = myvector[i];
i++;
}
If you are reading doubles from a stream (file) we can simplify this:
double value;
while(file >> value) {
myvector.push_back(value);
}
The operator>> will read from a stream into the type you want and do the conversion automatically (if the conversions exists).
You could use a stringstream as an intermediate if each line had more information on it. Like a word an integer and a double.
std::string line;
while(std::getline(file, line)) {
std::stringstream lineStream(line);
std::string word;
int integer;
double real;
lineStream >> word >> integer >> real;
}
But this is overkill if you just have a single number on each line.
Now lets look at a csv file.
This is a line based file but each value is seporated by ,. So here you would read a line then loop over that line and read the value followed by the comma.
std::string line;
while(std::getline(file, line)) {
std::stringstream lineStream(line);
double value;
char comma;
while(lineStream >> value) {
// You successfully read a value
if (!(lineStream >> comma && comma == ',')) {
break; // No comma so this line is finished break out of the loop.
}
}
}
Don't put a test for good() in the while condition.
Why is iostream::eof inside a loop condition considered wrong?
Also worth a read:
How can I read and parse CSV files in C++?
I was wondering if, like in C, in C++ there was a way to take at once two different type of varibales as inputs.
For example I am supposed to read a command (a string) followed by an index(an integer) from a user, and they separated by a space.
The >> operator for a std::istream is overloaded for many different types. Any class which inherits >> from std::istream can read inputs from all the types >> is overloaded for. This means you can use the >> operator with std::cin, std::ifstream, std::istringstream, etc. to read in multiple types.
The basic syntax for your case would have the form
std::string s;
int n;
std::cin >> s >> n; // or std::ifstream, etc.
Of course you should perform error checking to make sure you actually received what you expected. You can use the ! operator to check if the stream is (not) in a good state. So in your case you might use the following:
std::string s;
int n;
if (!std::cin) {
// error handling here
} else {
std::cin >> s; // get the std::string
}
if (!std::cin) {
// error handling here
} else {
std::cin >> n; // get the int
}
Suppose we have a string line:
14.6527 39.5652 -344.226 -3.34672
Let's call this string, str_line.
My question is, how can we parse this into a float array, float data[4].
I tried using getline from stringstream but to no avail (see below for representation of my code). Any help would be appreciated :)
for(int i=0;i<4;i++){
stringstream ss(str_line);
ss.getline( str_line, 8, ' ' );
data[i]=atof(ss);
}
You should declare stringstream object ss once, don't do it in a loop.
Then you have to only use the operator >> to extract floats from the stream.
stringstream ss(str_line);
for(int i=0;i<4;i++){
ss >> data[i];
}
If you're reading from a file, you can use a file stream like ifstream and read floats directly from it. The stream will ignore any whitespaces including newlines.
Use the >> operator on stringstream:
ss >> data[i];
I want to parse a file which describes a set of data line by line. Each datum consists of 3 or four parameters: int int float (optional) string.
I opened file as ifstream inFile and used it in a while loop
while (inFile) {
string line;
getline(inFile,line);
istringstream iss(line);
char strInput[256];
iss >> strInput;
int i = atoi(strInput);
iss >> strInput;
int j = atoi(strInput);
iss >> strInput;
float k = atoi(strInput);
iss >> strInput;
cout << i << j << k << strInput << endl;*/
}
The problem is that the last parameter is optional, so I'll probably run into errors when it is not present. How can i check in advance how many parameters are given for each datum?
Furthermore,
string line;
getline(inFile,line);
istringstream iss(line);
seems a bit reduldant, how could I simplyfiy it?
Use the idiomatic approach in this situation, and it becomes much simpler:
for (std::string line; getline(inFile, line); ) {
std::istringstream iss(line);
int i;
int j;
float k;
if (!(iss >> i >> j)) {
//Failed to extract the required elements
//This is an error
}
if (!(iss >> k)) {
//Failed to extract the optional element
//This is not an error -- you just don't have a third parameter
}
}
By the way, atoi has some highly undesired ambiguity unless 0 is not a possible value for the string you're parsing. Since atoi returns 0 when it errors, you cannot know if a return value of 0 is a successful parsing of a string with a value of 0, or if it's an error unless you do some rather laborious checking on the original string you had it parse.
Try to stick with streams, but in situations where you do need to fall back to atoi type functionality, go with the strtoX family of functions (strtoi, strtol, strtof, etc). Or, better yet, if you're using C++11, use the stoX family of functions.
You could use a string tokenizer How do I tokenize a string in C++?
In particular: https://stackoverflow.com/a/55680/2436175
Side note: you do not need to use atoi, you could simply do:
int i,j;
iss >> i >> j;
(but this wouldn't handle alone the problem of optional elements)
I'm trying input a phone number in the format: 555-555-5555 into a struct with three int's. I've tried using getline with a delimiter of "-", but I keep getting the error: "cannot convert parameter 1 from 'int' to 'char *'".
I tried creating a temp char* variable to store the number in and then type casting it to int, but that didn't work.
How should I go about doing this?
Thanks
edit:
here's some of the code:
void User::Input(istream& infile) {
char* phone_temp;
...
infile.getline(phone_temp, sizeof(phoneNum.areaCode), "-");
phoneNum.areaCode = (int)phone_temp;
...
}
Since you are posting this as a c++ question, and not a c question, Use istringstream
http://www.cplusplus.com/reference/iostream/istringstream/
From my head it your code would become something like:
std::string sPhoneNum("555-555-5555");
struct
{
int p1;
int p2;
int p3;
} phone;
char dummy;
std::istringstream iss(sPhoneNum);
iss >> phone.p1; // first part
iss >> dummy; // '-' character
iss >> phone.p2; // second part
iss >> dummy; // '-' character
iss >> phone.p2; // last part
EDIT:
now that you have posted example code, I see you already start with an istream, you can just use the >> operator directly, no need to create another istringstream operator. See examples: http://www.cplusplus.com/reference/iostream/istream/operator%3E%3E/
Also, stay away from c-style conversion methods with char * and atoi stuff if you don't have to, working with std::string and istreams is the "right" C++ way. It avoids memory leaks and other nasty problems.
Reading a phone number from a stream:
Assuming the number is well formatted:
void User::Input(istream& infile)
{
int part1;
int part2;
int part3;
char dash1;
char dash2;
infile >> part1 >> dash1 >> part2 >> dash2 >> part3;
/*
* !infile will return false if the file is in a bad state.
* This will happen if it fails to read a number from
* the input stream or the stream ran out of data.
*
* Both these conditions constitute an error as not all the values will
* be set correctly. Also check that the dash[12] hold the dash character.
* Otherwise there may be some other formatting problem.
*/
if ((!infile) || (dash1 != '-') || (dash2 != '-'))
{
throw int(5); // convert this to your own exception object.
}
}
if I understand correctly, try atoi() or stringstream to convert from char* to int
See this example on how you can tokenize the line. This question will also help.
Then use atoi to convert string to int.
You can't cast a char* to an int and expect a correct value. A char* is an address in memory, so when you cast it to int, you'll get a memory address in your int. You need to call a function, such as atoi() to algorithmically convert the data char* is pointing to into an integer.
Another viable option, although not quite C++, is:
char a[10],b[10],c[10];
scanf("%d-%d-%d", a, b, c);
It appears you're trying to convert a char to an integer, in which case you'd want to use the atoi function or a string stream.
rather than using infile.getline() use the free standing version with a std::string:
getfile(infile, buffer);
After that, if you'd like you can do an addition getline():
istringstream phonenumber(buiffer);
string areacode = getline(phonenumber, part1. '-');
or you can use the extractor >> (that's what it's for!)
int areacode;
phonenumber >> areacode;
Just a side note: if you're using char* do make sure you allocate space for it, or at least point to allocated space.