How to read float from a file in C - c

Suppose the file is organized in this way:
1.2 # 3.4 # 4.0
2.3 # 2.3 # 1.2
Read the file in C and store data in an array. Meanwhile, you should judge how many lines there are.
My problem is 1) I don't know how to declare the array as I don't know how many numbers exist in the file, so should I go over the file previously and count the number?
2) I don't know how to judge line number as the last '\n' in the file may exist or may not.

The answer to 1) How to declare the array if you don't know the number of elements in advance, is unsolvable with primitive vectors, you'll have to create your own growing-capable vector.
typedef struct {
double * v;
unsigned int size;
} Vector;
This struct is the basis of the new data type. You'll need an API such as:
Vector createVector();
void addToVector(Vector *v, double x);
double getFromVector(Vector *v, unsigned int pos);
void modifyInVector(Vector *v, unsigned int pos, double x);
unsigned int sizeOfVector(Vector * v);
void destroyVector(Vector *v);
The key members of the API are createVector, destroyVector and addToVector. Since this is probably homework, I won't resolve this to you.
In createVector, you basically have to put all fields to 0.
In destroyVector, you have to free() v;
In addToVector, you'll have to resize() the reserved space so another new item fits:
size_t newSize = ( v->size +1 ) * sizeof( double );
Now you have to call realloc() with the new size.
And that's basically all. If you want better performance, you can introduce also the capacity of the vector, so you don't have to make it grow each time you add a new value. For example, the people that built the STL in C++ make the vector class grow to its double each time the capacity is exceeded. But, anyway, that's another story.

atof (ascii to float):
http://en.wikipedia.org/wiki/Atof

Use fscanf:
The fscanf() function shall read from the named input stream. [...] Each function reads bytes, interprets them according to a format, and stores the results in its arguments. Each expects, as arguments, a control string format described below, and a set of pointer arguments indicating where the converted input should be stored.

The following code reads from the stdin console, processes the numbers in the format you gave and prints them out again so one can check for correctness.
#include <stdio.h>
int main(int ac, char *av[])
{
float a, b, c;
scanf("%f # %f # %f", &a, &b, &c);
printf("%f # %f # %f", a, b, c);
printf("\n");
}
Albeit this code works, it is not very robust. It requires the EXACT sequence ' # ' of characters between numbers and there is nothing but a newline allowed after the last number in a row.
For a more robust solution you would have to find the character index of the start of each number and do a fscanf on that location.

Floating point has precision loss for decimal fractions. For example, a simple number like "0.1" needs an infinite number of bits to represent it accurately.
For the numbers you've shown (only one digit after the decimal point), a better idea would be to multiply each number by 10 to avoid the precision loss that floating point would cause. This would involve writing your own "ASCII to integer" conversion routine that pretends the decimal point is one place to the right of where it actually is. It would also save space, as (for the numbers you've shown, where no number is greater than 25.6) you could store them in an array of 8-bit integers (chars).
Good luck with your homework!

Related

Using unsigned int as array index could lead to buffer overflows?

I have this code in which I have to find security vulnerabilities.
win() {
printf("Congratulations!");
}
setter(unsigned int i, int v, int * a) {
a[i] = v;
}
main() {
int i, v;
int a[50];
puts("i");
scanf("%d", i);
puts("v");
scanf("%d", v);
setter(i, v, a)
}
Reading on the Internet, I've found that when a conversion from an int to an unsigned int takes place, if the int is a negative number, it will be converted into a very high unsigned int. So, probably the vulnerabilty in this code is due to this conversion which takes place when setter is called in the main function. So, an attacker could give the following input: i=-1, v=40 and he will access to a part of the memory which isn't reserved to the buffer a and so, in the setter function, the attacker will be able to overwrite important values. For example, the attacker could overwrite the return address with the address of the win function in order to execute win when setter returns. Am I right?
Summary of some comments and some additions
Firstly, the code is wrong. The arguments to scanf needs to be pointers:
scanf("%d", &i); // Note the &
if the int is a negative number, it will be converted into a very high unsigned int.
Yes, this is technically true, and it's also true that this may lead to accessing the array out of bounds. However, even if you change to unsigned, there is nothing preventing the attacker from simply typing any number, including whatever the number (unsigned) -1 will be on the particular system.
The correct way of solving this security issue is to check that the inputted number are in the range [0,49]. If you use an unsigned number, you may skip checking if it's below zero for obvious reasons. But you still need to do a range check.

Why my answer is 0.00.. confuse how to convert int to float struct

there's something wrong in these variables.
can someone fix this? my answer keep getting on 0.00
Test case:
we want to find the mean between 3 numbers using struct
input=2,
2 of them are: 3 5 8 and 3 5 7
out put should be:
//*3+5+8=(16)/3=5.33
//*3+5+7=(15)/3=5.00
#include<stdio.h>
struct rata{
float in1;
float in2;
float in3;
};
float rata2(in1,in2,in3){
return (float)((in1+in2+in3)/3);
}
void main(){
int i,n;
char hasil[100];
scanf("%d",&n);
struct rata walao;
for (i=0;i<n;i++){
scanf("%d %d %d",&walao.in1,&walao.in2,&walao.in3);
hasil[i]=rata2(walao.in1,walao.in2,walao.in3);
}
for (i=0;i<n;i++){
printf("%.2f\n",hasil[i]);
}
}
There are 3 errors in your code that is preventing you from getting the correct answer. Can you find them? Here's a hint, they have to do with types.
Below are the answers and the reasons behind them.
char hasil[100] is assigning hasil to be a char array of size 100. While chars can be assigned numerical values, they are to be treated as integers if they are. Floats =/= Integers, and this should be rectified by saying float hasil[100]
scanf("%d %d %d",&walao.in1,&walao.in2,&walao.in3) is scanning for 3 digits. Since floats can also be assigned integer values, this is valid. However, the language requires that all values used in a calculation should be the same type (hint for 3!). To fix you can do 1 of 2 things, both are legal but entirely up to you. You can either write it as scanf("%f %f %f",&walao.in1,&walao.in2,&walao.in3) or keep it as is. Your choice will come to play in final error
The input rata2 is taking is unspecified. Is it ints? floats? chars? It doesn't know but it trys to resort to using ints, as mostly everything in C can be represented by a number. Since it resorts to ints, the value returned by your calculation is an int as well and no late cast to float will change that. Those variables need to be specified as something and how you handled error 2 decides what you do here. If you changed the earlier scanf to take floats instead of digits, rewrite rata as float rata2(float in1, float in2, float in3), remove the cast and you're done. If you kept as is, rewrite rata as float rata2(int in1, int in2, int in3), and rewrite the return as return ((float)in1 + (float)in2 + (float)in3)/3;. Either course of action is acceptable but its far more easier and faster specifying them as floats then trying to cast everything (Plus its a LOT cleaner).
This should rectify your code (tested it on my machine). Also, for future note, do
scanf("%d",&n);float hasil[n];
It makes more sense and you don't have to run into the issue of people specifying memory you don't have access to.

Bizarre situation - 100 digit number input asked

I need to make a program that can take numbers of up to 100 digits as input. No standard int datatype will be able to do that! I've never come across such a bizarre situation.
I don't get it at all. How am I supposed to solve this?
The question I'm working on is this:
A whole number will be given, and you have to make a program that will
determine whether it's an even or odd number.
Input Specification
In the first line, there will be an integer T denoting the number of
testcases. In the following T lines, a non-negative integer will be
given. The number can have a maximum of 100 digits.
Output Specification
For every whole number given, you will have to print whether it's odd
or even as output.
Can anyone guide me on how to solve the problem (if it is even possible to do so)?
The program will take a number as input and determine whether it's odd or even.
Read the input in a string (char [101]) and analyze only last digit to check whether number is odd or even. Rest of the digits are irrelevant for this task.
There is no standard numeric type guaranteed to hold that many digits. You need to store the value in a different way, e.g., as a string or other array. If you need to perform arithmetic on these numbers, you need to implement those operations for the types you use, or use some kind of arbitrary precision library.
(Tip: You also don't necessarily need the entire number for certain operations, e.g., you can tell whether it is even or odd by looking only at the last digit…)
The exercise is to determine whether a whole number of up to 100 digits is odd or even.
This does not require you to perform arbitrary arithmetic on the number, so if you need to handle numbers larger than the largest integer type on your system, you can treat them as a string of digits.
Whether it is even or odd only depends on the last digit.
To all those who took the time and effort to answer this question,
Thanks for the answers. And thanks for showing the way. I greatly appreciate the help!
The solution to the problem which I have coded is -
#include <stdio.h>
#include <string.h>
int main()
{
int T, i, j;
scanf("%d", &T);
for (i=1; i<=T; i++)
{
char N[101];
scanf("%s", N);
int k = strlen(N);
int p = N[k-1] - 48; //char to int conversion
if (p % 2 == 1)
{
printf("odd\n");
}
else
{
printf("even\n");
}
}
return 0;
}

Why is prime number check getting wrong results for large numbers?

This small C script checks if a number is a prime... Unfortunately it doesn't fully work. I am aware of the inefficiency of the script (e.g. sqrt optimization), these are not the problem.
#include <stdio.h>
int main() {
int n, m;
printf("Enter an integer, that will be checked:\n"); // Set 'n' from commandline
scanf("%d", &n); // Set 'n' from commandline
//n = 5; // To specify 'n' inside code.
for (m = n-1; m >= 1; m--) {
if (m == 1) {
printf("The entered integer IS a prime.\n");
break;
}
if (n % m == 0) {
printf("The entered integer IS NOT a prime.\n");
break;
}
}
return 0;
}
I tested the programm with a lot of numbers and it worked... Then I tried a bigger number (1231231231231236) which is clearly not a prime...
BUT: the program told me it was!?
What am I missing...?
The number "1231231231231236" is too big to fit in an "int" data type. Add a printf statement to show what number your program thinks you gave it, and if that's prime, your program works fine; else, you might have a problem that merits checking. Adding support for integers of arbitary size requires considerable extra effort.
The reason you are having this problem is that intrinsic data types like int have a fixed size - probably 32 bits, or 4 bytes, for int. Given that, variables of type int can only represent 2^32 unique values - about 4 billion. Even if you were using unsigned int (you're not), the int type couldn't be used to store numbers bigger than around 4 billion. Your number is several orders of magnitude larger than that and, as such, when you try to put your input into the int variable, something happens, but I can tell you what doesn't happen: it doesn't get assigned the value 1231231231231236.
Hard to know without more details, but if your ints are 32-bit, then the value you've passed is outside the allowable range, which will no doubt be represented as something other than the value you've passed. You may want to consider using unsigned int instead.
The given number is too large for integer in C. Probably it only accepted a part of it. Try Printing the value of n.

How to printf long long

I'm doing a program that aproximate PI and i'm trying to use long long, but it isn't working.
Here is the code
#include<stdio.h>
#include<math.h>
typedef long long num;
main(){
num pi;
pi=0;
num e, n;
scanf("%d", &n);
for(e=0; 1;e++){
pi += ((pow((-1.0),e))/(2.0*e+1.0));
if(e%n==0)
printf("%15lld -> %1.16lld\n",e, 4*pi);
//printf("%lld\n",4*pi);
}
}
%lld is the standard C99 way, but that doesn't work on the compiler that I'm using (mingw32-gcc v4.6.0). The way to do it on this compiler is: %I64d
So try this:
if(e%n==0)printf("%15I64d -> %1.16I64d\n",e, 4*pi);
and
scanf("%I64d", &n);
The only way I know of for doing this in a completely portable way is to use the defines in <inttypes.h>.
In your case, it would look like this:
scanf("%"SCNd64"", &n);
//...
if(e%n==0)printf("%15"PRId64" -> %1.16"PRId64"\n",e, 4*pi);
It really is very ugly... but at least it is portable.
Your scanf() statement needs to use %lld too.
Your loop does not have a terminating condition.
There are far too many parentheses and far too few spaces in the expression
pi += pow(-1.0, e) / (2.0*e + 1.0);
You add one on the first iteration of the loop, and thereafter zero to the value of 'pi'; this does not change the value much.
You should use an explicit return type of int for main().
On the whole, it is best to specify int main(void) when it ignores its arguments, though that is less of a categorical statement than the rest.
I dislike the explicit licence granted in C99 to omit the return from the end of main() and don't use it myself; I write return 0; to be explicit.
I think the whole algorithm is dubious when written using long long; the data type probably should be more like long double (with %Lf for the scanf() format, and maybe %19.16Lf for the printf() formats.
First of all, %d is for a int
So %1.16lld makes no sense, because %d is an integer
That typedef you do, is also unnecessary, use the type straight ahead, makes a much more readable code.
What you want to use is the type double, for calculating pi
and then using %f or %1.16f.
// acos(0.0) will return value of pi/2, inverse of cos(0) is pi/2
double pi = 2 * acos(0.0);
int n; // upto 6 digit
scanf("%d",&n); //precision with which you want the value of pi
printf("%.*lf\n",n,pi); // * will get replaced by n which is the required precision

Resources