Reputation: 209
I have a CSV file where the values are separated by commas, something like this:
224,321,345,56.6
225,322,245,46.7
etc,etc,etc.....
All the values must be treated as floats.
The problem is when I try to read the values as floats:
fscanf(file,%f,&value);
If I print the result
printf("The first value is: %f",value)
I get:
The first value is 224,321
How do I read a float value when this value have comma instead of dot?
Upvotes: 2
Views: 4186
Reputation: 153547
C solution
The OP's scanf()
is evidently using floating point decimal_point
of of ","
. Unfortunately the data uses a decimal_point
of of "."
.
The C solution is 4 steps: 1) Determine the current locale 2) change locale 3) call sscanf()
4) restore locale.
#include <locale.h>
// Maybe CurrentLocaleName = "" will work.
// That's the locale-specific native environment.
// Otherwise the value may be available in preceding code.
const char *CurrentLocaleName = TBD();
// In the "C" locale, a decimal_point is ".".
if (NULL == setlocale(LC_NUMERIC, "C")) {
handle_local_change_error();
}
if (first_in_line) {
if (1 != fscanf(file, "%f", &value)) {
handle_scan_error();
}
}
else {
if (1 != fscanf(file, " ,%f", &value)) {
handle_scan_error();
}
}
if (NULL == setlocale(LC_NUMERIC, CurrentLocaleName)) {
handle_local_change_error();
}
Upvotes: 2
Reputation: 153929
Whether the comma is considered a decimal separator or not depends on the locale. You've labeled this for both C and C++; in this case, the solution is different.
In C++, forget about fscanf
and use std::istream
. Then
imbue your stream with std::locale("C")
.
In C, it's a lot harder, since you have to change the global locale. And almost certainly restore it. And if you're multithreaded, do so in a critical section, protected from anyone else who might want to modify the locale as well.
Upvotes: 0
Reputation: 9062
Your post is a little bit ambiguous. You said that in your file you have values separated by comma, and after that you say that you want to read a float value that has comma instead of dot.
Anyway, the default behaviour is to take commas as separators, so 123,324 is readed like 123.00. But, in the following reading, you will get the same value. So, you may want to write it like this:
fscanf(file,"%f, ",&value);
If you want to use comma as a separator, instead of dot (altough I see that you have some values using dot), then you need another separator, like a space, in your files, to separe 2 consecutive values. The file you specified can not be used like this.
Upvotes: 0
Reputation: 1
CVS format contains a bunch of data divided by comma. So when you're trying to parse a cvs file, you have to put the comma symbol as part of your format parameter in scanf function. I believe the following code would be helpful.
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
using namespace std;
int main(int argc, char * argv[]) {
if(argc <= 1) {
printf("No file specified!\n");
exit(0);
}
char * filename = argv[1];
FILE *file = fopen(filename,"rb");
if(0 != file) {
float value = 0;
while(!feof(file)) {
fscanf(file, "%f,", &value);
printf("%f ",value);
}
printf("\n");
}
fclose(file);
return 0;
}
Upvotes: 0
Reputation:
I'm slightly new to coding, but wouldn't you be able to simply remove the comma first and then read it? Simply use a function that runs through the line and eliminates all commas. This seems like the simplest solution to me.
Upvotes: 0
Reputation:
Simple answer: The format is ambiguous. Ether quote values or disambiguate by choosing a different separator (maybe a semicolon)
Another answer (if floating point values have no comma): Switch to the "C"-locale.
Upvotes: 1
Reputation: 409196
One way is to read it as integers, then convert to floating point.
Another is to read line-by-line, split at the comma, and convert each number one-by-one to floating point values.
Both of these solutions have very nice and pretty simple C++ implementations. More work to do it in C.
Upvotes: -1