Dear All,

I have a text file containing these lines:

12345
12
123
1234
123456
1234567890
123456789032453
1234567890724832445
12345.123456
12345.123
12.12
12

And I want to read them from c:\numbers.txt and store them into an array and then do some calculations, then save the results in another file(c:\results.txt).
I have wrote the following program for just reading lines of a file and store into an array:

#include <stdio.h>
#include <stdlib.h> /* required for atoi */

int main(void) {
int  i=0;
double numbers[]={0};
char line[20];  /* declare a char array */

FILE *file;  /* declare a FILE pointer  */
file = fopen("c:\\numbers.txt", "r");  /* open a text file for reading */

while(fgets(line, 100, file)!=NULL) {       /* keep looping until NULL pointer... */
printf("Lines of numbers.txt file are: %s", line);
numbers[i]=atoi(line); /* convert string to int */
i++;
}

for (i=0 ; i<sizeof(numbers) ; i++)
{ printf("\nThe number %d of %d is: %i", i+1,sizeof(numbers), numbers[i]); }

fclose(file);

return 0;
}

The first problem : the numbers are not correct in the array. it shows this output:

Lines of numbers.txt file are: 123
Lines of numbers.txt file are: 1234
Lines of numbers.txt file are: 123456
Lines of numbers.txt file are: 1234567890
Lines of numbers.txt file are: 123456789032453
Lines of numbers.txt file are: 1234567890724832445
Lines of numbers.txt file are: 12345.123456
Lines of numbers.txt file are: 12345.123
Lines of numbers.txt file are: 12.12
Lines of numbers.txt file are: 12
The number 1 of 8 is: 0
The number 2 of 8 is: 822096433
The number 3 of 8 is: 905972275
The number 4 of 8 is: 171258932
The number 5 of 8 is: 0
The number 6 of 8 is: -1266679808
The number 7 of 8 is: 2126512128
The number 8 of 8 is: -792723456

Another problem is that some times the two first lines of input file is not shown.

Mehdi

first post ... with a clear question and readable code!
5
Contributors
11
Replies
16
Views
7 Years
Discussion Span
Last Post by Banfa
Featured Replies
• 1

[code]while(fgets(line, 100, file)!=NULL) { /* keep looping until NULL pointer... */[/code] "I have detected danger Will Robinson" More specifically I have detected that line was declared [icode]char line[20];[/icode] so is a 20 byte array but you have passed a pointer to line and told fgets to copy up to 100 …

while(fgets(line, 100, file)!=NULL) {       /* keep looping until NULL pointer... */

"I have detected danger Will Robinson"

More specifically I have detected that line was declared char line[20]; so is a 20 byte array but you have passed a pointer to line and told fgets to copy up to 100 characters into it leaving yourself open to a buffer overrun. For safety this should be

while(fgets(line, sizeof line, file)!=NULL) {       /* keep looping until NULL pointer... */

And again

numbers[i]=atoi(line); /* convert string to int */

but numbers is declared double numbers[]={0}; with no array size but an initaliser list with a single entry means that numbers has a size of 1 so as soon as i > 0 you have an out of bounds array access.

Additionally your file appears to contain floating point values and you are using double type to store your converted value but you are calling int atoi ( const char * str ); which returns int and explains many of your conversion errors. You should try calling double atof ( const char * str ); .

To get your numbers array the right size you are going to have to do something using dynamic memory allocation with malloc/realloc.

Yes

what Banfa said about your character array's size and the number of characters read by fgets() must match.

but you don't necessarily have to allocate your "numbers" array dynamically. you can, for simplicity's sake, just declare it to be some arbitrarily large size.

double numbers[100];

since these are "doubles" (double floating point) you can not use "atoi" but must use "atod". you must also use the format specifier "%f" when printing.

numbers[i]=atod(line); /* convert string to double float*/

you also can not use "sizeof(numbers)" in your for loop like you think you can, for two reasons. first reason is that (at least with a static array size) the number of elements used will vary. the second reason, even if you were to dynamically allocate the array, is that the size of the array is equal to the number of bytes used and not the number of values contained. each double value uses at least 8 bytes.

so if you were to dynamically allocate your array size with malloc, you could use sizeof to determine the number of elements if you divide the array size by the size of each element sizeof(numbers)/sizeof(double) , but i think a simpler way is to just use the count of the number of elements that you read, since you are already counting them anyhow

totalNums = i;
for (i=0 ; i<totalNums ; i++) {
printf("\nThe number %d of %d is: %f", i+1, totalNums, numbers[i]);
}

.

Edited by jephthah: n/a

Dear Banfa and Jephthah,
Thank you so much for the useful answers.
I made the changes except :

numbers=atod(line); /* convert string to double float*/

because when I change atoi to atod, it shows:

warning: function declared implicitly

With atoi it runs well and shows integers in the output but I need to store double floating numbers in the array.
Here is my last code:

#include <stdio.h>
#include <stdlib.h> /* required for atoi */

int main(void) {
int  i=0,totalNums;
double numbers[100];
double atof ( const char * str );
char line[100];  /* declare a char array */

FILE *file;  /* declare a FILE pointer  */
file = fopen("c:\\numbers.txt", "r");  /* open a text file for reading */

while(fgets(line, sizeof line, file)!=NULL) {       /* keep looping until NULL pointer... */
printf("Lines of numbers.txt file are: %s", line);
numbers[i]=atoi(line);  /* convert string to double float*/
i++;
}
totalNums = i;
for (i=0 ; i<totalNums ; i++) {
printf("\nThe number %d of %d is: %f", i+1, totalNums, numbers[i]);

}
fclose(file);
return 0;
}

and the results:

Lines of numbers.txt file are: 123
Lines of numbers.txt file are: 1234
Lines of numbers.txt file are: 123456
Lines of numbers.txt file are: 1234567890
Lines of numbers.txt file are: 123456789032453
Lines of numbers.txt file are: 1234567890724832445
Lines of numbers.txt file are: 12345.123456
Lines of numbers.txt file are: 12345.123
Lines of numbers.txt file are: 12.12
Lines of numbers.txt file are: 12
The number 1 of 12 is: 12345.000000
The number 2 of 12 is: 12.000000
The number 3 of 12 is: 123.000000
The number 4 of 12 is: 1234.000000
The number 5 of 12 is: 123456.000000
The number 6 of 12 is: 1234567890.000000
The number 7 of 12 is: -2045891067.000000
The number 8 of 12 is: -1581136707.000000
The number 9 of 12 is: 12345.000000
The number 10 of 12 is: 12345.000000
The number 11 of 12 is: 12.000000
The number 12 of 12 is: 12.000000

Dear Banfa and Jephthah,
Thank you so much for the useful answers.
I made the changes except :
because when I change atoi to atod, it shows:
With atoi it runs well and shows integers in the output but I need to store double floating numbers in the array.

When you change your code from doing the wrong thing to doing the right thing and you get errors in compilation the correct course of action is not to change back to doing the wrong thing but to understand and fix the source of the errors.

You do not need line 7 of your lastest listing as atof is declared in stdlib.h. In fact it is very poor style to re-declare a standard library function like this.

If you want to convert floating point numbers you will need to call atof.

Edited by Banfa: n/a

So, I deleted line 7 and I used atod.
Here is the error when I run it:

warning: function declared implicitly

Do you have any suggestion?

Post the code, it sounds like you plunked in an unnecessary prototype again.

Post the code, it sounds like you plunked in an unnecessary prototype again.

#include <stdio.h>
#include <stdlib.h> /* required for atoi */

int main(void) {
int  i=0,totalNums;
double numbers[100];
char line[100];  /* declare a char array */

FILE *file;  /* declare a FILE pointer  */
file = fopen("c:\\numbers.txt", "r");  /* open a text file for reading */

while(fgets(line, sizeof line, file)!=NULL) {       /* keep looping until NULL pointer... */
printf("Lines of numbers.txt file are: %s", line);
numbers[i]=atod(line);  /* convert string to double float*/
i++;
}
totalNums = i;
for (i=0 ; i<totalNums ; i++) {
printf("\nThe number %i of %i is: %f", i+1, totalNums, numbers[i]);
}
fclose(file);

return 0;
}

Post the code, it sounds like you plunked in an unnecessary prototype again.

Or not, but it was a decent guess...

Ok. Well, there's been discussion of atod but I find no such function out there (I may be ignorant of some bit of C lore here). atof should do the job for you (from cplusplus.com "On success, the function returns the converted floating point number as a double value.")

Edited by jonsca: n/a

Or not, but it was a decent guess...

Ok. Well, there's been discussion of atod but I find no such function out there (I may be ignorant of some bit of C lore here). atof should do the job for you (from cplusplus.com "On success, the function returns the converted floating point number as a double value.")

I also could not find info about atod. It seems that there is not such a function in stdlib.h.
atof does the job but the precision is up to 6 digits after point(i.e. up to 0.123456 is shown and longer digits are rounded up: 0.123457).

Then write your own atod() . Conversion functions are simple since you have the numbers right there in your string.

I also could not find info about atod. It seems that there is not such a function in stdlib.h.
atof does the job but the precision is up to 6 digits after point(i.e. up to 0.123456 is shown and longer digits are rounded up: 0.123457).

No it should give 15 digits of precision or 14 after the point assuming 1 before the point.

May be this is the cause of the confusion, atof returns double not float so there is no atod as it would be superfluous.

This topic has been dead for over six months. Start a new discussion instead.
Have something to contribute to this discussion? Please be thoughtful, detailed and courteous, and be sure to adhere to our posting rules.