How to fix error in my strcat function - c++

The code below is in my header file:
char mystrcat(char *s1, const char *s2) //strcat function
{
mystrcpy(s1 + mystrlen(s1), s2);
return s1;
}
The error is the return s1; "return value type does not match the function type."
I know that the strcat function appends a copy of the source string to the destination string, but how would I fix this error.
The other part of my code is in the main.cpp If you need more code just tell me.

Your signature should look like
char* mystrcat(char *s1, const char *s2)
// ^~~~~~ Note the pointer

You function should return char, but you are returning s1 that is char*
Make sure you understand problem that it's possible that there's no allocated space at the end of s1

1) ERROR: "return value type does not match the function type
CAUSE: s1 is char*; your signature returns "char"
SOLUTION: change your signature to char *
2) What is mystrcpy()? What errors might be lurking there?
3) More importantly, who allocates space for the "s1" you're returning?
4) What happens if the returned value is larger than the original value (a likely case)? Do you get a buffer overrun?
5) What happens if the original value is read-only (another likely case)?
Etc...

Related

string to char* function

Quite new to c / c++. I have a question about the below code:
char* string2char(String command){
if (command.length() != 0) {
char *p = const_cast<char*>(command.c_str());
return p;
}
}
void setup() {}
void loop() {
String string1 = "Bob";
char *string1Char = string2char(string1);
String string2 = "Ross";
char *string2Char = string2char(string2);
Serial.println(string1Char);
Serial.println(string2Char);
}
This basically outputs repeatedly:
Ross
Ross
I understand I'm failing to grasp the concept of how pointers are working here - would someone be able to explain it? And how would I alter this so that it could show:
Bob
Ross
This function :
char* string2char(String command){
if (command.length() != 0) {
char *p = const_cast<char*>(command.c_str());
return p;
}
}
Does not make much sense, it takes string by value and returns pointer to its internal buffer, with cased away constnes(don't do it). You are getting some odd behaviour as you are returning values of object that already was destroyed, pass it by ref. Also I'm curious why you need to do all this stuff, can't you just pass:
Serial.println(string1.c_str());
Serial.println(string2.c_str());
As noted by Mark Ransom in the comments, when you pass the string by value, the string command is a local copy of the original string. Therefore you can't return a pointer to its c_str(), because that one points at the local copy, which will go out of scope when the function is done. So you get the same bug as described here: How to access a local variable from a different function using pointers?
A possible solution is to rewrite the function like this:
const char* string2char(const String& command){
return command.c_str();
}
Now the string is passed by reference so that c_str() refers to the same string object as the one in the caller (string1). I also took the libery to fix const-correctness at the same time.
Please note that you cannot modify the string by the pointer returned by c_str()! So it is very important to keep this const.
The problem here is that you've passed String command to the function by value, which makes a copy of whatever String you passed to the function. So, when you call const_cast<char*>(command.c_str()); you're making a pointer to the c string of that copied String. Since the String you've cast is within the scope of the function, the memory is freed when the function returns and the pointer is essentially invalid. What you want to do is change the argument to String & command which will pass a reference to the string, whose memory won't be freed when the function returns.
Your issue revolves around your argument.
char* string2char(String command){
// create a new string that's a copy of the thing you pass in, and call it command
if (command.length() != 0) {
char *p = const_cast<char*>(command.c_str());
// get the const char* that this string contains.
// It's valid only while the string command does; and is invalidated on changing the string.
return p; /// and destroy command - making p invalid
}
}
There are 2 ways to resolve this. The first and most complex, is to pass command in by reference. Thus const String& command and then work with that.
The alternative, which is much simpler, is to completely delete your function; make your char* const char* and just call c_str() on the string; ie
String string1 = "Bob";
const char *string1Char = string1.c_str();

How can I convert const char* to string and then back to char*?

I'm just starting c++ and am having difficulty understanding const char*. I'm trying to convert the input in the method to string, and then change the strings to add hyphens where I want and ultimately take that string and convert it back to char* to return. So far when I try this it gives me a bus error 10.
char* getHyphen(const char* input){
string vowels [12] = {"A","E","I","O","U","Y","a","e","i","o","u","y"};
//convert char* to string
string a;
int i = 0;
while(input != '\0'){
a += input[i];
input++;
i++;
}
//convert a string to char*
return NULL;
}
A: The std::string class has a constructor that takes a char const*, so you simply create an instance to do your conversion.
B: Instances of std::string have a c_str() member function that returns a char const* that you can use to convert back to char const*.
auto my_cstr = "Hello"; // A
std::string s(my_cstr); // A
// ... modify 's' ...
auto back_to_cstr = s.c_str(); // B
First of all, you don't need all of that code to construct a std::string from the input. You can just use:
string a(input);
As far as returning a new char*, you can use:
return strdup(a.c_str()); // strdup is a non-standard function but it
// can be easily implemented if necessary.
Make sure to deallocate the returned value.
It will be better to just return a std::string so the users of your function don't have to worry about memory allocation/deallocation.
std::string getHyphen(const char* input){
Don't use char*. Use std::string, like all other here are telling you. This will eliminate all such problems.
However, for the sake of completeness and because you want to understand the background, let's analyse what is going on.
while(input != '\0'){
You probably mean:
while(*input != '\0') {
Your code compares the input pointer itself to \0, i.e. it checks for a null-pointer, which is due to the unfortunate automatic conversion from a \0 char. If you tried to compare with, say, 'x' or 'a', then you would get a compilation error instead of runtime crashes.
You want to dereference the pointer via *input to get to the char pointed to.
a += input[i];
input++;
i++;
This will also not work. You increment the input pointer, yet with [i] you advance even further. For example, if input has been incremented three times, then input[3] will be the 7th character of the original array passed into the function, not the 4th one. This eventually results in undefined behaviour when you leave the bounds of the array. Undefined behaviour can also be the "bus error 10" you mention.
Replace with:
a += *input;
input++;
i++;
(Actually, now that i is not used any longer, you can remove it altogether.)
And let me repeat it once again: Do not use char*. Use std::string.
Change your function declaration from
char* getHyphen(const char* input)
to
auto hyphenated( string const& input )
-> string
and avoid all the problems of conversion to char const* and back.
That said, you can construct a std::string from a char_const* as follows:
string( "Blah" )
and you get back a temporary char const* by using the c_str method.
Do note that the result of c_str is only valid as long as the original string instance exists and is not modified. For example, applying c_str to a local string and returning that result, yields Undefined Behavior and is not a good idea. If you absolutely must return a char* or char const*, allocate an array with new and copy the string data over with strcpy, like this: return strcpy( new char[s.length()+1], s.c_str() ), where the +1 is to accomodate a terminating zero-byte.

Adding a pointer to a string in C++

I am confused with const pointers in C++ and wrote a small application to see what the output would be. I am attempting (I believe) to add a pointer to a string, which should not work correctly, but when I run the program I correctly get "hello world". Can anyone help me figure out what how this line (s += s2) is working?
My code:
#include <iostream>
#include <stdio.h>
#include <string>
using namespace std;
const char* append(const char* s1, const char* s2){
std::string s(s1); //this will copy the characters in s1
s += s2; //add s and s2, store the result in s (shouldn't work?)
return s.c_str(); //return result to be printed
}
int main() {
const char* total = append("hello", "world");
printf("%s", total);
return 0;
}
The variable s is local inside the append function. Once the append function returns that variable is destructed, leaving you with a pointer to a string that no longer exists. Using this pointer leads to undefined behavior.
My tip to you on how to solve this: Use std::string all the way!
you're adding const char* pointer to a std::string and that is possible (see this reference). it wouldn't be possible to make that operation on char* type (C style string).
however, you're returning a pointer to local variable, so once function append returns and gets popped of the stack, the string that your returned pointer is pointing to would not exist. this leads to an undefined behavior.
Class std::string has overloaded operator += for an operand of type const char *
basic_string& operator+=(const charT* s);
In fact it simply appends the string pointed to by this pointer to the contents of the object of type std::string allocating additionly memory if required. For example internally the overloaded operator could use standard C function strcat
Conceptually it is similar to the following code snippet.
char s[12] = "Hello ";
const char *s2 = "World";
std::strcat( s, s2 );
Take into account that your program has undefined behaviour because total will be invalid after destroying local object s after exiting function append. So the next statemnent in main
printf("%s", total);
can result in undefined behaviour.

Annoying C++ gcc warning message

I've written the following program to match regular expressions in C++
#include <regex.h>
#include <iostream>
using namespace std;
/*
* Match string against the extended regular expression in
* pattern, treating errors as no match.
*
* return true for match, false for no match
*/
bool match(const char *string, char *pattern)
{
int status; regex_t re;
if (regcomp(&re, pattern, REG_EXTENDED|REG_NOSUB) != 0)
return false;
/* report error */
status = regexec(&re, string, (size_t) 0, NULL, 0);
regfree(&re);
if (status != 0) {
return false; /* report error */
}
return true;
}
int main()
{
string str = "def fadi 100";
bool matchExp = match(str.c_str(), "^[Dd][Ee][Ff][' '\t]+[A-z]+([,])?[''\t]+[0-9]+$");
cout << (matchExp == true ? "Match": "No match") << endl;
}
The program works fine just as expected, but when I compile the code using gcc with the -Wall -Werror arguments (Linux environment), I get a very annoying warning message saying the following:
main.cpp: In function ‘int main()’:
main.cpp:33:90: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
Is there a way to force the compiler to believe that str.c_str() is the same as char * str? if so, how?
No, there isn't. That conversion was deprecated in C++03 and is illegal in C++11; don't do it.
Deprecation of that conversion comes from the fact that string literals are read-only, hence const; accessing them using a pointer to non-const char could possibly lead to modifying const objects, hence invoking undefined behavior. The warning isn't annoying; it is meant to save you from possibly crashing your application - or worse.
Also, you are wrong in reading the warning message; it isn't about c_str(), it is about passing string literal as char *.
The only way to really fix your code is to change second parameter of your match to be const char *, not char *, and copy the passed string to a new, buffer, internal to that function (why not in main()? Because with internal buffer, you have less boilerplate on the caller's side).
I'd also like to suggest totally different solution, since the question is tagged "C++": Boost.Regex.
Is there a way to force the compiler to believe that str.c_str() is the same as char * str?
That's actually not the issue here - you are already passing str.c_str() as a const char*.
The issue is that the second parameter is (also) a string literal, but has type char*. Try changing the second parameter to const char*.
If that still raises errors (due to the regex.h functions not specifying the correct const-ness), you're going to have to do something like this in main() or match():
char pattern[] = "^[Dd][Ee]...etc";
bool matchExp = match(str.c_str(), pattern);
See here for the reason why.
The problem is that a string literal should be only assigned to a pointer of a const char, so you need to change match to take a char const* pattern (which should be possible when you pass a string literal)
Make 2 parameter of function match const char *, warning is because of it

Convert std::string to char * alternative

I have done a search in google and been told this is impossible as I can only get a static char * from a string, so I am looking for an alternative.
Here is the situation:
I have a .txt file that contains a list of other .txt files and some numbers, this is done so the program can be added to without recompilation. I use an ifstream to read the filenames into a string.
The function that they are required for is expecting a char * not a string and apparently this conversion is impossible.
I have access to this function but it calls another function with the char * so I think im stuck using a char *.
Does anyone know of a work around or another way of doing this?
In C++, I’d always do the following if a non-const char* is needed:
std::vector<char> buffer(str.length() + 1, '\0');
std::copy(str.begin(), str.end(), buffer.begin());
char* cstr = &buffer[0];
The first line creates a modifiable copy of our string that is guaranteed to reside in a contiguous memory block. The second line gets a pointer to the beginning of this buffer. Notice that the vector is one element bigger than the string to accomodate a null termination.
You can get a const char* to the string using c_str:
std::string str = "foo bar" ;
const char *ptr = str.c_str() ;
If you need just a char* you have to make a copy, e.g. doing:
char *cpy = new char[str.size()+1] ;
strcpy(cpy, str.c_str());
As previous posters have mentioned if the called function does in fact modify the string then you will need to copy it. However for future reference if you are simply dealing with an old c-style function that takes a char* but doesn't actually modfiy the argument, you can const-cast the result of the c_str() call.
void oldFn(char *c) { // doesn't modify c }
std::string tStr("asdf");
oldFn(const_cast< char* >(tStr.c_str());
There is c_str(); if you need a C compatible version of a std::string. See http://www.cppreference.com/wiki/string/basic_string/c_str
It's not static though but const. If your other function requires char* (without const) you can either cast away the constness (WARNING! Make sure the function doesn't modify the string) or create a local copy as codebolt suggested. Don't forget to delete the copy afterwards!
Can't you just pass the string as such to your function that takes a char*:
func(&string[0]);