C++ Primer ex 4.30

A

arnuld

i think this needs some improvement.

/* C++ Primer - 4/e

* chapter 4- Arrays & Pointers, exercise 4.30 * STATEMENT
* write a programme to concatenate the two C-style strings literals
putting the result in a C-style string. then write a programme to
concatenate 2 standard library strings.

*/


#include <iostream>
#include <string>
#include <cstring>

int main()
{
const char* sl1 = "first";
const char* sl2 = "second";

const size_t final_size = strlen(sl1) + strlen(sl2) + 2; /* since we
need a space between the two strings and a NULL
terminator in the end, so we added 2 here */

char* final_sl = new char[final_size];

strcpy(final_sl, sl1);
strcat(final_sl, " ");
/* where does the '\0' of 1st string literal will go ?
does "final_sl" look like this:
['f','i','r','s','t','\0',' ','s','e','c','o','n','d','\0']
*/
strcat(final_sl, sl2);

std::cout << final_sl << std::endl;

delete [] final_sl;


/* standard library strings */
std::string s1 = "first";
std::string s2 = "second";

std::string s3 = s1 + " " + s2;

std::cout << s3 << std::endl;

return 0;
}

======== OUTPUT ===========
~/programming/cpp $ g++ -ansi -pedantic -Wall -Wextra ex_04-30.cpp
~/programming/cpp $ ./a.out
first second
first second
~/programming/cpp $
 
V

Victor Bazarov

arnuld said:
i think this needs some improvement.

/* C++ Primer - 4/e

* chapter 4- Arrays & Pointers, exercise 4.30 * STATEMENT
* write a programme to concatenate the two C-style strings
literals putting the result in a C-style string. then write a
programme to concatenate 2 standard library strings.

*/


#include <iostream>
#include <string>
#include <cstring>

int main()
{
const char* sl1 = "first";
const char* sl2 = "second";

const size_t final_size = strlen(sl1) + strlen(sl2) + 2; /* since we
need a space between the two strings and a NULL
terminator in the end, so we added 2 here */

char* final_sl = new char[final_size];

strcpy(final_sl, sl1);
strcat(final_sl, " ");
/* where does the '\0' of 1st string literal will go ?

Nowhere. It stays in the 1st literal. The destination string gets
its own temrinator after each 'strcpy' or 'strcat', but every time
you invoke 'strcat' again, the terminator is overridden by the first
character of the source string.
does "final_sl" look like this:
['f','i','r','s','t','\0',' ','s','e','c','o','n','d','\0']

No, it does not. Drop the first null char, then you get the real
string. Examine the contents in the debugger or print it out char
by char (since it's an array, after all) in a loop. You will see
that there is no first '\0'. BTW, if there were, the output would
consist only of "first" and no " second" because it would stop at
the null character.
*/
strcat(final_sl, sl2);

std::cout << final_sl << std::endl;

delete [] final_sl;


/* standard library strings */
std::string s1 = "first";
std::string s2 = "second";

std::string s3 = s1 + " " + s2;

I prefer direct initialisation:

std::string s1("first");
std::string s2("second");
std::string s3(s1 + " " + s2);

And really there is no sense to have three separate statements
to declare/define those objects (unless your company's stupid
coding standard requires those), so I'd write

std::string s1("first"), s2("second"), s3(s1 + " " + s2);
std::cout << s3 << std::endl;

return 0;
}

======== OUTPUT ===========
~/programming/cpp $ g++ -ansi -pedantic -Wall -Wextra ex_04-30.cpp
~/programming/cpp $ ./a.out
first second
first second
~/programming/cpp $

V
 
J

Junhui Tong

arnuld said:
i think this needs some improvement.

/* C++ Primer - 4/e

* chapter 4- Arrays & Pointers, exercise 4.30 * STATEMENT
* write a programme to concatenate the two C-style strings literals
putting the result in a C-style string. then write a programme to
concatenate 2 standard library strings.

*/


#include <iostream>
#include <string>
#include <cstring>

int main()
{
const char* sl1 = "first";
const char* sl2 = "second";

const size_t final_size = strlen(sl1) + strlen(sl2) + 2; /* since we
need a space between the two strings and a NULL
I think you needn't place a space here (just like the function `strcat')
terminator in the end, so we added 2 here */

char* final_sl = new char[final_size];

strcpy(final_sl, sl1);
strcat(final_sl, " ");
I think you cannot use `strcat' here, because you are now implementing
another `strcat'.
/* where does the '\0' of 1st string literal will go ?
does "final_sl" look like this:
['f','i','r','s','t','\0',' ','s','e','c','o','n','d','\0']
*/
strcat(final_sl, sl2);

std::cout << final_sl << std::endl;

delete [] final_sl;


/* standard library strings */
std::string s1 = "first";
std::string s2 = "second";

std::string s3 = s1 + " " + s2;

std::cout << s3 << std::endl;

return 0;
}

======== OUTPUT ===========
~/programming/cpp $ g++ -ansi -pedantic -Wall -Wextra ex_04-30.cpp
~/programming/cpp $ ./a.out
first second
first second
~/programming/cpp $
 
J

Jerry Coffin

[ ... ]
* write a programme to concatenate the two C-style strings literals
putting the result in a C-style string. then write a programme to
concatenate 2 standard library strings.

Just FWIW, I don't see anything here to indicate that you're supposed to
put a space between the strings being concatenated.

[ ... ]
strcpy(final_sl, sl1);
strcat(final_sl, " ");
/* where does the '\0' of 1st string literal will go ?
does "final_sl" look like this:
['f','i','r','s','t','\0',' ','s','e','c','o','n','d','\0']
*/
strcat(final_sl, sl2);

I think I'd replace this chunk of code with something like:

sprintf(final_s1, "%s %s", sl1, sl2);

Though, of course, I doubt I'd do anything like that in C++ at all...

To answer your question, the first strcpy copies the original string
into the destination, including the terminating NUL. strcat then finds
the end of the string and overwrites the NUL with the first character in
the string being concatenated, and adds another NUL at the end of the
string it concatenates to the first. In your case, you do another
strcat, which does the same thing again. Over time, your result string
looks like:

strcpy: ['f','i','r','s','t','\0']
strcat 1: ['f','i','r','s','t',' ','\0']
strcat 2: ['f','i','r','s','t',' ','s','e','c','o','n','d','\0']

In the first two cases, the remainder of the allocated space is filled
with indeterminate data.

To answer a point you made in a related thread, both 0 and '\0' are
required to have the value zero. The only difference between them is the
type -- 0 is an int whereas '\0' is a char (unlike in C, where they both
have type int). A C-style string is terminated by a char with the value
zero.
 
J

James Kanze

[...]
std::string s1("first");
std::string s2("second");
std::string s3(s1 + " " + s2);
And really there is no sense to have three separate statements
to declare/define those objects (unless your company's stupid
coding standard requires those),

Or unless you want other people to be able to read and maintain
your code. C++ declaration syntax is already bad enough without
abusing it.
so I'd write
std::string s1("first"), s2("second"), s3(s1 + " " + s2);

So that the first professional who comes along, and is concerned
with maintainability, would have to rewrite it. That's a very
good example of something you should not do.
 
V

Victor Bazarov

James said:
[...]
std::string s1("first");
std::string s2("second");
std::string s3(s1 + " " + s2);
And really there is no sense to have three separate statements
to declare/define those objects (unless your company's stupid
coding standard requires those),

Or unless you want other people to be able to read and maintain
your code. C++ declaration syntax is already bad enough without
abusing it.
so I'd write
std::string s1("first"), s2("second"), s3(s1 + " " + s2);

So that the first professional who comes along, and is concerned
with maintainability, would have to rewrite it. That's a very
good example of something you should not do.

I just love how easy it is to get into a religious war over a non-
issue like that.
 
A

Alf P. Steinbach

* Victor Bazarov:
James said:
[...]
std::string s1("first");
std::string s2("second");
std::string s3(s1 + " " + s2);
And really there is no sense to have three separate statements
to declare/define those objects (unless your company's stupid
coding standard requires those),
Or unless you want other people to be able to read and maintain
your code. C++ declaration syntax is already bad enough without
abusing it.
so I'd write
std::string s1("first"), s2("second"), s3(s1 + " " + s2);
So that the first professional who comes along, and is concerned
with maintainability, would have to rewrite it. That's a very
good example of something you should not do.

I just love how easy it is to get into a religious war over a non-
issue like that.

Heya Victor, I think James' follow up was quite reasonable; you was the
one using loaded words like "stupid". And I agree with James. Not only
is the source code more readable with separate declarations, it's also a
convention that helps avoid some simple errors, it better supports
editing, and it better supports debugging because you can run up to a
given declaration, so it's not religious, just what's practical in C++.
 
V

Victor Bazarov

Alf said:
* Victor Bazarov:
James said:
On Jul 24, 3:18 pm, "Victor Bazarov" <[email protected]>
wrote: [...]
std::string s1("first");
std::string s2("second");
std::string s3(s1 + " " + s2);
And really there is no sense to have three separate statements
to declare/define those objects (unless your company's stupid
coding standard requires those),
Or unless you want other people to be able to read and maintain
your code. C++ declaration syntax is already bad enough without
abusing it.

so I'd write
std::string s1("first"), s2("second"), s3(s1 + " " + s2);
So that the first professional who comes along, and is concerned
with maintainability, would have to rewrite it. That's a very
good example of something you should not do.

I just love how easy it is to get into a religious war over a non-
issue like that.

Heya Victor, I think James' follow up was quite reasonable; you was
the one using loaded words like "stupid". And I agree with James. Not
only is the source code more readable with separate declarations,

<shrug>

IMNSHO muliplying 'std::string' like it does in the code fragment above
is NOT more readable, whatever you and James may have to say about it;
everybody's standards of readability are different.

There has to be a significant number of people agreeing with some
point of view to make that point of view reasonable. As to loadedness
of any words you choose to pick on, I've dealt with enough coding
standards to have my opinion on them and to be able to call some of
them stupid. I am not going to continue this.
it's also a convention that helps avoid some simple errors, it better
supports editing, and it better supports debugging because you can
run up to a given declaration, so it's not religious, just what's
practical in C++.

It's a *style* issue. Of course it *is* religious.

V
 
J

Jim Langston

Victor Bazarov said:
Alf said:
* Victor Bazarov:
James Kanze wrote:
On Jul 24, 3:18 pm, "Victor Bazarov" <[email protected]>
wrote: [...]
std::string s1("first");
std::string s2("second");
std::string s3(s1 + " " + s2);
And really there is no sense to have three separate statements
to declare/define those objects (unless your company's stupid
coding standard requires those),
Or unless you want other people to be able to read and maintain
your code. C++ declaration syntax is already bad enough without
abusing it.

so I'd write
std::string s1("first"), s2("second"), s3(s1 + " " + s2);
So that the first professional who comes along, and is concerned
with maintainability, would have to rewrite it. That's a very
good example of something you should not do.

I just love how easy it is to get into a religious war over a non-
issue like that.

Heya Victor, I think James' follow up was quite reasonable; you was
the one using loaded words like "stupid". And I agree with James. Not
only is the source code more readable with separate declarations,

<shrug>

IMNSHO muliplying 'std::string' like it does in the code fragment above
is NOT more readable, whatever you and James may have to say about it;
everybody's standards of readability are different.

There has to be a significant number of people agreeing with some
point of view to make that point of view reasonable. As to loadedness
of any words you choose to pick on, I've dealt with enough coding
standards to have my opinion on them and to be able to call some of
them stupid. I am not going to continue this.
it's also a convention that helps avoid some simple errors, it better
supports editing, and it better supports debugging because you can
run up to a given declaration, so it's not religious, just what's
practical in C++.

It's a *style* issue. Of course it *is* religious.

Personally, I also break up declarations on each line. Its not as easy to
see each one, and some can cause confusion. Such as:
char* a, b, c;

Also, lines can tend to get long with initialization etc.. and it can get
confusing as to what is being declared.

I agree, however, that it is a style issue.

Calling a style issue you don't agree with as "stupid", however, does make
it a religious issue.
 
V

Victor Bazarov

Jim said:
[..]
Personally, I also break up declarations on each line. Its not as
easy to see each one, and some can cause confusion. Such as:
char* a, b, c;

Also, lines can tend to get long with initialization etc.. and it can
get confusing as to what is being declared.

I agree, however, that it is a style issue.

Calling a style issue you don't agree with as "stupid", however, does
make it a religious issue.

Please reread my post in which the word "stupid" appeared first.
Then please post an apology for misunderstanding of *what* I called
stupid.

V
 
J

James Kanze

IMNSHO muliplying 'std::string' like it does in the code
fragment above is NOT more readable, whatever you and James
may have to say about it; everybody's standards of readability
are different.

Readability can be tested, and more or less objectively
measured. (Not that anyone is actually doing it, of course.)
There has to be a significant number of people agreeing with some
point of view to make that point of view reasonable.

Number of people agreeing is very orthogonal with reasonability.
As to loadedness of any words you choose to pick on, I've
dealt with enough coding standards to have my opinion on them
and to be able to call some of them stupid. I am not going to
continue this.
It's a *style* issue. Of course it *is* religious.

It stops being a style issue when someone has to maintain the
code. For example, by changing the type of one of the
variables, without changing the others.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads

C++ Primer ex 5.18 5
C++ Primer ex 9.27 4
C++ Primer ex 7.3 21
C++ Primer ex 7.16 - arguments to main 15
C++ Primer ex 3.14 8
C++ Primer ex 7.6 17
C++ Primer ex 4.16 2
C++ Primer ex 9.14 11

Members online

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,065
Latest member
OrderGreenAcreCBD

Latest Threads

Top