Mxyk
Mxyk

Reputation: 10698

Reading a number from a file and converting it to an integer in C

I have a FILE variable, declared as FILE *fin. fin = fopen( "points.dat", "r" ); is initialized after the declaration. I've been trying to loop through fin while fgetc( fin ) != '\n'. Here's where I am stumped.

I want to store each character on line 1 of points.dat into a char *, which I can later invoke atoi on to store as an integer. How should I do this? I've tried it, but I keep getting segmentation faults and other weird errors. Here's my latest attempt:

FILE *fin;
char c;
int counter = 0;
int countPoints;
char *readFirst;

fin = fopen( "points.dat", "r" );

while( ( c = fgetc( fin ) ) != '\n' ) {

    readFirst[counter] = c;
    counter++;
}

countPoints = atoi( readFirst );

printf("%d\n", countPoints);

Note: this is not in its entirity a homework assignment. This is just a very small thing I need to get working before I can actually do the homework assignment.

Upvotes: 0

Views: 234

Answers (5)

znkr
znkr

Reputation: 1756

When I see this right, you just use your char pointer without initializing it to something. That means your pointer points to some unknown memory area. If you are lucky you get a segmentation fault (that's why initializing a pointer to NULL is a good idea), if not: Welcome in the realm of undefinedness.

If you want to store something you should first create some memory for it. You can do that either on the stack (char readFirst[size]) or on the heap (malloc()). In every case you need to know beforehand how much memory you will be needing. You need to know this at compile time for the stack variant and at run time for the heap variant. That of course means that you need a method to find out how much memory you will be needing.

Upvotes: 0

John Bode
John Bode

Reputation: 123558

Well, the immediate problem is that you haven't set aside any memory for readFirst to point to. When you write readFirst[counter] = c, you're trying to assign the value of c to some random memory location that you may or may not own (hence the segfaults).

If you know how big the array needs to be ahead of time, you should declare readFirst as

char readFirst[SIZE];

It takes roughly 3.3 bits on average to represent a decimal digit; round that down to 3, and you can figure your array size as the bit width of an int divided by 3 plus 2 for the sign and 0 terminator. Thus, a 32 bit int will require an array of 9 + 2 = 11 characters. A 64-bit integer value will require 22 + 2 = 24.

But this all begs another question; do you need to read the input one character at a time and then convert to an integer value? If the input file is simply text representations of integers, you could bypass that whole mess and simply use fscanf with the %d conversion specifier (although that has its own set of issues).

Alternately, you could use fgets to read an entire text string at once and convert the text using strtol (atoi doesn't give you the same error handling capability as strtol).

Upvotes: 0

Dennis
Dennis

Reputation: 14477

You're getting a segmentation fault because char *readFirst; only declares a pointer, but it doesn't reserve any space to hold the data.

Either declare readFirst directly as an array (char readFirst[size];) or use the function malloc() to allocate the space.

Upvotes: 1

Aarkan
Aarkan

Reputation: 4109

You have not allocated any memory to readFirst and also it is not terminated with NULL character as C expects.

Its better to use fgets to read a string and fputs to write the string. That way you dont have to look for the newline. Also, it will be useful if you post the code of writing to file.

You could also use standard c++ file handling (using std::iostream), to make the job even easier.

Upvotes: 2

wswatson
wswatson

Reputation: 11

readFirst is an uninitialized char pointer. You either need to alloc a new block of memory to hold the characters or assign it to a statically allocated array of chars. Also, if you are going to read the data a single byte at a time, you will need to null terminate the string before passing it into atoi or it will read passed the end of the buffer and segfault as well.

See if you can figure it out from there. If you need more help, message me.

Upvotes: 0

Related Questions