C++ declaring variable inside if statement - c++

I have a really basic problem in c++, I'm reading a tab separated file and I want to declare an array with the dimension if the number of fields the file has (work with different files with different widths) so I need to read the first line and count the number of fields, I tried this:
while(getline(t, line));{
...
if(!flag)
{int array[size][5];
flag=1}
...
}
But then I get the error:
error: 'array' was not declared in this scope
I understand it is because the scope of the variable is in the if loop, is there any way to declare a null array and resize it? Or will I have to use pointers?

The size of an array must be a compile-time constant. Use a std::vector if you want a dynamically-sized array.
Other issues with your code:
Remove the semicolon after the while, or your loop body will only be executed once after the whole file is read.
Add a semicolon after flag=1.

You are writing C++, so why not use a std::vector<std::vector<int> >? If possible (here it is) try not to use raw pointers.

Pointers will be the way to go...

int array[size] possible just in C99.
In C++ plain-C array sizes should be compile-time constant.

Related

C++ const array appending

I have this program which consists of a loader and different statically linked modules. The entrypoint of the program goes into a loop which executes all the module initialization-routines. The function-pointers to these routines are stored in a constant array in the main.cpp file.
My problem is that everytime I want to add or remove one of the modules I have to modify the array.
I feel like there should be a method of automating this process. Is there a way to let the preprocessor load and parse a text-file holding the function-names? Or can I append new entries to the constant array from another .cpp file? How do I generate this array at compile-time?
Thanks in advance!
If the list of modules is known in compile time, while do not simple list them in makefile?
For anyone who cares. I have actually solved my problem. Turns out that gcc has a feature
called 'section' which lets you create static memory regions that can be extended multiple times
during compile-time by just specifying a declaration with this attribute. This created memory region
packs the inserted elements side by side zero terminated, which gives it the characteristics of an array sorta. The memory location, lets call our section "name", can be accessed by defining extern const char pointers named __start_name and __end_name. Thanks gcc. :-)

c++ default array size override with command line arguments

I saw one question on similar lines
Specify Array from Command Line Argument
Although my problem is bit different.
I have multiple files implementing arrays of same size (NOC_SIZE). My program has a default mode and a user mode (command line arguments). I gave the 'unsigned int NOC_SIZE = 16;' line in my code before the start of main function. In another header file I declared a struct (noc_package) with parameter 'static unsigned int NOC_SIZE;'. This header file in included in all files where ever required.
But in the files where I have declared an array (int arr[noc_package :: NOC_SIZE]) it gives an error saying array bound not an integer.
Can somebody suggest a way around this?
Thank you.
C++ doesn't support variable-length arrays.
You're better of using an std::vector instead:
std::vector<int> arr(noc_package::NOC_SIZE);

Declaring a string array in GNU C++

To me it seems like it should be so simple, but I just feel like I'm missing something.
I have in my header file a private variable _stoplist When I declared it in the header file the code looks just like this.
private:
std::string _stoplist[];
But when later in my function I decide to access this, it segfaults on anything.
_stoplist[_length];
//cout << _length << prints 104 (its a valid int and everything)
_stoplist[0] = "b";
Crashes in the std::string.assign() code with a segfault. I have a gut feeling that I'm missing something obvious here but I haven't quite found out what yet.
Thanks in advance!
EDIT: Ok, thanks for all the help. For anyone else who may read this, I would recommend to use one of the answers below since that is the smart way to do it. In my case though since I needed to dynamically allocate it without using vector I just used the following code.
private:
std::string *_stoplist;
and then in my cpp file
_stoplist = new string[_length];
Yeah, turns out that it really was way simple, and I just was over looking that part.
You're getting an array out of bounds error because _stoplist doesn't have a size. You should either give it a size, and only access elements within that range, such as:
private:
std::string _stoplist[100];
now you should be able to index _stoplist[0] through _stoplist[99]. However a better solution would probably to use std::vector instead, as it's a lot safer.
private:
std::vector< std::string > _stoplist;
Then you can use its member functions such as resize() to grow it to whatever size you need.
That's because a variable declared as std::string[] is basically just a pointer. To use it, you need to allocate memory for it. If you want to allocate fixed memory for it, try declaring it as e.g. std::string _stoplist[5]; instead.

I have lots of questions about c++ that are really confusing me

I started learning c++ about 3 weeks ago after 2 years of java. It seems so different but im getting there. my lecturer is a lovely guy but any time i ask a question as to why something is that way or this way. he just responds "because it is".
Theres lots of comments in the code below with a few random questions, but the main problem is im getting two build errors, one says the arraytotal has not been initialized (even though i found a value for it) and the other says an external reference in main.
would anyone mind reading the code and answering a few comments within, and maybe the overall problem im having?
#include<string>
#include<fstream>
#include<ostream>
using namespace std;
//double decimals[5] ={2,4,6,8,10};
const int arraySize = 5;
// does an arraySize have to be const always? is it so it doesnt channge after the array has been created?
//double decimals[arraySize];
/*
this array is being created in the function averageN() but why?
cant i just create it up top and reference it in?
*/
// why do you have to write the name of the function up here before you even create it?
double averageN();
int main()
{
averageN();
return 0;
}
// why does the array have to be created here?
double averageN(double decimals[arraySize])
{
double average;
double arrayTotal;
for (int i = 0; i<5;i++)
{
// fills with random numbers from 0 - 10
decimals[i] = (0+(rand()%10));
}
// find the total of all the elements in the array
for (int i = 0; i < arraySize;i++)
{
double currentElement = decimals[i];
arrayTotal = (currentElement+arrayTotal);
//arrayTotal +=decimals[i]) ;
}
// return the average
average = (arrayTotal/arraySize);
return 0.0;
}
// does an arraySize have to be const always? is it so it doesnt channge after the array has been created?
Yes, it has to be const, moreover, it must be a constant expression, which means its size must be known at compile-time (not at runtime).
If you want to resize arrays, then the best is to use the standard container std::vector. Or use dynamically allocated arrays if you want a fixed-size array, but the size is not known until runtime
/*
this array is being created in the function averageN() but why?
cant i just create it up top and reference it in?
*/
if you speak about decimals, then no, it is a global variable, you can use it from anywhere.
// why do you have to write the name of the function up here before you even create it?
You must declare any name in C++ prior to its use. Since you call this function in main, it must be at least declared beforehand. You can also provide the definition (body) before main.
// why does the array have to be created here?
Oops, it appears that there's a big mixup in your code. As a matter of fact, you have 2 functions named averageN, one is averageN that takes no parameters, other is AveraeN taking an array of double.You never defined the first one, just declared.
Errors:
doubleTotal is not initialized. Well it is not
double arrayTotal; change to
double arrayTotal = 0.0;
unresolved extenal in main - that's the AverageN function in main you are caling. You never wrote a body for it. You created a function that takes an array, which wasn't useful since your array is global. Just delete the array parameter from AverageN definition.
HTH
P.S. Read S. Lippmann's C++ Primer. It's the best book for beginners ther is for C++. IMO :)
const gives the compiler a clue that the item should not be changed and if the code attempts it then the compiler can flag an error.
the function name is mentioned before the actual declaration the main() function needs to reference it before the compiler has actually come to compile it (as it later on in the code file). You can move the whole function before the main() to avoid this.
double averageN(double decimals[arraySize]) is saying this function takes an array. It doesn't say that it create the array. If you look in the function, it takes the array, and adds calculated values into it (decimals[i] = (0+(rand()%10))). This function also calculates an average over the array and returns that as a double.
So to answer your big question what's wrong - read the last point and look at the call you are making -averageN(); - can you see how this is not the correct call?
OK, here's your only assignment into arrayTotal:
arrayTotal = (currentElement+arrayTotal);
Now, what is the value of arrayTotal after this assignment? Well, it depends on its value before the assignment. What was its value before the very first assignment? You don't know. It could be anything because you never gave it an initial value.
const int arraySize = 5;
// does an arraySize have to be const always? is it so it doesnt channge after the array has been created?
C++ basically supports two kinds of arrays: fixed-size arrays, that are declared as type name[size], and dynamic arrays that are allocated with new[].
For fixed-size array you must provide their size to the compiler so that it can set aside enough memory for the array. As the size must be known to the compiler, you can only specify it with a const variable or a literal.
Although it is possible to create dynamically allocated arrays yourself, by invoking new[], this will give you some headaches getting the memory management right. It is better to use existing classes that do this for you, like std::vector.
//double decimals[arraySize];
/*
this array is being created in the function averageN() but why?
cant i just create it up top and reference it in?
*/
You can create it up here, but that would give anybody access to the array. For a small program like this that is not a big problem, but consider that there are a dozen other files that can also access the array and change it at unexpected moments.
It is basically the same question as to why you don't make all classes and members public in Java: to limit who has access.
// why do you have to write the name of the function up here before you even create it?
double averageN();
You have to declare the function before you can use it. C++ has the requirement that all names you use must have been declared to the compiler before their first use, and the compiler will read a file in sequential order from the top to the bottom.
Note that this declaration does not match the function definition you give below. As C++ supports function overloading, the two are considered different functions, because they accept different parameters (none versus a pointer)
int main()
{
averageN();
return 0;
}
// why does the array have to be created here?
double averageN(double decimals[arraySize])
{
This does not create an array. Instead it specifies that the function expects to be called with a pointer argument (the arraySize is completely ignored and you can't pass an array to a function in C++, so the parameter is adjusted to read double *decimals).
To get a working program, you need to change the two lines above to
double averageN()
{
double decimals[arraySize];
double average;
double arrayTotal;
Both average and arrayTotal are not initialised. That means they will start with some unknown value.
For average, thatis not a problem, because the first thing you do with it is assign a new value. But for arrayTotal, you are adding values to it, so you must let it start with a known value.
for (int i = 0; i<5;i++)
{
// fills with random numbers from 0 - 10
decimals[i] = (0+(rand()%10));
}
// find the total of all the elements in the array
for (int i = 0; i < arraySize;i++)
{
double currentElement = decimals[i];
arrayTotal = (currentElement+arrayTotal);
//arrayTotal +=decimals[i]) ;
}
// return the average
average = (arrayTotal/arraySize);
return 0.0;
}
My quick answers without double checking (its been awhile since I've developed in C++) are:
arraytotal has not been initialized
I suspect that your compiler flags this as an error to make sure you do it. If you don't, you can't be sure what it will be initialized to. Traditionally for debug builds, C/C++ initialized memory to some debug value to help identify uninitialized variables. Set arrayTotal = 0 when it is initialized and that should go away. (Best practice)
e.g. double arrayTotal = 0;
external reference in main
I suspect this is because your prototype for averageN does not match the method defined later. A prototype needs to include the types of the parameters as well as the return type. Change the prototype from double averageN(); to double averageN(double []); and I believe that will fix that problem.
does an arraySize have to be const always? is it so it doesnt channge after the array has been created?
Since you are using it to define the size of the array passed into averageN, yes. Setting the size of the array like this requires a constant value.
This array is being created in the function averageN() but why?
cant i just create it up top and reference it in?
It is not being created in averageN. It is a formal parameter to averageN. The caller of averageN needs to provide the appropriate variable and pass it in. Then from within the method, you access it through decimals.
why do you have to write the name of the function up here before you even create it?
This is the function prototype. It is necessary if the function is referenced in code before the function is defined. This could be resolved in other ways as well, such as moving the definition of averageN before all uses of it.
Couple of problems:
Your forward declaration of averageN is not correct
Code:
double averageN();
The supplied version below takes a parameter.
Your declaration of averageN does not quite work
Declaring parameters of type array is not intuitively obvious.
Normally people let the array degrade to a pointer to the array and pass a length as a second parameter.
Code:
double averageN(double *decimals, int arraySize)
If you want to only pass arrays of a specific size you need to do so by reference:
double averageN(double (&decimals)[arraySize])
Your call to averageN() in main.
You are passing zero parameters. Now this matches the forward declaration but not the actual definition.
Result I would change the code like this:
extern double averageN(double (&decimals)[arraySize]);
int main()
{
double data[arraySize];
averageN(data);
return 0;
}
// why does the array have to be created here?
double averageN(double (&decimals)[arraySize])
{
In addition to the technical details of the other answers, instead answering the complaint in your first paragraph: one way to get quality answers to "why" C++ questions is to ask in one of the Usenet groups, because, like with StackOverflow there are Real Experts hanging out there, but unlike StackOverflow even a beginner's question is likely to get an answer from a member of the standardization committee, and if you're lucky even from those who have penned the standard (like Andrew Koenig or currently Pete Becker). In earlier times Bjarne was there too. But recent years he hasn't posted much.
Basic novice "why" questions:alt.comp.lang.learn.c-c++. Francis Glassborow hangs out there. He's a committe member and author of several successful C++ introductory books. He also knows a bit of math, and since the posting frequency there is low (what with StackOverflow!), you are almost assured that any halfway interesting question will be answered almost immediately -- and correctly -- by Francis, in a snap. :-)
General questions about the C++ language: comp.lang.c++and/or comp.lang.c++.moderated. The latter group is moderated and has a charter. The moderation reduces noise -- e.g. no spam -- but adds delay. Some committee members prefer to post mostly in the unmoderated group (e.g. James Kanze), some, like Pete Becker and Howard Hinnant, post in both groups, and some well known experts, e.g. Andrei Alexandrescu, now apparently only post in the moderated group.
Questions about what the standard means, reports about errors in the standard and so on (in earlier times this was also where you formally reported defects in the standard): [comp.std.c++]. This is also a moderated group, and unfortunately the mod delay is now almost unbearably long. But as a novice you're probably less interested in the formal details, and more interested in rationales and explanations, for which [comp.lang.c++] and [comp.lang.c++.moderated] are great groups (I think StackOverflow's main advantage is when you're wondering "what's the bug in this code" or questions that in principle can be resolved by just reading the relevant documentation).
Finally, I've linked to Google Groups which provides a web based interface, but you can access these groups more directly from a Usenet client like Thunderbird (or e.g. the Opera browser, which has a built-in client). All you have to do in order to access Usenet via a local client is to configure the client, telling it about a server, like the free EternalSeptember. Or AIOE.
Cheers & hth.,
– Alf
One thing nobody seems to have commented on: your return statement at the end of averageN is wrong. You say you're returning the average, then you calculate the radius, and then return 0.0;. Try return average; or return arrayTotal/arraySize;.

Visual Studio Debugger can't view arrays after they have been passed to functions

I have a function like this:
MyFunction(double matrix[4][4])
{/*do stuff*/}
I am calling this from an outer function (the otuer function is a member function of a class, in case that matters):
OuterFunction()
{
double[4][4] x;
initialize(x); //this function puts the data I want in the matrix
MyFunction(x);
}
I am trying to debug this progaram using the Visual Studio debugger. The problem is that when I am looking at the locals for the OuterFunction, I can see all the elements of the array just fine, but when I am looking at the locals for MyFunction, I can only see the first row of the array, and it says it's a matrix[4]* rather than a matrix[4][4]. This even happens when I am only passing a one dimensional array - I pass in a matrix[4], then the debugger identifies it as a matrix* and only lets me see the first element of the array. Is it possible to fix this so I can see all of the array in the debugger?
It is can be solved by using a vector of vectors, or having your matrix variable in the watch windows like "matrix,4". The ",4" is a format that tells the debugger show 4 elements.
When you pass the matrix[][] to the function then you are actually only passing a pointer matrix**. The C code in the function has no idea of what the size of the matrix is and so neither does the debugger.
To use the function or general marticies you will have to pass the dimensions to the function.
You can see later values of say matrix* in the debugger by asking for *(matrix + n).
But you are using C++ not C so much easier to use C++ things like std::vector (If doing C++ you very rarely declare arrays to be passed around)