Reading string user input into an array of any size - c++

so I'm currently trying to read user input into a char array, but every single example I've looked at defines the size of the array upon its initialization. What I'm looking for, essentially, is a way to read user input (perhaps with getline, as I would want to read user input as a string) and store it in an array.
Let's say a user inputs this into the program:
This is a string
I would want the array size to be able to fit that string, and place the null terminator after the "g". Then, another user could put a string of any size that they so desired into the program, but I would basically want my program to always make the array size just enough to contain what was read in from input.
I haven't been able to get this working and it's been a couple of hours of browsing endless pages, so any help would be appreciated! Thanks.

As Tony Delroy said on his comment (I can't comment yet), you should be using std::string.
If you really need an char array, as parameter to a function for example, you can use the function c_str() to get the content of the std::string as a const char* array or if you need a char* array, you can copy the content of the array given by c_str() to a dynamically allocated array, using
char* cstr = new char[str.length() + 1];
strcpy(cstr, str.c_str());
As an addend, you need to include the header cstring in order to use the function strcpy and need to use delete[] cstr to delete the char* when you're not going to use it anymore
#include <iostream>
#include <cstring>
using namespace std;
// string argument as std::string
void foo(string str) {
// function body
}
// argument as const char*
void bar(const char* str) {
// function body
}
// argument as char*
void baz(char* str) {
// function body
}
int main() {
string str;
getline(cin, str);
foo(str);
bar(str.c_str());
char* cstr = new char[str.length() + 1];
strcpy(cstr, str.c_str());
baz(cstr);
delete[] cstr;
return 0;
}

you should use std::string for that.
the null terminator has no use in std::string, because you can just use:
string.size()
to get the size of the user input.
if want to traverse a string like a char array one by one it should look like something like this:
std::string input;
std::getline(std::cin, input);
for (int i = 0; i < input.size() ; i++)
{
std::cout << input[i];
}

Related

return char array from function that passes parameters

I'm working with a piece of C++ code that reads lines from a txt file and then assign each line to to an array called lines. Then it calls a function that converts each element in the lines array to a char array and then return the resulted char array. This step is where I stuck. How could I return a char array from the function toChar and assign the returned array to another array so I can use it as I need? (the rest of the code should use each returned char array to write it in a pipe, this not important right now but just to clarify why I need to learn to return an array from a function)
Here is the code I'm using:
#include <fstream>
#include <iostream>
#include <string.h>
#include <unistd.h>
#include <cstdlib>
using namespace std;
char * toChar(string line);
int main()
{
string lines[0] = "line1";
char* a = toChar(lines[0]);
return 0;
}
char * toChar(string line)
{
char a[1024];
strcpy(a, line.c_str());
return a;
}
Please note that in this code I'm trying to shrink the code so I'm assigning a simple string value to the array
when I try to compile this code, the error below appears:
warning: address of local variable 'a' returned
any help or suggestion is greatly appreciated..
First use a const & in passing the string to the function to avoid the unnecessary copying, and be able to use temporaries, e.g. toChar("I am temp");
The are the following alternatives:
(1) Return std::string
std::string toChar(std::string const & line)
{
char a[1024];
strcpy(a, line.c_str());
return a;
}
Of course it is assumed that line is smaller than 1024 chars with the null termination symbol
(2) Return an allocated array the
char * toChar(std::string const & line)
{
char * a = new char[1024];
strcpy(a, line.c_str());
return a;
}
but you will have to actually manage it and delete it later.
(3) Allocate the array and pass it to the function
void toChar(string const & line, char a[])
{
strcpy(a, line.c_str());
}
I imagine that you actually want to extract a C-string from an std::string , or some part of it. The proper way to do it is (3).
The warning is correct and practically is an error. You're declaring the char array locally so it will be deleted after going out of scope of that function and its address will be no more valid.
Since you're using c++ avoid char array and use a std::string.
If you want to access to the internal storage of your string you can call line.c_str() which returns a const char *.
Hence you won't need you function toChar that creates a local array that will go out of scope at the end of your function.
You could simply do :
int main()
{
string lines[0] = "line1";
const char* a = lines[0].c_str();
return 0;
}
But I advise you to keep manipulating std::string as they will handle string better than a simple char *.
And if you want a copy, just do it : std::string mycopy = lines[0].

How can I convert const char* to string and then back to char*?

I'm just starting c++ and am having difficulty understanding const char*. I'm trying to convert the input in the method to string, and then change the strings to add hyphens where I want and ultimately take that string and convert it back to char* to return. So far when I try this it gives me a bus error 10.
char* getHyphen(const char* input){
string vowels [12] = {"A","E","I","O","U","Y","a","e","i","o","u","y"};
//convert char* to string
string a;
int i = 0;
while(input != '\0'){
a += input[i];
input++;
i++;
}
//convert a string to char*
return NULL;
}
A: The std::string class has a constructor that takes a char const*, so you simply create an instance to do your conversion.
B: Instances of std::string have a c_str() member function that returns a char const* that you can use to convert back to char const*.
auto my_cstr = "Hello"; // A
std::string s(my_cstr); // A
// ... modify 's' ...
auto back_to_cstr = s.c_str(); // B
First of all, you don't need all of that code to construct a std::string from the input. You can just use:
string a(input);
As far as returning a new char*, you can use:
return strdup(a.c_str()); // strdup is a non-standard function but it
// can be easily implemented if necessary.
Make sure to deallocate the returned value.
It will be better to just return a std::string so the users of your function don't have to worry about memory allocation/deallocation.
std::string getHyphen(const char* input){
Don't use char*. Use std::string, like all other here are telling you. This will eliminate all such problems.
However, for the sake of completeness and because you want to understand the background, let's analyse what is going on.
while(input != '\0'){
You probably mean:
while(*input != '\0') {
Your code compares the input pointer itself to \0, i.e. it checks for a null-pointer, which is due to the unfortunate automatic conversion from a \0 char. If you tried to compare with, say, 'x' or 'a', then you would get a compilation error instead of runtime crashes.
You want to dereference the pointer via *input to get to the char pointed to.
a += input[i];
input++;
i++;
This will also not work. You increment the input pointer, yet with [i] you advance even further. For example, if input has been incremented three times, then input[3] will be the 7th character of the original array passed into the function, not the 4th one. This eventually results in undefined behaviour when you leave the bounds of the array. Undefined behaviour can also be the "bus error 10" you mention.
Replace with:
a += *input;
input++;
i++;
(Actually, now that i is not used any longer, you can remove it altogether.)
And let me repeat it once again: Do not use char*. Use std::string.
Change your function declaration from
char* getHyphen(const char* input)
to
auto hyphenated( string const& input )
-> string
and avoid all the problems of conversion to char const* and back.
That said, you can construct a std::string from a char_const* as follows:
string( "Blah" )
and you get back a temporary char const* by using the c_str method.
Do note that the result of c_str is only valid as long as the original string instance exists and is not modified. For example, applying c_str to a local string and returning that result, yields Undefined Behavior and is not a good idea. If you absolutely must return a char* or char const*, allocate an array with new and copy the string data over with strcpy, like this: return strcpy( new char[s.length()+1], s.c_str() ), where the +1 is to accomodate a terminating zero-byte.

How to put a string inside a char* variable in c++

well I'm going to be brief here.
I have this variable:
char* String;
and a function:
void AddString(char str[])
{
}
And I need to add the str to String at the end of it for example:
if String = "ABC"
and str = "123"
after the function AddString String = "ABC123"
I searched all over the web, but I couldn't find what I need, any help?
In C++, use std::string rather than C-style character arrays:
#include <string>
std::string String;
void AddString(std::string str) {
String += str;
}
If you really want to do that by steam, then you'll need to allocate a large enough array for the result, copy the strings in, and remember to put a terminator (zero-valued character) after the end. C library functions like strlen, strcpy and strcat might be useful. The details are left as an exercise, since the question is about C++ not C.
For using C strings you have functions inside the cstring header file. To concatenate strings you have strcat
use strcat to combine the two char*
strcat takes two parameters, the destination char array c1 and the source char array c2.
You need to be sure that c1 is big enough to hold all the char from c1 and c2.
However you could use c++ strings. and the + operator will handle this for you.
string s1, s2;
string s3 = s1+s2
char* String;
void AddString(char str[])
{
strcat(String , str);
}
/*Also, make sure you have allocated space for String before using AddString*/
String = malloc(25*sizeof(char)); //25 just an example.
Also, since this is tagged for C++
You should be using std::string instead as shown in other answers

C++: initialize char array with a string?

Let's say I have a string called garbage.
Whatever's in garbage, I want to make a char array out of it. Each element would be one char of the string.
So, code would be similar to:
const int arrSize = sizeof(garbage); //garbage is a string
char arr[arrSize] = {garbage};
But, this will give an error "cannot convert string to char in initialization".
What is the correct way to do this? I just want to feed the darn thing a string and make an array out of it.
C++ std::string maintains an internal char array. You can access it with the c_str() member function.
#include <string>
std::string myStr = "Strings! Strings everywhere!";
const char* myCharArr = myStr.c_str();
Keep in mind that you cannot modify the internal array. If you want to do so, make a copy of the array and modify the copy.
I think what you're after is a lot simpler:
char arr[] = "some interesting data (garbage)";
You could just use garbage.data(), which is already a pointer to the first element of an array of chars containing your string data.
Or here is a heavy way to do so.
#include <string>
std::string temp = "something";
char* myChar = new char(temp.length());
for(int i = 0; i < temp.length(); ++i){
a[i] = temp[i];
}

Converting a string to char*

I am trying to write a function to convert a std::string to char* .
The first one I have written was this:
char* $ (string str)
{
char* cstr;
const unsigned int length=str.size();
cstr=new char[1000];
for(int i=0;i<length;i++)
cstr[i]=str[i];
cstr[length]=0;
return cstr;
}
But the problem was the memory leak: let's suppose that I do this:
char* cstr;
string str1("hello"),str2("hello2");
cstr=$(str1);
cstr=$(str2);
There is a memory leak in this case.The first allocated string is not reachable but it's reference is lost.
So I made the same using static:
char* $ (string str)
{
static char cstr[1000];
const unsigned int length=str.size();
for(int i=0;i<length;i++)
cstr[i]=str[i];
cstr[length]=0;
return cstr;
}
But the problem now is that the static char fields are accessible:
char* cstr;
string str("hello");
cstr=$(str);
$(str)[5]='!';
This is possibile, the 6th character is modified and so also the C-style string pointed by cstr is modified.
Using const:
const char* $ (string str)
{
static char cstr[1000];
const unsigned int length=str.size();
for(int i=0;i<length;i++)
cstr[i]=str[i];
cstr[length]=0;
return cstr;
}
The problem is that a char pointer is not compatible with a const char pointer, so I can't do this:
string str("hello");
char* cstr;
cstr=$(str);
But I can only use a const char pointer.
What I would do is to have a function which the return value could be placed only as right operand, but not as left operand of an assignment.How could this be done?
I tried to do this:
char* toCharArray(string& str)
{
std::unique_ptr<char>p(new char[1000]);
char* temp=p.get();
for(unsigned int i=0;i<str.size();i++)
{
*temp=str[i];
temp++;
}
return p.get();
}
But the problem is still there, I don't see the difference between this and the other solution I posted using static.Since a code like this:
char* cstr;
string str("hello");
cstr=toCharArray(str);
toCharArray(str)[0]='o';
cout << cstr;
Modifies the string (prints "oello").
Problem still not solved.
You can prevent memory leaks by returning the allocated array as either std::unique_ptr<char[]> or std::vector<char>; both will release the memory if they are reassigned or go out of scope.
You can get a char* pointer to the contents as ptr.get() or &vec[0] respectively.
By the way, since the length is known, the array length really should be length+1, not 1000. Fixed-sized buffers are an overrun waiting to happen. Also, $ is not a portable name for a function.
http://www.cplusplus.com/reference/string/string/c_str/
Look at the example, specifically:
char * cstr, *p;
string str ("Please split this phrase into tokens");
cstr = new char [str.size()+1];
strcpy (cstr, str.c_str());
You need to create a new char * and copy the contents of the std::string over it.
You can use strcpy.
I don't see why you're surprised by the memory leak. If you're making a copy of something, you've got to put it somewhere.
You can either put all the copies in the same place (running a risk of overflow, and putting the onus of taking a proper copy on the client, or they run the risk of unexpected corruption), or you do the allocation (they still have to do the freeing, but at least they don't have to copy), or you get them to pass a buffer and a size into your function.
And seriously, $ as a function name?
What about str.c_str()? Or strdup(str.c_str()) if you want a copy.