2d character array to float and integer array - unexpected float elements

I'm hoping to get an answer that doesn't require changing my methods. I'm an electrical student, not software, so I just need to get this to work.

I'm reading a text file that has numerical information for x amount of elements, where each element has numerical data for 64 pixels as well as a number for an identifier.

I'm working towards loading all the data from this text document into 2 arrays. a float array for all the pixel data (each piece of data is 9 characters[example -0.608261], and an integer array for all the integer data (all data is 1 or -1).

my code is completely functioning apart from an issue with the elements of the float array containing extra digits when I load them from the character array. This is my method:

Declare a 2d character array, where the first dimension is the word and the second dimension is the character for each word:

1
2
3
4
5
6
	// declare a 2d array of characters, where the first dimension holds each word and the second dimension holds each letter of each word. In this case
	char** verification_string_array = new char* [char_count];
	for (int i = 0; i < char_count; ++i) 
	{
		verification_string_array[i] = new char[9];
	}


Move the data from the initial 1d character array that holds the entire text file into the 2d array, so that each element of the first dimension holds one of the "words" (whether thats pixel information or an identifier isn't important).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
	// store character array into string array, use spaces as indicater to index string array (each string array element holds 1 word)
	for (int i = 0; i < file_size - 1; i++)
	{
		//if (the character isn't a space) AND (the character isn't a new line), add character to current word
		if ((char_array[i] != ' ') && (char_array[i] != '\n'))
		{
			verification_string_array[k][m] = char_array[i];
			m++;
		}
		//if (the character is a space) OR (the character is a newline and isn't preceeded by a space), start a new word
		else if (char_array[i] == ' ' || (char_array[i] == '\n' && char_array[i - 1] != ' '))
		{
			k++;
			m = 0;
		}
	}


now load the character array into the float array and integer array

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

	// set  variables for upcoming iterations
 	j = 0;
	k = 0;
	m = 0;

	for (int i = 3; i < char_count; i++)
	{
		if (k < 64)
		{
			sscanf(verification_string_array[i], "%f", &pixel_array[j]);
			k++;
			j++;
		}
		else
		{
			sscanf(verification_string_array[i], "%d", &identifier_array[m]);
			k = 0;
			m++;
		}
	}


my problem is, if we consider the first element of actual information (first 3 elements are header information) from the watch window:

verification_string_array[3] = 0x017ce268 "-0.693180yyyYYYc$"

all I wanted was the numbers. When I load this into the float array, I get this result:

pixel_array[0] = -0.693180025

which has extra digits

Can anyone offer some clarification as to what my issue is?
Last edited on
What type is pixel_array?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// Example program
#include <iostream>
#include <string>
#include <cstdio>

using namespace std;

int main()
{	
	const char* verification_string_array = "-0.693180yyyYYYc$";
	
	float pixel = 0.0f;
	sscanf(verification_string_array, "%f", &pixel);
	
	std::cout << pixel << '\n';
}

-0.69318
Last edited on
> (each piece of data is 9 characters[example -0.608261],
For which, you will need a 10 character array.
To make it a useful string, you always need to append a \0 to it.

verification_string_array[i] = new char[10];

and
1
2
verification_string_array[k][m] = char_array[i];
verification_string_array[k][m+1] = '\0';


> if ((char_array[i] != ' ') && (char_array[i] != '\n'))
There are no guards to stop you running off the end of your allocated space.
m and k should be range checked at every step to make sure you're not wandering off into the weeds.
computers are finite, but a fun math problem you may see in your proofs class is that there are more numbers between 0 and 1 than there are whole numbers.
or, basically, there are an infinite number of numbers between 1/2 and 1/3 and so on and so forth.

anyway, computers cannot represent all the decimal numbers using only a few bits per value. You frequently find values that are not exactly what you said, eg you assign it 0.123 or whatever value and later print it and see 0.1229999999999999999999999 is printed. I am not sure you are running into this here, it could be the bugs mentioned above, but if you continue to code you WILL see this and should be aware that 'its ok' for most code to be like that. When it isn't ok, you need to do something else, like use a 64 bit integer with a shift, eg 123 divided by 1000 (which is much nicer is all the values are divided by the same constant, you can work with that directly for most problems, eg money, you just work in pennies and its fine).

even if you fix how it prints (less decimal places and rounded or whatnot) the actual value in the box will be what it will be.

the issue is much less severe if you always use doubles instead of floats.
when I change ganado's code to printf 1.20f (this exceeds what can be stored and some of the output is just noise with that many digits) I get...
-0.6931800246...
when I change that to use double, I get:
-0.69318000000000001837
Last edited on
What type is pixel_array?


Its a float, but i'm declaring it dynamically (from what I understand. I'm still pretty new)

1
2
3
4
5
	//declare array to hold entire file's pixel numbers
	float* pixel_array = new float[3750 * 64];

	//declare array to hold entire file's object identifier number (-1 or 1)
	int* identifier_array = new int[3750];


Maybe this is why it works in your method and not mine?

These files are large so I didn't have success working from the stack

For which, you will need a 10 character array.
To make it a useful string, you always need to append a \0 to it.


I've changed to a 10 character array. But I still have the same issue. I'm guessing that when moving this information into the 2d array I need to make the last character of each '\0'?

I don't understand why the integer is giving me the same problem. Is there just a float vs integer thing?

Thanks folks
Also, the first 2 steps are unnecessary, just read the info with scanf, make sure to utilize the return value from scanf to see that it worked, you have no idea otherwise.

Your code looks like C not C++. I know it's a struggle to learn new things, but C++ is so much better. Try to learn howto use std::vector, and std::string, avoid memory management with new
Maybe this is why it works in your method and not mine?
That's not the issue (at least, not by itself). Let us know what happens once you make sure your strings are properly null-terminated.
I didn't have success with the Null character.

Verification_String_array[3] "-0.693180i"

pixel_array[0] = -0.693180025
did you read my post?

0 is needed ('\0' is numerically zero) at the end of all C style text strings, yes. You can have a char array that means something other than text (small integers, binary data from a file, whatever else are common) but the C string tools require that zero, as does cout and printf and so on.
it is placed for you when using the string functions, as long as you stay in your allocated size. If you go past your size, you have a bug and at that point anything goes. Where you get into trouble is hands-on string work, where you try to do the string function work yourself.
Last edited on
did you read my post?


I see what you are getting at now.

I guess at the end of the day, with what I'm using these arrays for, extreme accuracy is not important and I should have considered this before posting.

I'm going to work with what I have as it shouldn't make a difference.

Thanks for all the help folks
Last edited on
I should have considered this before posting.


Very few people were not taken by surprise the first time they ran into this. Good luck!
Topic archived. No new replies allowed.