Changing variable name inside a loop - c++

I'm trying to create a loop that will will create a new variable but also change the name of the variable, such as increasing in value, automatically. Not sure if this is possible because you cant have dynamic variables?
if (cin.get() == '\n')
{
m ++; // Add an integer to m
string (1 + m); //Trying to name the string the value of m + 1, i.e 3
cin.ignore():
getline(cin, (1 + m))
myfile << (1 + m) << endl;
}
That is my current code which is full of errors but hopefully readable enough to gain an understanding of what I'm trying to do.
Bad title, don't know what else to call it.

You're misunderstanding C++ if you try to "rename a variable".
C++ is a compiled language in which the names of the variables only exist in your source code as a means of handling them, but not in the compiled program.
You hence can't also create a variable with a specific name at runtime -- variable names simply don't exist then.
You probably want some kind of container that maps values to keys, think of a dictionary, where you can say "for this integer value 12, I store the string monkey" or so. Have a look at std::map.
Now, you're really not making much sense right now; and try to do things that aren't really the way C++ works for anyone who learned it in a ordered manner. I'd really recommend getting a C++ book or tutorial and start with that. It's going to turn out to safe you a lot of time! Here's a list of recommended C++ books and ressources.

You can't. It's not possible in C++.
To declare and initialize a variable in each iteration is however possible:
for (int i = 0; i != 10; ++i) {
int var = i; // Declare 'var' and assign value of 'i' to it.
} // 'var' object goes out of scope and is destroyed
Names are visible from the point where they are declared until the end of the scope in which the declaration appears. Names have scope and Objects have lifetimes.

The closest thing to "renaming" in C++ would be declaring a reference of the "old named" variable with the new name.
int a = 2;
int &b = a;
//you can now call either `b` or `a` to get the value
Creating new variables on the fly is not possible. The correct insert any compiled language name here way of doing it is by pushing values into a container (array, map, stack..etc). With maps, you can do something similar to what you want, but it's different one only "maps" a string to a value.
#include <map>
#include <string>
#include <sstream> //for int to string conversion
std::string stringify(int val)
{
std::stringstream ss;
ss << n;
return ss.str();
}
int main()
{
std::map<std::string, int> values;
for (int i = 0; i < 10; i ++){
values[stringify(i)] = i*100;
}
std::cout << values["1"]; // prints 100
std::cout << values["9"]; // prints 900
return 0;
}

Related

Array of pointers to structs

EDIT: Im quite new to c++ and programming as a whole.
I'm supposed to make a program where i use stucts and and an array of structs.
Security council < > Member of Security council
My task was to use the concept of "UML aggregation" to create a program where I use structs and struct arrays. (I hope you understand what I'm trying to say)
Since a Member of a Security council is a part of a Security council, and not the other way around, the struct of Security council must have an array of its members.(bear with me)
//example
struct Member_sc{
char * name;
int age;
};
struct Security_council{
Member_sc members[10];
};
Now, I've created this program and everything works perfectly (according to my teacher), but now she told me create an exact copy, but instead of the "members" array I must use an array of pointers to the Member_sc structs. Since I havent completely figured out how pointers work, I have come across some problems.
I can post the code to the original program if needed, but it contains 4 files(main, header, and some function files) and it would be a pain to try and post it here.
here is the prototype (all in one file, for now)
#include <iostream>
using namespace std;
struct member_sc{
string name;
};
struct security_council{
member_sc *point;
security_council **search; // ignore this for now
int n;
security_council():n(0){}
};
void in_mem( member_sc &x){
getline(cin,x.name);
}
void out_mem(member_sc &x){
cout<<x.name<<endl;
}
void in_SC(security_council &q, member_sc &x){
int num; //number of members
cin>>num;
for(int i=0; i<num; ++i){
in_mem(x);
q.point[q.n]=x;
q.n++;
}
}
void out_SC(security_council &q,member_sc &x){
for(int i=0; i<q.n; ++i){
out_mem(q.point[i]);
}
}
int main(){
member_sc y;
security_council x;
in_mem(y); // works
out_mem(y); // works
in_SC(x,y); // crashes after i input the number of members i want
out_SC(x,y); //
system("pause");
return 0;
}
The program crashes after you input the number of members you want in your Security council.
Is my way of thinking right? or should I use dynamic memory allocation?
in addition to that (my teacher gave me an additional task) create a search function using pointers. i thought that pointer to pointer may be good for that, but im not sure.
Any help or advice would be greatly appreciated.
( i think ill figure out the search thingy once i figure out how pointers to structs work)
The first part of your issue is this:
cin >> num;
this reads only the digits that have been typed and stops at the newline. Then, in in_mem the call to getline immediately reads a newline. You need to do:
cin >> num;
cin.ignore();
this will drain the input stream of any remaining input, or catch up so to speak.
However your core problem is that you don't allocate any memory for "point" to point to.
A pointer is just a variable holding a value that happens to be the address (offset from 0) of a thing in memory. If you are going to the airport and write "Gate 23" on a post-it note, the post it note is a pointer and "Gate 23" is the value.
In your code, that variable is uninitialized and will either be 0, if you are lucky, or some random address in memory if you aren't so lucky.
To the airport analogy: you arrive at the airport and find that your post-it note has "pizza" written on it. Not helpful.
Your teacher has actually specified an "array of pointers". Break that down: pointer to what? member_sc, that's member_sc*. And now make it an array
member_sc* pointers[10];
NOTE: This is not good, modern C++ - in modern C++ you would use something called a smart pointer (std::unique_ptr) probably.
std::unique_ptr<member_sc[]> pointers(new member_sc[10]);
Now you have 10 pointers instead of just one, and all of them will need some allocation to point to. The easiest way to do this is with the new keyword and the copy constructor:
for (int i = 0; i < num; i++) {
in_mem(x);
pointers[q.n] = new member_sc(x); // make a clone of x
q.n++;
}
or in modern C++
for (int i = 0; i < num; i++) {
in_mem(x); // x is temporary for reading in
pointers[q.n] = std::make_unique<member_sc>(x);
q.n++;
}
However there is a limitation with this approach: you can only have upto 10 security council members. How do you work around this? Well, the modern C++ answer would be to use a std::vector
std::vector<member_sc> members;
// ditch n - vector tracks it for you.
// ...
for (int i = 0; i < num; ++i) {
in_mem(x);
q.members.push_back(x);
// q.n is replaced with q.members.size()
// which is tracked automatically for you
}
but I'm guessing your teacher wants you to actually understand pointers before you get to forget about them with modern luxuries.
We need to re-use the pointer stuff we've just used above and change "pointers" to an array of pointers.
Which means we're going to want a pointer to a set of pointer-to-member_sc.
member_sc** pointers;
We'll need to assign some memory for this to point to:
cin >> num;
cin.ignore();
if (num == 0) {
// do something
return;
}
pointers = new member_sc[num];
luckily, using a pointer to an array is as easy as using an array, the only major difference being that you lose the size-of-array information -- all you have is the address, not the dimensions.
for (int i = 0; i < num; i++) {
in_mem(x);
q.pointers[i] = new member_sc(x);
q.n++;
}
I'm deliberately not providing you with a complete working example because this is obviously for a class.
You never initialize the memory that the point member refers to, yet then in statement q.point[q.n]=x; you attempt to use it.
Basically, after you read in the number of members, and before the for loop where you read in the individual members, you need to allocate an array of an appropriate number of member_sc objects and store it in q.point. Don't forget to free this memory when done using it.
Once you do that, you can also remove the member_sc &x argument from both in_SC and out_SC, as that will become unnecessary.
Finally, some validation of your input seems to be in place. Consider what will happen if the user enters a negative number, and you attempt to use that directly to determine the size of memory to allocate.
Here's a simple example showing how to use a dynamically allocated array of structures:
#include <iostream>
#include <string>
struct member_sc {
std::string name;
};
void test_array(int count)
{
if (count <= 0) {
return; // Error
}
// Allocate an array of appropriate size
member_sc* members = new member_sc[count];
if (members == nullptr) {
return; // Error
}
// ... fill in the individual array elements
for(int i(0); i < count; ++i) {
// ... read from input stream
// I'll just generate some names to keep it simple
members[i].name = "User A";
members[i].name[5] += i; // Change the last character, so we have different names
}
// Now let's try printing out the members...
for(int i(0); i < count; ++i) {
std::cout << i << ": " << members[i].name << "\n";
}
delete[] members;
}
int main(int argc, char** argv)
{
for(int count(1); count <= 10; ++count) {
std::cout << "Test count=" << count << "\n";
test_array(count);
std::cout << "\n";
}
return 0;
}
Example on Coliru
Of course, there are many other issues with this style of code, but I believe that's beside the point of this question. For example:
Instead of using bare pointers, it would be more appropriate to use some kind of a smart pointer.
Instead of a simple array, use some kind of collection, such as a vector.
Since you are asked to use an array of pointers, do so: replace
Member_sc members[10];
with
Member_sc* members[10];
Then fill out that array using dynamic memory allocation. As a matter of good form, at the end of the program remember to release the dynamic memory you have used.

Passing a variable to function for reference an array into

I need to call function which contains many cases.
I'd like to pass it a variable which can reference different arrays.
This example demonstrates more clearly what I'm trying to achieve:
void bob(int debut, int fin, string flag){
string arrayflag = "pfhistory_FR_" + flag;
for (i = debut; i < fin; i++){
std::cout << arrayflag[i].DP << endl
}
};
If you want a variable which can reference different array's, you are require a 2D array. A 2D array can be thought of as an array of arrays, and you can index the arrays using a variable.
Roughly speaking C++ is a statically-bound language. This means that objects are resolved at compile time, not run time. As such, what you're trying to do is not possible in C++, but has to be implemented manually. Something like this:
void bob(int debut, int fin, string flag){
auto *arrayflag =
flag == "1" ? prhistory_FR_1 :
flag == "2" ? prhistory_FR_2 :
prhistory_FR_3;
for (i = debut; i < fin; i++){
std::cout << arrayflag[i].DP << endl
}
};
But this has all the markings of XY problem. You probably are asking something completely different, except that you think that this approach is the answer to your real question. But it's not. Whatever you're trying to do, the real answer is most likely something else. You just need to figure out what you're really asking.

cpp(15): error C2182: 'input' : illegal use of type 'void'

after making a fresh start on a new program i made for learning how arrays work in combinatio0n with void ive ran into the following problem.
cpp(15): error C2182: 'input' : illegal use of type 'void'
Does anyone know what causes this? I am new to the concept of void and array.
#include "stdafx.h"
#include <iostream>
using namespace std;
void input (int x );
int main()
{
int x = 0;
int a[ 5 ];
input ( a[ 5 ]);
{
void input(x);
for(int i = 1; i < 5; i++) {
cin >> a [ i ];
}
cin.get();
cout << a [ 3 ];
cin.get();
}
}
Your code has many problems with it. It's just not valid C++ as it is. Remember that C++, like any other programming language, is unforgiving when it comes to syntax. If it's not exactly the right syntax, it's not going to compile. You can't just write what you think makes sense. You need to learn the correct syntax and apply it.
It looks like you want everything from the for loop to the last cin.get() to be part of a function called input. To do that, you need to use the appropriate syntax for defining a function and you need to do it outside any other functions:
void input(int x) {
for(int i = 1; i < 5; i++) {
cin >> a [ i ];
}
cin.get();
cout << a [ 3 ];
cin.get();
}
This still has a problem though. The parameter type is int, yet it looks like you want to pass the entire array:
void input(int x[])
Note that this is not actually an array type parameter, but is really a pointer. When you pass an array to this function, x will be a pointer to its first element. The [] is just a convenient syntax.
Then, instead of passing a[5] to the function (which is an element that does not exist, since only a[0] to a[4] exist), you should be passing just a:
input(a);
You also loop from 1 to 4 - I'm not sure if this is intentional. If you want to input a value for each element of the array, you should be looping from 0 to 4.
You're going to have more errors after resolving the current one. Here's some quick pointers that may help. I don't want to just give you a solution because you are still learning and that won't help:
void as a keyword refers to the "nothing type" and is used in functions to denote having no return value
curly braces {} denote scope and can be used to define the body of a function, loop, or control statement
Functions themselves need to be declared and defined. The definition, or body of the function, can be later on in your code but the declaration needs to be present before you call it
Here's an example program to illustrate basic function parts:
#include <iostream>
// declaration
void Welcome();
int main()
{
// function call
Welcome(); // displays "Hello World"
return 0;
}
// definition
void Welcome()
{
std::cout << "Hello World" << std::endl;
}
More on functions
As far as arrays they are basically a contiguous block of memory large enough to hold a given amount of the same type. Here's a few things to remember about arrays:
They work with integral types as well as objects but are usually used for plain old data. e.g. int intArray[5]; is an array of 5 int types.
The index starts at 0 meaning intArray[0] from previous example is the first integer.
Using the array operator you can get and set values e.g. int last = intArray[4]; or intArray[0] = -1;
More on arrays
Check out the other answers for more on how to pass arrays as parameters but I also recommend picking a Good C++ Book ;-)

Passing array of objects to a class

#include "average.c++"
#include "name.c++"
class Grade {
public:
Grade() {}
void searcharray(Name *array[]) {
int i;
for(i = 0; i <= 10; i++){
printf("%s", array->name);
}
}
};
int main() {
int i;
char line[64];
Name *names[10];
for(i = 0; i < 5; i++){
scanf("%s", &line);
names[i] = new Name(line);
}
Grade *test;
test = new Grade();
test->searcharray(names);
}
This code gives the error
"grade.c++ in member function 'void Grad::searcharray(Name*)':
grade.c++:11:25: error: request for member 'name' in ' array', which is of pointer type 'Name*' (maybe you meant to use '->' ?)"
I need help making this work. I am guessing it is something simple like extending the class like you would in Java but not sure how this works in c++.
I am assuming you can pass an array of objects to a class like you would in C with just an array.
The root to my question is to find a solution and to get a reason for this code being wrong.
Your code can be substantially improved by taking advantage of the Standard library. The problem with your initial code was that you were doing array->name where array was a C-style array (technically the pointer into which it decayed). An expression like that isn't possible unless you obtain the pointer at the index first:
array[i]->name;
Moreover, the for loop in which that line was written is traversing the array 1 too many times. The conditional statement i <= 10 should be i < 10 so you won't dereference an address past the end of the array.
Anyway, instead of showing your code with the corrections, I thought I might as well show you what it should look like if you use vectors, memory-management, and std::string. I hope this helps:
#include <iostream>
#include <string>
#include <vector>
#include <memory>
class Grade
{
public:
Grade() { }
static void searcharray(const std::vector<std::unique_ptr<Name>>& array)
{
for (const auto& obj : array)
{
std::cout << obj->name;
}
}
};
int main()
{
std::string name;
std::vector<std::unique_ptr<Name>> names;
while (std::cin >> name)
names.push_back(std::unique_ptr<Name>(new Name(name)));
// names.push_back(std::make_unique<Name>(name))
Grade::searcharray(names);
}
Note that I also made searcharray static since it has nothing to do with a given instance of Grade.
As others have pointed out the problem is that you're using a parameter declared Name *array[] like array->name.
Remember that C++ built on top of C, which follows a rule 'declaration mimics use', which means that the way a variable is declared looks like the way it is used. So with the declaration:
Name *array[]
The way you get a name out of this is:
*array[i]
And name is a member of Name so you have to get a Name object first. Then you can tack on member access:
(*array[i]).name
And then you can use the -> shortcut where (*x).y is the same as x.y:
array[i]->name
Other issues:
Your code appears to be heavily influenced by the style of code required for the 1989 or 1990 version of C. You should try to avoid that as it makes writing C++ code much worse than it has to be.
You declare a Grade * and allocate it immediately. You can combine the declaration with initialization into:
Grade *test = new Grade();
But you don't need to use a pointer anyway: use Grade test; (and if you did need a pointer then you should use a smart pointer. Never use 'naked' new.)
Similarly you can avoid new when you create Names.
Name names[10]; // assuming that Name is default constructible
for(...) {
...
name[i] = Name(line);
}
You should avoid a fixed size array here. Instead you should default to using std::vector:
std::vector<Name> names;
for (...) {
...
names.push_back(Name(line)); // or in C++11 names.emplace_back(line);
}
You should declare the variable i as part of the for loop, not as a variable outside it:
for (int i=0; i<10; ++i)
When you read input you should avoid scanf and fixed sized buffers. Instead, if you're reading lines you should probably start off with std::getline and std::string.
std::string line;
while (std::getline(std::cin, line)) { // read as many lines as there are, not just 10 no matter what
names.emplace_back(line);
}

modifying contents of local variable of a function in a subfunction through pointer

I have the following sample code. Just wanted to know if is valid to take address of a local variable in a global pointer and then modify it's contents in a sub function. Following program correctly modifies value of variable a . Can such practice cause any issues ?
#include <iostream>
#include <vector>
using namespace std;
vector<int*> va;
void func()
{
int b ;
b = 10;
int * c = va[0];
cout << "VALUE OF C=" << *c << endl;
*c = 20;
cout << "VALUE OF C=" << *c << endl;
}
int main()
{
int a;
a = 1;
va.push_back(&a);
func();
cout << "VALUE IS= " << a << endl;
return 0;
}
This is OK, as long as you don't try to dereference va[0] after a has gone out of scope. You don't, so technically this code is fine.
That said, this whole approach may not be such a good idea because it makes code very hard to maintain.
I'd say that if your program grows you could forget about a change you made in some function and get some weird errors you didn't expect.
Your code is perfectly valid as long as you call func() while being in the scope of a. However, this is not considered to be a good practice. Consider
struct HugeStruct {
int a;
};
std::vector<HugeStruct*> va;
void print_va()
{
for (size_t i = 0; i < va.size(); i++)
std::cout<<va[i].a<<' ';
std::cout<<std:endl;
}
int main()
{
for (int i = 0; i < 4; i++) {
HugeStruct hs = {i};
va.push_back(&hs);
}
print_va(); // oups ...
}
There are 2 problems in the code above.
Don't use global variables unless absolutely necessary. Global variables violate encapsulation and may cause overlay of variable names. In most cases it's much easier to pass them to functions when needed.
The vector of pointers in this code looks awful. As you can see, I forgot that pointers became invalid as soon as I left for-loop, and print_va just printed out garbage. The simple solution could be to store objects in a vector instead of pointers. But what if I don't want HugeStruct objects to be copied again and again? It can take quite a lot of time. (Suppose that instead of one int we have a vector of million integers.) One of the solutions is to allocate HugeStructs dynamically and use vector of smart pointers: std::vector<std::shared_ptr<HugeStruct>>. This way you don't have to bother about memory management and scope. Objects will be destroyed as soon as nobody will refer to them.