C++ Arrays and Vectors - c++

I am new to C++ and this is not really part of my major so I am a little lost! If I can contact anyone personally for help please let me know :)
My program will need to read in ten integer values from a file, and store them in an array or vector. The reading of the values should be done in a separate function that takes an integer array as a parameter, and read from a file named tempInput.txt. I am unsure how to create an integer array as a parameter.
Then, from main, you will call another function, whose signature and return type is thus:
bool isDangerous(int tempArray[ ]);
If you could help me with part one or two that would be great!
namespace std;
int divison(int,int);
int main()
{
void readData(int tempArray[ ]);
int tempInput[10];
readData(tempInput);
//int size=10; //Array size
int sum =0;
//for(int i=0;i<size;i++) //Loop which inputs arrays data and
// {
//cout << myArray[i] << endl;
// }
return 0;
}

As best as I can understand the question, here's some code to get you started (Note that I haven't filled in everything exactly, I don't want to do your work for you)
#include<fstream> //So we can read from files
#include<iostream>
using namespace std;
void readData(int tempArray []) {
//Open file and read data into temp array
//If you need help reading data, see:
//http://www.cplusplus.com/doc/tutorial/files/
}
bool isDangerous(int tempArray []) {
//Do things
}
int main() {
int tempInput [10];
readData(tempInput); //Read the data into tempInput
bool result;
result = isDangerous(tempInput); //Do something with isDangerous
return 0;
}

Related

Passing a dynamic array of structs c++

I need to read a .txt file and use the first number as the array size in a function called getData.
In my code, I am able to read the file and assign it to the array size as listSize. I am also able to fill the rest of the array with the .txt information. When I print out what is in my array WITHIN the getData function, it works.
The problem is that when I try to access the array outside of the getData function my program crashes. I am new to pointers, and c++ in general. I don't think I am passing it or calling it correctly. I have had a hard time finding information to assist me in the problem.
How can I access the arrays I created in getData?
#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>
using namespace std;
struct menuItemType
{
string menuItem;
double menuPrice;
};
void getData(int& listSize, menuItemType menuList[], int orderList[]);
int main()
{
menuItemType *menuList = 0; //-----pointers
int *orderList = 0;
int listSize;
getData(listSize, menuList, orderList);
cout << menuList[0].menuItem; //-----This is what crashes the program
return 0;
}
//-----Get Menu Function
void getData(int& listSize, menuItemType menuList[], int orderList[])
{
//-----Declare inFile
ifstream inFile;
string price, size;
//-----Open inFile
inFile.open("Ch9_Ex5Data.txt");
//-----Get Amount of Items, Convert to int
getline(inFile, size);
listSize = stoi(size);
//-----Set Array Size
menuList = new menuItemType[listSize];
orderList = new int[listSize];
//-----Get Menu
for (int x = 0; x < listSize; x++)
{
//-----Get menuItem
getline(inFile, menuList[x].menuItem);
//-----Get menuPrice convert to double
getline(inFile, price);
menuList[x].menuPrice = stod(price);
}
//------PRINT WORKS HERE ----- This print made me think i created the
//arrays correctly
for (int x = 0; x < listSize; x++)
{
cout << menuList[x].menuItem << endl
<< menuList[x].menuPrice
<< endl;
}
inFile.close();
}
The contents of the .txt
8
Plain Egg
1.45
Bacon and Egg
2.45
Muffin
0.99
French Toast
1.99
Fruit Basket
2.49
Cereal
0.69
Coffee
0.50
Tea
0.75
Setting menuList and orderList in getData does not update the pointers in main. It would if you used references to pointers:
void getData(int& listSize, menuItemType*& menuList, int*& orderList);
Even better, use references to std::vector and quit mucking around with owning pointers and new and delete.
Let's Rewrite your code for a better C++ness, with explanations. :)
#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>
Don't do using namespace std just because you can type less things, namespaces helps you by telling you where this particular thing you invoked came from. if you really wanna write string instead of std::string, pull that particular thing, not the whole namespace, like this:
using std::string;
Your struct seems right, but you need to choose if your types will start with capitals or not, I always start my types with capitals but this is a choice:
struct MenuItemType
{
string menuItem;
double menuPrice;
};
Now, your getData should, well, get your data. so the type matters. your data is not 'void' as you declared, it's an array of MenuItemType, you can then declare them as vector and not even care about pointers.
Other thing: all of your parameters in getData shouldn't be parameters - they are all things that you would get from the text file that your program will parse, so the only thing that matters for the getData is the text file, so this is your variable.
std::vector<MenuItemType> getData(const std::string& textFile)
{
std::ifstream inFile;
std::string price, size, item;
inFile.open(textFile);
getline(inFile, size);
int listSize = stoi(size);
std::vector<MenuItemType> result;
result.reserve(listSize);
for (int x = 0; x < listSize; x++)
{
getline(inFile, item);
getline(inFile, price);
result.push_back(MenuItemType{item, stod(price)});
}
return result;
}
See how I didn't closed the file? It will be closed as soon as you leave the function, there's no need to call that unless you need the file to close before the function finishes.
Thumbs up rule: don't deal with pointers unless you have to.
As for your main function:
int main()
{
std::vector<MenuItemType> menuList = getData("Ch9_Ex5Data.txt");
cout << menuList[0].menuItem;
return 0;
}
You could rewrite that in a faster way if you are sure what types are you using, the code above is equivalent to this one:
int main()
{
auto menuList = getData("Ch9_Ex5Data.txt");
cout << menuList[0].menuItem;
return 0;
}

Run time error for dynamic memory allocation in C++

I am a newbie for OOP concepts and while trying to solve Project Euler Problem 7, to find 10001th prime number, I tried to do it using a class but encountered 2 major errors.
instantiating the class prime_n
initializing its argument
I have posted the code here for reference:
#include<iostream>
#include<cstdio>
using namespace std;
class prime_n
{
int j,k;
int n;
int *store;
public:
prime_n(int num)
{
n=num;
store[n];
}
static int isPrime(int j)
{
for(int i=2;i*i<=j;i++)
{
if(j%i==0) return 0;
}
return 1;
}
void find_n()
{
for(int i=0;i<n;i++)
{
store[i]=0;
}
store[0]=2;
j=3;
k=1;
while(store[n-1]==0)
{
if(isPrime(j)) store[k++]=j;
j+=2;
}
}
int get_num()
{
int value=store[n-1];
return value;
}
};
int main()
{
int num, req_num;
printf("Enter the position at which prime number is to be found ");
scanf("%d",&num);
printf("\nnumber = %d",num);
prime_n p = new prime_n(num);
req_num = p.get_num();
printf("The required prime number is %d\n",req_num);
return 0;
}
It would be a great help if someone could help me figure out where I am actually going wrong. Thanks a lot in advance!
Use
prime_n p(num);
or (not recommended in this particular case)
prime_n * p = new prime_n(num);
// some other code
req_num = p->get_num(); // note the -> operator replacing . in case of pointers
delete p;
The first case declares p on stack and it is automatically deallocated when the program leaves the scope (main function in this case)
The second one allocates space on heap and p is the pointer to it. You have to deallocate the memory manually.
As for your second question, the C++ way would be
#include <iostream>
...
int num;
std::cout << "Enter the position at which prime number is to be found "
std::cin >> num;
std::cout << std::endl << "Number = " << num << std::endl;
You provide a constructor:
prime_n(int num)
{
n=num;
store[n];
}
I think you are under the impression that store[n] creates an array with n elements, but that is not so; it attempts to access the (n+1)th element of an an array. Since store does not point anywhere (we are in the constructor, after all), the program crashes.
You probably want to write store = new int[num] instead.
And then I cannot see any call to find_n() originating from get_num() which is called in main(), so that your program would for now just return a random value.

Read File then Create Array Function C++

I am new to C++ and lately I was having trouble reading a file. That problem is now fixed. What I'd like to do now is to use the file I read to create an array, but all this has to be done in a function, this means the function has to return an array so I can use it on the main. The process I follow:
Read File
Create Array
Return Array Adress.
In the main: Use function to put an array in a variable.
My code so far:
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <string>
using namespace std;
void imprimeArreglo (int[],int);
int* leeArreglo(string&);
int i;
void imprimeArreglo(int a[])
{
cout << a[i] << endl;
}
int* leeArreglo(string nombre)
{
ifstream arch(nombre.c_str());
string tamStr;
int tam;
if(arch.is_open())
{
getline(arch,tamStr);
tam=atoi(tamStr.c_str());
int arr[tam];
for(int i=0;i<tam;i++)
{
arch >> arr[i];
}
int *ret=arr;
return ret;
}
return 0;
}
int main()
{
string nombre = "arr.txt";
int *a= leeArreglo(nombre.c_str());
imprimeArreglo(a);
return 0;
}
What my arr.txt file looks like:
10
9 8 22 33 76 0 23 100 -8 45
I think this should print (with imprimeArreglo(a)):
9 8 22 33 76 0 23 100 -8 45
But the only thing I get in the console is:
2292592 Which I think it's a memory adress??? What am I doing wrong? Is there a better way to do it without using vectors?
Thanks in advance!
This would be a simple way of doing it:
#include <iterator>
#include <vector>
#include <fstream>
std::vector<int> fileContents(const std::string& filename)
{
ifstream inputFile(filename.c_ctr());
std::istream_iterator<int> end;
std::istream_iterator<int> it(inputFile);
return std::vector<int>(it, end);
}
This reads all the numbers into a vector. You may have to modify it to ignore the first 10, for example by calling std::advance(it, 1); just after initializing it.
You are returning a reference to a local variable. When your function go out of scope the array arr is freed and therefore the address return is just garbage.
If you want to return an address that lives after the function is called, do something like:
int *arr = new int[tam];
Then the address will be valid after the function is called but in terms of design this is not great as you leave the responsibility to free the array on the caller.
I would personally wrap all of this in a class and and have the array member of it.
Ok after some research and consulting, I got the answer! Thank you everyone for helping me :). This is the code that made the things happens (USING ARRAYS!!)
int* readArray(string name)
{
ifstream fil(name.c_str());
string sizeStr;
int size;
if(fil.is_open())
{
getline(fil,sizeStr);
size=atoi(sizeStr.c_str());
int* arr = new int[size+1];
for(int i=1;i<size+1;i++)
{
fil >> arr[i];
}
//We stash the size in the first position ;)
arr[0]=size;
//cout << arr[0]<< "\n";
//We point to the position of the array + 1. (The 0 pos is used for the size)
int *ret=arr+1;
return ret;
delete[] ret;
}
else cout << "ERROR...!\n";
return 0;
}
As you can see my function returns a pointer. And I delete it. (Still need to see if that delete[] is well positioned tho.)
Also since what I return is a pointer I can't really know what the size of my array is using sizeof(arr)/sizeof(int). So what I did is to save it into a position of the array, that way I can call it whenever I want by using array[-1].
Thank you all again!

Constructor issue <Unable to read memory>

I have to create a class Histogram and make operations on this class. The input can be one dimensional array or a two dimensional array. The problem appears when i convert the array into a matrix. This what i have tried so far. The error is <Unable to read memory>
histrogram.h
#ifndef HISTOGRAM_H
#define HISTOGRAM_H
#include<iostream>
class Histogram
{
private:
int** matrix;
int lines;
void SortMatrix();
public:
Histogram(){ }
Histogram(int elements[], int elementsNr);
Histogram(int** m, int l);
void Print();
};
#endif
historgram.cpp
#include"histogram.h"
using namespace std;
Histogram::Histogram(int** m, int l)
{
matrix=m;
lines=l;
SortMatrix();
}
Histogram::Histogram(int elements[], int elementsNr)
{
lines=0;
//initialize matrix : elementrNr lines and 2 columns
int** matrix=new int*[elementsNr];
for(int i=0;i<elementsNr;i++)
{
matrix[i]=new int[2];
matrix[i][0]=INT_MIN;
matrix[i][1]=INT_MIN;
}
//search each element from the array in the matrix
bool found=false;
for(int i=0;i<elementsNr;i++)
{
found=false;
for(int j=0;j<elementsNr;j++)
{
//the element was found in the matrix ( on the first column )
if(matrix[j][0] == elements[i])
{
matrix[j][1]++;
found=true;
break;
}
}
if(!found)
{
matrix[lines][0]=elements[i];
matrix[lines][1]=1;
lines++;
}
}
SortMatrix();
}
void Histogram::SortMatrix()
{
bool flag=true;
int temp;
for(int i=0;(i<lines) && flag;i++)
{
flag=false;
if(matrix[i+1][0]>matrix[i][0])
{
temp=matrix[i][0];
matrix[i][0]=matrix[i+1][0];
matrix[i+1][0]=temp;
flag=true;
}
}
}
void Histogram::Print()
{
for(int i=0;i<lines;i++)
{
cout<<matrix[i][0]<<" : " <<matrix[i][1]<<endl;
}
}
main.cpp
#include"histogram.h"
#include<iostream>
using namespace std;
int main()
{
int arr[]={6,7,3,1,3,2,4,4,7,5,1,1,5,6,6,4,5};
Histogram h(arr,17);
h.Print();
}
Here
int** matrix=new int*[elementsNr];
replace with
matrix=new int*[elementsNr];
becausematrix is already a member variable. You are creating a new temporary variable double pointer named matrix and allocating memory to it rather than your member variable matrix
A couple of people have already given you advice about how to fix some of the problems with this code. I'll give slightly different advice that may initially seem a bit brutal by comparison, but I'll try to demonstrate how it's honestly useful rather than nasty.
I would throw out your existing code with the possible exception of what you have in main, and start over, using an std::map. What you're doing right now is basically trying to re-create the capabilities that std::map already provides (and even when your code is fixed, it's not doing the job as well as std::map does right out of the box).
Using map, your whole program comes out to something like this:
std::ostream &operator<<(std::ostream &os, std::pair<int, int> const &d) {
return os << d.first << " : " << d.second;
}
int main() {
std::map<int, int> h;
for (int i=0; i<17; i++)
++h[arr[i]];
std::copy(h.begin(), h.end(),
std::ostream_iterator<std::pair<int, int> >(std::cout, "\n"));
return 0;
}
If you want to maintain virtually the same interface as your histogram class provided, it's pretty easy to do that -- the for loop goes into the constructor, the copy into print (and SortMatrix disappears, because a map is always sorted).
By doing this, you change from an O(N2) algorithm to an O(N log N) algorithm. The bugs others have pointed out disappear completely, because the code that contained them is no longer needed. The only real disadvantage I can see is that the result will probably use a bit more memory -- it uses a balanced tree with individually allocated nodes, which is likely to introduce a fair amount of overhead for nodes that only contain 2 ints (and a bit for balancing). I can't quite imagine worrying about this though -- long before you have enough nodes for the memory usage to become significant, you have way too many to present to even consider presenting to the user.
#mathematician1975 already provided an answer for the main problem. There's another bug in SortMatrix(): you only swap the elements of the first column, therefore after sorting, the counts (in the second column) will not be correct anymore. You'll have to insert
temp=matrix[i][1];
matrix[i][1]=matrix[i+1][1];
matrix[i+1][1]=temp;
to get it working.

C++ Int getting random value after function that isn't supposed to change it

Okay - yes, this is homework, but it isn't mine. I have a friend taking an introductory C++ course who asked me for help, and I helped them write this program, but there is one weird bug that I can't figure out. Any helpful suggestions would be greatly appreciated. Thanks!!
The following is the code. The problem is that after the add_loop function, the int loop_size gets a random value. Within the function, it has the value it is supposed to have, but afterwards, it changes.
#include <iostream>
#include <string>
#include <stdlib.h>
#include <time.h>
using namespace std;
#define STRING_SIZE 50
void get_template (char StemLoop [])
{
char Template [STRING_SIZE];
cout<<"Please enter a template for the stem:";
cin>> Template;
strcpy (StemLoop, Template);
}
void add_loop (char StemLoop[], int loop_size)
{
char random_loop [STRING_SIZE];
int random_array[STRING_SIZE];
for (int i=0; i<loop_size; i++)
{
random_array[i] = rand() % 4;
if (random_array[i]==0)
random_loop[i]='A';
else if (random_array[i]==1)
random_loop [i]='U';
else if (random_array[i]==2)
random_loop [i]='G';
else if (random_array[i]==3)
random_loop [i]='C';
}
strcat (StemLoop, random_loop);
}
void add_complement(char StemLoop[], int loop_size)
{
int x =strlen(StemLoop);
int j=0;
char complement [STRING_SIZE]="";
for (int i=0; i<(x-loop_size); i++)
{
if (StemLoop[i]=='A')
complement[j]='U';
else if (StemLoop[i]=='U')
complement[j]='A';
else if (StemLoop[i]=='G')
complement[j]='C';
else if (StemLoop[i]=='C')
complement[j]='G';
j++;
}
strcat(StemLoop,complement);
}
void main()
{
int loop_size=0;
cout<<"Please enter the size of the loop: ";
cin>>loop_size;
char StemLoop [STRING_SIZE];
//Part1: the template
get_template (StemLoop);
//This is supposed to be the function that adds the loop of random "genes".
//It works, and within it the int loop_size is the correct value...
add_loop (StemLoop, loop_size);
/*...but here it is a random number. It's as if the random value generated
within the function is getting assigned to it. And of course, it's throwing off the
entire program.
*/
//Part#3: the complement
add_complement (StemLoop, loop_size);
cout<<"The complete stem-loop strand is:"<<StemLoop<<endl;
}
You're not 0-terminating random_loop before you use it in strcat, so strcat can write all over your stack. Try this:
random_loop[i] = 0;
strcat (StemLoop, random_loop);
A more serious problem could be that you're not checking you have enough room to strcat.