You are here:

C++/reading reference table

Advertisement


Question
Hi,
How are you? I have a program that needs to read in a reference table during runtime. The program would refer to this table from time to time. The table is basically two 1-dimensional arrays of doubles. Currently I do it by referring to a function which is nothing more than the statements for arrays:

void readRef()
{
array1[0]=2.45; array2[0]=5.17;
array1[1]=3.78; array2[1]=3.12;
.....
array1[1700]=4.67; array2[1700]=0.12;
}

I do this because I don't know how to make a text file part of the compiled application (static). Anyway, my method should work, but I run into weird problems. For example it compiles on 32 Debian to give a 1 MB executable which runs fine. When I compile the same program on 64 bit Scientific Linux (RedHat) it takes a long time to compile and the executable is 70 MB and it won't run (I get a weird message that an X-something is not found). I'm using Qt. I'm pretty sure that my functions that contain all the array definitions cause this. Do you know what is happening? I'm very thankful for any ideas.
Regards,
Andres

Answer
I am sorry but in short no I cannot say why your are seeing this behaviour. There is no way like enough detail in your question for me to even make an educated guess on what might be causing this problem. I have no idea of what other code you are using (other than you mention Qt - and you are using a 64-bit build of Qt for the 64-bit version of your program aren't you?), how you have built it, what (other) errors there might be in the code, or even what the exact error was (mentioning X-something is not really very precise is it? I have a thought that X might have something to do with coordinates and Qt might use such things, or that Linux uses X windows as it GUI system and so there will be a whole lot of X related things to do with the X window system, but then it might refer to something specific to your program or something else entirely - X on its own totally lacks context - sorry).

However I would _not_ fixate on your array initialisation functions being the problem. As far as I can tell from the question these functions initialise global arrays of double. Assuming both Linux installations are running on x86 hardware then as far as I know instances of the double type are represented by 64-bit values (i.e. 8 byte values) for both 32 and 64 bit variants of platform and compiler. Hence in both cases a 1700 element array of doubles would require only 8*1700 bytes. Assuming both arrays are of similar size then they should only require 25K - 30K (if both contained 1700 elements as indicated by the readRef function in your question then they would require 27200 bytes to store).

I would look more closely at the error you are getting from the 64-bit build. That and possibly the excessive size might indicate some other problem - or maybe the size indicates differences in the build behaviour - for example maybe you are linking libraries statically in the 64 bit build and dynamically in the 32 bit build. Try using a search engine to scour the Internet (i.e. use a search engine such as Google, Bing or Yahoo) to see if others have had this problem - sometimes even vaguely similar cases can give you a few hints. Other possibilities are that the 64 bit version did not build correctly for some reason or is showing up a latent bug - such as an uninitialised variable or using something after it is dead (i.e. destroyed, unallocated) or some other usage that resulted in undefined behaviour which just happened to mean OK (for the moment) in the 32 bit build but Crash! in the 64-bit build.

Try to isolate the problem. For example, if you suspect your array initialisation code of being at fault then extract it as a separate module and wrap it in a test program. Build the program on both 32 and 64 bit systems and see what happens.

Maybe you could write unit tests for each part of your program's non-UI parts (testing UIs is tricky) - business logic, supporting functionality such as the reference arrays etc. Then you can make sure each part builds and functions satisfactorily on _all_ platforms you wish to build on by first making sure their associated unit tests build, run, and pass. This may require you to re-factor your code into a more modular and decoupled form if it is not in such a form already - which is almost certainly a Good Thing. Then once each part is known to function correctly build them together with the GUI portion.

One thing I can give explicit help with is array initialisation in C and C++. You can initialise arrays in C and C++ by listing the values in { and } as the array initialiser value:

   double array1[1700] =   { 2.45
         , 3.78
         , ...
         .
         .
         .
         , 4.67
         };

   double array2[] =   { 5.17
         , 3.12
         , ...
         .
         .
         .
         , 0.12
         };

If you do not give an explicit array size then the compiler will compute it from the number of initialiser values provided, which I show for example purposes for array2 above. If a size is given then if the initialiser list contains less than the specified number of elements the remaining elements are zero initialised; if it contains more then the program is ill formed and you should get a compiler error.

If the array values are for reference purposes then they are probably not intended to be mutable, so should be marked const:

   const double array1[1700] =   ...
         
or:

   double const array1[1700] =   ...

Note that if you do not specify an array size then you can obtain its size using sizeof:

   size_t array2_size = sizeof( array2 ) / sizeof ( double );

   assert( array2_size==1700 && "array2 has the wrong number of initialisers" );

There is more on array initialisation in C at:

   http://publications.gbdirect.co.uk/c_book/chapter6/initialization.html

The array initialisation features and usage is of course applicable to C++.

[Note: In C and C++ objects of struct types (or in C++ class types with restrictions that make them similar in features to struct types) can also have their members initialised using an initialiser list. In the latest C++11 revision list initialisation has been generalised to apply to objects of most types.

As these topics are an aside to your question I shall leave you to research the details if you are interested.
-- end note]

If the data in the tables never or hardly ever changes then it may be the simplest solution to just enter the list initialisation values by hand in an appropriate C/C++ source file - I have done this in the past for such one-off fixed static tables of data.

If these tables are fixed for a build of your program but may change between builds then you could consider generating them from the source data as C/C++ using a simple script (e.g. Python, Perl, PHP CLI...) - or even a C/C++ program - that reads the source data in and outputs a C/C++ source file containing the definition of array1 or array2 with all the data values as the array initialisation list. This could become a part of your build, in make terms the target would be the C/C++ source file containing the array1 / array2 definition, it will be dependent on the source data file and the command used to process one into the other would be the utility script/program written to do the job - presumably with appropriate command line arguments.

If however the data in the tables may change during the use of a particular build then you will have to read the values into memory (that is, into the arrays) at runtime (which of course is an option for the previous two cases). To make this task as easy as possible you should supply the source data as a simple to read set of values (e.g. one array's set of values per file, each file containing one value per line, first line different in that it gives the number of following values). You will have to decide on things such as what the file names are and where they should reside up front so your program can locate and open them for reading.

In order to perform file I/O you will need to use the C++ IOStreams library components (or the C library equivalents, but you are asking a C++ expert...). You can find out more in various places and references. One such online reference can be found at:

   http://www.cplusplus.com/reference/iostream/

Various other C++ library facilities will probably be of use such as std::string.

   http://www.cplusplus.com/reference/string/

An alternative collection type to plain C/C++ built-in arrays such as std::vector<double> might also prove useful:

   http://www.cplusplus.com/reference/stl/vector/

I am having to direct you to such resources as the details are quite involved and I feel are a bit beyond the scope of an AllExperts Q & A.

An example program performing data format translation that shows using these features, and probably a few more, can be found at:

   http://www.cplusplus.com/forum/beginner/2351/

These are by no means the only such resources or examples available - again Google (or search engine of choice) is your friend. One book I have used one heck of a lot is my C++ standard library reference, which also happens to be a bit of a tutorial: "The C++ Standard Library A Tutorial and Reference" by Nicolai M. Josuttis. Note that this is one of the first books to have a new edition covering the shiny new C++11 library features so if wish to obtain a copy but you are not able to use such features yet try to find an original 1st edition.

C++

All Answers


Answers by Expert:


Ask Experts

Volunteer


Ralph McArdell

Expertise

I am a software developer with more than 15 years C++ experience and over 25 years experience developing a wide variety of applications for Windows NT/2000/XP, UNIX, Linux and other platforms. I can help with basic to advanced C++, C (although I do not write just-C much if at all these days so maybe ask in the C section about purely C matters), software development and many platform specific and system development problems.

Experience

My career started in the mid 1980s working as a batch process operator for the now defunct Inner London Education Authority, working on Prime mini computers. I then moved into the role of Programmer / Analyst, also on the Primes, then into technical support and finally into the micro computing section, using a variety of 16 and 8 bit machines. Following the demise of the ILEA I worked for a small company, now gone, called Hodos. I worked on a part task train simulator using C and the Intel DVI (Digital Video Interactive) - the hardware based predecessor to Indeo. Other projects included a CGI based train simulator (different goals to the first), and various other projects in C and Visual Basic (er, version 1 that is). When Hodos went into receivership I went freelance and finally managed to start working in C++. I initially had contracts working on train simulators (surprise) and multimedia - I worked on many of the Dorling Kindersley CD-ROM titles and wrote the screensaver games for the Wallace and Gromit Cracking Animator CD. My more recent contracts have been more traditionally IT based, working predominately in C++ on MS Windows NT, 2000. XP, Linux and UN*X. These projects have had wide ranging additional skill sets including system analysis and design, databases and SQL in various guises, C#, client server and remoting, cross porting applications between platforms and various client development processes. I have an interest in the development of the C++ core language and libraries and try to keep up with at least some of the papers on the ISO C++ Standard Committee site at http://www.open-std.org/jtc1/sc22/wg21/.

Education/Credentials

©2016 About.com. All rights reserved.