Count strings in string array c++? - c++

How to sum number of strings in string array in which is not explicit defined how many elements it takes?
string str[] = { "astring", "bstring", "cstring", "dstring", "zstring" };
Need to find out how many elements array have?

template< typename T, size_t N >
/*constexpr*/ size_t size( T(&arr)[N]) )
{
return N;
}
constexpr if available (C++11) will allow you to use the return value for static (compile time) usage as a size of another array.

If str[] is statically defined (as shown), then this will work:
const size_t numElements = sizeof(str) / sizeof(str[0]);
If it's dynamically created, then you are going to need a marker to signal the last element (0 is being typically used if it's an array of pointers). Either that or the caller tells you how many elements there are (also common).

In addition to the methods already listed in other answers, another way to do this might be to add a guard value to the end of the array, such as an empty string. You can then iterate through the array until you hit the guard value.
Personally, I'd probably use C++11 and
std::vector<std::string> la = { "foo", "bar", "baz" };
so you can just query la.size() to get what you wanted... at runtime, anyway. Unfortunately, i don't see a way to use this trick with std::array, so it isn't a perfect alternative.

one way using pointers to count the elements of the array:
#include <iostream>
using namespace std;
int main() {
string str[] = { "astring", "bstring", "cstring", "dstring", "zstring" };
cout << ((&str)[1] - str); // 5
cout << endl;
return 0;
}
output:
5

I usually use a separate variable for tracking array size.
String str[] = { "astring", "bstring", "cstring", "dstring", "zstring" };
int strNum = 5;
And then if I need to reference any of the strings, I can just call it as such:
String foo = str[strNum-1];
And any time I update the array in a loop, i simply use strNum as the index to start writing new strings to, and then place a strNum++ within the loop immediately after each new string.

Related

Efficient way of creating an array/vector of strings and finding out the length of all strings in it

I want to create a function in which I can iterate over an array/vector containing a variable amount of strings, and I need to know the length of the strings before I send them to the function. How can I achieve this in an efficient way?
I have some loose idea of the function, but how do I efficiently sent an array/vector of strings to it and the size of all those strings combined. For example, the function could look something like this:
myFunc(vector<string> s, int totalWordLength) {
// Loop over strings in vector.
}
I could do something like this to create a vector of strings.
const char *args[] = {"12345", "678"};
vector<string> s(args, end(args));
But how do I then find out the size of the strings (8) in this without looping through it so that I can send it to myFunc(s, sizeOfStrings)?
If you have an idea to achieve the same result, by using an array instead or something, please let me know. I'm trying to do this as efficient as possible.
Iterate through container (container class irrelevant)
const char *args[] = {"12345", "678"};
vector<string> s(args, end(args));
size_t sizOfS = 0;
for( auto& item : s )
sizOfS += item.length();
Another way unites process of filling array and calculating length:
const char *args[] = {"12345", "678"};
std::vector<std::string> s;
s.reserve(sizeof(args)/sizeof(args[0]));
size_t sizOfS = 0;
for( const std::string& item : args )
{
sizOfS += item.length();
s.push_back(item);
}
Regardless of what you do, cost of the process would be O(n), where n = strings * their-total-length. There is no other defined way, but several functions which can turn loop into one-liner. Even if define your own container that would track length of strings, its cost would have same order.
Which container to use depends on what kind of actions you expect to perform, vector got constant cost of random access to container items, but linearly increasing cost of growing its storage. list may have cheap insertion\push cost but it got sequential iterator.
If you want to know the lengths of all of the strings in the vector and query it often (its not a one-off thing) then you can calculate the length of the strings when they are added together and store the total with the vector.
A quick example of this with a class:
class MyClassFoo {
public:
std::vector<std::string> items;
std::size_t total_item_sizes = 0;
void addItem(const std::string& item) {
total_item_sizes += item.length(); // Add its length to the total
items.emplace_back(item); // Add the item to the vector
}
}
Then you can pass this object around and query it.
If you want to be more efficent pass by reference or move single use parameters. This is important with something like a std::vector as you probably don't want to copy all it's elements.
As an aside it is unlikely this is actually neccasary, unless you are trying to sum the lengths of all the strings very frequently and there are a lot of them, your bottleneck will not be iterating over an std::vector. Your demand for 'efficency' smells like premature optimisation. Remember the 20-80 rule (80% of your program execution time is spent running 20% of your code).
Given your scenario, an approach could be to calculate the length of the strings at the time of construction of the vector.
One solution using a variadic template could be a wrapper like this (live):
#include <iostream>
#include <vector>
#include <string>
struct V
{
template <typename ... T>
V( T&& ... t ) : v{ std::forward<T>(t)... }
{
for ( const auto& s : v ) size += s.size();
}
std::vector<std::string> v;
std::size_t size {0};
};
int main()
{
const char *args[] = { "12345678", "6789", "1234", "5678" };
V obj ( std::begin(args), std::end(args) );
std::cout << "No. of Strings : " << obj.v.size() << '\n';
std::cout << "Total Length : " << obj.size << '\n';
return 0;
}
Output:
No. of Strings : 4
Total Length : 20

How to get the length of a class array in C++, without hardcoding?

I have a class array in C++. I have defined it as such:
Student* pliststudent = new Student[2]{ 3,5 };
I know that the class array decays into a pointer when we assign it to Student* pliststudent.
It becomes difficult to extract the length of the class array, without hardcoding it.
I implemented the code, such that it is not hardcoded (using friend function). But I think, a better solution must exist.
Following is my full code:
class Student
{
private:
int marks;
int counter=0;
public:
Student(int marks) : marks(marks)
{}
int FinalMarks()
{
marks *=2;
return marks;
}
friend int Length(Student ob1, Student ob2);
};
int Length(Student ob1, Student ob2)
{
int i = ++ob1.counter + ++ob2.counter;
return i;
}
int main()
{
Student* pliststudent = new Student[2]{ 3,5 };
//int length = sizeof(*pliststudent) / sizeof(pliststudent[0]); //This does not work.
int length = Length(pliststudent[0], pliststudent[1]);
for (int i = 0; i < length; i++)
{
cout << (pliststudent+i)->FinalMarks() << endl;
}
return 0;
}
Is there a better solution to this? I don't want to hardcode the size of the Student class array.
You cannot get the length of an array from a pointer to the array's first element. That information is lost when the array decays to a pointer.
You need to keep the length information somewhere, either yourself:
int length = 2;
Student* pliststudent = new Student[length]{ 3,5 };
or by using a container that tracks the length for you:
std::vector<Student> students{3, 5};
// students.size() returns the number of Student objects in the vector
Live Demo
If you must use a dynamic array, there is no way to automatically determine the size of the array. That information is "lost" when storing the array in a pointer as you have done.
There are several ways to work around this, the preferred one is the one already suggested in the comments, use std::vector<Student> instead. Vector is the standard library's dynamic array and is almost always what you want. And since it takes care of the memory management automatically, it is much simpler to work with.
However, if you must use dynamic arrays, (because this is a school assignment and you are not allowed to use std::vector), then you should store the size of the array in a separate variable, and pass that together with whatever you need to do.
const int nStudents = 2;
Student* pliststudents = new Student[nStudents]{3, 5};

Issues with instantiation of string

I'm having issues with instantiating strings and passing an array to another function. Yesterday, I had the following code and it was working fine:
string sources[8][3] = {
{"ab", "cd","ef"},
{"gh", "ij","kl"},
(...)
}
I want to pass the sources array as a parameter to another function which must have the following prototype:
size_t parse_data(char *ptr, size_t size, size_t nmemb, char *userdata){
So the variable will be userdata, that I would cast into an array of arrays of strings. I decided to use pointer, but I can't do better than that :
string** sources;
sources = new string*[8];
sources[0] = new string[3];
sources[0][0] = new string("ab");
Is there a more elegant way to do that?
Thanks
I'm not sure why you want to do it the way you are doing. But, since you list C++11, the static array can be instantiated with the following:
#include <array>
...
array<array<string, 3>, 8> sources;
Which is all on the stack, so no need to dynamically allocate strings.
Populating an entry could be done with sources[0][0] = string("foo");
You can populate everything at once using initializer_list:
array<array<string, 3>, 8> sources { "ab", "cd","ef", "gh", "ij","kl",
(...)};
You would call c_str() on the array item, when passing along a c-style string pointer to parse_data.
E.g.: sources[0][0].c_str()
Full example code:
#include <array>
#include <iostream>
using namespace std;
int main(int, char **)
{
array<array<string, 2>, 3> sources { "ab", "cd", "ef", "gh", "ij", "kl"};
for (size_t i = 0 ; i < sources.size() ; ++i) {
for (size_t j = 0 ; j < sources[0].size() ; ++j) {
std::cout << i << "," << j << ": " << sources[i][j] << std::endl;
}
}
return 0;
}
Output:
0,0: ab
0,1: cd
1,0: ef
1,1: gh
2,0: ij
2,1: kl
Taking from the previous answer by swalog, you can also do this
std::array<std::array<std::string, 3U>, 8U> strings
{{
{{"ab", "cd", "ef"}},
{{"gh", "ij", "kl"}}
}};
in order to fully mimic your original (and very neat) syntax.
Why the double braces you may ask? std::array is basically an array wrapper, so the first brace says "Initialize a std::array structure" and the second brace says "Initialize the internal array with these values". And then you have an std::array of std::arrays so you need to multiply this logic by two...
Downside to this idea is that auto-formatting IDEs don't like this very much, but unless you're making some high numbers of dimensions, you should be OK.
Edit:
In order to pass these values as char* you need to reinterpret cast a pointer to the array:
char* userData = reinterpret_cast<char*>(&strings);
and then reinterpret back to std::array<std::array<...>>*:
auto array = *reinterpret_cast<std::array<std::array<std::string, 3U>, 8U>*>(userData);
And then, obviously, if the caller returns before the data is used (e.g. calls a function in different thread to use the data), you need to allocate all the data on the heap, but I guess that'd be enough for another question thread...

Reverse a word using function call

How can input a word and reverse the output of it. I made a function to calculate the length of the word and from here I have to reverse the word depending on the length of it.
How can I do that?
#include<iostream>
using std::cout;
using std::endl;
using std::cin;
int LengthOfString( const char *); // declaring prototype for length of the string
int reverse(const char []);
int main()
{
char string1[100];
cout<<"Enter a string: ";
cin>>string1;
cout<<"Length of string is "<<LengthOfString(string1);
system("PAUSE");
return 0;
}
int LengthOfString( const char *x)
{
int index;
for(index = 0; *x!='\0';x++,index++);
return index;
}
int reverse(const char y[])
{
/* my attempted loop, its not right i know.
a[] = *index; // length of the word
for(int i=0; i<=index/2; i++)
for(j=0; j == length, j--) */
}
This wheel has already been invented, and exists in the standard library.
#include <iostream>
#include <string>
#include <algorithm>
int main()
{
std::string word;
std::cout << "Enter a word: ";
std::cin >> word;
std::reverse(word.begin(), word.end());
std::cout << "Reverse: " << word << std::endl;
return 0;
}
To understand exactly what's going on here, there are a few things that you must cover first:
data structures (classes)
containers
iterators
I hope you already know what a class is. In case you're still in introductory stuff, a class is basically a user defined collection of state and behavior. The author can choose to restrict access to the state or behavior of a class for a variety of reasons. In the case of std::string, the standard library string class, all of the state is hidden and only behavior is accessible.
The string class is a container that contains characters. There are numerous other container classes, each of which with different strengths and weaknesses. The string class contains a sequence of characters with a strict order. Other containers exist, such as std::set, std::vector, std::list, and others. std::string bears a passing resemblance to std::vector, and is a distant cousin of std::list. Each collection behaves differently and is suited for different things.
You might think you need to understand how the string class stores its data in order to reverse it, but you don't. This is where iterators come in. std::string owns a typedef, std::string::iterator, which is a special object which stores the location of a single element in a string. std::reverse is a library function which takes 2 iterators and repeatedly swaps their contents and moves them towards each other. This looks like this as it's happening:
v v <-- positions of iterators (start at the start, end at the end)
ABC <-- initial state
v v <-- the end iterator moved back
ABC
v v
CBA <-- the iterators swapped their values
vv <-- the begin iterator moved forward
CBA
V <-- the end iterator moved back; both iterators are in the same place
CBA <-- therefore, we're done, the string is reversed
One thing about iterators is they're kind of like pointers. In fact, you can pass pointers to some functions that expect iterators because they behave syntactically the same. Therefore, you should be able to write your own reverse function that uses pointers that basically does the same thing this did, except with char *s.
Here's some pseudocode that you should be able to write the function with (I won't write it out completely because it's homework):
namespace BaidNation
{
void reverse(char *begin, char *end)
{
loop forever
{
if (end equals begin):
done;
move end backwards;
if (end equals begin):
done;
swap end's and begin's characters;
move begin forwards;
}
}
}
Keep in mind that BaidNation::reverse (as well as std::reverse) expects for end the iterator that references the element AFTER the end of the collection, not the one that references the last element. How does it then make sense to use this?
Your LengthOfString function returns the number of non-null characters in a string. Since arrays are zero-indexed, we know that, like any other array, if we check string1 + LengthOfString(string1), we'll get a pointer to the character after the end which is, for once, exactly what we want.
Thus, we can use this to reverse the string:
BaidNation::reverse(string1, string1 + LengthOfString(string1));
If you have to use exactly the signature earlier, you can adapt this design into the other one:
int reverse(const char str[])
{
char *start = str, *end = str + LengthOfString(str);
BaidNation::reverse(start, end);
}
Based on the fact that the return type of your prototype function is int, it looks to me like you want to do an in-place reversal of a string. You first need to find out how long the string is (although you computed that before, you didn't pass the result to this function), then swap elements until you get to the middle. To make this work you need to pass, not a const char[], but just a char* (indicating that you will be changing the content):
int reverse(char* y)
{
int ii, n;
n = LengthOfString(y); // "no built in functions - otherwise, use strlen()
for(ii=0; ii<n/2;ii++) {
char temp;
temp = y[ii];
y[ii] = y[n - ii - 1];
y[n - ii] = temp;
}
}
Declare a new char* of the same length, and then loop as follows -
for(int i=0;i<stringLength;i++){
newString[i]=oldString[stringLength-i];
}
return newString;
Also you might want to consider using the String class instead of char*.

More than one variable type in array

I am busy with a dynamic 2d array and I have declared it as follows:
string** MakeArray(int row,int col)
{
string** array;
array = new string* [col];
for(int r = 0; r < row; r++)
{
array[r] = new string [col];
}
return array;
}
Now I can place string values in the array. How can I place Integer values in the first column and strings in second and integers in third, if my array is 4 by 99?
The elements in an array are all the same type. To get what you're after, you probably want to start off rather differently, with an array of structs:
struct whatever {
int a;
std::string b;
int c;
};
std::vector<whatever> your_array;
Edit: although it's almost certainly a lousy idea, if you really need this to be a 2D array, you could try making all your elements the same type of union:
union whatever {
int a;
std::string b;
};
This has some pretty severe limitations though -- in fact, putting a std::string in a union isn't officially supported at all. There's a fairly decent chance it'll work, but no guarantee of it at all. If you really, really need to do something like this, you can make that member of the union a pointer instead. That is guaranteed to work, but also guaranteed to be so clumsy that making mistakes with it is nearly inevitable.
Don't do that. Instead create a struct that will represent single record in a table, and contain a string and two integers. Then create one dimensional array of those structures.
struct record
{
int a;
std::string b;
int c;
};
record* MakeArray(int row)
{
return new record[row];
}
better yet, ditch arrays and use std::vector:
std::vector<record> array(99);
Have you looked at having a vector/array of tuples, if you have C++11 available to you? So you could do something such as:
#include <tuple>
#include <vector>
typedef std::tuple<int, std::string, int> MyTuple;
std::vector<MyTuple> MakeVector()
{
std::vector<MyTuple> vecTuples;
for( int i = 0; i < 5; ++i )
{
vecTuples.emplace_back( std::make_tuple<int, std::string, int>( i, "Test"+i, i+5 ) );
}
return vecTuples;
}
C++ is a "strong-typed" language. One of the things that means is you cannot mix data types (unless they are related, like base-derived class hierarchical relationship).
In other words what you are doing is not what C++ directly supports.
Having said that there's something you can do that would do what you want - have an array of triplets, like this:
struct triplet
{
int first;
string second;
int third;
};
triplet** MakeArray(...
What you are doing in your example looks alot like a JS code though. Maybe what you want is to store all your data as strings? Then yes, you can use a 2D array of strings, but that requires you to convert datum into string when storing it and converting back from string for calculations. Which is a major performance issue