convert string of ints and floats to a float array in C - c

what I'm trying to do is to send a string over the network. the point is that the server which receives the string must make the sum of all the numbers and send it back. so i think the easiest way is to take the string and put it in a float array (it does not matter if ints get in there aswell, since the final sum will be a float number).
unfortunately i have no idea how to do that, or more exactly, how to approach it. how do i take the numbers 1 by 1 from a string (let's say, each number is separated by a space)? there must be some function but i can't find it.
the language is plain C under unix.

Use strtod() to convert the first number in the string to double. Add that to your sum, then use the endptr return value argument to figure out if you need to convert another, and if so from where. Iterate until the entire string has been processed.
The prototype for strtod() is:
double strtod(const char *nptr, char **endptr);
Also note that you can run into precision issues when treating integers as floating-point.

You can use fscanf to read from a stream, just like you would use scanf to read from stdin.

You can use strtok to split your string and atof to convert it to float.
char* p;
float farr[100];
int i = 0;
//str is your incoming string
p = strtok(str," ");
while (p != NULL)
{
farr[i] = atof(p);
p = strtok(NULL, " ");
}
I just ran it in an online compiler - http://ideone.com/b3PNTr

you can use sscanf() to read the formatted input from a string.
you can use something like
string=strtok(input," ")
while(string!=NULL)
{ sscanf(string,"%f",&a[i]);
i++;
string=strtok(NULL," ");
}
inside a loop. you can use even atof() instead of using sscanf() with %f.

Related

Convert subsections of array of char to int

Is there a strtol() or sscanf() equivalent where you can specify the no. of chars to convert?
I have a use case where I need to convert sub sections of an array of chars to ints, so I don't have the terminating null char present
In other words, I'd like the equivalent of strncmp() in relation to strcmp()
i.e. strntol() or snscanf() but they don't seem to exist
I imagine i'll just have to copy and append a '\0' and use strtol() or sscanf() but just wanted to check I hadn't missed an existing function for this purpose
question is really do they exist? am i just searching for the wrong thing?
There is no equivalent for strtol, but you can use format specifier to limit the number of characters considered by sscanf:
char *str = "1234567890";
int n;
sscanf(&str[3], "%3d", &n);
printf("%d\n", n);
The %3d specifier instructs sscanf to take only three digits from str, while &str[3] tells sscanf to start at the index 3.
The above code prints 456 (demo).

incompatible types in assignment of `float' to `char[3]'

trying to figure out what is going on here. I'm just learning C, so go easy on me. :P I was assigned to create a unit converter from centimeters to inches. I've got it. Now I want to spice it up a little by creating options. My compiler isn't enjoying what I have. this is the first few lines....
main(void)
{
float centimeter;
char cnv[3];
float entry;
float oz;
float lb;
float cm;
float lb1;
centimeter=2.54;
lb1=2.2;
printf("Hello. Please type exactly, the type of conversion you would like to do.\n\n1. cm to in\n\n2. lb to kg\n");
scanf("%3c",&cnv);
if (strcmp(cnv=cm));
{
printf("Please enter your length in centimeters:\n");
scanf("%f",&entry);
printf("with %.0f centimeters in length, that converts to %.2f inches.",entry,entry/centimeter);
}
if (strcmp(cnv=lb));
{
printf("Please enter your weight in pounds:\n");
scanf("%f",&entry);
printf("with %.0f Pound(s) of weight, that converts to %.2f Kilogram(s).",entry,entry/lb1);
}
}
and it's giving me the error in the title. How can I fix this?
1) You're confusing = (assignment) with == (test for equality)
2) You can't compare a numeric value directly to a character array. You need to convert one or the other to a type which can be compared -- convert the number to string, if your using strcmp() (and understand how that function returns its results, which aren't what you've assumed here), or convert the string to a numeric type and compare that way.
The '=' operator is used for assigning values not comparison. You should use '==' for comparisons.
The values that you are of different types. You should convert one of the variables to the other type to compare.
Strings must be compared with some string comparison function like strcmp() as you have done, but strcmp() is a function and therefore the you should pass the parameters in with a comma separating them.
As an aside strcmp() returns 0 when the strings that you pass in are equivalent, so using a syntax more like this would be appropriate: if(!strcmp(cnv, cm)) or if(strcmp(cnv, cm) == 0)
If I might take a guess what you really were looking to do was something like: if(strcmp(cnv, "cm") == 0) cm is a name of a variable whereas "cm" is a zero terminated string with the characters 'c' and 'm'
The next thing that you will need to worry about is reading in the 3 characters from scanf, because if the input was "cm" and the user pressed enter to enter the text. The program scanned 3 characters one of which was the newline character '\n'. So when you go to do the strcmp() the program will compare each character up till it reaches a byte that has been zeroed out. With just 3 characters being read I am not sure if the string you are capturing is zero terminated, but I am sure that the string could contain a '\n' which would throw the results of strcmp() way off.
Thestrcmp syntax is not correct. For more about string compare function please check this link
http://www.tutorialspoint.com/ansi_c/c_strcmp.htm

How to tell "1.0" is a float but an integer in C language?

I have a program that accept orders by reading commands from a file.
In this file some commands are "float string", like "1.0","2.0", but they are invalid, what the program need is integer, like "1","2". So, how can I make the program understand the commands like "1.0" is invalid? Is there any neat way to do this?
char buf[CMDSIZE];
if(fgets(buf, CMDSIZE, stdin)) //buf likes this: "1.0 \n"
{
*prio = 1; *command = -1; *ratio =1.0;
// I need to make sure that command is not "1.0" or something like this
sscanf(buf, "%d", command);
switch(*command){....blahblah......}
}
Thank you.
It's easier to use strtol.
This will parse a base-10 integer. The pointer e will point to the first character after the integer. You can check to make sure it's a NUL byte and signal an error otherwise. (You also have to check that the input isn't empty.)
If you want to allow spaces / newlines after the number, you can do that too. Note that strtol eats leading whitespace -- but not trailing whitespace.
long v;
char *e;
v = strtol(buf, &e, 10);
if (!buf[0] || *e) {
error();
}
// v has number
Footnote: Checking for overflow and underflow with strtol is a little weird. You have to set errno to 0 first, call strtol, then check if the result is LONG_MIN or LONG_MAX and if errno is set to ERANGE.
Both scanf("%d"....) and scanf("%f"....) will succeed and return 1 when reading the input 1.0. (sscanf works the same way.) It's just that with "%d", it will stop reading before the decimal point.
You can use the format specifier %n with sscanf to see how many characters were read, and then look if the buffer contains more stuff afterwards.
Or, which might be easier, just look at the contents in the buffer with your own code, instead of sscanf, to see if there are only digits there.
in your special case, just to check difference between 1 and 1.0
use the code:
int ret = scanf("%d.%d",&i,&j);
if inputs is 1, the scanf only assign one value, the ret is 1
if inputs is 1.0, the scanf assign two value, the ret is 2.
if inputs is abcd, the scanf can't assign any value, the ret is 0
and regarding the return value of scanf, fscanf etc.
In C99 standard 7.19.6.4 The scanf function
The scanf function returns the value of the macro EOF if an input failure occurs before
any conversion. Otherwise, the scanf function returns the number of input items
assigned, which can be fewer than provided for, or even zero, in the event of an early
matching failure
You can use scanf with %f to store it as a floating point value
example or scan with %d to store it as an integer but it will not count the decimal
#include<stdio.h>
main()
{
float i;
int a;
printf("Enter a number which is a floating point value");
scanf("%f,%d",&i,&a);
}
here using scanf and %f we are storing it in a float variable i so 1.5,1.0
or any number with a decimal will be stored or if we only use the %d it will only store 1,2,3,4 any number without the decimal i.e if we give 2.5 it will only take 2

How store a number starting with 0 in C

Id just thought id ask this question to see whether it can actually be done.
if i want to store a number like "00000000000001", What would be the best way?
bearing in mind that this also has to be incrememted on a regular basis.
Im thinking either there is a way to do this with the integer or i have to convert to a char array somewhere along the line. This would be fine but its a pain to try and increment a string.
I would store it as an integer and only convert to the formatted version with leading zeros on demand when you need to produce output, for example with printf, sprintf etc.
It's far easier that way than storing a string and trying to perform arithmetic on strings. Not least because you have extra formatting requirements about your strings.
If for some reason it is awkward to store an integer as your master data do it like this.
Store the string as your master data.
Whenever you need to perform arithmetic, convert from string to integer.
When the arithmetic is complete, convert back to string and store.
You should simply store the number using an appropriate type (say, unsigned int), so that doing operations like 'increment by one' are easy - only bother worrying about leading zeros when displaying the number.
sprintf can actually do this for you:
unsigned int i = 1;
char buffer[64];
sprintf( buf, "%014u", i );
This prints '00000000000001'.
You could store it in a integer variable (provided there's an integer type that's wide enough for your needs). When printing, simply format the number to have the correct number of leading zeros.
#include <stdlib.h> // for itoa() call
#include <stdio.h> // for printf() call
int main() {
int num = 123;
char buf[5];
// convert 123 to string [buf]
itoa(num, buf, 10);
// print our string
printf("%s\n", buf);
return 0;
}

New to C: whats wrong with my program?

I know my way around ruby pretty well and am teaching myself C starting with a few toy programs. This one is just to calculate the average of a string of numbers I enter as an argument.
#include <stdio.h>
#include <string.h>
main(int argc, char *argv[])
{
char *token;
int sum = 0;
int count = 0;
token = strtok(argv[1],",");
while (token != NULL)
{
count++;
sum += (int)*token;
token = strtok(NULL, ",");
}
printf("Avg: %d", sum/count);
printf("\n");
return 0;
}
The output is:
mike#sleepycat:~/projects/cee$ ./avg 1,1
Avg: 49
Which clearly needs some adjustment.
Any improvements and an explanation would be appreciated.
Look for sscanf or atoi as functions to convert from a string (array of characters) to an integer.
Unlike higher-level languages, C doesn't automatically convert between string and integral/real data types.
49 is the ASCII value of '1' char.
It should be helpful to you....:D
The problem is the character "1" is 49. You have to convert the character value to an integer and then average.
In C if you cast a char to an int you just get the ASCII value of it. So, you're averaging the ascii value of the character 1 twice, and getting what you'd expect.
You probably want to use atoi().
EDIT: Note that this is generally true of all typecasts in C. C doesn't reinterpret values for you, it trusts you to know what exists at a given location.
strtok(
Please, please do not use this. Even its own documentation says never to use it. I don't know how you, as a Ruby programmer, found out about its existence, but please forget about it.
(int)*token
This is not even close to doing what you want. There are two fundamental problems:
1) A char* does not "contain" text. It points at text. token is of type char*; therefore *token is of type char. That is, a single byte, not a string. Note that I said "byte", not "character", because the name char is actually wrong - an understandable oversight on the part of the language designers, because Unicode did not exist back then. Please understand that char is fundamentally a numeric type. There is no real text type in C! Interpreting a sequence of char values as text is just a convention.
2) Casting in C does not perform any kind of magical conversions.
What your code does is to grab the byte that token points at (after the strtok() call), and cast that numeric value to int. The byte that is rendered with the symbol 1 actually has a value of 49. Again, interpreting a sequence of bytes as text is just a convention, and thus interpreting a byte as a character is just a convention - specifically, here we are using the convention known as ASCII. When you hit the 1 key on your keyboard, and later hit enter to run the program, the chain of events set in motion by the command window actually passed a byte with the value 49 to your program. (In the same way, the comma has a value of 44.)
Both of the above problems are solved by using the proper tools to parse the input. Look up sscanf(). However, you don't even want to pass the input to your program this way, because you can't put any spaces in the input - each "word" on the command line will be passed as a separate entry in the argv[] array.
What you should do, in fact, is take advantage of that, by just expecting each entry in argv[] to represent one number. You can again use sscanf() to parse each entry, and it will be much easier.
Finally:
printf("Avg: %d", sum/count)
The quotient sum/count will not give you a decimal result. Dividing an integer by another integer yields an integer in C, discarding the remainder.
In this line: sum += (int)*token;
Casting a char to an int takes the ASCII value of the char. for 1, this value is 49.
Use the atoi function instead:
sum += atoi(token);
Note atoi is found in the stdlib.h file, so you'll need to #include it as well.
You can't convert a string to an integer via
sum += (int)*token;
Instead you have to call a function like atoi():
sum += atoi (token);
when you cast a char (which is what *token is) to int you get its ascii value in C - which is 49... so the average of the chars ascii values is in fact 49. you need to use atoi to get the value of the number represented

Resources