0

This one

char *house2="JAM gain\r\n"

differs from this one:

string house, prefix="JAM ", suffix="\r\n";
cin>>house;
house = prefix + nickname + suffix;

char house2[100];
strncpy(house2, house.c_str(), sizeof(house));
return house2;

Even though I type "gain" on keyboard, I need to pass this char array with control-characters to api because without them it seems it's not working. what can I do to solve problem?

Ok real code:

string nickname, prefix="NICK ", suffix="\r\n";
cout<<"Choose nickname\n";
cin>>nickname;
nickname = prefix + nickname + suffix;
cout<<nickname;

char nick[100];
strncpy(nick, nickname.c_str(), sizeof(nickname));
return nick;
TryinHard
  • 4,078
  • 3
  • 28
  • 54
Pawel
  • 3
  • 5

3 Answers3

4

sizeof is not doing what you think. Instead of

strncpy(nick, nickname.c_str(), sizeof(nickname));

you want

strncpy(nick, nickname.c_str(), nickname.size());

But even then you open yourself up to buffer-overflow, so you really want

strncpy(nick, nickname.c_str(), sizeof(nick));

Next problem is that nick is local to your function so returning it is going to "cause bad things". You could make it static (and then run into complex problems with threads later...) or you could pass it in as an argument (which would then mean you couldn't use sizeof, for technical reasons). What you really need is something a lot simpler - just return the string, not the C string.

string getNick() {
    string nickname, prefix="NICK ", suffix="\r\n";
    cout<<"Choose nickname\n";
    cin>>nickname;
    nickname = prefix + nickname + suffix;
    cout<<nickname;
    return nickname;
}

And just to show that it really is doing what its supposed to be, here's a working online version. Here's its full code for posterity:

#include <iostream>
#include <string>

std::string getNick() {
    std::string nickname, prefix="NICK ", suffix="\r\n";
    std::cout<<"Choose nickname\n";
    std::cin>>nickname;
    nickname = prefix + nickname + suffix;
    std::cout<<nickname;
    return nickname;
}

int main() {
    std::string nick = getNick();

    std::cout<<"in main nick = '"<<nick<<"'"<<std::endl;
}

Input

gain
.

Output

Choose nickname
NICK gain
in main nick = 'NICK gain
'     

Since you have an API that takes a C string, you'll need to check the details for that api for ownership of the C-string - there are two options.

  1. The API takes ownership of the C string and will dealloc it later.
  2. The API makes a copy of the C string, and you control its lifetime.

In the first case you need to do this: (I'm assuming a C api, which will eventually free the passed in pointer - if its a badly designed C++ API which will delete[] it, you need to replace the malloc with a new char[nick.size()]

string nick = getNick();
char * buffer = (char*)malloc(nick.size()+1);
memcpy(buffer, nick.c_str(), nick.size());
buffer[nick.size()]=0;
your_api(buffer);

In the second case you can simply do

your_api(getNick().c_str());
Michael Anderson
  • 70,661
  • 7
  • 134
  • 187
0

Your code should be

string house, prefix="JAM ", suffix="\r\n";
string nickname;
cin>>nickname;
house = prefix + nickname + suffix;

char house2[100];
strncpy(house2, house.c_str(), sizeof(house2)); 
//or strncpy(house2, house.c_str(), house.length()); 
return string(house2);

Do not return house2 as char* as the memory will be destroyed once the function exits.

doptimusprime
  • 9,115
  • 6
  • 52
  • 90
0

PROBLEM SOLVED (why? :P )

string prawniczek=choosenick();
int TempNumOne=prawniczek.size();
char niczek[40];
for (int a=0;a<=TempNumOne;a++)
    {
        niczek[a]=prawniczek[a];
    }

ok problem was solved by simple rewriting chars at index position one by one

it has to mean that strncpy with nickname.c_str() works different.

anyway - i think that way is not elegant, even though it works

does anyone know how to do it in correct way?

UPDATE: moreover: when the loop is in main at translate to char array from choosenick() method it works perfectly, but when i do it inside method choosenick() and return translated loop result to main it doesn't work

Pawel
  • 3
  • 5