Is there an equivalent to Perls' split() function in C? - c

I'm trying to split real numbers in a C program using the decimal point as the delimter such that such that say, 1234.56 yields
(int) whole_num = 1234
(int) fraction = 56
Any ideas how I can go about doing this? Its been a loooong while since I mucked around with C, see? :)

void split( double num, int& whole_number, double& fraction) {
fraction = modf(num, &whole_number);
}
This works since modf takes the integer part of the double and returns the fractional part.

Assuming you want to split a string.
strtok_r and your favorite string-to-num function like strtol

If you're dealing with an actual floating-point number, as opposed to a string representation of such, you should use modf for splitting out the integral and fractional parts.
Perl's split splits by regex, so to replicate full functionality you'd need a regex library. For general string-splitting, you may be able to use strtok, but because it changes the string in-place, strtok_r (described on the same page) is recommended instead.

Related

What does atof stand for?

In C atof=a-to-f(loat) converts a string into a double precision float. I am wondering what the a part of atof stand for.
atof is a function in the C programming language that converts a string into a floating point numerical representation. atof stands for ASCII to float. It is included in the C standard library header file stdlib.h. Its prototype is as follows
double atof (const char *str);
The str argument points to a string, represented by an array of characters, containing the character representation of a floating point value. If the string is not a valid textual representation of a double, atof will silently fail, returning zero (0.0) in that case. [1]
Note that while atoi and atol return variable types corresponding with their name ("atoi" returns an integer and "atol" returns a long integer), atof however, does not return a float, it returns a double.
A related function is sscanf. This function extracts values from strings and its return argument is the number of valid values it managed to extract (so, unlike atof, sscanf can be used to test if a string starts with a valid number).
To best answer what the a stands for, go back to early 1970s when bytes cost approached dollars each.
Even if a originally stood for ASCII, atof() did not and still does not mean to convert ASCII into double as the implementation may have used an alternate character encoding. With EBCDIC or PETSCII, one could think of a as alpha and write code for atof() per that non-ASCII encoding.

String to double saving time conversion in c

I'm working on a benchmarking task for an operation (in C language under Linux) and in this operation we use a conversion from string to double a lot (using atof or sscanf functions) but the problem here is that they gave a relatively large time (145, 270 ns respectively) which is not suitable for the operation. So, Do you know any other conversion mechanism that save time?
I tried to use casting but it gave zero
double d;
char ch[] = "123.154";
d = *((double *) ch);
printf ("%lf\n", d); // result 0 (compiled using gcc)
Regards
atof() and sscanf() are generic methods that accept a huge variety of formats. If you know that the floating point values follow a certain pattern, you can try to optimize the conversion for the expected format. ie. no need to support (+-), no need to support Inf, Nan, or sci-notation (1.3e43) etc.
One can make a look up table that converts 3 characters at once from strings:
table[a*256+b*16+c] = a*100+b*10+c; where one simply concatenates the 4 LSB bits of e.g. string "432"; the hex value of the index would be then 0x432 and the content would be 432.
Casting means changing the interpretation of some binary data. Doubles or floats and integers are not binary compatible (except for the value of (+) 0). However the following cast works to check, if three first characters in a strings are numbers:
char num[]="123.123";
if ((*((int*)num) & 0x00f0f0f0) == 0x00303030) // can use faster conversion
// this means interpreting the pointer to string as a pointer to integer
// and then referencing the contents of the memory _as_ integer (+ some bitmasking)
Further, if the set of floating points is relatively small, or some particular value is very frequent, one might trade space for speed and opt for a hash table. If hash table has a match, one can compare the strings 4 or 8 bytes in parallel to verify (or skip that part, if the input is known to be valid). One can also combine these techniques by hashing the first 4 characters for an initial guess and continue from that next 4 characters at a time.
double d;
char ch[] = "123.154";
d = atof(ch);
printf ("%f\n", d);
Or:
printf ("%s\n", ch);

Converting floats and integers to char*

I'm new to C and was kind of thrust into this world of embedded processing with C. I need to convert to char* and output integers and floating point numbers (only 0.01 resolution) to an LCD screen with an 8 bit interface. I've been reading through some of the posts and I see all these great ideas for converting int and float to char* but I'm not exactly sure what's going on in them.
Can someone provide a method for my two queries and a little explanation?
It actually depends upon the standard library, and in some embedded systems that library is partially implemented, or even absent. With a fully standard C99 implementation you might do something like
char buf[40];
int i;
double x;
// compute i & x, then make a string from them with::
snprintf(buf, sizeof(buf), "i=%2d x=%.2f", i, x);
Then you might send that buf to your LCD port, or strdup it for later usage. (If you use strdup you'll need to free the result).
Read the documentation of snprintf for details. You probably should test the return int value of snprintf.
Since you're working on embedded programming you skould be aware of the fact that standard conversions often make use of divisions which are very taxing on any processor.
Since integers are converted using divide-by-ten you could instead implement a division using multiplication by invariant integers. This method should allow you to convert most values in the time it takes to convert a single digit in a value using division.
For floating point use the following steps:
save the sign and take the absolute value if sign is negative
multiply by 10.0 raised to the number of decimals you need
add 0.5 and convert to an integer
convert the integer to a string using the division method previously suggested
make sure the string is at least number of decimals + 1, insert ascii 0 at beginning as necessary
insert a minus sign at the beginning as required
insert a decimal point at the appropriate position
Here is an example that requires two decimals
3758.3125
375831.25 (multiply by 10^2)
375831.75 (add 0.5)
375831 (convert to integer)
"375831" (convert to string)
"3758.31" (insert decimal point => final result)
A somewhat more difficult case
-0.0625
0.0625 (keep sign)
6.25 (multiply by 10^2)
6.75 (add 0.5)
6 (convert to integer)
"6" (convert to string)
"006 (insert ascii 0 as required)
"-006" (insert minus sign)
"-0.06" (insert decimal point => final result)

C: How long can a double be when printed through printf()

I need to specify the exact length of a string to be printed from a double value, but I don't want to restrict the output any more than is necessary.
What is the maximum length that a 6-digit precision double will have when formatted by printf()?
Specifically, what value should I give to X in printf("%X.6lg",doubleValue); to ensure that no value gets truncated?
The reason I need to be specific about the length is that I'm defining an MPI derived datatype made up of lots of string representations of double values and must know their exact length in order to divide regions of the file between MPI processes.
I hope that's clear. Thanks in advance for answering.
use printf("%.6g", doubleValue) or printf("%.6Lg", doubleValue)
Note that leaving off the leading digits (the "width") in the precision specifier makes no demands on the length of the integral portion of the value. Also note that the undercase "l" will specify that your value is a long int. The uppercase "L" specifies a long double value.Also note that if you don't want this to be potentially changed to scientific notation (if it is a shorter representation), then you would use "f" instead of "g".See a printf reference here.
The maximum exponent of an IEEE double is 1023, so largest double will be 1 + 1/2 + 1/4 + 1/8 + ... etc * 2^1023. Which will be about 318 characters long, in decimal notation.
Why not use the "e" format specifier?
There's < float.h > containing many useful values, among them DECIMAL_DIG, which is for a long double however.
The same file will most likely tell you that a double on your platform has more than 6 digits of precision...
PS: Also note Demi's answer above. He points out various flaws in your printf() that escaped me.

Loading data from file in C

i am really struggling to load some numeric floating point data from a file into a C program...the file has floating point numbers with precision of 3 decimal points, each of which is in a single line...i wanted to load these values into an float array and then perform some calculations in it...however i tried loading it into an array of floats but it didn't store the values properly...i.e values like 123.45 were stored as 123.44999 or something..but i don't want this.
i tried to store this in a array of strings and then may be convert them into scaled integers. but i cannot get it to load into an array of string. can anyone tell me where i am going wrong. what i did is something like this.
unsigned char **data
............
data = malloc(sizeof(unsigned char *) * fileSize);
............
while (!feof(fp))
{
if (fscanf (fp, "%s", &data[j]) == 1) // if converted, increment counter
++j;
}
...........
i am a newbie so i am not so good with pointers. and after i load it into an string array, how do i convert it into scaled integers?
You may not have much choice when it comes to floating point numbers like 123.45 being displayed as 123.44999
The 'inaccuracy' of floating point representations has been discussed many times on SO, here's one example.
I would suggest you go back to treating the input as floats, but read up on accuracy issues.
don't use float, use double.
also you can use
double d;
read(d);
(int)(d*100) to get the int.
Unfortunately all you are hitting is the fact that some numbers cannot be accurately represented with a floating point data type. If you manually assigned 124.45 to a float in C (i.e. float f = 123.45) you get exactly the same problem.
Do you really need the level of accuracy? What are you plans for the data?
I would suggest that you use an ifstream to read into a string then convert it to a double.
string number;
ifstream yourfile("yourfile", ios::in);
if(yourfile)
while(yourfile >> number){
double yourFloat=strtod( number.c_str() );
}
How essential is this precision to your application? Floating point numbers can often be slightly inaccurate because they store numbers in a base 2 (binary) representation which cannot properly represent some base-10 numbers.
You have a few options, depending upon how important this precision is to your app.
Live with it. Maybe this inaccuracy isn't a problem for your application
Use Double. It has twice the space
to represent numbers, and will be
more accurate. It can still be inaccurate
in some cases.
Use fixed point math. If you only need to go to n decimal places, it might be worth looking this approach (as it eliminates the source of inaccuracy).
Keep the float as a character string or store it as a Binary Coded Decimal. You'll need to write functions for any mathematical operations you need and performance will be the poorest of these 4 options. But, you'll be able to work with decimal numbers of arbitrary precision without worrying about any loss of precision.
Options 3 or 4 require either the use of an external library, or rolling your own implementation. If 1 or 2 is good enough, then I wouldn't bother with these options.

Resources