Read File then Create Array Function C++ - 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!

Related

push object in the heap using pointer to the static container

class Node_Str{
public:
string name;
string value;
string type;
Node_Str(string name,string value,string type){
name=name;
value=value;
type=type;}};
static stack<Node_Str> s;
void find_token(string input){
int cursor=0;
string current="";
while(cursor<input.length()){
char value;
value=input[cursor];
cout<<value<<endl;
if(value=='('||value==')'||value=='+'||value=='-
'||value=='*'||value=='/'){
Node_Str* p=new Node_Str("pare",string(1,value),"Pare");
s.push(*p);
cursor++;
delete p;}
if(value==' '){
cursor++;
}
if(value=='1'||value=='2'||value=='3'||value=='4'){
Node_Str* p=new Node_Str("num",string(1,value),"Number");
s.push(*p);
cursor++;
delete p;}}}
int main(){
while(!s.empty()){
cout<<s.top().value<<" ";
s.pop(); }
return 0; }
The find_token function should separate the input string by white Space and constructing the Node_Str object with the value of that string. Then in the
main function, I would like to print it. The characters are limit. Just '1', '2','3','4','+,'-','*','/'.
Input is 4 + 4 , output should be 4+4. However, there is no output.
The comments already said about memory leak and forgetting to call find.
In addition to that, stack is a container in which to last to be pushed in would be the first to be popped out. In order to output 0 1 2 3, you would need to push in the stack in the sequence of 3 2 1 0.
Just giving a better version.
#include <iostream>
#include <stack>
using std::cout;
using std::stack;
static stack<int> s;
void find()
{
int* p;
for (int i = 3; i >= 0; i--) {
p = new int(i);
s.push(*p);
delete p; // p itself does not have to be returned so it can be safely deleted here
//This can also ne replaced by directly using s.push(i)
}
}
int main() {
find();
while (!s.empty())
{
cout << s.top() << " ";
s.pop();
}
return 0;
}
as suggested by leyanpan, data should be pushed into reverse order, to get the desired output. One more point is no need of dynamic allocation for int type. It is always better to store non array built in types in stack rather than heap.
Also allocating stack data structure as static variable will extend scope up to program termination. Better to use stack object as a local variable in main and pass it as are reference argument to function find.

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;
}

Segmentation fault during counting of elements in array of strings c++

I am trying to solve an old problem found on topcoder. I am immediately stuck in trying to find the number of elements in an array of strings. Here is my code
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string>
using namespace std;
class MiniPaint {
private:
size_t numLines;
public:
int leastBad(string picture[], int maxStrokes) {
numLines = 0;
while (!picture[numLines].empty()) {
numLines++;
}
cout << numLines << '\n';
return 0;
}
};
int main() {
MiniPaint instance;
string picture[] = {"BBBBBBBBBBBBBBB", "WWWWWWWWWWWWWWW", "WWWWWWWWWWWWWWW", "WWWWWBBBBBWWWWW"};
instance.leastBad(picture, 10);
return 0;
}
This code gives me a segmentation fault. Something is going wrong, the code is a little bit excessive for just the functionality of counting the number of elements but of course I want to extend the class to include more functionality. If anyone can explain what is going wrong here I would be grateful! Thanks in advance.
EDIT: when I expand the code by
cout << picture[numlines] << '\n';
in the while loop, to show the actual elements in the array, first the four proper strings are shown and then somehow it endlessly prints spaces to the terminal. So the problem lies somewhere in the fact that
picture[4].empty()
does not return true, even though picture has only four elements.
Your while loop condition assumes that the last string in the array is empty:
int leastBad(string picture[], int maxStrokes) {
numLines = 0;
while (!picture[numLines].empty()) {
But your input string array defined in main() is not terminated with an empty "" string.
So you may want to add this empty string terminator:
// inside main()
string picture[] = {..., "" /* Empty string terminator */ };
In addition, in modern C++ I'd encourage you to use array container classes instead of raw C-style arrays, typically std::vector<std::string>.
In this case, you can use the size() method to get the array size (i.e. element count), or just a range-for loop for iterating through the whole array.
You access the array out of bounds.
When you call picture[4] you want to access a string object which is not there end the call to the function empty() is on uninitialized memory.
You either need to store how big the array is and iterate until numLines<=3 or you can use a vector
std::vector<std::string> picture = ...
for(std::string line : picture)
{
//do stuff
}
You are out of array bounds at picture[numLines]. You should pass array length or calculate it and check the index numLines. Code will look like:
size_t length = sizeof(picture) / sizeof(*picture); // For VS use _countof macro
while (numLines < length && !picture[numLines].empty())
{
++numLines;
}

C++ Arrays and Vectors

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;
}

Why does printing a string array output hexadecimal?

Why does the following program print "0x2ffee4" to the console?
#include <string>
#include <iostream>
using namespace std;
int main() {
string city1[] = "toronto";
cout << city1;
return 0;
}
The first line shouldn't compile, but there's a GCC bug that makes it compile and behave equivalently to something like
std::string city1[] = {"toronto", "toronto", "toronto", "toronto",
"toronto", "toronto", "toronto", "toronto"};
(8, because "toronto" is 8 characters including the terminating null. Yes, that means that if you used "Chargoggagoggmanchauggagoggchaubunagungamaugg", it would create an array of 46 strings, each storing "Chargoggagoggmanchauggagoggchaubunagungamaugg".)
Needless to say, you shouldn't rely on a compiler bug.
Under GCC's buggy behavior, city1 would be an array of std::strings; there's no operator << overload that support printing such a thing. Instead, in std::cout << city1, the array decays to a pointer to its first element, and the address stored in the pointer is printed instead.
You probably meant to write std::string city1 = "toronto";. One string, not an array of it.
The answer given by T.C. is correct, I would also like to mention that if you was expecting to print out "toronto" to the console using cout then you would want to do this:
include <string>
include <iostream>
int main() {
using namespace std;
// string city1[] = "toronto"; // Compiler Error - Do Next Line Instead
string city1[] = { "toronto" };
cout << city1[0];
return 0;
}
Any time you want to initialize an array of any type during declaration you need to use = { }; To set each array's element separated by commas. Look at this code sample:
#include <string>
#include <iostream>
int main() {
using namespace std;
string cities[] = { "New York", "Philadelphia", "Chicago", "Boston" };
// Same As Above Except Size Of Array Is Defined First Then The Elements
string cities[4];
cities[0] = "New York";
cities[1] = "Philadelphia";
cities[2] = "Chicago";
cities[3] = "Boston";
unsigned index = 0;
for ( ; index < 4; index++ ) {
cout << cities[index] << endl;
}
return 0;
}
If you are not initializing the array when declaring it then you must specify the array's size.
int main() {
int iArray[]; // Compiler Error
int iArray[] = { 4, 3, 2, 1, 6 }; // Okay and is the same as
int iArray[5]; // Okay
iArray[0] = 4;
iArray[1] = 3;
iArray[2] = 2;
iArray[3] = 1;
iArray[4] = 6;
return 0;
}
If you are not using the bracket operator with an index value to send to the console output stream std::cout then the hex value you are getting is correct as
T.C had already stated; it is returning the address of the first index. This is why in c / c++ arrays and pointers are similar (they are not the same, but behave almost like one another). The main difference with arrays is that they are constant in size, the size has to be known at compile time, and can not be dynamically changed in size without having to store the contents into a temp variable while creating a new array with a larger size then copying all the data into the new array and then cleaning up the old array. With pointers they do not behave this way, pointers can be dynamically allocated on the heap using new, but also must be deleted when that variable has no more use to prevent memory leaks, if the pointer is delete before hand and something tries to access it that memory address is no longer valid and doesn't belong to the caller, these are normally seen as unhandled exceptions, heap corruption, etc. and will crash your program. The same goes for arrays when you try to index them past their bounds.
#include <iostream>
int main() {
// Arrays Are 0 Indexed
int iArray[3] = { 1, 2, 3 };
// If you try to do this to access the last element
std::cout << iArray[3] << std::endl; // Program Will Crash
// Since Arrays Are 0 Indexed And The Size Of The Array Is 3
// The 3rd Value Is Indexed At 2, And By Trying To Index Location Of Array
// At 3, This Memory Doesn't Belong To You, And It Is Undefined Behavior.
// This Memory Could Contain Nothing, Random Data, Or Even Data That Belongs To
// Something Else Which If Changed Can Even Cause System Failure
return 0;
}