I am creating int array using c++ and trying to get the length of it
int *masterArray;
int count = 0;
int a = 0;
int var = 0;
ifstream myfile("sample_10.txt");
if (myfile.is_open())
{
while(myfile.good())
{
string word;
while(getline(myfile, word))
{
count++;
}
cout << "count: " << count << endl;
masterArray = new int [count];
myfile.clear();
myfile.seekg(0);
while(getline(myfile, word, '\n'))
{
cout << word << " ";
istringstream ( word ) >> var;
masterArray[a] = var;
a ++;
}
}
}
name of the int array is master array, and after I add variables in the array
I do..
cout << "sizeof(masterArray) : " <<sizeof(masterArray);
which gives me 8, instead of 10.
I tried to print out all variables stored in the array and it gives me 10, which means all variables are stored correctly.
should I retrieve the length by doing
cout << "sizeof(masterArray) : " <<sizeof(masterArray) / sizeof(*masterArray);
??
Because that gives me 2 (obviously, cuz it is dividing 8 by 4)
Thanks
Your masterArray variable is of pointer type. I suppose you are on a 64bit machine, so the pointers are 8 bytes. That's why it gives you 8 when you do a sizeof().
There is no standard way of getting the size of an array, at least not that I know of. You have a count that you get from the user and allocate the array with. I guess it would be best to keep that and use it.
I would suggest to use std::vector in your case. Note, that in C++ it is a common practice to use vectors for any array-like objects. You should have very strong arguments if you want to manage dynamically allocated arrays by yourself.
You already got the length - it's count. It's the only way of knowing a length of dynamically allocated array, by manually keeping track of it. As others have pointed out, you only get a pointer to the first element if you allocate an array via new. sizeof(masterArray) will return the size of this pointer and it happens to be 8 bytes on your platform.
Im guessing you are using 64 bit computer? sizeof returns the size of the variable it given in this case a pointer in other words a memory address which in 64 bit computer is equal to 8 bytes. In order to find the length of the array in c you need to use another variable with the size of the array stored in it.
This
sizeof(masterArray);
gives you the size of an int*, which is 8 on your platform (or 64 bits, assuming an 8 bit char).
Looking at your code, it seems to me that you could use std::vector instead of the array, and add elements using the std::vector::push_back method. If you actually needed the length, you could get it from the size() method, but what you normally do with a vector is to iterate over its contents using it's begin and end iterators (see methods begin() and end() respectively).
Using sizeof to get the number of elements in an array will only work for variables that are declared as arrays. E.g. int masterArray[10];.
Your array is declared as an int * - later allocated dynamically - so you're getting the size of that type.
sizeof() only works on arrays. You're getting 8 because a pointer is 8 bytes (on a 64 bit system). You cannot determine the length of a dynamically allocated array. This means that you need to keep track of the length, rather than re-determining it.
By the way, this looks like a very good situation to use a vector.
Here's your example rewritten to using std::vector
std::vector<int> masterArray;
int var = 0;
ifstream myfile("sample_10.txt");
if (myfile.is_open())
{
while(myfile.good())
{
string word;
while(getline(myfile, word))
{
count++;
}
cout << "count: " << count << endl;
masterArray.reserve(count); // will allocate at least count ints
myfile.clear();
myfile.seekg(0);
while(getline(myfile, word, '\n'))
{
cout << word << " ";
istringstream ( word ) >> var;
masterArray.push_back(var); // store the current word
}
}
}
Related
I have commented out the problematic string, attempted to pass the input to a string that is not a member of the struct, then passing it to the correct string, to no avail. To achieve the intended function, the string must go through this struct. Where is it going wrong?
Structure code:
#include <iostream>
#include <string>
#include <fstream>
#include <iomanip>
using namespace std;
class passingdata
{
public:
passingdata()
{
//constructor
};
~passingdata()
{
//destructor
};
int convertedResponse;
const string headers[4] = {"Labor/Materials", "Cost (per unit)", "Total Units", "Total Cost"}; //this is all to be written to a file later.
struct dynInputs
{
string name;
int perCost;
int unitTotal;
int totalCost = perCost * unitTotal;
};
void acceptInputs()
{
string name = "";
string response = "";
const string positiveResponse = "yes";
cout << "Would you like to insert a label?" << endl;
getline(cin, response);
if (response == positiveResponse)
{
populateSaveData();
}
else
{
//nothing yet
}
}
void populateSaveData()
{
if (convertedResponse = 1)
{
cout << "How many labels would you like to create?" << endl;
int labelCount;
cin >> labelCount;
cin.clear();
int labelsNeeded = labelCount;
dynInputs* dynamicInputs;
dynamicInputs = new dynInputs[labelsNeeded];
while (labelsNeeded > 0)
{
cout << "please type the name for this row" << endl;
cin.ignore();
//string tempName = "";
//getline(cin, tempName); this works!
getline(cin, dynamicInputs[labelsNeeded].name); //this breaks, goes to trash memory when done this way
system("pause");
cin.clear();
//tempName = dynamicInputs[labelsNeeded].name; breaks as well
cout << dynamicInputs[labelsNeeded].name << endl;
//cout << tempName << endl;
system("pause");
cout << "please type the cost of the unit, and the number of units" << endl;
cin >> dynamicInputs[labelsNeeded].perCost;
cin.clear();
cin >> dynamicInputs[labelsNeeded].unitTotal;
cin.clear();
labelsNeeded--;
}
cout << dynamicInputs[0].unitTotal << endl;
The dynamicInputs[labelsNeeded] array points to junk memory, yet I'm unsure of why it only crashes assigning value to the string.
In labelsNeeded you store the size of the array.
Then in the first iteration you use labelsNeeded to index into your array. Since C++ indexes an array starting from 0, the largest possible valid index is (the size of the array) - 1.
Eg.: For an array of size 4, your valid index range is [0, 1, 2, 3].
Now what you are doing is setting labelsNeeded to equal labelCount and then allocate an array of the size equalig labelsNeeded. And then in the first iteration you use the value of labelsNeeded as an index with this original value for accessing an element in your array. Which goes past the valid range of your array. Hence the program crashes.
I see that at the and of the iteration you decrement labelsNeeded but that is too late considering that you already tried to use the original value earlier in the code.
Your labelsNeeded > 0 condition for your while loop is also incorrect if you are using this "decrement the index at the end of the iteration" solution since it will fail to write the first (at index 0) element of your array.
Try moving the labelsNeeded-- line to the beginning of the iteration.
Note:
As to "why it only crashes assigning value to the string".
C++ (or rather the runtime) does not care whether your pointer points to a valid address or not. Simply because a pointer is just a memory address. By it self it is just a number stored in memory. A pointer that references invalid memory will only crash your program (or do other weird stuff) if you want to dereference it or in other words -> If you want to actually use the pointer to access that place in memory. It is not the "invalid" memory address in the pointer that crashes but the act of trying to access the memory at that address. The distinction may look subtle but is very important nonetheless. You can have any number of "null pointers" in the program as long as you don't try to dereference null.
Note 2:
Yours is an especially interesting mode of failure since it can fail in one of two places:
Since you are indexing an element that is one past the end of the array, that may as well coincide with the end of the heap that was assigned to the program. So it may crash there. But... Most likely your array is not allocated in such a place and there will still be accessible heap past the end of your array so dereferencing one element past your array may as well give you "something" and by something I mean some memory content cast to the type that you have. But of course from your point of view that is some random data.
If execution survived the previous section and now you have a struct with random data, you also have your string in your struct that is also filled with random garbage. Which means its pointer to the actual string content is also random (most likely pointing somewhere before or past your addressable space) as well as its size and other state information also being garbage. So if you reassign that string then its original content pointer will likely be accessed (eg.: deallocation) which will result in a crash.
I want to cout my string, everything works as it should, but when the string is shown, it immediately shows me the "example_4578.exe has stopped running" error. I have noticed that the problem is in the i < str[32].length part, because when I change it to i < 3, it works without any problem. How should I solve this?
std::string str[32];
cin >> str[1];
cout << "str[1]=" << str[1] << endl;
cin >> str[2];
cout << "str[2]=" << str[2] << endl;
for (int i = 0; i < str[32].length; i++)
{
cout << str[i];
}
EDIT 1.
I've made a huge mistake. I actually want to find the "number" of elements/words in "str". In my example, I have only designed two cins. But I actually want to design a "for" loop later on, so that the user can input as many words as he wants, so if he inputs 4 words, I want that code to return those number of words to me. How should I do this? In other words, how can I find out how many elements are in "str"?
Couple of things:
C++ is 0-indexed. What this means is that std::string str[32] has indices that go from 0 to 31, and str[32] should not be accessed. This will cause a crash.
str[31].length() (which is presumably what you wanted) is the length of the last string, not the length of the array. The length of the array is 32, and your loop should read for(int i = 0; i < 32; i++).
The main problem is that you are accessing an element (number 32) that is out of the bounds (0 - 31). To solve this problem and not repeat it again in the future use a range-for loop:
std::string str[32];
for (auto s : str)
std::cout << s;
str[32].length is not what you think.
I guess you meant somthing like: length of a 32-elements array. Right?
What you've written is pointer to funciton length of 33rd element of array.
This is because the types are:
std::string str[32]; // `str` is 32-element array of `std::strings`
str[32]; // `std::string` taken from 33rd position in array `str` (arrays' indexing starts at 0)
std::string has a member function named size_t std::string::length(). When referenced by name, you get its address.
To achieve what you wanted, you'd need to write:
for (int i = 0; i < 32; i++) {
cout << str[i];
}
Unfortunately, plain arrays don't have length (or anything similar) built in. So, you'd either need to use a constant, or (better) use a container, such as std::vector.
I have the below piece of code and I'm very confused by it. I'm trying to figure out how much memory (bytes of memory/space is actually being taken up by my partially filled array). I've got the below piece of code but I'm a bit confused.
If I declare a string array of 8 elements, and partially fill the elements with the two strings. The for loop will start at 0 and go until size of my array 32 possible bytes (assuming I need 4 bytes per string) divided by size of the first element in the array. That is returns 4 - the size of the element of the first string in the array. But that still doesn't tell me how many letters/characters are in that string.
I understand inside the loop we increment count when the value in the array doesn't equal a blank/null value. Giving us the total filled (non empty) positions in our array. However I still don't have a value for our actual amount of characters.
How does this tell us how many characters are in my strings?
#include <iostream>
#include <string>
using namespace std;
int main()
{
string test_array[8] = {"henry", "henry2"};
size_t count = 0;
for (size_t i = 0; i < sizeof(test_array)/sizeof(*test_array); i++)
{
cout << "NOT THE POINTER: "<<sizeof(test_array) << endl;
cout << "POINTER: "<<sizeof(*test_array) << endl;
if(test_array[i] != "")
count ++;
}
int num_elem = sizeof(test_array)/sizeof(test_array[0]);
cout << num_elem << endl;
cout << count << endl;
return 0;
}
To know how many characters are in a std::string use the size() method.
I am creating a dynamic array inside a function. The code (posted below) runs without any problem. I am wondering if the way I have written is the right way to do it or if it will create problems in more complicated codes in the future. I am aware that the specific task my program (below) is trying to achieve is better effected with strings or vectors. But I created this artificial example to get my question across. however, if you strongly feel that dynamic arrays should be avoided, please feel free to share your opinion and the reasoning for it.
Result of my prior research: I was unable to find a coherent discussion on legality and morality of creating dynamic arrays using new [] and later deleting them in a different scope.
Thanks for your thoughts and insights.
My example code follows:
==========================
#include<iostream>
#include<string>
#include<cctype>
using namespace std;
void getNonPunct(string _str, char* &_npcarr, int &_npsize);
int main()
{
string input_string;
char* npchar_arr;
int npsize;
cout << "Enter any string: ";
getline(cin, input_string);
getNonPunct(input_string, npchar_arr, npsize);
// Now display non-punctuation characters in the string
cout << "string with non-punctuation characters removed:\n";
for (int n = 0; n <= npsize - 1; n++)
cout << npchar_arr[n];
cout << "\n(" << npsize << ") non-punctuation characters\n";
// Now return the memory allocated with 'new' to heap
delete [] npchar_arr;
// Is it okay to 'delete' npchar_arr eve if it was created in the function
// getNonPunct() ?
return(0);
}
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void getNonPunct(string _str, char* &_npcarr, int &_npsize)
//This void function takes an input array of strings containing arbitrary
//characters and returns a pointer to an array of characters containing only
//the non-punctuation characters in the input string. The number of
//non-punctuation characters are stored in size. Prior to the function call,
//int_arr and size are undefined. After the function call, char_arr points to
//the first location of an array of the non-punctuation character array.
//'size' is equal to the number of non-punctuation characters in the input
//string.
{
// First get the number of non-punctuation characters in the string
int str_len, npcount = 0;
str_len = static_cast<int>( _str.length() );
_npsize = 0;
for (int i = 0; i <= str_len - 1; i++)
{
if ( !ispunct(_str[i]) )
_npsize++;
}
// Now that you know how many non-punctuation characters are in the string,
// create a (dynamic) character array of _npsize.
_npcarr = new char [_npsize];
for (int k = 0; k <= str_len - 1; k++)
{
if ( !ispunct(_str[k]) )
_npcarr[npcount++] = _str[k];
}
return;
}
Is it valid? Yes. The array pointed to by npchar_arr exists until you destroy it and it is okay to destroy it using a delete[] expression in another function.
Is it a good idea? No. You would be much better off using a smart pointer that manages the lifetime of the object automatically, releasing you from the responsibility of delete[]ing the pointer manually yourself.
Consider using a std::unique_ptr<char[]> if your compiler and Standard Library support unique_ptr, or std::auto_ptr or std::shared_ptr if you cannot use unique_ptr (shared_ptr may also be found in Boost and C++ TR1).
Allocating in one scope and deleting in another is one of the major reasons for using dynamic allocation instead of an automatic local variable.
As James says, prefer to use smart pointers to track dynamically allocated objects.
The only constraint I can think of on allocation in one scope and deallocation in another is multi-component applications where different components are built with different compilers (or maybe different versions of the same compiler). On Windows, each compiler provides its own memory management library, and you shouldn't free memory from a different component than the one that allocated it. Or you can use Windows-provided memory management routines which are common to all compilers (e.g. HeapAlloc/HeapFree). On Linux, everyone uses the glibc-supplied malloc, free, new[], and delete[], so it isn't such an issue. For other OSes, you need to investigate.
This example is very trivial, but image the following modification of your code:
int main()
{
string input_string;
char* npchar_arr;
int npsize;
cout << "Enter any string: ";
getline(cin, input_string);
getNonPunct(input_string, npchar_arr, npsize);
// Now display non-punctuation characters in the string
cout << "string with non-punctuation characters removed:\n";
for (int n = 0; n <= npsize - 1; n++)
cout << npchar_arr[n];
cout << "\n(" << npsize << ") non-punctuation characters\n";
return(0); // WHOOPS! I JUST RETURNED AND DIDN'T FREE THE MEMORY
delete [] npchar_arr;
// Is it okay to 'delete' npchar_arr eve if it was created in the function
// getNonPunct() ?
return(0);
}
I just returned before freeing the memory, which results in a memory leak! Of course, you might be thinking that you would never do such a thing, but imagine a much more complex program, it is easy to make such a mistake as the above, and using smart pointers as the other answers suggest, would alleviate you of having to worry about such tasks.
#include<iostream>
using namespace std;
int main()
{
char arr[200];
while(1) {
cin >> arr;
int i = sizeof(arr);
cout << "The arr input is "<< arr
<< " and the size of the array is "<< i << endl;
}
return 0;
}
For the input of 34,
This code outputs :The arr input is 34 and the size of the array is 200
while I want it to get the size of the used space of the array . So for The last input i want it to output :The arr input is 34 and the size of the array is 2
Can someone tell me how?
Maybe you want strlen(arr) here. It must be null terminated, otherwise the cout << arr would not have worked.
You would need to #include <cstring>
There's no automatic way to do what you want in the general case - you'll need to keep track somehow, either with your own counter, or by seeding the array with an 'invalid' value (that you define) and search for to find the end of the used elements (that's what the '\0' terminator character in a C-style string is).
In the example code you posted, the array should receive a null terminated C-style string, you can use that knowledge to count the number of valid elements.
If you're using C++ or some other library that has some more advanced data structures, you may be able to use one that keeps track of this kind of thing for you (like std::vector<>).
the size of the used space of the array
There is no such thing. If you have an array of 200 chars, then you have 200 chars. Arrays have no concept of "used" and "unused" space. It only works with C-strings because of the convention that those are terminated by a 0 character. But then again, the array itself cannot know if it is holding a C-string.
in a less involved manner, you can just count through each character till you hit a null with just a while loop. It will do the exact same thing strlen() does. Also, in practice, you should do type checking with cin, but i'll assume this was just a test.
#include <iostream>
using namespace std;
int main()
{
char arr[200];
int i;
while(1) {
cin >> arr;
i=0;
while (arr[i] != '\0' && i<sizeof(arr))
i++;
cout << "The arr input is "<< arr
<< " and the size of the array is "<< i << endl;
}
return 0;
}
Just for completeness, here is a much more C++ like solution that is using std::string instead of a raw char array.
#include <iostream>
#include <string>
int
main()
{
while (std::cin.good()) {
std::string s;
if (std::cin >> s) {
std::cout
<< "The input is " << s
<< " and the size is " << s.length()
<< std::endl;
}
}
return 0;
}
It doesn't use an array, but it is the preferable solution for this kind of problem. In general, you should try to replace raw arrays with std::string and std::vector as appropriate, raw pointers with shared_ptr (scoped_ptr, or shared_array, whatever is most appropriate), and snprintf with std::stringstream. This is the first step to simply writing better C++. You will thank yourself in the future. I wish that I had followed this advice a few years ago.
Try it
template < typename T, unsigned N >
unsigned sizeOfArray( T const (&array)[ N ] )
{
return N;
}