?
Solved

i want to copy a char buffer into string

Posted on 2003-03-31
23
Medium Priority
?
483 Views
Last Modified: 2010-04-01
i have a char buffer defined for 100.
the value in charbuff is to be copied in a string with the help of strcpy
but i get an error saying parameter1 of strcpy argument is not char*
0
Comment
Question by:Kumudini
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 8
  • 7
  • 2
  • +4
23 Comments
 
LVL 2

Expert Comment

by:Francoz
ID: 8243172
> value in charbuff is to be copied

Hope you've executed the below lines

char buffer[100];
char *str;

/*Do some stuff*/

strcpy(str,buffer);

In this case there wont be any compiler errors.
Is your variable str a char* or something else?
0
 
LVL 8

Expert Comment

by:Exceter
ID: 8243206
>> i have a char buffer defined for 100.
>> the value in charbuff is to be copied in a string with the help of strcpy
>> but i get an error saying parameter1 of strcpy argument is not char*

You mean you are trying to place a char array into an std::string? If so, strcpy is not needed for this task. You can simply use the string constructor, the assignment operator, or the assign method to accomplich this. For example,

char array[] = "My name is Exceter";

string s(array); // Uses constructor
string s = array; // Assignment operator
string s.assign( array ); // Assign method

Exceter
0
 

Author Comment

by:Kumudini
ID: 8243257
I want to copy in CString str only
0
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
LVL 8

Accepted Solution

by:
Exceter earned 200 total points
ID: 8243296
Okay then, the first two methods will work with a CString. For example,

char array[] = "My name is Exceter";

CString s( array ); // Use constructor
Cstring s = array; // Use assignment operator

Exceter
0
 
LVL 2

Expert Comment

by:Francoz
ID: 8243351
You can do simply by equating CString to buffer

        CString str;
     char buffer[100];
        str = buffer;

And if you insist on strcpy, then

     char* strin = new char[100];
     strcpy(buffer,"jayesh");
     strcpy(strin,buffer);
     str = strin;
     delete []strin;

0
 
LVL 8

Expert Comment

by:fl0yd
ID: 8247145
To make Francoz suggestion proper c++ code:

#include <string>

char buffer[100];
// fill it with whatever you want
std::string str = std::string( &buffer[0] );

.f
0
 
LVL 12

Expert Comment

by:Salte
ID: 8247151
You can't copy a char buffer into a CString using strcpy. CString has its own methods to manipulate a CString, do NOT use strcpy for that purpose.

char buf[100];

CString str(buf,100);

I am not sure but I believe this overload of the constructor makes a CString out of the char buffer.

If you already have a CString and you want to make that CString equal to the value in the buffer then you can do:

CString str;

str = CString(buf,100);

Now, if you say that this CString does not point to buf but to a copy of buf you are quite correct. Don't attempt to make it point anywhere else. This is internals of how CString work and do not try to mess with it.

Rather tell us what you want to achieve if you insist on such silliness, then we can tell you how to get around it so that you can solve your problem without messing with CString internals.

Alf
0
 
LVL 8

Expert Comment

by:fl0yd
ID: 8247412
CString has and overloaded operator= for const unsigned char* so writing

unsigned char buf[100];
CString str;
str = &buf[0];

is correct. I doubt that

str = buf;

will work though, since an unsigned char[100] just isn't the same thing as a unsigned char*.

.f

p.s.: if you have your buffer allocated as signed char[100] you should do this:

char buf[100];
CString str;
str = static_cast<const unsigned char*>( &buf[0] );
0
 
LVL 8

Expert Comment

by:fl0yd
ID: 8247441
D'oh, it also has and overload for const signed char, so writing

char buf[100];
CString str;
str = &buf[0];

is also correct. There is also a c'tor with a const char, so this

char buf[100];
CString str( &buf[0] );

is just as correct as this:

char buf[100];
CString str = &buf[0];

All of the above implementations perform a _copy_ of the buffer, so there you go, problem solved.

.f
0
 
LVL 12

Expert Comment

by:Salte
ID: 8251727
fl0yd,

for an array:

T arr[N];

where T is some type and N is an integer number.

arr is exactly the same as & arr[0] in almost all cases. There are a few exceptions but they are either obvious or rare (or both).

referencing an array is always a pointer to the first element of the array.


an expression like:

a[b]  in C and C++ is the same as *(a + b) unless a is a type T which has an overload of the index operator.

This also implies that for an array like arr above it is legal to write:

5[arr] = 3;

and it has the same meaning as:

arr[5] = 3;

Check it out, C and C++ allows that syntax!

Alf
0
 
LVL 8

Expert Comment

by:fl0yd
ID: 8252622
Salte,

    that may be the case with C's inferior type checking. In c++ 'T arr[N]' is definately a different type from 'T* arr'. So if in c++ you are calling a function that expects a char* as an argument, a standard-conforming compiler will not let you pass it a variable that is declared as 'char arr[100]'. The easiest way to illustrate that those type are in fact different would be a Typelist in conjunction with search functionality [as proposed by A. Alexandrescu]:

#include <iostream>

// NullType to mark end of Typelist
class NullType {};

// Typelist
template<class T, class U>
struct Typelist {
  typedef T Head;
  typedef U Tail;
};

// searching for type in Typelist
template<class TList, class T> struct IndexOf;

template<class T>
struct IndexOf<NullType, T> {
  enum { value = -1 };
};

template<class T, class Tail>
struct IndexOf<Typelist<T, Tail>, T> {
  enum { value = 0 };
};

template<class Head, class Tail, class T>
struct IndexOf<Typelist<Head, Tail>, T> {
private:
  enum { temp = IndexOf<Tail, T>::value };
public:
  enum { value = temp == -1 ? -1 : 1 + temp };
};

int main( int argc, char* argv[] ) {

  typedef Typelist<char*, NullType> CharPtrList;

  if( -1 != IndexOf<CharPtrList, char[100]>::value )
    std::cout << "Wow, you are right, they _ARE_ the same!!" << std::endl;
  else
    std::cout << "Oh well, fl0yd knows..." << std::endl;

  return( 0 );
}

I'd be interested in the output generated on your systems :-) Don't try this with msvc 6.0 as it won't even compile, haven't checked msvc.net, it may work.

.f
0
 
LVL 12

Expert Comment

by:Salte
ID: 8252928
fl0yd,

time for you to learn some C++.

If you declare an array like this:

T arr[N];

where T is a type and N is an integer then:

arr

in a plain expression is EXACTLY THE SAME as

& arr[0]

i.e. a pointer to the first element. This is specified in the standard.

There are a few exceptions. sizeof(arr) is different from sizeof(& arr[0]). This is because the argument to sizeof() isn't a plain expression but is handled differently from other expressions.

This does not mean that the TYPES T[N] and T * are the same or that they necessarily match for template functions.

That being said, let's examine what you wrote:

nt main( int argc, char* argv[] ) {

 typedef Typelist<char*, NullType> CharPtrList;

 if( -1 != IndexOf<CharPtrList, char[100]>::value )
   std::cout << "Wow, you are right, they _ARE_ the same!!" << std::endl;
 else
   std::cout << "Oh well, fl0yd knows..." << std::endl;

 return( 0 );
}

Now the IndexOf<CharPtrList, char[100]>::value is the one of interest here. It is a class member so we expand it:

IndexOf<Typelist<char *, NullType>, char[100]>::value

This is expanded from either:

struct IndexOf< TypeList<T,Tail>, T >

but as char * is not the same type as char[100] this isn't the correct version and so it is:


struct IndexOf< TypeList<Head, Tail>, T> instead.

This does not in any way disprove what I said. I never said the types are the same, they aren't. sizeof(T *) and sizeof(T[N]) are in general very different.

What I said is that it is silly to use

& arr[0]

anywhere as a simple "arr" is exactly the same:

int arr[100];

func(arr);

if func is a function that accepts a pointer to int this call is fine:

void func(int * vec);

You can also do pointer arithmetic on an array. The only thing is that an array act like a const pointer so you can't modify the 'pointer'. It will always point to the first element of the array.

*(arr + 3) works fine and does exactly what the rest of us expect.

You can even write:

3[arr] and it means exactly the same as arr[3] which is the more common way of writing it. Just try it out on your C++ compiler. If that compiler doesn't accept the 3[arr] syntax it isn't a C++ compiler.

At no place did I claim that the type T[100] (array of T) is the same as T * (pointer to T) which is what you tried to - in a roundabout way - disprove.

There are even simpler and more straight forward ways to prove what you tried:

template <class T>
struct foo;

template <class T,int N>
struct foo<T[N]> {
   enum {
      value = 1,
   };
};

template <class T>
struct foo<T *> {
   enum {
    value = 2,
   };
};

int main()
{
   if (foo<char[100]>::value == foo<char *>::value)
      cout << "They are not the same" << endl;
   else
      cout << "They are the same" << endl;
   return 0;
}

As you might expect this program will always print that they are not the same - which we already knew.

Go back to school fl0yd.

Alf
0
 
LVL 8

Expert Comment

by:fl0yd
ID: 8253104
Salte, there's absolutely no need for personal attacks here. The fact that you tried to do that merely shows your professional attitude, or lack thereof to be precise.

Anyway, since we seem to agree on the fact that char* and char[100] are different types we may also agree on the _FACT_ that a variable of type char[100] cannot, will not, must not be implicitly converted to a char*. I'm willing to take all those things back if you come up with the section in the ISO/ANSI standard that would back your claims. I would hunt it down myself, but honestly, you aren't worth my time.

.f
0
 
LVL 12

Expert Comment

by:Salte
ID: 8253414
>> Salte, there's absolutely no need for personal attacks here. The fact that you tried to do that merely shows your professional attitude, or lack thereof to be precise.

No personal attack, I just said that if you answer here as an expert it is expected that you know C++. You obviously do  not. I advice you to learn C++ before you try to teach others.

>> Anyway, since we seem to agree on the fact that char* and char[100] are different types

I believe we do.

>> we may also agree on the _FACT_ that a variable of type char[100] cannot, will not, must not be implicitly converted to a char*.

This is plain wrong. Again, learn C++.

>>  I'm willing to take all those things back if you come up with the section in the ISO/ANSI standard that would back your claims. I would hunt it down myself, but honestly, you aren't worth my time.

As you probably know the standard itself is not available on the net as it is for sale. I have a copy of it at home but I am not at home now. However, if you can settle for the 1996 draft, I just copied and pasted this from that draft:

1 An lvalue of type "array of N T" or "array of unknown bound of T"  can
  be  converted  to  an  rvalue of type "pointer to T."  The result is a
  pointer to the first element of the array.

It is listed under chapter 4: "standard conversions".

In other words:

T arr[N];

and then simply naming 'arr' in an expression which expects a 'pointer to T' works beautifully and exactly as expected.

As you could write lots of lines attempting to disprove it would be peanuts for you to write this simple program:

void func(int * arr)
{
   arr[3] = 7;
   2[arr] = 9;
};

int main()
{
   int arr[4];

   func(arr);
   cout << "arr[3] == " << 3[arr] << " (should be 7)" << endl;
   cout << "arr[2] == " << arr[2] << " (shoudl be 9)" << endl;
   return 0;
}

and see if you don't get the expected output.

Trust me, you can do this because it is standard C++. Claiming it isn't proves you don't know the standard.

If this doesn't convince you, let me quote Bjarne Stroustrup - incase you don't know, he's the creator of C++ and I think he knows what he's talking about:

From "The C++ programming language", 3rd edition page 91.

(near the bottom of the page).

In C++ pointers and arrays are closely related. The name of an array can be used as a pointer to its initial element. For example:

  int v[] = { 1, 2, 3, 4 };
  int * p1 = v; // pointer to inital element.
  int * p2 = &v[0]; // same thing
  int * p3 = &v[4]; // point just past the array.

On the next page he shows a picture of where the pointers are pointing.

You obviously don't know C++ and I suggest you learn it before you try to pose as an expert.

Alf
0
 
LVL 8

Expert Comment

by:fl0yd
ID: 8253865
Well, that's the draft version. If you are all that experienced, how come you never bought the complete standard? Lack of money? Arrogance? And maybe you should read the footnotes too, they contain viable information about deprecated features. Hope you have checked that with Annex D as well.

.f
0
 
LVL 2

Expert Comment

by:MirkoLMV
ID: 8254135
Maybe is better to calm down on the expertise issues. About the expert status, there is a still open problem: what needs someone to be considered as an expert ? In most cases was enough to master and currently employ more knowledge than his fellow specialist, but this did not mean that he would know in detail every area within his domain of expertise.
I have not found any material accepted even for a certain group or institution which would enclose all the issues to be mastered be someone as a minimal requirement to be recognized as an expert. I have not still found a book or tutorial on C++ equally great am all issues. I have noticed that these sources were rather complementary in many aspects. And slight variations on currently used compilers are creating additional problems.
Who enjoys in studying the history of science will find that every overall-accepted genius have made a few blunders, but the mankind preferred to remember the achievements.

0
 
LVL 12

Expert Comment

by:Salte
ID: 8254241
For one thing, I doubt many experts purchase the standard themselves. Only if you work on making a compiler or run time library for C++ do you need to have the standard around you. If you do and if you work for some employer it is normal that the employer pay for it so the cost isn't an issue.

Secondly, I am at work and I am not working on a compiler for C++ I am only using C++ daily in my job. There is no need for the standard. I know C++ well enough without it. If I am in doubt of some issue I will generally look it up on the net. I believe I also have a book with the C++ standard at home so I can look it up there if I want to. As I already said I am at work and not at home so I can't look it up that fast. I am afraid you have to wait until I get home.

Third, Standards do not change that fast. In particular the idea of equating an array with a pointer is one of the core elements of traditional C and abandoning that feature makes the language more distant from C than is necessary. True, some people feel that the lack of bounds checking in C and C++ is an issue and to them this idea of considering an array to be the same as a pointer to the first element when used in a general expression comes out as one of the things that must be changed before C++ can support bounds checking.

Fourth, your reference to annex D appear out of place. Annex D does enumerate various things that are depreceated but at least the online version which is available to me here does not list the 'array to pointer' immediate conversion as depreceated.

If you think of:

1 The  implicit  conversion  from  const  to non-const qualification for
  string literals (_ptr.array_) is deprecated.

Then this is concerning string literals and it concerns that the implicit conversion to non-const is depreceated.

char * ptr = "hello";

is deprecated, you should use:

const char * ptr = "hello";

You can also use:

const char str[] = "hello";

but then it's not a pointer any more. That doesn't matter much though since str by itself in most contexts would be a pointer to the 'h' of the string.

cout << str << endl;

str will be converted to a 'const char *' type pointing to the first 'h' of the string "hello".

str + 3 would be a pointer pointing to the second 'l'.
*(str + 3) would be the character 'l' and would be the same as str[3] and 3[str].

It is possible that the 3[str] might be considered archaic and deprecated at some time but the reason why it is permitted is that str[3] is the same as *(str + 3) which is the same as *(3 + str) so obviously 3[str] must also be allowed.

Of course, for a class X with [] operator overloaded you cannot do:

X x;

3[x] and hope that it will work. For such overloads you must use x[3]. Part of the reason for that is that for user defined types there are no connection between x[3] and *(x + 3), a class may define operator [] but not operator + and the operator + might not return a type that defines the operator * (prefix operator) and even if they do there's no requirement that x[3] is the same as *(x + 3) for a variable x of the user defined type X.

As I said, learn the language. It is possible that some future standard of C++ announce certian things as depreceated and it is possible that the 3[arr] form might be (although I don't believe it will happen in the near future) but even less than that would I believe that they abandon the 'array to pointer immediate conversion' thing as it is one of the core elements of C++ that is inherited from C.

Alf
0
 
LVL 8

Expert Comment

by:fl0yd
ID: 8255069
Thanks for pointing out repeatedly how little I actually know. And thanks again for continously belittleling me. You are truely _the_ master. I'm sure your coworkers are having a lot of fun with your attitude. If you are working at all, that is -- to me it looks more like someone spending his/her entire time hanging around a board, typing page after page, just to show off his skills to those poor little individuals, that will never quite make it to live up to your omipotent powers.

.f
0
 
LVL 12

Expert Comment

by:Salte
ID: 8255554
Believe it or not fl0yd, I do have a job.

I sit on a linux machine making software for telecom industry writing network code related to SIP standard. That's Session initiation protocol.

No, I generally do not belittle people. However, you are not a regular user, you are answering questions as an expert and as an expert people expect that you actually know your subject.

I do not have problems with my attitude and most people get along with me just fine. I just expect that if people give other people advice that they actually know what they are talking about. True, there are times when I myself have made a mistake and screwed up. However, when that occur I do admit my error and correct the mistake as soon as I realize it is a mistake.

I do not insist that I am correct even after I realize I am wrong. Now, it is possible you simply didn't realize you were wrong but one would expect that after it had been pointed out you would at least consult your C++ book or some other resource around and not just show an "I insist that I am right and you are wrong" attitude.

Alf
0
 
LVL 8

Expert Comment

by:fl0yd
ID: 8256276
Thanks dad. It's great having talked to you after so long.

.f
0
 
LVL 12

Expert Comment

by:Salte
ID: 8259700
fl0yd,

This has left the topic of this thread long ago. I suggest we let this issue lie. If you have any more gripe about this issue, please feel free to post a new posting where you state your opinion or whatever.

As MirkoLMV says it is a problem to define what constitutes an "expert" however, I do believe that one can expect from an expert that if someone content something he says that he at least check and verify that he is correct before he moves on. In any case this debate has been very much off topic and the poor guy who asked the question in this thread is not being helped by such a debate. I suggest we let it lie.

I believe Kumudini, if he is still around that he has got his help already. His main problem was that he tried to strcpy() into a CString destination and that is not the way to do it. I believe he has got his help. We should therefore let this thread close and not debate irrelevant issues.

However, I do want to point out that & arr[0] even if legal does appear odd to most C++ programmers since it is exactly the same as arr and it appears like a roundabout way of doing it. It is therefore clearer and simpler to just write 'arr' instead of '& arr[0]'. It is therefore best to teach people the C++ and C way of doing this.

I agree that in certain template code you might find:

& arr[0] instead of 'arr' since the type of 'arr' may not be known at the time you define the template.

Alf
0
 
LVL 11

Expert Comment

by:bcladd
ID: 9979143
No comment has been added lately, so it's time to clean up this TA. I will
leave a recommendation in the Cleanup topic area that this question is:

Answered: Points to Exceter: Grade A

Please leave any comments here within the next seven days.

Experts: Silence means you don't care. Grading recommendations are made in light
of the posted grading guidlines (http://www.experts-exchange.com/help.jsp#hi73).

PLEASE DO NOT ACCEPT THIS COMMENT AS AN ANSWER!

-bcl (bcladd)
EE Cleanup Volunteer
0

Featured Post

On Demand Webinar: Networking for the Cloud Era

Did you know SD-WANs can improve network connectivity? Check out this webinar to learn how an SD-WAN simplified, one-click tool can help you migrate and manage data in the cloud.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Templates For Beginners Or How To Encourage The Compiler To Work For You Introduction This tutorial is targeted at the reader who is, perhaps, familiar with the basics of C++ but would prefer a little slower introduction to the more ad…
  Included as part of the C++ Standard Template Library (STL) is a collection of generic containers. Each of these containers serves a different purpose and has different pros and cons. It is often difficult to decide which container to use and …
The viewer will learn how to pass data into a function in C++. This is one step further in using functions. Instead of only printing text onto the console, the function will be able to perform calculations with argumentents given by the user.
The viewer will learn how to use the return statement in functions in C++. The video will also teach the user how to pass data to a function and have the function return data back for further processing.
Suggested Courses

770 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question