Visual studio c++ shows that "string" on line 24 has one array element, but the top contains all the text that was input by the user. But when I send to PutString(), it disappears. Why?
#include <stdio.h>
void PutString( const char* pChar ){
for( ; *pChar != 0; pChar++ )
{
putchar( *pChar );
}
}
char* GetString(){
char c[100];
int i = 0;
do
{
c[i] = getchar();
}while( c[i++] != '\n' );
c[i] = '\0';
// PutString( c );
return c;
}
void main(){
char* string = GetString();
PutString( string );
}
Because c is a local variable within GetString and you are returning its address, after which it disappears (moves out of scope). That's undefined behaviour - you're not allowed to use stuff that's gone out of scope. In fact, if you run that through gcc, it tells you that quite explicitly:
qq.cpp:9: warning: address of local variable ācā returned
If you want to return non-simple things (such as arrays instead of integers or floats, which make a copy for you) from a function, you need to (for example) dynamically allocate it so that it survives function return. Something like changing:
char c[100];
into:
char *c = malloc (100); // or equivalent 'new'.
(and remembering to free/delete it eventually, of course).
Even though you may see it in the debugger when you return from GetString, it's still not guaranteed as per the standards.
In any case, there's a good chance the next stack manipulation (such as calling PutString) will wipe out the information.
Here's a C++ version that does it the new/delete way:
#include <stdio.h>
void PutString (const char* pChar ){
for (; *pChar != 0; pChar++)
putchar( *pChar );
}
char* GetString (void) {
char *c = new char[100]; // memory behind c will survive ...
int i = 0;
do {
c[i] = getchar();
} while (c[i++] != '\n');
c[i] = '\0';
return c;
} // ... past here ...
int main (void) {
char* string = GetString();
PutString (string);
delete[] string; // ... until here.
return 0;
}
I should also mention that there are probably better way to get line-based input in both C (fgets or see an earlier answer of mine) and C++ (such as the string getline and the char array getline).
You are returning pointer to a variable that is local to the function in GetString(), when the function returns, the space allocated to the variable is reclaimed.
To fix these you can either dynamically allocate space for the character array or declare it as static so that the lifetime of the variable becomes the entire program.
You GetString will not work correctly as the string (char c[100]) is put onto the stack. When the function gets to the return this will be deleted.
Either use malloc or pass into the function the array.
Related
I want to use pointer to store a char array generated by a function, then pass it to another function as a parameter, the code looks like this:
char* randString(){
//generate a rand string formed by 6 letters and numbers
char rSet[36];//a char set contains 0-9 and A-Z
for (int i=0;i<10;i++) rSet[i]=i+48;// get ASCII of 0-9
for (int i=10;i<36;i++) rSet[i]=i+55;// get ASCII of A-Z
char rString[7];
for (int i=0;i<6;i++){
int ind=rand()%36;
rString[i]=rSet[ind];// generate the random string
}
rString[6]='\0';
return rString;
}
void Print(char *b){
cout<<b;
}
int main(int argc, char* argv[])
{
char* a=randString();
Print(a);
}
the randString() function return a string composed by 6 random letter and number, then I store it with *a . when I tracked the pointer with debug, i found the content of *a is correct, with some stuff like "VG5GH2". However, when it was passed to Print() function, the content of the pointer was lost. Even the memory address is still the same, the value in there become some completely random stuff. If I do Print(randString()) also the same thing happend. Could someone help me out about this issue? I am pretty new to C++ and still not very clear with the use of pointer. Many thanks
When you create the character array it is being created in local scope and can't be used outside that function in which you're creating it. To tackle this problem the best way you can do in the same code is by creating the character array on heap. This will give you the exact result that you want to get.
char *rString;
rString = new char[6];
Finally, one should delete the variables created on heap! and you can do it by deleting the char pointer in which you're receiving the string from function
char* randString();
As
delete []a;
at the end of your program.
Memory issue buddy you just send back first char of your random string, the others destroyed when function done its job.But if you create them with 'new' keyword you has no problem to do anything you want.I hope this will help.
char* randString(){
//generate a rand string formed by 6 letters and numbers
char rSet[36];//a char set contains 0-9 and A-Z
for (int i=0;i<10;i++) rSet[i]=i+48;// get ASCII of 0-9
for (int i=10;i<36;i++) rSet[i]=i+55;// get ASCII of A-Z
srand(time(nullptr));
char *rString=new char[7];
for (int i=0;i<6;i++){
int ind=rand()%36;
rString[i]=rSet[ind];// generate the random string
}
rString[6]='\0';
return rString;
}
void Print(char *b){
cout<<b;
}
int main()
{
char *a=randString();
Print(a);
delete[] a;
return 0;
}
You are returning a pointer to a local variable inside the function. You are referencing stack memory- which will get used by other functions, variables as soon as the method/function exits.
One of the answers here mentions "dangling pointers". That term is applicable only when you malloc() then free() and re-used the pointer;
int *i = (int *) malloc(sizeof(int));
*i = 12;
free(i); // oops
printf("i = %d\n", *i);
If you want to write functions that return strings (char*), you have two options:
Allocate the memory inside the functions and then return it
As one of the parameters, you need to get the output buffer, and output buffer size.
As you are coding in C++ - use std::string everywhere, and don't use char* at all (note to self - still on output there is a memory copy... maybe passing the std::string out parameter as reference will help...?)
Example 1, note how we call the function and then release memory. Memory management is done by the function. This is not optimal, and I do not recommend this.
// in this function, the caller must release the memory
char* randStr1(int len) {
char* c = (char*) malloc(len), *cc = c;
for (int i=0; i<len; i++) {
*cc = rand()l
*cc++;
}
return c;
}
void foo1() {
char *c = randStr1(10);
printf("%s", c);
free(c);
}
Example 2: in this example, the memory allocation is done by the caller
char* randStr2(char *buffer, uint len) {
char *c = buffer;
while (len!=0) {
*c = rand();
c++;
len --;
}
return buffer;
}
void bar1() {
char buffer[100], *p;
p = randStr2(buffer, 100);
printf("%s", buffer); // or printf("%s", p);
}
Note how in the last example we do not need to de-allocate memory from the heap. The compiler will allocate and de-allocate memory from the stack.
I am having problem handling string array in C++.I tried below two methods.Still
not able to resolve the problem...Here it goes :
When I use :
string* fun(string* a,string*b)
{
string c[];
return c; /* c is string array type*/
}
it returns first string stored in string array c.I want whole string array to be returned.
When I used:
vector<string> fun(vector<string> a,vector<string> b){
vector<string> c;
return c;
}
still,i got some errors.
can you help me know where is the problem in both cases.
What modifications are required to obtain the desired result..
How can I handle string array in C++.
Thanx in advance !!
In the first version, you are returning a pointer to a local variable (your array), which will not exists any longer when you leave the scope. You need to create your array on the heap, e.g. with malloc or new. If you allocate it manually, don't forget to deallocate it.
In the second version, you are returning a copy of the vector declared in your function (if you modify the strings in the returned vector, they'll not be modified in a et b). You are creating an empty vector and not adding anything in it, so it'll not contains any string, though.
If you've got to return an object more complex than string you should pass to your function a link to vector (in your code) and fill it with values. That's a fast and right method.
vector<string> fun(vector<string> a,vector<string> b, vector<string>& result){
res.push_back("one");
res.push_back("two");
res.push_back("three");
}
In C/C++ while returning a string from function a local buffer if returned will not work.
The returned pointer should be a static buffer(like static string c[]) or pointer to a buffer passed in by the caller function (like string *fun(string *a, string *b, string *c) ) or pointer to a memory obtained using malloc/new but not local array.
In your first snippet, you could try initializing with new to allocate the space yourself.
string* func() {
string* c = new string[3];
c[0] = "Hello";
c[1] = "World";
c[2] = "<3";
return c;
}
in main:
m = func();
for(int i = 0; i < 3; i++)
{
cout << m[i] << endl;
}
That should prevent it from losing scope once the function ends. Don't forget to deallocate the space. Note you are returning a pointer to an array, not an array. Also, I had no problem running your second snippet of code. Please always share the errors you are getting.
You can't return arrays directly in C++(it inherits this from C). The way around it is to stuff it into a struct.
struct returned_array
{
string result[100];
};
returned_array fun()
{
returned_array result;
result.result[0] = "whatever";
return result;
}
I just picked an arbitrary size 100 for the example. If you want to base the return size on the size of an array that gets passed in, you can add a template parameter:
template<int N>
struct returned_array
{
string result[N];
};
template<int N>
returned_array<N> fun(string (&)[N])
{
returned_array<N> result;
result.result[0] = "whatever";
return result;
}
I have a C++ function to which I have to pass char* arguments[]. The prototype of this function is as follows:
void somefunc(char* arguments[])
To pass the above array to this function, I am generating this array from another function which can return me this char* array output, and this looks somehwhat like this.
char** genArgs(int numOfArgs,...)
{
va_list argList;
char** toRet = new char*[numOfArgs];
va_start (arguments, numOfArgs);
for(int cnt = 0; cnt < numOfArgs ; ++cnt)
toRet[cnt] = va_arg(argList, char*);
va_end(arguments);
}
I am confused how to actually write the above function correctly, given that I will be passing the inputs to function something like : genArgs(3, a.c_str(), b.c_str(), c.c_str()) or genArgs(2, a.c_str(), b.c_str())
How can I generate the above char* array without using char** (since this would have to be deleted before returning from the function to avoid memory leak).
From your declaration of genArgs, it seems that whenever you call genArgs, you know how many arguments you want to pass. Is this correct? If so (and if you are using C++11) then you can use std::array in the calling function. So instead of this:
char** arglist = genArgs (4, "MyArg1", mYaRG2", "LastArg", 0) ;
somefunc (arglist) ;
delete[] arglist ;
you can do it this way:
#include <array>
std::array<char*, 4> arglist { "MyArg1", mYaRG2", "LastArg", 0 } ;
somefunc (&arglist[0]) ;
But there is really nothing wrong with the first solution, unless you are a C++ ascetic. (However, you do need a return toRet ; statement in genArgs!)
this would have to be deleted before returning from the function to avoid memory leak
This is not entirely correct: although it is true that you need to eventually delete[] the pointer that you allocated with new[], you do not necessarily have to do it before exiting the function where the allocation happened.
You can do this:
// This allocates args; we now own the pointer
char **argsToPass = genArgs(2, a.c_str(), b.c_str());
// Make the call as usual
somefunc(argsToPass);
// Now that args are no longer needed, we delete them:
delete [] argsToPass;
The usual way would be to use an object that manages the lifetime of the array (such as a std::vector<char*> or a std::unique_ptr<char*[]>), and then to return that (so that the eventual release of the memory would be guaranteed by the type system):
std::vector<char*> genArgs(int numOfArgs,...)
{
std::vector<char*> toRet;
toRet.reserve(numOfArgs);
va_list argList;
va_start(argList, numOfArgs);
for(int cnt = 0; cnt < numOfArgs ; ++cnt) {
toRet.push_back(va_arg(argList, char*));
}
va_end(arguments);
return toRet;
}
To use this, do the following:
somefunc(&genArgs(3, a.c_str(), b.c_str(), c.c_str()).front());
Hello
Can somebody explain why second cout in func(char *p) doesn't work:
#include <cstdlib>
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
using namespace std;
char *strhex(char *str);
char *func(char *p);
int main()
{
char *ptr;
char *p=strhex("d");
cout<<"main:"<<p<<endl;
cout<<func(p)<<endl;
system("PAUSE");
return 0;
}
char *func(char *p)
{
cout<<"func1:"<<p<<endl;
char buffer[500]="";
char *zbuffer = buffer;
cout<<"func2:"<<p<<endl; ///doesn't work
return zbuffer;
}
char *strhex(char *str)
{
char buffer[500]="";
char *pbuffer = buffer;
int len = strlen( str );
for( int i = 0; i < len ;i++ )
{
itoa(str[i],pbuffer,16);
pbuffer +=2;
};
*pbuffer = '\0';
pbuffer=buffer;
return pbuffer;
}
Edit:
i'm using DEV C++ 4.9.9.2 on Windows
One big problem here is that strhex is returning a pointer to a local variable (buffer[]). This variable goes out of scope at the end of the function, so the return value points at undefined memory contents that can be overwritten at any time.
Your entire code doesn't work. Both functions return pointers to local arrays, which don't point to anything valid after the function returns. That causes undefined behavior. Since the value of p is one of these invalid pointers, you can't depend on it to be anything at any particular time ā that memory probably gets overwritten during func(). You need to either new[] and delete[] the appropriate memory or, preferably, use a proper C++ data structure like std::string.
it looks like it is working but the second cout in main is not printing out a value because you are returning an empty buffer.
Adding to others answers:
You need not reset pbuffer to point to the start of the array and then return it's value:
pbuffer=buffer;
return pbuffer;
you can just say
return buffer;
the array name is also a pointer(pointer to the first element of the array.
How can we access variables of a structure? I have a struct:
typedef struct {
unsigned short a;
unsigned shout b;
} Display;
and in my other class I have a method:
int NewMethod(Display **display)
{
Display *disp=new Display();
*display = disp;
disp->a=11;
}
What does **display mean? To access variables of struct I have used ->, are there other methods too?
As Taylor said, the double asterisk is "pointer to pointer", you can have as many levels of pointers as you need.
As I'm sure you know, the arrow operator (a->b) is a shortcut for the asterisk that dereferences a pointer, and the dot that accesses a field, i.e.
a->b = (*a).b;
The parentheses are necessary since the dot binds tighter. There is no such operator for double asterisks, you have to first de-reference to get to the required level, before accessing the fields:
Display **dpl = ...;
(*dpl)->a = 42;
or
(**dpl).a = 42;
Think of it as *(*display). When you want to pass the address of an integer to a function so that you can set the integer, you use:
void setTo7 (int *x) {
*x = 7;
}
: : :
int a = 4;
setTo7 (&a);
// a is now 7.
It's no different from what you have except that you want to set the value of a pointer so you need to pass the pointer to that pointer. Simple, no?
Try this out:
#include <stdio.h>
#include <string.h>
static void setTo7 (int *x) { *x = 7; }
void appendToStr (char **str, char *app) {
// Allocate enough space for bigger string and NUL.
char *newstr = malloc (strlen(*str) + strlen (app) + 1);
// Only copy/append if malloc worked.
if (newstr != 0) {
strcpy (newstr, *str);
strcat (newstr, app);
}
// Free old string.
free (*str);
// Set string to new string with the magic of double pointers.
*str = newstr;
}
int main (void) {
int i = 2;
char *s = malloc(6); strcpy (s, "Hello");
setTo7 (&i); appendToStr (&s, ", world");
printf ("%d [%s]\n",i,s);
return 0;
}
The output is:
7 [Hello, world]
This will safely append one string value to another, allocating enough space. Double pointers are often used in intelligent memory allocation functions, less so in C++ since you have a native string type, but it's still useful for other pointers.
**display is just a double pointer (a pointer to a pointer of type Display).
The ** means that its a pointer-to-a-pointer. Basically it points to another pointer that then points to something else, in your case a Display structure.
If you called the function with only the object you can access the members with the . operator.
int NewMethod(Display display)
{
Display disp = display;
disp.a=11;
}
But this way you are not modifying directly the Display display object but a local copy. Your code suggests that the changes to the object are needed outside of the function so your only option is the one you described (well, maybe passing the argument by refference but the syntax then would more or less the same (->)).
Since disp is a Pointer you have to use ->
If you just have a "normal" variable (i.e. on the stack)
Display d;
you can write d.a
A struct is the same as a class. The only difference (I am aware of) is that all members are public by default.
You can do (*disp).a=11;
it is called dereferencing