What does strcpy(s+i, s+i+1) mean? - c++

I have this piece of code:
int i = 0;
char s[12];
strcpy(s,"abracadabra");
cout << strlen(s);
while(i < strlen(s))
{
if (s[i]=='a') strcpy(s+i, s+i+1);
else i++;
}
cout << " " << s;
But I can't understand why the output is brcdbr.
I thought that s+i means s[n+i] or something like that?
Can someone explain to me how this works?

In your terminal type man strcpy
char *strcpy(char *dest, const char *src);
The strcpy() function copies the string pointed to by src,
including the terminating null byte ('\0'), to the buffer pointed
to by dest. The strings may not overlap, and the destination
string dest must be large enough to receive the copy. Beware of
buffer overruns! (See BUGS.)
So you are copying all bytes from your string,
from src: index i + 1 (the next letter after 'a') to '\0'
to dest: index i (letter 'a') to '\0'
NB: As stated in the comments it is a very inefficient way and undefined behavior to get rid of the 'a', but I guess you came here for the explanation about s+i, it means &s[i] or even &i[s].
Read more about "Pointer arithmetic"
If you want an efficient way take a look at this post

Can someone explain to me how this works?
it doesn't work, the behavior of the program is undefined. Nothing meaningful can be said about the outcome (even if it looks correct in some specific case).
For example, here on godbolt the output is not brcdbr but brcdrr.
That's because it's illegal to invoke strcpy with overlapping source and destination pointers:
C11 §7.24.2.3 The strcpy function
The strcpy function copies the string pointed to by s2 (including the
terminating null character) into the array pointed to by s1. If
copying takes place between objects that overlap, the behavior is
undefined.
(note: C++ inherits C rules for C standard library functions)
Anyway, if you just wanted to know the intention behind strcpy(s+i, s+i+1), in C++ expressions an array automatically decays to a pointer. So char s[12] becomes char* s. Then the expression s+i becomes pointer arithmetic - taking an address of ith element pointed-to by s. It is equivalent to writing &s[i], i.e. taking an address of ith element in s. The same applies to s+i+1 - it evaluates to a pointer to the i+1th element in s. The intention of the strcpy call was to copy the remainder of the string after a to the memory are starting at a, i.e. to shift the remaining characters forward by one, thus overwriting the a.
A better way in C++ would be to use std::string and the erase-remove idiom to remove the characters a from the string:
#include <iostream>
#include <algorithm>
#include <string>
int main() {
std::string s = "abracadabra";
s.erase(std::remove(s.begin(), s.end(), 'a'), s.end());
std::cout << s << std::endl;
}
Prints:
brcdbr

Related

How to reverse a string using pointers?

How to reverse a string using pointers. I don't understand any of the answers online. I need it to be explained really slowly.
For an assignment, I need to use pointers to reverse a string (and to use that to test if something is a palindrome), and I cannot for the life of me understand any of the answers to similar questions online. In this question, for instance, the top answer is:
void rev_string(char *str)
{
char *p = str, *s = str + strlen(str) - 1;
while (p < s) {
char tmp = *p;
*p++ = *s;
*s-- = tmp;
}
}
This barely makes sense to me.
First of all, why is the input a char when we're looking to reverse a string? The * marks it as a pointer as well, right? Why is the input a pointer when we're looking to reverse a string?
I understand the first line of code with the variable initialization is meant to set pointer p equal to the start of the string, and pointer s to the tail of the string, but why?
I get the feeling that *p++ and *s-- are supposed to go to the next letter or the previous letter of the string, respectively, but why does that work?
Please assist.
I think the main problem with your example is that the coding style is bad.
Good code is readable (another good lesson to learn today).
The use of prefix and postfix ++, -- in the original code
while correct do also not help in making clear what the code is doing.
Another lesson is not to sacrifice readability for premature optimization like that. Compilers are smart and can optimize quite a bit of your input.
#include <iostream>
void reverse(char* input)
{
const std::size_t offset_of_last_character = strlen(input) - 1;
char* begin_pointer = &input[0]; // front_pointer now contains address of first character in string
char* end_pointer = &input[offset_of_last_character]; // end_pointer now contains address of last character in the string
while (begin_pointer < end_pointer) // as long as pointers don't cross-over in memory continue
{
// swap the characters pointed to
// first iteration this will be first and last character,
// second iteration this will be the second and the character and last but one character, etc...
std::swap(*begin_pointer, *end_pointer);
++begin_pointer; // move one address up in memory, this is where the next character is found
--end_pointer; // move on address down in memory, this is where the previous character is found
}
}
int main()
{
char input[] = "!dlrow olleH";
reverse(input);
std::cout << input;
return 0;
}
First of all, why is the input a char when we're looking to reverse a string? The * marks it as a pointer as well, right? Why is the input a pointer when we're looking to reverse a string?
The code is C. A string in C is a NUL-terminated array of chars. Thus a "hello" string is indeed a char str[6] = {'h', 'e', 'l', 'l', 'o', (char)0x00}; How do you pass this to a function? You pass the pointer char * to the very first element of a string.
I understand the first line of code with the variable initialization is meant to set pointer p equal to the start of the string, and pointer s to the tail of the string, but why?
Because the function considers the input pointer to point at the start of a char array with the aforementioned properties. Pointers p and s are meant to point inside the array. Pointer p is initially set at the start of the array, pointer s is initially set at a strlen(str) - 1 offset into the array. The offset is exactly where the last character in the array is.
I get the feeling that *p++ and *s-- are supposed to go to the next letter or the previous letter of the string, respectively, but why does that work?
The feeling is correct. These two are just pointers inside the array, they just travel along array's elements. This syntax used here says: "dereference the pointer, and right after the expression is done (may think compiler sees ;) increment/decrement the pointer".
To finish it up. I really recommend the "C Programming Language" book to read. Strings in C, passing arrays to functions, and pointer arithmentics are what the given code is about.

in the C ++ stl, does the string container actually contain a string with a closing 0? [duplicate]

Will the below string contain the null terminator '\0'?
std::string temp = "hello whats up";
No, but if you say temp.c_str() a null terminator will be included in the return from this method.
It's also worth saying that you can include a null character in a string just like any other character.
string s("hello");
cout << s.size() << ' ';
s[1] = '\0';
cout << s.size() << '\n';
prints
5 5
and not 5 1 as you might expect if null characters had a special meaning for strings.
Not in C++03, and it's not even guaranteed before C++11 that in a C++ std::string is continuous in memory. Only C strings (char arrays which are intended for storing strings) had the null terminator.
In C++11 and later, mystring.c_str() is equivalent to mystring.data() is equivalent to &mystring[0], and mystring[mystring.size()] is guaranteed to be '\0'.
In C++17 and later, mystring.data() also provides an overload that returns a non-const pointer to the string's contents, while mystring.c_str() only provides a const-qualified pointer.
This depends on your definition of 'contain' here. In
std::string temp = "hello whats up";
there are few things to note:
temp.size() will return the number of characters from first h to last p (both inclusive)
But at the same time temp.c_str() or temp.data() will return with a null terminator
Or in other words int(temp[temp.size()]) will be zero
I know, I sound similar to some of the answers here but I want to point out that size of std::string in C++ is maintained separately and it is not like in C where you keep counting unless you find the first null terminator.
To add, the story would be a little different if your string literal contains embedded \0. In this case, the construction of std::string stops at first null character, as following:
std::string s1 = "ab\0\0cd"; // s1 contains "ab", using string literal
std::string s2{"ab\0\0cd", 6}; // s2 contains "ab\0\0cd", using different ctr
std::string s3 = "ab\0\0cd"s; // s3 contains "ab\0\0cd", using ""s operator
References:
https://akrzemi1.wordpress.com/2014/03/20/strings-length/
http://en.cppreference.com/w/cpp/string/basic_string/basic_string
Yes if you call temp.c_str(), then it will return null-terminated c-string.
However, the actual data stored in the object temp may not be null-terminated, but it doesn't matter and shouldn't matter to the programmer, because when then programmer wants const char*, he would call c_str() on the object, which is guaranteed to return null-terminated string.
With C++ strings you don't have to worry about that, and it's possibly dependent of the implementation.
Using temp.c_str() you get a C representation of the string, which will definitely contain the \0 char. Other than that, i don't really see how it would be useful on a C++ string
std::string internally keeps a count of the number of characters. Internally it works using this count. Like others have said, when you need the string for display or whatever reason, you can its c_str() method which will give you the string with the null terminator at the end.

Why does cout << &r give different output than cout << (void*)&r?

This might be a stupid question, but I'm new to C++ so I'm still fooling around with the basics. Testing pointers, I bumped into something that didn't produce the output I expected.
When I ran the following:
char r ('m');
cout << r << endl;
cout << &r << endl;
cout << (void*)&r << endl;
I expected this:
m
0042FC0F
0042FC0F
..but I got this:
m
m╠╠╠╠ôNh│hⁿB
0042FC0F
I was thinking that perhaps since r is of type char, cout would interpret &r as a char* and [for some reason] output the pointer value - the bytes comprising the address of r - as a series of chars, but then why would the first one would be m, the content of the address pointed to, rather than the char representation of the first byte of the pointer address.. It was as if cout interprets &r as r but instead of just outputting 'm', it goes on to output more chars - interpreted from the byte values of the subsequent 11 memory addresses.. Why? And why 11?
I'm using MSVC++ (Visual Studio 2013) on 64 bit Win7.
Postscript: I got a lot of correct answers here (as expected, given the trivial nature of the question). Since I can only accept one, I made it the first one I saw. But thanks, everyone.
So to summarize and expand on the instinctive theories mentioned in my question:
Yes, cout does interpret &r as char*, but since char* is a 'special thing' in C++ that essentially means a null terminated string (rather than a pointer [to a single char]), cout will attempt to print out that string by outputting chars (interpreted from the byte contents of the memory address of r onwards) until it encounters '\0'. Which explains the 11 extra characters (it just coincidentally took 11 more bytes to hit that NUL).
And for completeness - the same code, but with int instead of char, performs as expected:
int s (3);
cout << s << endl;
cout << &s << endl;
cout << (void*)&s << endl;
Produces:
3
002AF940
002AF940
A char * is a special thing in C++, inherited from C. It is, in most circumstances, a C-style string. It is supposed to point to an array of chars, terminated with a 0 (a NUL character, '\0').
So it tries to print this, following on in to the memory after the 'm', looking for a terminating '\0'. This makes it print some random garbage. This is known as Undefined Behaviour.
There is an operator<< overload specifically for char* strings. This outputs the null-terminated string, not the address. Since the pointer you're passing this overload isn't a null-terminated string, you also get Undefined Behavior when operator<< runs past the end of the buffer.
Conversely, the void* overload will print the address.
Because operator<< is overloaded based on the data type.
If you give it a char, it assumes you want that character.
If you give it a void*, it assumes you want an address.
However, if you give it a char*, it takes that as a C-style string and attempts to output it as such. Since the original intent of C++ was "C with classes", handling of C-style strings was a necessity.
The reason you get all the rubbish at the end is simply because, despite your assertion to the compiler, it isn't actually a C-style string. Specifically, it is not guaranteed to have a string-terminating NUL character at the end so the output routines will just output whatever happens to be in memory after it.
This may work (if there's a NUL there), it may print gibberish (if there's a NUL nearby), or it may fall over spectacularly (if there's no NUL before it gets to memory it cannot read). It's not something you should rely on.
Because there's an overload of operator<< which takes a const char pointer as it's second argument and prints out a string. The overload that takes a void pointer prints only the address.
A char * is often - usually even - a pointer to a C-style null-terminated string (or a string literal) and is treated as such by ostreams. A void * by contrast unambiguously indicates a pointer value is required.
The output operator (operator<<()) is overloaded for char const* and void const*. When passing a char* the overload for char const* is a better match and chosen. This overload expects a pointer to the start of a null terminated string. You give it a pointer to an individual char, i.e., you get undefined behavior.
If you want to try with a well-defined example you can use
char s[] = { 'm', 0 };
std::cout << s[0] << '\n';
std::cout << &s[0] << '\n';
std::cout << static_cast<void*>(&s[0]) << '\n';

Store value in Pointers as an Array - C++

I am trying to make a function like strcpy in C++. I cannot use built-in string.h functions because of restriction by our instructor. I have made the following function:
int strlen (char* string)
{
int len = 0;
while (string [len] != (char)0) len ++;
return len;
}
char* strcpy (char* *string1, char* string2)
{
for (int i = 0; i<strlen (string2); i++) *string1[i] = string2[i];
return *string1;
}
main()
{
char* i = "Farid";
strcpy (&i, "ABC ");
cout<<i;
}
But I am unable to set *string1 [i] value. When I try to do so an error appears on screen 'Program has encountered a problem and need to close'.
What should I do to resolve this problem?
Your strcpy function is wrong. When you write *string1[i] you are actually modifying the first character of the i-th element of an imaginary array of strings. That memory location does not exist and your program segfaults.
Do this instead:
char* strcpy (char* string1, char* string2)
{
for (int i = 0; i<strlen (string2); i++) string1[i] = string2[i];
return string1;
}
If you pass a char* the characters are already modifiable. Note It is responsibility of the caller to allocate the memory to hold the copy. And the declaration:
char* i = "Farid";
is not a valid allocation, because the i pointer will likely point to read-only memory. Do instead:
char i[100] = "Farid";
Now i holds 100 chars of local memory, plenty of room for your copy:
strcpy(i, "ABC ");
If you wanted this function to allocate memory, then you should create another one, say strdup():
char* strdup (char* string)
{
size_t len = strlen(string);
char *n = malloc(len);
if (!n)
return 0;
strcpy(n, string);
return n;
}
Now, with this function the caller has the responsibility to free the memory:
char *i = strdup("ABC ");
//use i
free(i);
Because this error in the declaration of strcpy: "char* *string1"
I don't think you meant string1 to be a pointer to a pointer to char.
Removing one of the * should word
The code has several issues:
You can't assign a string literal to char* because the string literal has type char const[N] (for a suitable value of N) which converts to char const* but not to char*. In C++03 it was possible to convert to char* for backward compatibility but this rule is now gone. That is, your i needs to be declared char const*. As implemented above, your code tries to write read-only memory which will have undesirable effects.
The declaration of std::strcpy() takes a char* and a char const*: for the first pointer you need to provide sufficient space to hold a string of the second argument. Since this is error-prone it is a bad idea to use strcpy() in the first place! Instead, you want to replicate std::strncpy() which takes as third argument the length of the first buffer (actually, I'm never sure if std::strncpy() guarantees zero termination or not; you definitely also want to guarantee zero termination).
It is a bad idea to use strlen() in the loop condition as the function needs to be evaluated for each iteration of the loop, effectively changing the complexity of strlen() from linear (O(N)) to quadratic (O(N2)). Quadratic complexity is very bad. Copying a string of 1000 characters takes 1000000 operations. If you want to try out the effect, copy a string with 1000000 characters using a linear and a quadratic algorithm.
Your strcpy() doesn't add a null-terminator.
In C++ (and in C since ~1990) the implicit int rule doesn't apply. That is, you really need to write int in front of main().
OK, a couple of things:
you are missing the return type for the main function
declaration. Not really allowed under the standard. Some compilers will still allow it, but others will fail on the compile.
the way you have your for loop structured in
strcpy you are calling your strlen function each time through
the loop, and it is having to re-count the characters in the source
string. Not a big deal with a string like "ABC " but as strings get
longer.... Better to save the value of the result into a variable and use that in the for loop
Because of the way that you are declaring i in
`main' you are pointing to read-only storage, and will be causing an
access violation
Look at the other answers here for how to rebuild your code.
Pointer use in C and C++ is a perennial issue. I'd like to suggest the following tutorial from Paul DiLorenzo, "Learning C++ Pointers for REAL dummies.".
(This is not to imply that you are a "dummy," it's just a reference to the ",insert subject here> for Dummies" lines of books. I would not be surprised that the insertion of "REAL" is to forestall lawsuits over trademarked titles)
It is an excellent tutorial.
Hope it helps.

strncpy equivalent for std::string?

Is there an exact equivalent to strncpy in the C++ Standard Library? I mean a function, that copies a string from one buffer to another until it hits the terminating 0? For instance when I have to parse strings from an unsafe source, such as TCP packets, so I'm able to perform checks in length while coping the data.
I already searched a lot regarding this topic and I also found some interesting topics, but all of those people were happy with std::string::assign, which is also able to take a size of characters to copy as a parameter. My problem with this function is, that it doesn't perform any checks if a terminating null was already hit - it takes the given size serious and copies the data just like memcpy would do it into the string's buffer. This way there is much more memory allocated and copied than it had to be done, if there were such a check while coping.
That's the way I'm working around this problem currently, but there is some overhead I'd wish to avoid:
// Get RVA of export name
const ExportDirectory_t *pED = (const ExportDirectory_t*)rva2ptr(exportRVA);
sSRA nameSra = rva2sra(pED->Name);
// Copy it into my buffer
char *szExportName = new char[nameSra.numBytesToSectionsEnd];
strncpy(szExportName,
nameSra.pSection->pRawData->constPtr<char>(nameSra.offset),
nameSra.numBytesToSectionsEnd);
szExportName[nameSra.numBytesToSectionsEnd - 1] = 0;
m_exportName = szExportName;
delete [] szExportName;
This piece of code is part of my parser for PE-binaries (of the routine parsing the export table, to be exact). rva2sra converts a relative virtual address into a PE-section relative address. The ExportDirectory_t structure contains the RVA to the export name of the binary, which should be a zero-terminated string. But that doesn't always have to be the case - if someone would like it, it would be able to omit the terminating zero which would make my program run into memory which doesn't belong to the section, where it would finally crash (in the best case...).
It wouldn't be a big problem to implement such a function by myself, but I'd prefer it if there were a solution for this implemented in the C++ Standard Library.
If you know that the buffer you want to make a string out of has at least one NUL in it then you can just pass it to the constructor:
const char[] buffer = "hello\0there";
std::string s(buffer);
// s contains "hello"
If you're not sure, then you just have to search the string for the first null, and tell the constructor of string to make a copy of that much data:
int len_of_buffer = something;
const char* buffer = somethingelse;
const char* copyupto = std::find(buffer, buffer + len_of_buffer, 0); // find the first NUL
std::string s(buffer, copyupto);
// s now contains all the characters up to the first NUL from buffer, or if there
// was no NUL, it contains the entire contents of buffer
You can wrap the second version (which always works, even if there isn't a NUL in the buffer) up into a tidy little function:
std::string string_ncopy(const char* buffer, std::size_t buffer_size) {
const char* copyupto = std::find(buffer, buffer + buffer_size, 0);
return std::string(buffer, copyupto);
}
But one thing to note: if you hand the single-argument constructor a const char* by itself, it will go until it finds a NUL. It is important that you know there is at least one NUL in the buffer if you use the single-argument constructor of std::string.
Unfortunately (or fortunately), there is no built in perfect equivalent of strncpy for std::string.
The std::string class in STL can contain null characters within the string ("xxx\0yyy" is a perfectly valid string of length 7). This means that it doesn't know anything about null termination (well almost, there are conversions from/to C strings). In other words, there's no alternative in the STL for strncpy.
There are a few ways to still accomplish your goal with a shorter code:
const char *ptr = nameSra.pSection->pRawData->constPtr<char>(nameSra.offset);
m_exportName.assign(ptr, strnlen(ptr, nameSra.numBytesToSectionsEnd));
or
const char *ptr = nameSra.pSection->pRawData->constPtr<char>(nameSra.offset);
m_exportName.reserve(nameSra.numBytesToSectionsEnd);
for (int i = 0; i < nameSra.numBytesToSectionsEnd && ptr[i]; i++)
m_exportName += ptr[i];
Is there an exact equivalent to strncpy in the C++ Standard Library?
I certainly hope not!
I mean a function, that copies a string from one buffer to another until it hits the terminating 0?
Ah, but that's not what strncpy() does -- or at least it's not all it does.
strncpy() lets you specify the size, n, of the destination buffer, and copies at most n characters. That's fine as far as it goes. If the length of the source string ("length" defined as the number of characters preceding the terminating '\0') exceeds n, the destination buffer is padded with additional \0's, something that's rarely useful. And if the length if the source string exceeds n, then the terminating '\0' is not copied.
The strncpy() function was designed for the way early Unix systems stored file names in directory entries: as a 14-byte fixed-size buffer that can hold up to a 14-character name. (EDIT: I'm not 100% sure that was the actual motivation for its design.) It's arguably not a string function, and it's not just a "safer" variant of strcpy().
You can achieve the equivalent of what one might assume strncpy() does (given the name) using strncat():
char dest[SOME_SIZE];
dest[0] = '\0';
strncat(dest, source_string, SOME_SIZE);
This will always '\0'-terminate the destination buffer, and it won't needlessly pad it with extra '\0' bytes.
Are you really looking for a std::string equivalent of that?
EDIT : After I wrote the above, I posted this rant on my blog.
There is no built-in equivalent. You have to roll your own strncpy.
#include <cstring>
#include <string>
std::string strncpy(const char* str, const size_t n)
{
if (str == NULL || n == 0)
{
return std::string();
}
return std::string(str, std::min(std::strlen(str), n));
}
The string's substring constructor can do what you want, although it's not an exact equivalent of strncpy (see my notes at the end):
std::string( const std::string& other,
size_type pos,
size_type count = std::string::npos,
const Allocator& alloc = Allocator() );
Constructs the string with a substring [pos, pos+count) of other. If count == npos or if the requested substring lasts past the end of the string, the resulting substring is [pos, size()).
Source: http://www.cplusplus.com/reference/string/string/string/
Example:
#include <iostream>
#include <string>
#include <cstring>
int main ()
{
std::string s0 ("Initial string");
std::string s1 (s0, 0, 40); // count is bigger than s0's length
std::string s2 (40, 'a'); // the 'a' characters will be overwritten
strncpy(&s2[0], s0.c_str(), s2.size());
std::cout << "s1: '" << s1 << "' (size=" << s1.size() << ")" << std::endl;
std::cout << "s2: '" << s2 << "' (size=" << s2.size() << ")" << std::endl;
return 0;
}
Output:
s1: 'Initial string' (size=14)
s2: 'Initial string' (size=40)
Differences with strncpy:
the string constructor always appends a null-terminating character to the result, strncpy does not;
the string constructor does not pad the result with 0s if a null-terminating character is reached before the requested count, strncpy does.
Use the class' constructor:
string::string str1("Hello world!");
string::string str2(str1);
This will yield an exact copy, as per this documentation: http://www.cplusplus.com/reference/string/string/string/
std::string has a constructor with next signature that can be used :
string ( const char * s, size_t n );
with next description:
Content is initialized to a copy of the string formed by the first n characters in the array of characters pointed by s.