Sign in to follow this  

C++ : trouble with arrays ?

This topic is 4547 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi, i'm trying to read a binary file containing integers, and then write the file in ascii mode. What i do is this: #define IDRISI_MAP_X 256 #define IDRISI_MAP_Y 256 unsigned int *idrisipMap = (unsigned int *) malloc( IDRISI_MAP_X * IDRISI_MAP_Y ); FILE *idrisi ; idrisi = fopen(project_texture , "rb" ); fread( idrisipMap, 1, IDRISI_MAP_X * IDRISI_MAP_Y, idrisi ); fclose(idrisi); // Finished reading file, now we start to write FILE *idrisi_out ; idrisi_out = fopen("C:\\temp\\idrisi_out.txt" , "w" ); for (int i=0; i<IDRISI_MAP_X * IDRISI_MAP_Y; i++) { fprintf(idrisi_out,"%i,", *idrisipMap++); // this crash the app when i goes > 16384 //fprintf(idrisi_out,","); This works filling the file with , } fclose(idrisi_out); I'm no expert, so i do not know how to use the debugger, and i dont understand what is the problem: seems to me i allocated the idrisipMap pointer correctly, but for some reasons it has an overflow. Thanks Alex

Share this post


Link to post
Share on other sites
Interesting. From looking at your code, there is inconsistency where fprintf() expects int (%1) and the pointer is unsigned int.

Kuphryn

Share this post


Link to post
Share on other sites
You need to specify the number of bytes to allocate when using malloc.
In this case, malloc(sizeof(unsigned int)*(IDRISI_MAP_X * IDRISI_MAP_Y)).
You'll also to specify the number of bytes when using fread.

Share this post


Link to post
Share on other sites
as said before


unsigned int *idrisipMap = (unsigned int *) malloc( IDRISI_MAP_X * IDRISI_MAP_Y * sizeof(unsigned int) );



Malloc wants the number of bytes, and typically an int is 4 bytes.

Share this post


Link to post
Share on other sites
Thanks guys, now the routine does not crash anymore.
However, i'm still no able to get the correct output.
The input file is a binary raster file which contains a sort of image map: values should go from 0 to 334.
Instead, the idrisi_out.txt is filled with 0's, while i was expecting to have several integer values ranging just from 0 to 334 as well.


Share this post


Link to post
Share on other sites
Please title your post as "C: whatever" rather than "C++: whatever" if you are looking for help with C. If this really is supposed to be C++ code, then be aware that much nicer options that will avoid these kinds of mistakes have been available for many years in the standard library:


#include <iostream>

// First, toss this in to your own library - it's an admitted shortcoming of the
// new libraries, that comes from not wanting to assume that a chunk of
// characters could be valid data if interpreted in other ways

template <typename T>
void readInto(std::istream& source, T* dest, unsigned int size) {
source.read(reinterpret_cast<char *>(dest), size * sizeof(T));
// We could use this manually too. Unfortunately we still have to worry about
// the type size, but we don't have to worry about separate "size of item"
// and "number of items" - actually this is a problem in your case; you want
// 'sizeof(unsigned int)' rather than '1' in your fread() call, AFAIK.
}

const unsigned int IDRISI_MAP_X = 256;
const unsigned int IDRISI_MAP_Y = 256;
const unsigned int IDRISI_SIZE = IDRISI_MAP_X * IDRISI_MAP_Y;

unsigned int *idrisipMap = new unsigned int[IDRISI_SIZE];
std::ifstream idrisi(project_texture, std::ios::binary);
readInto(idrisi, idrisipMap, IDRISI_SIZE);
// Don't need to close this; it will be close automatically at end of scope
// but we can do it now, e.g. if we wanted to reopen the same file right away
// like : idrisi.close();

// Finished reading file, now we start to write
std::ofstream idrisi_out("C:/temp/idrisi_out.txt");
// You can and should use forward slashes in filenames, even when that's not the
// system file separator.
for (int i=0; i < IDRISI_SIZE; i++) {
idrisi_out << idrisipMap[i] << ",";
// No more messing about with format specifiers. The type of each item is
// checked at compile-time, and the appropriate code is generated to output
// each item in a formatted way. You could thus use either "," or ',' with
// identical effect.
}
// Don't forget to deallocate allocated memory! (Regardless of how it was
// allocated - but the allocation and deallocation methods MUST match!)
delete[] idrisipMap;
// On the other hand, since the size is known statically, you don't need a
// dynamic allocation, but should probably just use a static buffer instead :/


Share this post


Link to post
Share on other sites
Quote:
Original post by Zahlman
Please title your post as "C: whatever" rather than "C++: whatever" if you are looking for help with C. If this really is supposed to be C++ code, then be aware that much nicer options that will avoid these kinds of mistakes have been available for many years in the standard library:


You say that and yet you use new[] instead of std::vector and ignore standard algorithms =|


#include <iostream>
#include <vector>

// First, toss this in to your own library - it's an admitted shortcoming of the
// new libraries, that comes from not wanting to assume that a chunk of
// characters could be valid data if interpreted in other ways

template <typename T>
void readInto(std::istream& source, T* dest, unsigned int size) {
source.read(reinterpret_cast<char *>(dest), size * sizeof(T));
// We could use this manually too. Unfortunately we still have to worry about
// the type size, but we don't have to worry about separate "size of item"
// and "number of items" - actually this is a problem in your case; you want
// 'sizeof(unsigned int)' rather than '1' in your fread() call, AFAIK.
}

const unsigned int IDRISI_MAP_X = 256;
const unsigned int IDRISI_MAP_Y = 256;
const unsigned int IDRISI_SIZE = IDRISI_MAP_X * IDRISI_MAP_Y;

std::vector<unsigned int> idrisipMap(IDRISI_SIZE);
std::ifstream idrisi(project_texture, std::ios::binary);
readInto(idrisi, &*idrisipMap.begin(), IDRISI_SIZE);
// Don't need to close this; it will be close automatically at end of scope
// but we can do it now, e.g. if we wanted to reopen the same file right away
// like : idrisi.close();

// Finished reading file, now we start to write
std::ofstream idrisi_out("C:/temp/idrisi_out.txt");
// You can and should use forward slashes in filenames, even when that's not the
// system file separator.

copy( idrisipMap.begin(), idrisipMap.end(),
ostream_iterator<unsigned int>( idrisi_out, "," ) );
// Who needs an explicit loop?

// Note that std::vector is dealing with our memory for us,
// so we don't need to delete anything here!

Share this post


Link to post
Share on other sites
Quote:
Original post by me22
Quote:
Original post by Zahlman
Please title your post as "C: whatever" rather than "C++: whatever" if you are looking for help with C. If this really is supposed to be C++ code, then be aware that much nicer options that will avoid these kinds of mistakes have been available for many years in the standard library:


You say that and yet you use new[] instead of std::vector and ignore standard algorithms =|

*** Source Snippet Removed ***
Whoa, easy there buddy! He was showing how new() is C++'s replacement for malloc(), not introducing him to the concept of vectors and algorithms in one fell swoop.
Still, your post is the next logical thing that could have been shown to the OP.

Share this post


Link to post
Share on other sites
Ok, let's go for the new libraries, but i got tons of errors ... please teach me ...


#include <windows.h> // Header File For Windows
#include <stdio.h> // Header File For Standard Input / Output
#include <stdarg.h> // Header File For Variable Argument Routines
#include <math.h> // Header File For Math Operations
#include <iostream>
#include <algorithm>
#include <string>
#include <iostream>

using namespace std;
template <typename T>
void readInto(std::istream& source, T* dest, unsigned int size) {
source.read(reinterpret_cast<char *>(dest), size * sizeof(T));
}

const unsigned int IDRISI_MAP_X = 256;
const unsigned int IDRISI_MAP_Y = 256;
const unsigned int IDRISI_SIZE = IDRISI_MAP_X * IDRISI_MAP_Y;

unsigned int *idrisipMap = new unsigned int[IDRISI_SIZE];
std::ifstream idrisi("E:/temp/pippo.rst", std::ios::binary);
readInto(idrisi, idrisipMap, IDRISI_SIZE);

std::ofstream idrisi_out("C:/temp/idrisi_out.txt");

for (int i=0; i < IDRISI_SIZE; i++) {
idrisi_out << idrisipMap[i] << ",";
}

delete[] idrisipMap;



and these are the compile errors:

Compiling...
fileinput.cpp
e:\Documents and Settings\terrestrial\Desktop\K-NN.source-lite\fileinput.cpp(21) : error C2079: 'idrisi' uses undefined class 'std::basic_ifstream<_Elem,_Traits>'
with
[
_Elem=char,
_Traits=std::char_traits<char>
]
e:\Documents and Settings\terrestrial\Desktop\K-NN.source-lite\fileinput.cpp(21) : see reference to class template instantiation 'std::basic_ifstream<_Elem,_Traits>' being compiled
with
[
_Elem=char,
_Traits=std::char_traits<char>
]
e:\Documents and Settings\terrestrial\Desktop\K-NN.source-lite\fileinput.cpp(21) : see reference to class template instantiation 'std::basic_ifstream<_Elem,_Traits>' being compiled
with
[
_Elem=char,
_Traits=std::char_traits<char>
]
e:\Documents and Settings\terrestrial\Desktop\K-NN.source-lite\fileinput.cpp(21) : error C2078: too many initializers
e:\Documents and Settings\terrestrial\Desktop\K-NN.source-lite\fileinput.cpp(22) : error C2501: 'readInto' : missing storage-class or type specifiers
e:\Documents and Settings\terrestrial\Desktop\K-NN.source-lite\fileinput.cpp(22) : error C2365: 'readInto' : redefinition; previous definition was a 'function'
e:\Documents and Settings\terrestrial\Desktop\K-NN.source-lite\fileinput.cpp(12) : see declaration of 'readInto'
e:\Documents and Settings\terrestrial\Desktop\K-NN.source-lite\fileinput.cpp(22) : error C2078: too many initializers
e:\Documents and Settings\terrestrial\Desktop\K-NN.source-lite\fileinput.cpp(24) : error C2079: 'idrisi_out' uses undefined class 'std::basic_ofstream<_Elem,_Traits>'
with
[
_Elem=char,
_Traits=std::char_traits<char>
]
e:\Documents and Settings\terrestrial\Desktop\K-NN.source-lite\fileinput.cpp(24) : see reference to class template instantiation 'std::basic_ofstream<_Elem,_Traits>' being compiled
with
[
_Elem=char,
_Traits=std::char_traits<char>
]
e:\Documents and Settings\terrestrial\Desktop\K-NN.source-lite\fileinput.cpp(24) : see reference to class template instantiation 'std::basic_ofstream<_Elem,_Traits>' being compiled
with
[
_Elem=char,
_Traits=std::char_traits<char>
]
e:\Documents and Settings\terrestrial\Desktop\K-NN.source-lite\fileinput.cpp(24) : error C2440: 'initializing' : cannot convert from 'const char [23]' to 'int'
This conversion requires a reinterpret_cast, a C-style cast or function-style cast
e:\Documents and Settings\terrestrial\Desktop\K-NN.source-lite\fileinput.cpp(26) : error C2059: syntax error : 'for'
e:\Documents and Settings\terrestrial\Desktop\K-NN.source-lite\fileinput.cpp(26) : error C2143: syntax error : missing ')' before ';'
e:\Documents and Settings\terrestrial\Desktop\K-NN.source-lite\fileinput.cpp(26) : error C2143: syntax error : missing ';' before '<'
e:\Documents and Settings\terrestrial\Desktop\K-NN.source-lite\fileinput.cpp(26) : error C2501: 'i' : missing storage-class or type specifiers
e:\Documents and Settings\terrestrial\Desktop\K-NN.source-lite\fileinput.cpp(26) : error C2143: syntax error : missing ';' before '++'
e:\Documents and Settings\terrestrial\Desktop\K-NN.source-lite\fileinput.cpp(26) : error C2501: 'i' : missing storage-class or type specifiers
e:\Documents and Settings\terrestrial\Desktop\K-NN.source-lite\fileinput.cpp(26) : error C2086: 'int i' : redefinition
e:\Documents and Settings\terrestrial\Desktop\K-NN.source-lite\fileinput.cpp(26) : see declaration of 'i'
e:\Documents and Settings\terrestrial\Desktop\K-NN.source-lite\fileinput.cpp(26) : error C2059: syntax error : ')'
e:\Documents and Settings\terrestrial\Desktop\K-NN.source-lite\fileinput.cpp(26) : error C2143: syntax error : missing ';' before '{'
e:\Documents and Settings\terrestrial\Desktop\K-NN.source-lite\fileinput.cpp(26) : error C2447: '{' : missing function header (old-style formal list?)
e:\Documents and Settings\terrestrial\Desktop\K-NN.source-lite\fileinput.cpp(30) : error C2059: syntax error : 'delete'

NeHe_OpenGL_Basecode - 18 error(s), 0 warning(s)

Share this post


Link to post
Share on other sites
iMalc: just be glad there's no copy_n in <algorithm> -- otherwise I'd have replaced readInto(idrisi, &*idrisipMap.begin(), IDRISI_SIZE); with std::copy_n( istream_iterator(idrisi), IDRISI_SIZE*sizeof(unsigned int), reinterpret_cast<char*>(&*idrisipMap.begin()) ); >;)

And penetrator, is that what you tried to compile? Since without a main() function, I'm not surprised it's not happy :P

The code we posted was intended to demonstrate how the stuff works, not to be a complete workable program...

Oh, any you should also be using the C++-style headers. <cmath> instead of <math.h>, <cstdlib> instead of <stdlib.h>, and similarly for all other standard headers ( note that does NOT mean <cwindows> ).

Share this post


Link to post
Share on other sites

This topic is 4547 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this