How to declare an array of strings in C++? - c++

I am trying to iterate over all the elements of a static array of strings in the best possible way. I want to be able to declare it on one line and easily add/remove elements from it without having to keep track of the number. Sounds really simple, doesn't it?
Possible non-solutions:
vector<string> v;
v.push_back("abc");
b.push_back("xyz");
for(int i = 0; i < v.size(); i++)
cout << v[i] << endl;
Problems - no way to create the vector on one line with a list of strings
Possible non-solution 2:
string list[] = {"abc", "xyz"};
Problems - no way to get the number of strings automatically (that I know of).
There must be an easy way of doing this.

C++ 11 added initialization lists to allow the following syntax:
std::vector<std::string> v = {"Hello", "World"};
Support for this C++ 11 feature was added in at least GCC 4.4 and only in Visual Studio 2013.

You can concisely initialize a vector<string> from a statically-created char* array:
char* strarray[] = {"hey", "sup", "dogg"};
vector<string> strvector(strarray, strarray + 3);
This copies all the strings, by the way, so you use twice the memory. You can use Will Dean's suggestion to replace the magic number 3 here with arraysize(str_array) -- although I remember there being some special case in which that particular version of arraysize might do Something Bad (sorry I can't remember the details immediately). But it very often works correctly.
Also, if you're really gung-ho about the one line thingy, you can define a variadic macro so that a single line such as DEFINE_STR_VEC(strvector, "hi", "there", "everyone"); works.

Problems - no way to get the number of strings automatically (that i know of).
There is a bog-standard way of doing this, which lots of people (including MS) define macros like arraysize for:
#define arraysize(ar) (sizeof(ar) / sizeof(ar[0]))

Declare an array of strings in C++ like this : char array_of_strings[][]
For example : char array_of_strings[200][8192];
will hold 200 strings, each string having the size 8kb or 8192 bytes.
use strcpy(line[i],tempBuffer); to put data in the array of strings.

One possiblity is to use a NULL pointer as a flag value:
const char *list[] = {"dog", "cat", NULL};
for (char **iList = list; *iList != NULL; ++iList)
{
cout << *iList;
}

You can use the begin and end functions from the Boost range library to easily find the ends of a primitive array, and unlike the macro solution, this will give a compile error instead of broken behaviour if you accidentally apply it to a pointer.
const char* array[] = { "cat", "dog", "horse" };
vector<string> vec(begin(array), end(array));

You can use Will Dean's suggestion [#define arraysize(ar) (sizeof(ar) / sizeof(ar[0]))] to replace the magic number 3 here with arraysize(str_array) -- although I remember there being some special case in which that particular version of arraysize might do Something Bad (sorry I can't remember the details immediately). But it very often works correctly.
The case where it doesn't work is when the "array" is really just a pointer, not an actual array. Also, because of the way arrays are passed to functions (converted to a pointer to the first element), it doesn't work across function calls even if the signature looks like an array — some_function(string parameter[]) is really some_function(string *parameter).

Here's an example:
#include <iostream>
#include <string>
#include <vector>
#include <iterator>
int main() {
const char* const list[] = {"zip", "zam", "bam"};
const size_t len = sizeof(list) / sizeof(list[0]);
for (size_t i = 0; i < len; ++i)
std::cout << list[i] << "\n";
const std::vector<string> v(list, list + len);
std::copy(v.begin(), v.end(), std::ostream_iterator<string>(std::cout, "\n"));
}

Instead of that macro, might I suggest this one:
template<typename T, int N>
inline size_t array_size(T(&)[N])
{
return N;
}
#define ARRAY_SIZE(X) (sizeof(array_size(X)) ? (sizeof(X) / sizeof((X)[0])) : -1)
1) We want to use a macro to make it a compile-time constant; the function call's result is not a compile-time constant.
2) However, we don't want to use a macro because the macro could be accidentally used on a pointer. The function can only be used on compile-time arrays.
So, we use the defined-ness of the function to make the macro "safe"; if the function exists (i.e. it has non-zero size) then we use the macro as above. If the function does not exist we return a bad value.

#include <boost/foreach.hpp>
const char* list[] = {"abc", "xyz"};
BOOST_FOREACH(const char* str, list)
{
cout << str << endl;
}

#include <iostream>
#include <string>
#include <vector>
#include <boost/assign/list_of.hpp>
int main()
{
const std::vector< std::string > v = boost::assign::list_of( "abc" )( "xyz" );
std::copy(
v.begin(),
v.end(),
std::ostream_iterator< std::string >( std::cout, "\n" ) );
}

You can directly declare an array of strings like string s[100];.
Then if you want to access specific elements, you can get it directly like s[2][90]. For iteration purposes, take the size of string using the
s[i].size() function.

Related

Assigning values to character arrays inside of a structure array in C++

I am new to C++, but very familiar with Python. Trivial tasks in Python seem to be much more complex in C++. I am attempting to make a simple game where a word in a foreign language is printed on screen, the user guesses the value, if correct they are awarded a point and continue guessing what the value of other numbers printed on screen are. The problem I am facing that for the course I am taking we are not allowed to use strings only character arrays. The reason for this has not been explained by the instructor.
In Python, I would create a tuple of strings for the foreign word numbers:
foreignWords = ('een', 'twee', 'drie'....)
index 0 would be the word for one in Dutch, index 1 would be the word for two in Dutch, etc. I would use a function to randomly select a number between 0 and the length of foreignWords, print it on screen, etc. Very simple to do.
I thought I could simply create a structure array and strcopy the char arrays into the struct array.
struct numbers
{
char numberWord[7];
};
int main()
{
numbers numberChoices[10];
strcpy(numberChoices[0].numberWord, 'een');
strcpy(numberChoices[1].numberWord, 'twee');
strcpy(numberChoices[2].numberWord, 'drie');
strcpy(numberChoices[3].numberWord, 'vier');
strcpy(numberChoices[4].numberWord, 'vijf'):
strcpy(numberChoices[5].numberWord, 'zes');
etc.
That doesn't work though. It produces an error:
string.h:129:14: error: initializing argument 2 of ‘char* strcpy(char*, const char*)’ [-fpermissive]
extern char *strcpy (char *__restrict __dest, const char *__restrict __src)
^
However, if I create a for-loop and input the char array via cin >> the structure array will store my entries and they can be called by index.
Essentially, what I would like to do is make an array of char arrays that way I can an index get the value back and trivially keep track of the numerical value of the word (numberChoices[i].numberWord, i+1 = numerical value of the printed word). I don't know if this appropriate approach or not, but I am trying to be efficient, because the structure array would be referenced quite a bit to read what is stored in memory, save that value to a new variable and manipulate the referenced char array by deleting characters randomly and having the user guess what value the printed words.
What is the correct way to go about making an array of char arrays where the char array elements are hard coded?
Your code syntax is worng. You must represent char arrays as "abc", but not like 'abc'.
So your code must be like:
numbers numberChoices[10];
strcpy(numberChoices[0].numberWord, "een");
strcpy(numberChoices[1].numberWord, "twee");
strcpy(numberChoices[2].numberWord, "drie");
strcpy(numberChoices[3].numberWord, "vier");
strcpy(numberChoices[4].numberWord, "vijf"):
strcpy(numberChoices[5].numberWord, "zes");
Secondly you must remember that char arrays like "een" have extra char called null terminate '\0' so you must define array with enough size to store your characters and that extra character. That concept is called 'null terminating string'.
'\0' character is required to properly define your string size in functions like strcpy, strlen e. t. c. because you can not know about array size only by pointer to its first element (all array literals are considered like pointers in C/C++).
In C++ there is a distinction between single and double quotes: single quotes denote a single character literal, e.g. 'a', '0', '\n' while double quotes are used for c-strings, e.g. "a.u.b".
So replace
strcpy(numberChoices[0].numberWord, 'een');
with
strcpy(numberChoices[0].numberWord, "een");
In addition to the quote mix-up pointed out by others, you can take advantage static initialization to make some of that work go away.
struct numbers
{
char numberWord[7];
};
numbers numberChoices[10] =
{
{"een"},
{"twee"},
{"drie"},
{"vier"},
{"vijf"},
{"zes"},
...
};
int main()
{
std::cout << numberChoices[1].numberWord << std::endl;
}
And if possible within the constraints of your assignment, a further simplification:
const char * numberChoices[] =
{
"een",
"twee",
"drie",
"vier",
"vijf",
"zes",
...
};
int main()
{
std::cout << numberChoices[1] << std::endl;
}
It would seem that std::string is off the table for you. Pity. Use it where possible. It will save you a lot of trouble.
avoid c-style strings. use the c++ concepts:
#include <string>
#include <array>
struct numbers
{
std::string numberWord;
};
int main()
{
numbers numberChoices[] = {
{ "een" },
{ "twee" },
{ "drie" },
{ "vier" },
{ "vijf" },
{ "zes" },
// ... etc
};
}
Let's ignore your course requirestments for a moment;
You shouldn't use any magic indexes! use map instead, with meaningful keys;
With a proper map and string usage your code could look similar to this example:
#include <iostream>
#include <vector>
#include <string>
#include <unordered_map>
using foreign_word = std::string;
using foreign_words = std::vector<foreign_word>;
using language = std::string;
using language_words_map = std::unordered_map<language, foreign_words>;
int main() {
language_words_map lwm = {
{ "deutch", {"een", "twee", "drie"} },
/* ... and so on */
};
return 0;
}
see: http://ideone.com/BI6QjL

Creating binary (custom length) string in C++ [duplicate]

If I want to construct a std::string with a line like:
std::string my_string("a\0b");
Where i want to have three characters in the resulting string (a, null, b), I only get one. What is the proper syntax?
Since C++14
we have been able to create literal std::string
#include <iostream>
#include <string>
int main()
{
using namespace std::string_literals;
std::string s = "pl-\0-op"s; // <- Notice the "s" at the end
// This is a std::string literal not
// a C-String literal.
std::cout << s << "\n";
}
Before C++14
The problem is the std::string constructor that takes a const char* assumes the input is a C-string. C-strings are \0 terminated and thus parsing stops when it reaches the \0 character.
To compensate for this, you need to use the constructor that builds the string from a char array (not a C-String). This takes two parameters - a pointer to the array and a length:
std::string x("pq\0rs"); // Two characters because input assumed to be C-String
std::string x("pq\0rs",5); // 5 Characters as the input is now a char array with 5 characters.
Note: C++ std::string is NOT \0-terminated (as suggested in other posts). However, you can extract a pointer to an internal buffer that contains a C-String with the method c_str().
Also check out Doug T's answer below about using a vector<char>.
Also check out RiaD for a C++14 solution.
If you are doing manipulation like you would with a c-style string (array of chars) consider using
std::vector<char>
You have more freedom to treat it like an array in the same manner you would treat a c-string. You can use copy() to copy into a string:
std::vector<char> vec(100)
strncpy(&vec[0], "blah blah blah", 100);
std::string vecAsStr( vec.begin(), vec.end());
and you can use it in many of the same places you can use c-strings
printf("%s" &vec[0])
vec[10] = '\0';
vec[11] = 'b';
Naturally, however, you suffer from the same problems as c-strings. You may forget your null terminal or write past the allocated space.
I have no idea why you'd want to do such a thing, but try this:
std::string my_string("a\0b", 3);
What new capabilities do user-defined literals add to C++? presents an elegant answer: Define
std::string operator "" _s(const char* str, size_t n)
{
return std::string(str, n);
}
then you can create your string this way:
std::string my_string("a\0b"_s);
or even so:
auto my_string = "a\0b"_s;
There's an "old style" way:
#define S(s) s, sizeof s - 1 // trailing NUL does not belong to the string
then you can define
std::string my_string(S("a\0b"));
The following will work...
std::string s;
s.push_back('a');
s.push_back('\0');
s.push_back('b');
You'll have to be careful with this. If you replace 'b' with any numeric character, you will silently create the wrong string using most methods. See: Rules for C++ string literals escape character.
For example, I dropped this innocent looking snippet in the middle of a program
// Create '\0' followed by '0' 40 times ;)
std::string str("\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00", 80);
std::cerr << "Entering loop.\n";
for (char & c : str) {
std::cerr << c;
// 'Q' is way cooler than '\0' or '0'
c = 'Q';
}
std::cerr << "\n";
for (char & c : str) {
std::cerr << c;
}
std::cerr << "\n";
Here is what this program output for me:
Entering loop.
Entering loop.
vector::_M_emplace_ba
QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
That was my first print statement twice, several non-printing characters, followed by a newline, followed by something in internal memory, which I just overwrote (and then printed, showing that it has been overwritten). Worst of all, even compiling this with thorough and verbose gcc warnings gave me no indication of something being wrong, and running the program through valgrind didn't complain about any improper memory access patterns. In other words, it's completely undetectable by modern tools.
You can get this same problem with the much simpler std::string("0", 100);, but the example above is a little trickier, and thus harder to see what's wrong.
Fortunately, C++11 gives us a good solution to the problem using initializer list syntax. This saves you from having to specify the number of characters (which, as I showed above, you can do incorrectly), and avoids combining escaped numbers. std::string str({'a', '\0', 'b'}) is safe for any string content, unlike versions that take an array of char and a size.
In C++14 you now may use literals
using namespace std::literals::string_literals;
std::string s = "a\0b"s;
std::cout << s.size(); // 3
Better to use std::vector<char> if this question isn't just for educational purposes.
anonym's answer is excellent, but there's a non-macro solution in C++98 as well:
template <size_t N>
std::string RawString(const char (&ch)[N])
{
return std::string(ch, N-1); // Again, exclude trailing `null`
}
With this function, RawString(/* literal */) will produce the same string as S(/* literal */):
std::string my_string_t(RawString("a\0b"));
std::string my_string_m(S("a\0b"));
std::cout << "Using template: " << my_string_t << std::endl;
std::cout << "Using macro: " << my_string_m << std::endl;
Additionally, there's an issue with the macro: the expression is not actually a std::string as written, and therefore can't be used e.g. for simple assignment-initialization:
std::string s = S("a\0b"); // ERROR!
...so it might be preferable to use:
#define std::string(s, sizeof s - 1)
Obviously you should only use one or the other solution in your project and call it whatever you think is appropriate.
I know it is a long time this question has been asked. But for anyone who is having a similar problem might be interested in the following code.
CComBSTR(20,"mystring1\0mystring2\0")
Almost all implementations of std::strings are null-terminated, so you probably shouldn't do this. Note that "a\0b" is actually four characters long because of the automatic null terminator (a, null, b, null). If you really want to do this and break std::string's contract, you can do:
std::string s("aab");
s.at(1) = '\0';
but if you do, all your friends will laugh at you, you will never find true happiness.

C++ Code optimization

I have created my custom function to turn a wstring into lower case. However, it is pretty slow in DebugMode. Yes, I know ReleaseMode is what counts, but anyway it is pretty unnerving.
wstring wstringToLower(wstring u)
{
wstring s;
for (int i=0;i<u.size();i++)
{
wstring sChar;
sChar=u.substr(i,1);
int iChar=static_cast<int>(sChar[0]);
int iNewChar=charCodeToLower(iChar);
wstring sNewChar=wstring(1,iNewChar);
s.append(sNewChar);
}
return s;
}
Does anybody see anything obvious that I could improve to speed up the code, even in DebugMode?
Thank you!
There's no need to make temporary strings.
So, for start, instead of:
wstring sNewChar=wstring(1,iNewChar);
s.append(sNewChar);
This should do the trick:
s.push_back(iNewChar);
Then, instead of:
wstring sChar;
sChar=u.substr(i,1);
int iChar=static_cast<int>(sChar[0]);
This should work:
int iChar=static_cast<int>(u[i]);
And, of course, as noted by Marcel, you can do everything on the passed copy, avoiding the extra string allocation.
Also, as noted in the comments: How to convert std::string to lower case? . Also, read all answers (and comments) here: how to Make lower case letters for unicode characters :
#include <algorithm>
#include <string>
#include <iostream>
using namespace std;
int main()
{
::setlocale(LC_ALL,"");
std::wstring data = L"НЕМАЊА БОРИЋ"; // Wide chars
std::transform(data.begin(), data.end(), data.begin(), ::towlower);
// prints немања борић
std::wcout << data << std::endl;
return 0;
}
http://en.cppreference.com/w/cpp/string/wide/towlower
First of all I would avoid to allocate memory for variables each run, since allocating is a heavy operation.
Then do not call u.size() in the for-loop declaration. It will be called every loop otherwise. Every function call less that you call in a loop is a good win for performance.
Next everything Nemanja Boric said in the other answer.
And since the variable u is passed as copy, you can use it as return value and operate directly on it.
wstring wstringToLower(wstring u)
{
int size = u.size();
for (int i = 0; i < size; ++i)
{
u[i] = charCodeToLower(static_cast<int>(u[i]));
}
return u;
}
Conclusion: Basically avoid to allocate memory or calling functions in loops. Do just as much as you really have to.
There is actually no need for the wstringToLower function at all. You can use <algorithm> to do most of the work:
std::wstring str = "Some String";
std::transform(str.begin(), str.end(), str.begin(), ::towlower);
If you are trying to localize it, you may want to modify it slightly:
std::wstring str = "Some String";
std::locale loc; // set your locale
std::transform(str.begin(), str.end(), str.begin(), [](wchar_t c)
{
return use_facet<ctype<wchar_t>>(loc).tolower(c);
});

In C++, I thought you could do "string times 2" = stringstring?

I'm trying to figure out how to print a string several times. I'm getting errors. I just tried the line:
cout<<"This is a string. "*2;
I expected the output: "This is a string. This is a string.", but I didn't get that. Is there anything wrong with this line? If not, here's the entire program:
#include <iostream>
using namespace std;
int main()
{
cout<<"This is a string. "*2;
cin.get();
return 0;
}
My compiler isn't open because I am doing virus scans, so I can't give the error message. But given the relative simplicity of this code for this website, I'm hoping someone will know if I am doing anything wrong by simply looking.
Thank you for your feedback.
If you switch to std::string, you can define this operation yourself:
std::string operator*(std::string const &s, size_t n)
{
std::string r; // empty string
r.reserve(n * s.size());
for (size_t i=0; i<n; i++)
r += s;
return r;
}
If you try
std::cout << (std::string("foo") * 3) << std::endl
you'll find it prints foofoofoo. (But "foo" * 3 is still not permitted.)
There is an operator+() defined for std::string, so that string + string gives stringstring, but there is no operator*().
You could do:
#include <iostream>
#include <string>
using namespace std;
int main()
{
std::string str = "This is a string. ";
cout << str+str;
cin.get();
return 0;
}
As the other answers pointed there's no multiplication operation defined for strings in C++ regardless of their 'flavor' (char arrays or std::string). So you're left with implementing it yourself.
One of the simplest solutions available is to use the std::fill_n algorithm:
#include <iostream> // for std::cout & std::endl
#include <sstream> // for std::stringstream
#include <algorithm> // for std::fill_n
#include <iterator> // for std::ostream_iterator
// if you just need to write it to std::cout
std::fill_n( std::ostream_iterator< const char* >( std::cout ), 2, "This is a string. " );
std::cout << std::endl;
// if you need the result as a std::string (directly)
// or a const char* (via std::string' c_str())
std::stringstream ss;
std::fill_n( std::ostream_iterator< const char* >( ss ), 2, "This is a string. " );
std::cout << ss.str();
std::cout << std::endl;
Indeed, your code is wrong.
C++ compilers treat a sequence of characters enclosed in " as a array of characters (which can be multibyte or singlebyte, depending on your compiler and configuration).
So, your code is the same as:
char str[19] = "This is a string. ";
cout<<str * 2;
Now, if you check the second line of the above snippet, you'll clearly spot something wrong. Is this code multiplying an array by two? should pop in your mind. What is the definition of multiplying an array by two? None good.
Furthermore, usually when dealing with arrays, C++ compilers treat the array variable as a pointer to the first address of the array. So:
char str[19] = "This is a string. ";
cout<<0xFF001234 * 2;
Which may or may not compile. If it does, you code will output a number which is the double of the address of your array in memory.
That's not to say you simply can't multiply a string. You can't multiply C++ strings, but you can, with OOP, create your own string that support multiplication. The reason you will need to do that yourself is that even std strings (std::string) doesn't have a definition for multiplication. After all, we could argue that a string multiplication could do different things than your expected behavior.
In fact, if need be, I'd write a member function that duplicated my string, which would have a more friendly name that would inform and reader of its purpose. Using non-standard ways to do a certain thing will ultimately lead to unreadable code.
Well, ideally, you would use a loop to do that in C++. Check for/while/do-while methods.
#include <iostream>
#include <string>
using namespace std;
int main()
{
int count;
for (count = 0; count < 5; count++)
{
//repeating this 5 times
cout << "This is a string. ";
}
return 0;
}
Outputs:
This is a string. This is a string. This is a string. This is a string. This is a string.
Hey there, I'm not sure that that would compile. (I know that would not be valid in c# without a cast, and even then you still would not receive the desired output.)
Here would be a good example of what you are trying to accomplish. The OP is using a char instead of a string, but will essentially function the same with a string.
Give this a whirl:
Multiply char by integer (c++)
cout<<"This is a string. "*2;
you want to twice your output. Compiler is machine not a human. It understanding like expression and your expression is wrong and generate an error .
error: invalid operands of types
'const char [20]' and 'int' to binary
'operator*'

Reviewing C++: Int to Char

It's been a while since I have worked with C++, I'm currently catching up for an upcoming programming test. I have the following function that has this signature:
void MyIntToChar(int *arrayOfInt,char* output)
Int is an array of integers and char* output is a buffer that should be long enough to hold the string representation of the integers that the function receives.
Here is an example of the usage of such function:
int numbers[3] = {11, 26, 81};
char* output = ""; // this I'm sure is not valid, any suggestions on how to
// to properly initialize this string?
MyIntToChar(numbers,output);
cout << output << endl; // this should print "11 26 81" or "11, 26, 81".
// i.e. formatting should not be a problem.
I have been reviewing my old c++ notes from college, but I keep having problems with these. I'm hating myself right now for going to the Java world and not working in this.
Thanks.
void MyIntToChar(int *arrayOfInt, char* output);
That's wrong in several ways. First, of all, it's a misnomer. You cannot, in general, convert an integer into one character, because only ten of all intergers (0...9) would fit into one. So I will assume you want to convert integers into _strings instead.
Then, if you pass arrays to functions, they decay to pointers to their first element, and all information about the array's size is lost. So when you pass arrays to function, you need to pass size information, too.
Either use the C way of doing this and pass in the number of elements as std::size_t (to be obtained as sizeof(myarray)/sizeof(myarray[0])):
void MyIntToStr(int *arrayOfInt, std::size_t arraySize, char* output);
Or do it the C++ way and pass in two iterators, one pointing at the first element (so-called begin iterator) and the other pointing to one behind the last (end iterator):
void MyIntToStr(int *begin, int *end, char* output);
You can improve on that by not insisting on the iterators being int*, but anything which, when dereferenced, yields an int:
template< typename FwdIt >
void MyIntToStr(FwdIt begin, FwdIt end, char* output);
(Templates would require you to implement the algorithm in an header.)
Then there's the problems with the output. First of all, do you really expect all the numbers to be written into one string? If so, how should they be separated? Nothing? Whitespace? Comma?
Or do you expect an array of strings to be returned?
Assuming you really want one string, if I pass the array {1, 2, 3, 4, 5} into your function, it needs space for five single-digit integers plus the space needed for four separators. Your function signature suggests you want me to allocate that upfront, but frankly, if I have to calculate this myself, I might just as well do the conversions myself. Further, I have no way of telling you how much memory that char* points to, so you can't check whether I was right. As generations of developers have found out, this is so hard to get right every time, that several computer languages have been invented to make things easier for programmers. One of those is C++, which nowadays comes with a dynamically resizing string class.
It would be much easier (for you and for me), if I could pass you a stirng and you write into that:
template< typename FwdIt >
void MyIntToChar(FwdIt begin, FwdIt end, std::string& output);
Note that I this passes the string per non-const reference. This allows you to modify my string and let's me see the changes you made.
However, once we're doing this, you might just as well return a new string instead of requireing me to pass one to you:
template< typename FwdIt >
std::string MyIntToChar(FwdIt begin, FwdIt end);
If, however, you actually wanted an array of strings returned, you shouldn't take one string to write to, but a means where to write them to. The naive way of doing this would be to pass a dynamically re-sizable array of dynamically re-sizable string. In C++, this is spelled std::vector<std::string>:
template< typename FwdIt >
void MyIntToStr(FwdIt begin, FwdIt end, std::vector<std::string>& output);
Again, it might be better you return such an array (although some would disagree since copying an array of string might be considered to expensive). However, the best way to do this would not require me to accept the result in form of a 'std::vector'. What if I needed the strings in a (linked) list instead? Or written to some stream?
The best way to do this would be for your function to accept an output iterator to which you write your result:
template< typename FwdIt, typename OutIt >
void MyIntToStr(FwdIt begin, FwdIt end, OutIt output);
Of course, now that's so general that it's hard to see what it does, so it's good we gave it a good name. However, looking at it I immediately think that this should build on another function which is needed probably even more than this one: A function that takes one integer and converts it to one string. Assuming that we have such a function:
std::string MyIntToStr(int i);
it's very easy to implement the array versions:
template< typename FwdIt, typename OutIt >
void MyIntToStr(FwdIt begin, FwdIt end, OutIt output)
{
while(begin != end)
*output++ = MyIntToStr(*begin++);
}
Now all that remains for you to be done is to implement that std::string MyIntToStr(int i); function. As someone else already wrote, that's easily done using string streams and you shouldn't have a problem to find some good examples for that. However, it's even easier to find bad examples, so I'd rather give you one here:
std::string MyIntToStr(int i);
{
std::ostringstream oss;
oss << i:
if(!oss) throw "bah!"; // put your error reporting mechanism here
return oss.str();
}
Of course, given templates, that easy to generalize to accepting anything that's streamable:
template< typename T >
std::string MyIntToStr(const T& obj);
{
std::ostringstream oss;
oss << obj:
if(!oss) throw "bah!"; // put your error reporting mechanism here
return oss.str();
}
Note that, given this general function template, the MyIntToStr() working on arrays now automatically works on arrays of any type the function template working on one object works on.
So, at the end of this (rather epic, I apologies) journey, this is what we arrived at: a generalized function template to convert anything (which can be written to a stream) into a string, and a generalized function template to convert the contents of any array of objects (which can be written to a stream) into a stream.
Note that, if you had at least a dozen 90mins lectures on C++ and your instructors failed to teach you enough to at least understand what I've written here, you have not been taught well according to modern C++ teaching standards.
Well an integer converted to string will require a max of 12 bytes including sign (assuming 32bit), so you can allocate something like this
char * output= new char[12*sizeof(numbers)/sizeof(int)];
First of all, it is impossible to use your method that way your example says:
char* output has only a size of 1 byte (don't forget the null-terminator '\0'). So you can't put a whole string in it. You will get segmentation faults. So, here you are going to make use of the heap. This is already implemented in std::string and std::stringstream. So use them for this problem.
Let's have a look:
#include <string>
#include <sstream>
#include <iostream>
std::string intArrayToString(int *integers, int numberOfInts)
{
std::stringstream ss;
for (int i = 0; i < numberOfInts; i++)
{
ss << integers[i] << ", ";
}
std::string temp = ss.str();
return temp.substr(0, temp.size() - 2); // Cut of the extra ", "
}
And if you want to convert it to char*, you can use yourString.c_str();
Here's a possibility if you are willing to reconsider a change in prototype of the function
template<int n>
void MyIntToChar(int (&iarr)[n], string &output){
stringstream ss;
for(size_t id = 0; id < n; ++id){
ss << iarr[id];
if(id != n - 1) ss << " ";
}
output = ss.str();
}
int main(){
int numbers[3] = {11, 26, 81};
string out = "";
MyIntToChar(numbers, out);
}
You should take a look at the std::stringstream, or, more C-ish (as char* type instead of strings might suggest) sprintf.
did you try sprintf(),it will do your work.For char * initialization,you have to either initialize it by calling malloc or you can take is as a char array and pass the address to the function rather then value.
Sounds like you would like to use C lang. Here's an example. There's an extra ", " at the end of the output but it should give you a feel for the concept. Also, I changed the return type so that I would know how many bytes of output were used. The alternative would be to initialize output would nulls.
int MyIntToChar(int *arrayOfInt, char* output) {
int bytes_used = 0; // use to bump the address past what has been used
for (int i = 0 ; i < sizeof(arrayOfInt); ++i)
bytes_used += sprintf(output + bytes_used, "%u, ", arrayOfInt[i]);
return bytes_used;
}
int main() {
int numbers[5] = {5, 2, 11, 26, 81}; // to properly initialize this string?
char output[sizeof(int)*sizeof(numbers)/sizeof(int) + sizeof(numbers)*2]; // int size plus ", " in string
int bytes_used = MyIntToChar(numbers, output);
printf("%*s", bytes_used, output);// this should print "11 26 81" or "11, 26, 81".
}