C++ getting the size of an array of strings - c++

I need to use an array of strings with an unknown size. Here I have an example to see if all works fine. I need to know that array's size in ClassC but without passing that value as an argument. I've see so many ways to do it (here and in google) but as you will see now, they didn't work. They return the number of chars in the first position of the array.
void ClassB::SetValue()
{
std::string *str;
str = new std::string[2]; // I set 2 to do this example, lately it will be a value from another place
str[0] ="hello" ;
str[1] = "how are you";
var->setStr(str);
}
Now, in ClassC if I debug, strdesc[0] ="hello" and strdesc[1] = "how are you", so I suppose that class C is getting the info ok....
void classC::setStr(const std::string strdesc[])
{
int a = strdesc->size(); // Returns 5
int c = sizeof(strdesc)/sizeof(strdesc[0]); // Returns 1 because each sizeof returns 5
int b=strdesc[0].size(); // returns 5
std::wstring *descriptions = new std::wstring[?];
}
So.. in classC, how can I know strdesc's array size, that should return 2?? I have also tried with:
int i = 0;
while(!strdesc[i].empty()) ++i;
but after i=2 the program crashes with a segmentation fault.
Thanks,
Edit with the possibles SOLUTIONS:
Conclusion: There is no way to know the array's size once I pass its pointer to another function
Pass the size to that function... or...
Use vectors with std::vector class.

how can I know strdesc's array size
You cannot know the size of an array from a pointer to that array.
What you can do is pass the size as another parameter. Or even better, use a vector instead.
but after i=2 the program crashes with a segmentation fault.
Accessing beyond the array boundary has undefined behaviour.

With this Kind of code you will get memory leaks and other kind of C-style problems.
use vector:
#include <vector>
#include <string>
#include <iostream>
...
std::vector<std::string> my_strings;
my_strings.push_back("Hello");
my_strings.push_back("World");
std::cout << "I got "<< my_strings.size() << " strings." << std::endl;
for (auto& c : my_strings)
std::cout << c << std::endl;

Related

C++ median finder program works on 50% of random number sequences, can someone tell me why? [duplicate]

So my C++ instructor told us in class that there was no function to determine an array size in C++ and I was not satisfied with that. I found a question here on stackoverflow that gave this bit of code (sizeof(array)/sizeof(*array)) and while I don't exactly understand it, I understand it takes the total amount of memory allocated to the array and divides it by what I assume is the default memory allocation of its data type...(???)
I decided I wanted to practice writing functions (I'm in CS 111 - Fundamentals 1) and write a function that returned the number of elements in any array I passed it. This is what I wrote:
#include <iostream>
using namespace std;
int length_of_array(int some_list[])
{
// This only returns the integer 1 for some reason
return (sizeof(some_list)/sizeof(*some_list));
}
int main()
{
// Declare and initialize an array with 15 elements
int num_list[] = {2,4,6,8,10,12,14,16,18,20,22,24,26,28,30};
//Outputs what I assume is the total size in bytes of the array
cout << sizeof(num_list) << endl;
//Outputs what I assume to be size of memory set aside for each in element in an array
cout << sizeof(*num_list) << endl;
//This extrapolates array's number of elements
cout << "This is the output from direct coding in the\nint main function:\n" <<
(sizeof(num_list)/sizeof(*num_list)) << endl;
//This function should return the value 15 but does not
int length = length_of_array(num_list);
cout << "This is the length of the array determined\n";
cout << "by the length_of_array function:\n" << length << endl;
return 0;
}
The function returns 1 no matter what I do. Would somebody please give me a C++ specific workaround and explanation of how it works?
Thank you.
The problem is here:
int length_of_array(int some_list[]);
Basically, whenever you pass an array as the argument of a function, no matter if you pass it like int arr[] or int arr[42], the array decays to a pointer (with ONE EXCEPTION, see below), so the signature above is equivalent to
int length_of_array(int* some_list);
So of course when doing sizeof(some_list)/sizeof(*some_list) you will get the ratio between the size of the pointer the array decayed to and the size of the type representing the first element. In your case, 1, as it looks like on your machine the size of a pointer is probably 4 bytes (32 bits), same as the size of an int.
So my C++ instructor told us in class that there was no function to determine an array size in C++ and I was not satisfied with that.
YOUR TEACHER IS WRONG! There is a way of passing an array by reference and getting its size:
template<size_t N>
int length_of_array(int (&arr)[N])
{
std::cout << N << std::endl; // WORKS!
return N;
}

Use the new operator to allocate an array of integers using the parameter as the size of the array within a function

I've been stuck on this problem and I'm hoping someone can explain where I'm wrong on this. I'm working on an assignment where I need to:
1) Allocate an array that can contain 100 int values by calling allocIntArray and assign the returned pointer to ptr1.
2) Use the new operator to allocate an array of integers using the parameter as the size of the array.
3) Return the pointer that is returned by the new operator.
4) Print out the new array.
I'm trying to print out the array after passing the size I want through the function.
int main() {
int *ptr = NULL;
ptr1 = *allocIntArray(100);
cout << ptr1 << endl;
return 0;
}
//The function I want to call
int *allocIntArray(int size) {
int *newarr = nullptr;
newarr = new int[size];
return newarr;
}
However when I call the function, the output comes out as 00F011E8.
I'm currently trying to understand why this is the output and not the first value in the array. (Just the number 1)
I've been having a lot of trouble grasping pointers any help understanding would be greatly appreciated.
Thanks to everyone who took the time to respond.
From what I understand from assignment directions, I shouldn't need to use vectors. I'm trying to modify my current code to display the array output and this is what currently comes up when I run it.[enter image description hereMy current results
At first, if you're using C++, you should use std::vector/std::array. This avoids a huge amount of possible problems.
It would look like:
#include <iostream>
#include <vector>
int main()
{
// create array of size 10 and initialize it with 0's
std::vector<int> vec(10, 0);
// print array
for(auto a : vec)
std::cout << a << '\t';
std::cout << std::endl;
}
If it's some kind of exercise, you have done four big mistakes:
you dereference the returned pointer to the array. So you get the value of the first element in the array and not the array itself. Simply remove the *.
you print out the address of the first element of the array. To print the array, you have to iterate over each element of the array. This can be done in a for loop:
for(int i = 0; i < 10; ++i)
std::cout << ptr1[i] << '\t';
you want to print out the array uninitialized. In fact, you try to print out some random values which are there in the memory. At first, you have to assign the elements values.
you forget to delete the array by using
delete[] ptr1;
I just have to answer as you seem to be missing some important fundamentals. Either the instructor should be dismissed or you have not paid enough attention in the class. So...
ptr1 = *allocIntArray(100);
You could not have pasted code that compiles, ptr1 is not declared.
You need to understand what the * operator does. What ever value to the right of * must be a pointer. What a pointer is should be fundamental in your understanding. If you had:
int* ptr1 = *allocIntArray(100);
You should have gotten a compiler error, so you must have:
int ptr1;
Somewhere along the line. As allocIntArray(...) returns a pointer, then *allocIntArray(...) gives you an integer.
You would have wanted to:
int* ptr1 = allocIntArray(100);
To get a pointer to the new array. Then you:
std::cout << ptr1 << std::endl;
So, what is ptr1? If it is a pointer then all you are doing is printing the pointer value. Per your stated problem, I'd say ptr1 is in fact a pointer. std::cout has not facility to work with a pointer as you expect. At that, it would have no way of determining the size of your array.
You would want to (And it hurts my fingers to write like this):
for(size_t i= 0; i < 100; ++i)
std::cout << ptr1[i] <<" ";
But!!!
4) Print out the new array.
So what will it print? There was never an instruction to initialize the array. It will print out what ever garbage is sitting in the array when it was created.
Side note, that the instructor has you doing a:
using namespace std;
Says much, as he/she should never have allowed it.

C++ array as parameter reference by default?

forgive me for asking such a simple question, but I couldn't connect the dots from previous answers on SO or other sites. I have read that arrays are passed by reference by default and elsewhere I have read that arrays decay to pointers when passed into functions. I am trying to pass an array to a function and modify it, but cannot reconcile the previous two statements. I am not sure whether I am passing in a pointer or reference to toBin and whether it even matters. The following code is my attempt at making changes to the b array in the toBin function.
When I print the modified array, I get a whole bunch of unexpected text much bigger than the original allocated array of size 11 eg 1000000000 submarine blahblahblah. My expected output is 1000000000.
void toBin(int x,char a[]){ //passed by reference by default
std::cout << a << std::endl;
for (int i=9;i>=0;i--){
if(pow(2,i)<=x){
x=x-pow(2,i);
a[9-i]='1'; //i-1 because char b[] is zero indexed
};
}
}
int main()
{
char c[]="submarine";
double combination = pow(2,sizeof(c)-1);
char b[11]={'0','0','0','0','0','0','0','0','0','0'};
toBin(512, b);
for (int i=0;i<combination;i++){
std::cout << *(b+i) << std::endl;
}
}
Basically you pass everything to the function well. Thing that broke your output it's loop itself.
double combination = pow(2,sizeof(c)-1);
...
for (int i=0;i<combination;i++){
std::cout << *(b+i) << std::endl;
}
Your combination variable can have value like 2^8. So you point by*(b+i) to the address going far beyond the allocated array. To repair it you need change your loop to that:
for (int i=0;i< sizeof(b);i++){

Program "has stopped working" while working with an array of pointers

I'm trying to make an array of strings, and connect them with a linked list. The problem is we can only use arrays. The instructor said we can't use templates, vectors etc. Those are the only ways I've found to be able to do this. I don't think this is even a linked list, he wants our arrays to be handled in the parallel instead of pointing to the next element in line.
#include <iostream>
#include <string>
using namespace std;
int main ()
{
string names [4] = {"Dick", "Harry", "Sam", "Tom"};
string *nameptr[4];
for(int x = 0; x < 4; x++)
{
*nameptr[x] = names[x];
cout << nameptr[x] << " ";
cout << &nameptr[x] << endl;
}
}
What's wrong with this code? What am I missing?
I'm lost, if anyone could shed some light on this it would be great.
Your question isnt' clear but to make your code run.
Try update
*nameptr[x] = names[x];
to
nameptr[x] = &names[x];
string names[4] = {"Dick", "Harry", "Sam", "Tom"}; is an array of std::string objects. string *nameptr[4]; is an array of pointers to std::string objects.
To initialize pointer, you need to assign the address it will point to to it: nameptr[x] = &names[x];
Dereference operator (*) is used when you want to access the memory where your pointer points to. For example printing the string that nameptr[x] points to: std::cout << *nameptr[x];
Explanation of why your program "has stopped working": You've declared string *nameptr[4];, i.e. the array of pointers, but you didn't initialize it. Then in your loop you were trying to do *nameptr[x] = names[x];, which means "take the names[x] object and replace the object that nameptr[x] points to with it". You were dereferencing pointer that has not yet been initialized, which leads to undefined behaviour

C++: Trouble with Pointers, loop variables, and structs

Consider the following example:
#include <iostream>
#include <sstream>
#include <vector>
#include <wchar.h>
#include <stdlib.h>
using namespace std;
struct odp {
int f;
wchar_t* pstr;
};
int main()
{
vector<odp> vec;
ostringstream ss;
wchar_t base[5];
wcscpy_s(base, L"1234");
for (int i = 0; i < 4; i++)
{
odp foo;
foo.f = i;
wchar_t loopStr[1];
foo.pstr = loopStr; // wchar_t* = wchar_t ? Why does this work?
foo.pstr[0] = base[i];
vec.push_back(foo);
}
for (vector<odp>::iterator iter = vec.begin(); iter != vec.end(); iter++)
{
cout << "Vec contains: " << iter->f << ", " << *(iter->pstr) << endl;
}
}
This produces:
Vec contains: 0, 52
Vec contains: 1, 52
Vec contains: 2, 52
Vec contains: 3, 52
I would hope that each time, iter->f and iter->pstr would yield a different result. Unfortunately, iter->pstr is always the same.
My suspicion is that each time through the loop, a new loopStr is created. Instead of copying it into the struct, I'm only copying a pointer. The location that the pointer writes to is getting overwritten.
How can I avoid this? Is it possible to solve this problem without allocating memory on the heap?
What you've got here is undefined behavior. Each time through your loop you create and destroy an array and then assign its address to foo.pstr and push it back into your vector. The compiler just happens to create that array in the same place every time (which is logical but not necessary). When you print it out you're technically printing out deleted data it's just that the system isn't bitch slapping you for it because it's not protected space. The memory location simply has whatever it was assigned last.
You fix this by discontinuing the use of raw character pointers and arrays.
...
odp foo;
foo.f = i;
wchar_t loopStr[1]; //A
foo.pstr = loopStr; //B
foo.pstr[0] = base[i]; //C
vec.push_back(foo);
...
A - You allocate an array (of size 1) to the stack
B - You assign foo.pstr to point to the array on the stack
C - You assign base[i] to the first element of the array (which is on the stack)
After the for loop exits its current cycle the variable loopStr is no longer in scope and its content is undefined. The next loop iteration will most likley re-use the same memory address (hence why you get the same value when you print at the end). If you have optimisations turned on your C compiler may be able to warn you about taking addresses of local variables (although I doubt it).
Without using any heap allocation I would think your only option is to fix the size of foo.pstr in odp, i.e.
struct odp {
int f;
wchar_t pstr[1];
};
or allocate the array on the heap as part of the odp initialisation
...
odp foo;
foo.f = i;
foo.pstr = new wchar_t [1];
foo.pstr[0] = base[i];
vec.push_back(foo);
...
better still use std::wstring since you are using c++, and let it do the memory allocation and management for you.
It looks like pstr is pointing to the locally scoped variable loopStr, so the results are undefined (it appears to still have the last stored value in it when printing the results). If you printed the address of pstr in the loop, I believe it would be the same for each position in the loop.
foo.pstr = loopStr; // wchar_t* = wchar_t ? Why does this work?
This doesn't work, at least not in the way you want it to. loopStr is an array, but you can use it like a pointer too. So when you assign to the pointer foo.pstr, it gets the address of the first element in loopStr. That happens to be a local variable allocated on the stack and is only valid inside the for loop.