Hey guys I'm having a little problem with unsigned char and reading a file of integers into the array.

1. What the program is suppose to do:
It's suppose to dynamically create an array of unsigned char that is the correct size to read in the array of numbers. The program then reads the numbers into the array. This is all taking place in a static library that is separate to the main program. The class returns a pointer to the array in main. (not got a problem with this so far)

2. What the problem is:
My problem is reading in the file into an unsigned char array. I've been told to do it this way but I'd normally use an int array. I'm not sure if I should be typecasting or just reading it in. I've spent hours on this and need to get it out of the way so I can move onto the next part.

The code for the file read function is below.

C1dArray::C1dArray(int size)
{
	pArray = new unsigned char *[size];
}

Function to create the unsigned char.

int C1dArray::LoadC1dArray(char *imgName)
{
		int i;
		int fileSize = 0;
		int buffer;
	
		ifstream myStream;
		myStream.open(imgName, ios::binary);//opens input stream with given file name.

		if(!myStream){//File load error
			cout << "Unable to open file with the name " << imgName << endl;
			system("pause");
			return (0);//exit
		}
		else {				

			while(!myStream.eof())
			{
				myStream >> buffer;//to advance 1 line at a time.
				fileSize++;
			}
		
			size = fileSize;
			myStream.seekg (0, ios::beg);//returns to front of file.

			pArray = new unsigned char [size];
		
			for(i=0;i<size;i++)
			{
				myStream >> pArray[i];
			}		
				
		}
}

If I do it like this the program breaks I'm not sure if the constructor is getting called properly because the pointer doesn't seem to be fully working. Any help is appreciated and if more code from the program is required then please do ask. Thanks in advance.

Recommended Answers

All 8 Replies

That will not get you the number of bytes you need to allocate for the character array. What that does get you is the number of integers in the file. Those are two different things.

Each digit in the file will take up one character in the unsigned character array. So the number 123 till require 4 bytes (3 for the digits plus 1 for a whitespace between them).

Since you have to read them into an unsigned character array you can have to treat them as normal characters, not integers. All you have to do is use seekg() to locate end of file, tellg() to get file size, allocate the unsigned char array that size + 1, then call read() to read the entire file into memory at one shot.

Ah thanks a lot Ancient Dragon.

What I have done now is:

myStream.seekg (0, ios::end);//moves to the end of the file.
			fileSize = myStream.tellg();//gets the size of the file in bytes.

			size = fileSize +1;

			pArray = new unsigned char *[size];

			myStream.read(reinterpret_cast<char *> (pArray),(size)*sizeof(unsigned char));//reads the whole file into pArray

If I wanted to out put the whole array for debugging what would be the best way to do this? Sorry having problems getting my head around the unsigned char idea. Do I even have to use reinterpret_cast? Thanks .

>>pArray = new unsigned char *;

Remove the star. You want to allocate an array of characters, not pointers

You need anoter seekp() to reset the file descriptor back to beginning of file before read.

after the read() you will want to null-terminate the string because read() doesn't do that for you.

You could do just cout << pArray << '\n';

Removing the star causes:

Error 1 error C2440: '=' : cannot convert from 'unsigned char *' to 'unsigned char **'

The Array is defined as:

unsigned char **pArray

I got it to output using.

cout.write(reinterpret_cast<char *> (pArray),(size));

Is this bad practise?

To use later in the program I'd just extract into a temporary array and recast it back into int? Last question. Thanks once again in advance.

how is pArray declared? I thought it was unsigned char* pArray; >> Is this bad practise?
No, but if you had null-terminated the string then cout << would have worked too.

splitting that string up into its individual itegers will require stingstream class and vector

It's declared as unsigned char **pArray;

I was given the member functions and had to write the definitions. It was the only way the array fit into it.

Would it be possible to split with another array now that I know the size of the file?

First, pArray should be declared as unsigned char* (no double stars).

Allocate for pArray with new unsigned char.

If you are reading the characters as each being an individual number from 0 to 255 in binary format (since this is how you open the file), then forget about adding a null-character at the end or casting to char* with cout.write(), yes it will turn your array into something like a C-string that can be printed, but the output will be ludacris, random gibberish. To print out the numerical values, output them within a for-loop and a cast to (int). If it is a string in the file, then load it normally and use char*.

I was given all the member functions and had to fill in the code.
The reason I declared it with double stars is two of the functions that I was given were written as so:

unsigned char ** C1dArray::get1dArray()
{
	return pArray;	
}
void C1dArray::set1dArray(unsigned char **uc_img)
{	
	**pArray = **uc_img;
}

If I declare it with one star than the program throws an error. I'm not able to do it another way because this is what the specification says. I'm not sure why it's suppose to be done this way.

EDIT: Think I have got it now any way. Thank's so much to you both.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.