Strcpy in c++ doesn't work - c++

Can anyone tell why strcpy in this code returns an empty string?
#include <iostream>
char* strcpy(char* dest, const char* from) {
for ( ; *from; dest++, from++) {
*dest = *from;
}
return dest;
}
int main() {
char a[] = "aba";
char b[] = "hello";
std::cout << strcpy(a, b);
return 0;
}
The compiler I'm using is GNU G++11 4.9.2
upd: this doesn't work either
#include
char* strcpy(char* dest, const char* from) {
for ( ; *from; dest++, from++) {
*dest = *from;
}
*dest = '\0';
return dest;
}
int main() {
char a[] = "abaaa";
char b[] = "hello";
std::cout << strcpy(a, b);
return 0;
}

Try using temp pointer:
char* strcpy(char* dest, const char* from) {
char *tmp = dest;
for ( ; *from; tmp++, from++) {
*tmp = *from;
}
*tmp = '\0';
return dest;
}
Also consider allocate memory for the dest with appropriate number of characters.

The function and the program itself are invalid.:)
For example array a can not accomodate all characters from array b because its size is less than the size of b. (The size of a is equal to 4 while the size of b is equal to 6)
char a[] = "aba";
char b[] = "hello";
So the call strcpy(a, b) in this statement
std::cout << strcpy(a, b);
results in undefined behaviour.
As for the function then it does not copies the terminating zero from the sourse string to the destination string. And it does not return pointer to the first character of the destination string because inside the function pointer dest is changed (it was increased)
The correct function can look like
char* strcpy( char* dest, const char* from )
{
char *p = dest;
while ( *p++ = *from++ );
return dest;
}

Instead of incrementing dest and from in the loop, try this:
char *StrCpy (char *dest, const char *from){
int i=0;
for (i=0;i<strlen(from);i++){
*(dest+i) = *(from+i);
}
*(dest+(strlen(from)))='\0';
return dest;
}

Related

Why isn't my char* shrinking after popping a char

For context, I'm rewriting the string class in C++ to use on microcontrollers, specifically Arduino, so that it doesn't use the standard library functions not supported by Arduino.
I've looked at several answers here that show how to pop a char off a char*. However, within my function it doesn't seem to correctly edit the char*.
My string class
#include <stdlib.h> // malloc
namespace micro_std {
class string {
private:
const int MAX_SIZE = 4096; // Maximum size on 16bit controllers.
char* data = nullptr;
int _length = 0;
public:
string(char* data) {
this->data = data;
for (int i = 0; data[i] != '\0'; i++)
_length++;
}
int size(void) const { return _length; }
int length(void) const { return _length; }
int max_size(void) const { return MAX_SIZE; }
bool empty(void) const { return _length == 0; }
char at(int index) const { return data[index]; }
char back(void) const { return data[_length - 1]; }
char front(void) const { return data[0]; }
char* str(void) const { return data; }
void clear(void) { _length = 0; data = nullptr; }
// removed for brevity //
char pop_back(void) {
_length--;
char character = data[_length];
data[_length] = '\0';
return character;
}
// removed for brevity //
};
}
And how I'm testing my code, specifically the pop_back function.
#include <stdio.h> // printf
#include "micro_std/string.h"
int main(int argc, char** argv) {
micro_std::string x = "abcdef";
// Testing pop_back function
printf("%d %s\n", x.length(), x.str());
for (int i = 0; i < 5; i++) {
char res = x.pop_back();
printf("%d %c %s\n", x.length(), res, x.str());
}
//printf("%s\n", x.str());
return 0;
}
And, if needed, my compiler arguments
g++ -w -std=c++2a -O3 program.cpp -o program
Running this program gives me the following output:
6 abcdef
5 f abcdef
4 e abcdef
3 d abcdef
2 c abcdef
1 b abcdef
Instead of the output I want:
6 abcdef
5 f abcde
4 e abcd
3 d abc
2 c ab
1 b a
Where the output is formatted like "(length) (char popped) (result string)". Why isn't the data member data being altered when calling the pop_back function?
Why isn't the data member data being altered when calling the pop_back function?
Even if the code compiles (which it shouldn't, since you are trying to construct x with a string literal, which is a const char[] array that cannot be assigned to a non-const char*), x would be pointing its data member at a string literal, thus data[_length] = '\0'; inside of pop_back() would invoke Undefined Behavior trying to alter read-only memory.
To make your code work, you MUST make a copy of the input data, eg:
#include <stdlib.h> // malloc
namespace micro_std {
class string {
private:
const int MAX_SIZE = 4096; // Maximum size on 16bit controllers.
char _data[MAX_SIZE];
int _length = 0;
public:
string(const char* str) {
for (int i = 0; str[i] != '\0'; ++i) {
data[i] = str[i];
++_length;
}
data[_length] = '\0';
}
...
void clear(void) { _length = 0; }
...
};
}

Trying to concatenate array of c-strings with delimiter

Here is my code
int main(int argc, char *argv[]) {
char const *strings[10] = {"dhh", "aci", "cdh"};
join_def(strings, 'l');
return EXIT_SUCCESS;
}
// part 1 read lines
void join_def(char const **strings, char delim) {
char *t = new char[100];
//int length = 0;
t[0] = '\0';
int x = sizeof(strings);
std::cout << delim << std::endl;
for (int i = 0; i < x; i++) {
int size = 0;
while(strings[i][size]!='\0'){
size++;
std::cout << strings[i][size] << std::endl;
}
}
}
I have spent hours now I just can't get to concatenate it
For this task, I cannot use cstring or anything other than iostream so please don't suggest.
The output needs to be a c-string = "dhhlacilcdh"
First, you cannot determine the number of elements in an array passed to a function, as that array will decay to a simple pointer. So, your sizeof(strings) expression will evaluate (at compile time) to the (fixed) size, in bytes, of a pointer. For the function to be 'aware' of how many elements there are in an array, it needs to be explicitly told (by way of an extra argument).
Second, you have your i' and size indexes the wrong way round in the std::cout << strings[i][size] << std::endl; line and, further, you increment size before printing the relevant character, whereas it should be incremented after you've printed it.
The code below also does the actual concatenation of the strings, and the modified join_def function now returns a pointer to that result (which must be freed when you're finished with it);
#include <iostream>
char* join_def(char const** strings, char delim, int x)
{
char* t = new char[100];
int length = 0;
t[0] = '\0';
//int x = sizeof(strings);
std::cout << delim << std::endl;
for (int i = 0; i < x; i++) {
int size = 0;
while (strings[i][size] != '\0') {
std::cout << strings[i][size] << std::endl;
t[length++] = strings[i][size]; // Append this character
size++;
}
t[length++] = delim; // Append delimiter
}
t[length] = '\0'; // Append nul-terminator
return t;
}
int main()
{
char const* strings[10] = { "dhh", "aci", "cdh" };
char* result = join_def(strings, 'l', 3);
std::cout << result << std::endl;
free(result);
return 0;
}
Note, also, that I have moved the join_def function code to before the main (which calls it). If you don't do this, then will at least have to provide a (forward) declaration of that function before main (just a char* join_def(char const** strings, char delim, int x); on its own will do).
Feel free to ask for further clarification and/or explanation.
I'm not exactly sure what you're trying to do, but maybe this helps?
#include <iostream>
// part 1 read lines
void join_def(char const **strings, char delim)
{
char *t = new char[100];
//int length = 0;
t[0] = '\0';
int x = 0;
for (int i = 0; strings[i] != nullptr; i++)
x += sizeof(strings[i]) - 1;
std::cout << delim << std::endl;
for (int i = 0; strings[i] != nullptr; i++)
{
int size = 0;
while (strings[i][size] != '\0')
{
size++;
std::cout << strings[i][size] << std::endl;
}
}
}
int main(int argc, char *argv[])
{
char const *strings[] = {"dhh", "aci", "cdh", nullptr};
join_def(strings, 'l');
return EXIT_SUCCESS;
}
this is what you are looking for?
look that I remove all the std::endl because it like '\n'
also i moved your size++ after the std::cout
#include <iostream>
// part 1 read lines
void join_def(char const **strings, char delim,int length) {
char *t = new char[100];
//int length = 0;
t[0] = '\0';
int x = length;
for (int i = 0; i < x; i++) {
int size = 0;
while(strings[i][size]!='\0'){
std::cout << strings[i][size]; //<--print befure increment size
size++;
}
std::cout << delim;
}
}
int main(int argc, char *argv[]) {
char const *strings[] = {"dhh", "aci", "cdh"};
join_def(strings,'|',3); //<- need to send the length of the char* array
return EXIT_SUCCESS;
}

Remove substrings from a C-style string "in place" in C++ code

I had an interview task to remove substring from a current string without using string functions or additional memory...I tried just with strlen but didn't find the way to change it in place...
#include <stdio.h>
#include <string.h>
#include <iostream>
using namespace std;
int main()
{
char * str = "this that there";
char * substr = "th";
removeSubstr(str,substr);
cout<<str; //should be now "is at ere"
return 0;
}
void removeSubstr(char * str, const char * substr){
}
Since you remove characters from the original string, the string is shrinking, so you do not need additional space. You just have to copy characters from a higher index (source) to a lower index (destination).
If the source index points to a position that starts with the searched substring, you must skip it.
The skip function simply compares the beginning of the source string against the substring, and returns the source (if it does not start with the substring) or the source plus the length of substring (if it starts with the substring).
Demo
#include <iostream>
char* skip_if( char* s, const char* ss )
{
char* p = s;
const char* pp = ss;
while( *p == *pp && *p )
p++, pp++;
return *pp ? s : p;
}
void remove( char* s, const char* ss )
{
char *ps = s; // source
char *pd = s; // destination
while( *ps )
{
ps = skip_if( ps, ss );
*pd++ = *ps++;
}
*pd = 0;
}
int main()
{
using namespace std;
char str[] = "this that there this that there";
const char* substr = "th";
remove( str, substr );
cout << str;
return 0;
}
The string functions exist for a reason. If you are not to use them, can you create them from scratch?
If so, here is my solution to the problem. Very educational to write custom string functions with the const requirements.
As mentioned in the comments, this won't work unless the string passed in can be modified, so I made it a non-constant string.
Let me know if this meets the interview challenge:
#include <iostream>
bool myStrnCmp(char *str1, const char *str2, int len) {
char *cptr1 = (char *) str1;
char *cptr2 = (char *) str2;
for (int i = 0; i < len; i++) {
if (*(cptr1 + i) != *(cptr2 + i))
return false;
}
return true;
}
int mystrlen(const char* str) {
int i = 0;
while(*(str + i) != '\0')
i++;
return i;
}
int findSubStr(char *str, const char *substr) {
int position = 0;
int len = mystrlen(substr);
while(*(str + position) != '\0') {
for (int i = 0; i < len; i++) {
if (myStrnCmp(str + position + i, substr, len))
return position + i;
}
++position;
}
return -1;
}
void myStrCpy(char *str, const char *substr) {
memmove(str, substr, mystrlen(substr) + 1);
}
void removeSubstr(char *str, const char *substr) {
int position = findSubStr(str, substr);
while(position >= 0) {
myStrCpy(str + position, str+position+mystrlen(substr));
position = findSubStr(str, substr);
}
}
int main() {
char str[]{"this that there"};
char* substr = "th";
removeSubstr(str,substr);
std::cout<<str; //should be now "is at ere"
return 0;
}

Return a pointer to the last appearance of a character in a C-Style string (C++)

Return a pointer to the last appearance of c
appearing inside s and nullptr (0) if c does not appear inside s.
#include <string>
#include <iostream>
#include <cassert>
using namespace std;
const char* myStrRChr(const char* s, char c)
{
int curIdx = 0;
char last;
while (s[curIdx] != '\0')
{
if (s[curIdx] == c)
last = s[curIdx];
curIdx++;
}
if (s[curIdx] == c)
return last;
else
// return '\0', nullptr, NULL
return "";
}
int main()
{
char cstr[50] = "Abadabadoo!";
char buf[10];
const char * cat = "cat";
char dog[] = "Labradoodle";
cout << "\nmyStrRChr(cstr, 'a') expects adoo!" << endl;
cout << " -- " << myStrRChr(cstr, 'a') << endl;
return 0;
}
This code returns "adabadoo!". I can't wrap my mind around as to how to get the last instance of "char c."
You can do this by obtaining a pointer to the end of the string and decrementing down the string searching for the character c, and a pointer to the beginning of the string to know where to stop looping:
const char *mystrrchr(const char *str, char c)
{
int len = strlen(str);
char *p = const_cast<char *>(&str[len-1]);
char *stop = const_cast<char *>(&str[0]);
while(p>=stop)
{
if(*p==c)
{
return p;
}
p--;
}
return nullptr;
}

Returning null from a function that returns a pointer

I'm writing a program that involves a function that will take 2 strings as input . The function should return a pointer to the occurrence of str2 in str1 if it exists , if not it has to return NULL .The function should basically return str2 if it was found in str1 . The code works but i cant figure out how to return NULL from the function if newstring has no elements. Any guidance on how to return NULL if the newstring wasn't assigned would be appreciated, Thanks!
#include<iostream>
using namespace std;
template <class T>
int lenstr(T str1) // Function that finds length of a string , instead of using the strlen or sizeof functions.
// this function will work for all data types and not just char.
{
int count = 0;
while(str1[count] != '\0')
{
count++;
}
return count;
}
char* mystrstr(char *str1 , const char* str2)
{
int len1 = lenstr(str1);
int len2 = lenstr(str2);
char *newstring = new char[len2];
int i = 0;
for (int j = 0;j<len1;j++)
{
if(str1[j] == str2[i])
{
newstring[i] = str1[j];
i++;
}
else
{
i = 0;
}
}
return newstring;
}
void main()
{
char str1[28] = {"this is a test program"};
char str2[15] = {"tes"};
int len2 = lenstr(str2);
char* returnstring;
returnstring = mystrstr(str1,str2);
for(int i = 0;i<len2;i++)
{
cout<<returnstring[i];
}
cout<<endl;
delete returnstring;
}
Your variant of strstr doesn't return a pointer to the occurance of str2 in str1. It just takes as many letters from the str1, that are in str2 and returns pointer to new string.
This is what you need if your question is right:
char* mystrstr(char *str1 , char* str2)
{
int len1 = lenstr(str1);
int len2 = lenstr(str2);
char *ptr1, *ptr2;
char *result;
for(ptr1 = str1, ptr2 = str2; *ptr1; ptr1++)
{
if(*ptr2 == 0)
break;
if(*ptr1 == *str2)
result = ptr1;
if(*ptr1 == *ptr2)
{
ptr2++;
}
else
{
ptr2 = str2;
result = NULL;
}
}
return result;
}
int main()
{
char str1[28] = {"this is a test program"};
char str2[15] = {"tes"};
int len2 = lenstr(str2);
char* returnstring;
returnstring = mystrstr(str1,str2);
if(returnstring != NULL)
{
cout << returnstring;
}
else
{
cout << "returnstring is NULL" << endl;
}
delete returnstring;
}
Try initializing newstr with all 0's, like so:
char *newstring = new char[len2];
for (int i = 0; i < len2; i++) {
newstring[i] = '0';
}
(newstr should by default be initialized with 0s, but I'm not quite sure on this, so I just posted that loop since I'm not 100% on that)
And then, at the end of your loop, if newstring still contains 0 at the first index, return
nullptr.