Getting a word after a certain character? - c++

I'm trying to make myself a program that will take a String and give me the word after a certain character. So, for example:
String theString = "hello \t world"; // or "borld \t bello";
After the tab, I only want "world" and not "hello." This keeps crashing on me for some reason.
size_t delimiter = theString.find_last_of('\t');
char *test;
if (theString.find("hello") != string::npos) {
strcpy(test, theString.substr(delimiter + 1).c_str());
else if (theString.find("borld") != string::npos) {
strcpy(test, theString.substr(delimiter + 1).c_str());
}
cout << test;

From strcpy manual:
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.
In your code, you declare test as a pointer to char* but you never initialize it.
test is therefore a pointer to indeterminate value. You then attempt to copy data to that inderminate location, resulting in the crash.
You can fix this easily by initializing test to point to memory you can strcpy to. Be sure to allow enough to not write beyond the buffer.

always the same mistake why you write to test without initializing it?
char *test; // no memory allocated so using it will cause a segfault
char test[50]; // just for explaining we allocate 50 bytes for pointer test
// char* test = new char[50]; // the same above but here dynamic memory
// delete[] test; // free up memory because dynamic memory is not automatically freed

Related

Dumb questions: strcat and char pointers

I am usually not using pointer chars when working with strings but I usually think they are better in the sense that I can print the whole string without iterating each character.
Anyway since I don't use them I don't really know how these two interact. When running the following code the program crashes, so I've got no clue what to do since there's no error.
int main(){
char s[]="abcde";
char *p;
for(unsigned int i=0;i<strlen(s);i++)
strcat(p,s+i);
cout<<*p;
}
I tried representing both strings as pointers and it didn't change anything. It crashes only if I try to print the second array. I tried *p++=*s or something similar I've found on google but it still crashes, what am I doing wrong?
Pointer p points nowhere, you need to reserve memory for the second array. For example,
char *p = new char [strlen(s) + 1];
Also strcat in a for loop is not the best way to copy a string. Try
strcpy(p, s);
(after allocating memory to p, of course).
Addition: If you need to use strcat instead of strcpy, you need to initialize string p with empty string, that is:
char *p = new char [strlen(s) + 1];
*p = '\0';
You are not allocating memory to a pointer p. When you call strcat without allocating memory of course you will get segmentation fault since strcat will try to write to a memory pointer by the pointer p.
You don't need a for loop for concatenating strings. strcat function does full string copying to memory pointed by p.
If you want print whole string don't deference pointer p fi you want print the whole string, deferencing results in printing only the first character of a string.
#include<iostream>
#include<cstring>
int main(){
char s[]="abcde";
//Allocating memory to so that p points valid memory.
char concatenatedString[50] = "";
//Initializing pointer to allocated memory.
char *p = concatenatedString;
// for(unsigned int i = 0;i < strlen(s); i++) //Not required.
strcat(p,s);
//Here don't dereference if you want to print whole string.
std::cout<<p;
}

String to const char * in c++ puts garbage at end

I have a struct that needs to store const char * for later. The string gets destroyed by then. The code that i have till now for the same is
HttpRequest* send(string reply)
{
int len = strlen(reply.c_str());
char *buffer = new char[len+1];
strncpy(buffer, reply.c_str(), len);
cout << "LEN:"<<reply.length()<<endl;
cout << "OG:"<<reply<<endl<<"TC:"<<buffer<<endl<<"CS"<<reply.c_str()<<endl;
this->res.response = "test";
return this;
};
res.response is the char * that i want to store the value in. The output from cout that i am getting is
LEN:5
OG:hello
TC:hello�������������������q{
CShello
This behavior is pretty strange to me. Can someone please explain what i am doing wrong. Also the above code shows me using strlen but i am getting the same result using length() in c++ also.
Also it is worth mentioning that this happens only the first time that i invoke this, after that it goes fine.
You never put the null terminator:
char *buffer = new char[len+1];
strncpy(buffer, reply.c_str(), len);
buffer[len] = 0; // <-- HERE
strncpy doesn't add it.
Your arguments to strncpy() make the function misunderstand that there is no space for terminating null-character, so it isn't written. Correct the argument like
strncpy(buffer, reply.c_str(), len+1);
In this code, it is guaranteed that the length of buffer is sufficient to store the string, so you can simply use strcpy() instead of the strncpy() like this:
strcpy(buffer, reply.c_str());
You can use strdup() function if your system supports it. Using it, the lines
int len = strlen(reply.c_str());
char *buffer = new char[len+1];
strncpy(buffer, reply.c_str(), len);
can be replaced with
char *buffer = strdup(reply.c_str());
Note that strdup() is a function from C and it uses malloc() internally, so you must use free(), not delete[], to free the memory allocated via strdup().
Don't use strncpy until you've read and understood its documentation. And then don't use it. It's a very specialized function, and there's no need to deal with its quirks here. The code in the question allocates enough space for the result, so just use strcpy.
The problem is that this statement
strncpy(buffer, reply.c_str(), len);
does not copy the terminating zero ( '\0' ) of the original string to buffer.
You should use the standard C function strlen with objects of type std::string only in case when the objects contain embedded zeroes. Otherwise use member functions of the class std::string size or length.
Instead of the standard C function strncpy you could use standard C function strcpy to copy the zero-terminated string in the buffer.
For example
char *buffer = new char[len+1];
strcpy( buffer, reply.c_str() );

C++ substring from string

I'm pretty new to C++ and I'm need to create MyString class, and its method to create new MyString object from another's substring, but chosen substring changes while class is being created and when I print it with my method.
Here is my code:
#include <iostream>
#include <cstring>
using namespace std;
class MyString {
public:
char* str;
MyString(char* str2create){
str = str2create;
}
MyString Substr(int index2start, int length) {
char substr[length];
int i = 0;
while(i < length) {
substr[i] = str[index2start + i];
i++;
}
cout<<substr<<endl; // prints normal string
return MyString(substr);
}
void Print() {
cout<<str<<endl;
}
};
int main() {
char str[] = {"hi, I'm a string"};
MyString myStr = MyString(str);
myStr.Print();
MyString myStr1 = myStr.Substr(10, 7);
cout<<myStr1.str<<endl;
cout<<"here is the substring I've done:"<<endl;
myStr1.Print();
return 0;
}
And here is the output:
hi, I'm a string
string
stri
here is the substring I've done:
♦
Have to walk this through to explain what's going wrong properly so bear with me.
int main() {
char str[] = {"hi, I'm a string"};
Allocated a temporary array of 17 characters (16 letters plus a the terminating null), placed the characters "hi, I'm a string" in it, and ended it off with a null. Temporary means what it sound like. When the function ends, str is gone. Anything pointing at str is now pointing at garbage. It may shamble on for a while and give some semblance of life before it is reused and overwritten, but really it's a zombie and can only be trusted to kill your program and eat its brains.
MyString myStr = MyString(str);
Creates myStr, another temporary variable. Called the constructor with the array of characters. So let's take a look at the constructor:
MyString(char* str2create){
str = str2create;
}
Take a pointer to a character, in this case it will have a pointer to the first element of main's str. This pointer will be assigned to MyString's str. There is no copying of the "hi, I'm a string". Both mains's str and MyString's strpoint to the same place in memory. This is a dangerous condition because alterations to one will affect the other. If one str goes away, so goes the other. If one str is overwritten, so too is the other.
What the constructor should do is:
MyString(char* str2create){
size_t len = strlen(str2create); //
str = new char[len+1]; // create appropriately sized buffer to hold string
// +1 to hold the null
strcpy(str, str2create); // copy source string to MyString
}
A few caveats: This is really really easy to break. Pass in a str2create that never ends, for example, and the strlen will go spinning off into unassigned memory and the results will be unpredictable.
For now we'll assume no one is being particularly malicious and will only enter good values, but this has been shown to be really bad assumption in the real world.
This also forces a requirement for a destructor to release the memory used by str
virtual ~MyString(){
delete[] str;
}
It also adds a requirement for copy and move constructors and copy and move assignment operators to avoid violating the Rule of Three/Five.
Back to OP's Code...
str and myStr point at the same place in memory, but this isn't bad yet. Because this program is a trivial one, it never becomes a problem. myStr and str both expire at the same point and neither are modified again.
myStr.Print();
Will print correctly because nothing has changed in str or myStr.
MyString myStr1 = myStr.Substr(10, 7);
Requires us to look at MyString::Substr to see what happens.
MyString Substr(int index2start, int length) {
char substr[length];
Creates a temporary character array of size length. First off, this is non-standard C++. It won't compile under a lot of compilers, do just don't do this in the first place. Second, it's temporary. When the function ends, this value is garbage. Don't take any pointers to substr because it won't be around long enough to use them. Third, no space was reserved for the terminating null. This string will be a buffer overrun waiting to happen.
int i = 0;
while(i < length) {
substr[i] = str[index2start + i];
i++;
}
OK that's pretty good. Copy from source to destination. What it is missing is the null termination so users of the char array knows when it ends.
cout<<substr<<endl; // prints normal string
And that buffer overrun waiting to happen? Just happened. Whups. You got unlucky because it looks like it worked rather than crashing and letting you know that it didn't. Must have been a null in memory at exactly the right place.
return MyString(substr);
And this created a new MyString that points to substr. Right before substr hit the end of the function and died. This new MyString points to garbage almost instantly.
}
What Substr should do:
MyString Substr(int index2start, int length)
{
std::unique_ptr<char[]> substr(new char[length + 1]);
// unique_ptr is probably paranoid overkill, but if something does go
// wrong, the array's destruction is virtually guaranteed
int i = 0;
while (i < length)
{
substr[i] = str[index2start + i];
i++;
}
substr[length] = '\0';// null terminate
cout<<substr.get()<<endl; // get() gets the array out of the unique_ptr
return MyString(substr.get()); // google "copy elision" for more information
// on this line.
}
Back in OP's code, with the return to the main function that which was substr starts to be reused and overwritten.
cout<<myStr1.str<<endl;
Prints myStr1.str and already we can see some of it has been reused and destroyed.
cout<<"here is the substring I've done:"<<endl;
myStr1.Print();
More death, more destruction, less string.
Things to not do in the future:
Sharing pointers where data should have been copied.
Pointers to temporary data.
Not null terminating strings.
Your function Substr returns the address of a local variable substr indirectly by storing a pointer to it in the return value MyString object. It's invalid to dereference a pointer to a local variable once it has gone out of scope.
I suggest you decide whether your class wraps an external string, or owns its own string data, in which case you will need to copy the input string to a member buffer.

Segmentation Fault in deleting char pointer

I'm posting two fragments here.
The first one is giving me Segmentation Fault on deallocating the memory. Second one is working fine.
1)
int main()
{
char* ch = new char;
ch = "hello";
cout << "\n " << ch << endl;
delete[] ch; ////OR delete ch; ---> have tried both
return 0;
}
2)
int main()
{
char* ch = new char;
cin >> ch;
cout << "\n " << ch << endl;
delete[] ch; ///OR delete ch /// Both are working fine....
return 0;
}
Could anybody please tell me why the first one is failing with Segmentation Fault and second one is working fine with both delete and delete[]. Because to me both the program seems to same.
new char generates exactly 1 character (not an array of 1 character, use new char[1] for that)
so delete[] doesn't apply
in the first example, you overwrite your pointer to your allocated 1 character with a pointer to the character string "hello" - deleting this string (as it is static memory) will result in sesgfault
Edit
int main()
{
char* ch = new char; // ch points to 1 character in dynamic memory
ch = "hello"; // overwrite ch with pointer to static memory "hello"
cout<<"\n "<<ch<<endl; // outputs the content of the static memory
delete[] ch; // tries to delete static memory
return 0;
}
There are issues with both examples:
char* ch = new char;`
ch = "hello";`
The new returns an address that points to dynamically allocated memory. You must save this return value so that delete can be issued later. The code above overwrites this value with "hello" (a string-literal). You now have lost the value, and thus can not call delete with the proper value.
The second example, even though you say "works fine" is still faulty.
char* ch = new char;`
delete[] ch; ///OR delete ch /// Both are working fine....`
The wrong form of delete is used. You allocated with new, so you must deallocate with delete, not delete[]. It works this way: new->delete, new[]->delete[].
Unlike most other languages, if you go against the rules of C++, corrupt memory, overwrite a buffer, etc., there is no guarantee that your program will crash, seg fault, etc. to let you know that you've done something wrong.
In this case, you're lucky that simple types such as char* are not affected by you using the wrong form of delete. But you cannot guarantee that this will always work if you change compilers, runtime settings, etc.
There are a couple of problems with each, namely that you're only allocating a single character when you're trying to allocate a character array.
In the first example, you're also allocating a single character and then subsequently reassign the pointer to a character array - ch = "hello" will not copy the string, just reassign the pointer. Your call to delete[] will then attempt to delete a string that is not heap allocated, hence the seg fault. And you're also leaking the char you allocated, too.
In the first one, you change the pointer to point to a string literal:
ch = "hello";
String literals are static arrays, so mustn't be deleted.
The second is wrong for at least two reasons:
you allocate a single character, not an array; a single character would be deleted with delete not delete[]
cin>>ch will (most likely) read more than one character, but you've only allocated space for one.
Both of these cause undefined behaviour, which might manifest itself as a visible error, or might appear to "work fine" - but could fail when you least expect it.
To allocate an array, use new char[SIZE]; but even then, you can't prevent the user from giving too much input and overflowing the buffer.
Unless you're teaching yourself how to juggle raw memory (which is a dark art, best avoided unless absolutely necessary), you should stick to high-level types that manage memory for you:
std::string string;
string = "hello";
std::cout << string << '\n';
std::cin >> string;
std::cout << string << '\n';
there are several errors in your programs.
In the first program you are not deleting something dynamically allocated but the statically allocated string "hello". Infact when you execute ch="hello" you are not copying the string in the wrongly allocated buffer "new char" ( this new just allocates one char, not what you are looking for ) but you makes the pointer ch to point to the start of the string "hello" located somewhere in the non writable memory ( normaly that string are pointed directly into the executable ). So the delete operation is trying to deallocate something that cannot be deallocate. So the first program culd be rewritten like:
int main()
{
const char* ch = "hello";
cout<<"\n "<<ch<<endl;
return 0;
}
or like
int main()
{
char* ch = new char[strlen("hello")+1];
strcpy( ch, "hello");
cout<<"\n "<<ch<<endl;
delete[] ch; // with square brackets, it's an array
return 0;
}
Here's what's wrong with both snippets:
First snippet:
char* ch = new char; ch = "hello";
It's not legal to assign a string literal to a non-const char pointer .
Also, you re-assign the pointer immediately after you call new. The original value returned by new is now lost forever and can not be free for the duration of the program. This is known as a memory leak.
delete[] ch;
You try to deallocate the string literal. This crashes your program. You are only allowed to delete pointers that you get from new and delete[] pointers that you get from new[]. Deleting anything else has undefined behaviour.
Second snippet:
cout<<"\n "<<ch<<endl;
ch points to a single character, not a zero terminated char array. Passing this pointer to cout has undefined behaviour. You should use cout << *ch; to print that single character or make sure that ch points to a character array that is zero terminated.
delete[] ch;
You allocated with new, you must deallocate with delete. Using delete[] here has undefined behaviour.
Both are working fine....
"working fine" is one possible outcome of undefined behaviour, just like a runtime error is.
To answer the question, neither snippet is correct. First one crashes because you got lucky, second one appears to work because you got unlucky.
Solution: Use std::string.
You should use something like:
char* ch = new char[6] ;
strcpy(ch,"hello") ;
...
delete[] ch ;

String dimension error whel dealing with new operator

I'm trying to make something similar to the strlen(str,str) function (I have a return string) to learn using pointers and the new operator, here is my code:
char* strcat(char str1[], char str2[]){
int len=strlen(str1)+strlen(str2);
char* sfin = new char[len];
int i=0;
for (i=0;i<strlen(str1);i++)
*(sfin+i)=*(str1+i); //this could be *(sfin+i)= str1[i]
for (int j=0;j<strlen(str2);j++)
*(sfin+j+i)=*(str2+j); //this could be *(sfin+i+j)= str2[j]
return sfin;
}
It works, except for the thing that the new operator allocates too much memory (or is it right?), as seen from variables watcher:
P.S. in the main() function I retrieve str1 and str2 using gets(char*) and put them using puts(char*). len has the right content (9).
Results can be various: sometimes it puts the correct string and sometimes only two "strange" characters, depending on parametres.
Null-terminated strings need to be, well, null-terminted. You only copy all the characters up to the null-terminator but not the null-terminator itself. That is, if a program looks at the content of you string, it will continue looking until it finds a null-terminator. Make sure you add a null-terminator and also make sure the memory is deleted, e.g., using
std::unique_ptr<char[]> strcat(char const* str1, char const* str2) {
// ...
std::unique_ptr<char[]> ptr(new char[len]);
// ...
return ptr;
}
BTW, your use of strlen() in each iteration of the loop is likely to result in rather bad performance, especially if you have long strings.
In c and c++, strings have to be null terminated. The resulting string contains the values of string1 and string2 but it is not null terminated. The resulting string's length should be equal to strlen(strin1)+strlen(string2)+1 and the plus 1 char can be assigned the null terminator '\0'