segmentation fault (core dumped) in C++ strings - c++

#include<iostream>
#include<string>
using namespace std;
int STRLEN(char* s){
cout<<"\n1.";
int i=0;
while(s[i] != '\0'){
cout<<"\n2.";
i++;
}
return i;
}
int main(){
int i,j;
char* s1;
char* s2;
cout<<"\nEnter string : ";
cin.getline(s1,50);
cout<<s1;
cout<<"\nEnter string : ";
cin.getline(s2,50);
cout<<s2;
int L1=STRLEN(s1);
int L2=STRLEN(s2);
cout<<"\nL1 = "<<L1;
cout<<"\nL2 = "<<L2;
/*
for*(i=L1,j=0; i<L1+L2; i++,j++)
{
s1[i] = s2[j];
j++;
}
cout<<s1;*/
return 0;
}
the above code is giving me segmentation fault at line int L1=STRLEN(s1);
Please provide a solution , i want my string to be dynamically manipulated, so that i can extend the given string, also append new string to existing string without using inbuilt methods.
Also without using string data type

Actually, your function STRLEN looks norm (except couts inside and lack of const for s)
int STRLEN(const char* s)
{
int i=0;
while(s[i] != '\0')
{
i++;
}
return i;
}
The problem in memory allocation :getline does not allocate memory for you - you must allocate memory for strings
char* s1;
char* s2;
E.g. like:
char* s1 = malloc(100);
char* s2 = malloc(100);
Actually for your case with cin.getline(s2,50); 50 bytes will be enough:
char* s2 = (char*)malloc(50);
Here (char*) is explicit cast of a pointer type (see also static_cast for C++, and be informed that for C implicit cast is working in that case)
UPDATE:
Just to give you more examples and provoke more questions... the following is my modification of your program with comments for each section:
#include<iostream>
#include<string>
using namespace std;
int STRLEN(const char* s)
{
int i=0;
while(s[i] != '\0')
{
i++;
}
return i;
}
int main(void)
{
int i; // one counter will be enough
char* s1;
char* s2;
// allocation the memory
s1 = static_cast<char*>(malloc(50));
s2 = static_cast<char*>(malloc(50));
// check results of memory allocation
if(!s1 || !s2)
{
cerr << "Something went wrong!" << endl;
return 1;
}
// getting strings
cout<<"\nEnter the first string : ";
cin.getline(s1,50);
cout<< "S1 : [" << s1 << "]" << endl;
// clean input buffer before next string input
cin.clear(); // reset state of cin
cin.ignore(INT_MAX, '\n'); // clean the input buffer
// continue input
cout<<"\nEnter the second string : ";
cin.getline(s2,50);
cout<< "S2 : [" << s2 << "]" << endl;
// count sizes (like strlen)
int L1=STRLEN(s1);
int L2=STRLEN(s2);
// reallocate memory for resulting string in s1
if( !(s1 = static_cast<char*>(realloc(s1, L1+L2+1))) )
{
cerr << "Something went wrong while reallocating memory!" << endl;
return 1;
}
// manipulations with strings (like strcat)
for(i=0; i <= L2; i++) // <= to copy '\0' also
{
s1[i + L1] = s2[i];
}
cout<< "Result : [" << s1 << "]" << endl;
// deallocate memory
free(s1);
free(s2);
return 0;
}
And as molbdnilo rightly noted in the comments, in C++ it is better to use new and delete for memory allocation and deallocation, so after you figure out with my example try to get rid of C functions: malloc, realloc and free.
After that, like making your program even more C++ solution, consider changing the type of strings from char * to std::string this will definitely save you from memory allocation problem and make all other parts of program simpler (e.g. s1 += s2 operation will be possible). When you get to that read about getline for string

Related

Allocate and return string from function?

What is the best strategy is for returning a modified copy of a string from a function? From my experience in programming in C, I know that it is generally preferable to return a pointer to a large object (array or struct) instead of a copy.
I have the following example, where I pass a string type to a C++ function and return a char *. I was wondering how I should go about returning a string object instead. If I were to return a string, would it be advisable to return a copy or dynamically allocate it and return the pointer?
#include <iostream>
using namespace std;
char *removeSpaces(string sentence)
{
char *newSentence = new char[sentence.size()]; // At most as long as original
int j = 0;
for (int i = 0; i < sentence.size(); i++) {
if (sentence[i] == ' ') {
newSentence[j++] = ' ';
while (sentence[++i] == ' ');
}
newSentence[j++] = sentence[i];
}
return newSentence;
}
int main(void)
{
string sentence;
cout << "Enter a sentence: ";
getline(cin, sentence);
char *sentenceSpacesRemoved = removeSpaces(sentence);
cout << "After removing spaces: ";
cout << sentenceSpacesRemoved << endl;
delete[] sentenceSpacesRemoved;
return 0;
}
Thanks to copy elision, you can just return a stack-allocated string object from a function without any overhead:
std::string getString()
{
std::string str;
return str;
}
Moreover, you can get "guaranteed" elision (since C++17) if you construct the string right in the return expression:
std::string getString()
{
return std::string{};
}
If you don't need a copy at all, however, for your scenario you can just pass the string and remove whitespaces in-place:
void removeSpaces(std::string& sentence)
{
for (auto it = std::cbegin(sentence); it != std::cend(sentence); ++it) {
if (*it == ' ') {
it = sentence.erase(it);
}
}
}

String not being printed by C++

Sorry for the noob question, I'm a newbie programmer and transitioning from C to C++.
I could easily write a program to reverse a string in C the same way with minor changes but writing this in C++, why does this not print anything:
#include <iostream>
#include <string>
using namespace std;
int main(){
string s,p;
getline(cin,s);
int j=0,i = 0;
while(s[i]!='\0'){
i++;
}
i--;
while(i!=-1){
p[j] = s[i];
j++;
i--;
}
cout << p << endl;
return 0;
}
if i replace the p with say p[2], it correctly prints out the reverse 3rd character of the original string, but i cant find a way to print the whole string.
std::string str{"reverse me"};
std::string rev{str.rbegin(), str.rend()};
//or when you are not interested in the orignal string
std::reverse(str.begin(), str.end());
Giving the constructur of the reverse string the reversed iterators of your input string gives you the string in reversed order.
To fix your string reverse code you just have to resize the string object p:
int main(){
std::string s = "hello",
p;
p.resize(s.size()); // this was causing your problems, p thought it was size 0
for (int i = s.size() - 1, j = 0; i >= 0; i--, j++)
{
p[j] = s[i];
}
std::cout << p << std::endl;
return 0;
}
In addition to this, there is no need to find \0 in the string, while it will be there, you can just ask std::string what its size() is.
On a side note, while std::string probably allocates some memory by default, just assuming it has enough to store whatever you input is going to be undefined behaviour.
While there are ways to iterate over a std::string and fill the contents of another, the overload of std::basic_string::operator= will replace the content of p (if any) with the content of s in a simple assignment. See std::basic_string::operator=
For example:
#include <iostream>
#include <string>
int main (void) {
std::string s {}, p {};
std::cout << "enter string: ";
if (getline (std::cin, s)) {
p = s; /* simple assignment replaced content of p with content of s */
std::cout << "string in p : " << p << '\n';
}
}
Example Use/Output
$ ./bin/stringps
enter string: the string s
string in p : the string s
string p; doesn't have enough allocated space for directly accessing by something like p[j]
You can change to initialize p from copying s like below, your code will work.
string s;
getline(cin,s);
string p(s); // p will be allocated and be the same as s

Reversing a cstring array in a function using pointers c++

I have an assignment that wants me to get a cstyle string (just 1 word) from the user then use a function to reverse its letters. The function has to take in 2 parameters, the first that is the destination string, and the other that is the source string. It will take whatever is in the source string, reverse it, then store the reversed version in the second string.
But everytime I compile, I typed in hello it prints out: \370\365\277\357\376. I just learned how to use pointers and cstyle strings so I don't really know how to use them and I think thats what is messing up my code. I'm dont understand it that well though so I cant figure out where I'm going wrong at.
Please let me know if you know what I'm doing wrong. Thank you!
#include <iostream>
#include <cstring>
#include <string>
#include <cctype>
using namespace std;
void IsPalindrome(char *cstring);
void Reverse(char *str2[], char *str1[]);
int main() {
// user variables
char str1[81];
char reverse;
char str2[81];
strcpy (str2, str1);
//prompt user to input string
cout << "\nPlease input a string (80 chars max): ";
cin >> str1;
cout << "\nYour string is: " << str1 << endl;
//call function
Reverse(str2[81], str1[81]);
//Output reversed string
cout << "Your string reversed is: " << str2 << endl;
cout << "This is a " << "." << endl;
return 0;
}
void Reverse(char *str2, char *str1)
{
char* front, *rear;
int len = strlen(str1);
char temp;
front = str1;
rear = &str1[len - 1];
while(front < rear)
{
temp = *front;
*front = *rear;
*rear = temp;
front++;
rear --;
}
}
void IsPalindrome(char cstring)
{
}
Pointers make life harder, don't use them if you don't need them. As your assignment is to reverse a string, so just use string. string is const char* inside but it's much easier to handle.
Beside your problem with pointers and arrays in your code, you are getting your string from input using std::cin. Remember that this way you can't get strings that have white space one them (you will just get the first word).
Also there is some algorithm that do this kind of tasks for you these days but for educational reasons it's not bad to do it yourself.
Here is what you can do, in the code I mentioned places that you could use ready to use algorithms to do the task for you.
#include <iostream>
#include <cstring>
#include <string>
#include <cctype>
#include <algorithm>
void Reverse(std::string &inputStr);
int main()
{
// user variables
std::string str1 = "";
std::cout << "\nPlease input a string (80 chars max): ";
std::getline(std::cin, str1);
std::cout << "\nYour string is: " << str1 << std::endl;
Reverse(str1);
//You also can use stl algorithm to reverse string for you and don't do it manually like below, but as it is an assignment it would not be good
//std::reverse(str1.begin(), str1.end());
//Output reversed string
std::cout << "Your string reversed is: " << str1 << std::endl;
std::cout << "This is a " << "." << std::endl;
system("pause");
return 0;
}
void Reverse(std::string &str)
{
int n = str.length();
for(int i = 0; i < n / 2; i++)
{
char temp = str[i];
str[i] = str[n - i - 1];
str[n - i - 1] = temp;
//You also can use stl algorithm to do the swap for you like below
//std::swap(str[i], str[n - i - 1]);
}
}
NOTE: This example will reverse your original string that user entered, if you want to have the both original and reversed, you need to pass a copy of input to the function. something like this :
std::string str2(str1);
Reverse(str2);
std::cout << "Reversed : " << str2;
EDIT: To match your assignment requirements (have a function with two parameters and single word string) you can easily change the above code like this :
void Reverse(std::string inputStr, std::string &outputStr);
int main()
{
// user variables
std::string str1 = "";
std::string str2 = "";
std::cout << "\nPlease input a string (80 chars max): ";
std::cin >>str1;
std::cout << "\nYour string is: " << str1 << std::endl;
Reverse(str1, str2);
//You also can use stl algorithm to reverse string for you and don't do it manually like below, but as it is an assignment it would not be good
//std::reverse(str1.begin(), str1.end());
//Output reversed string
std::cout << "Your string original is: " << str1 << std::endl;
std::cout << "Your string reversed is: " << str2 << std::endl;
system("pause");
return 0;
}
void Reverse(std::string inputStr, std::string &outputStr)
{
outputStr = inputStr;
int n = outputStr.length();
for(int i = 0; i < n / 2; i++)
{
char temp = outputStr[i];
outputStr[i] = outputStr[n - i - 1];
outputStr[n - i - 1] = temp;
//You also can use stl algorithm to do the swap for you like below
//std::swap(str[i], str[n - i - 1]);
}
}
There is no need of using pointers for reversing a character array to another character array.
void Reverse(char *str2, char *str1)
{
int len = strlen(str1);
for(int n = 0; n< len; n++)
{
str2[n] = str1[len-n-1];
}
}

C++ String to Integer Issue Using atoi(str.c_str())

I am trying to represent a variable in the form of a string to a integer, I have done so using;
atoi(str.c_str())
The string is originally obtained from a text file and stored into a;
CharArrayPtr cmemblock;
Which is then represented as a string;
string str;
for(int i = 0; i < numberofvalues; i++)
{
str = cmemblock[i];
int number = atoi(str.c_str());
cout << number;
}
If I was to change the 'cout' to print str;
str = cmemblock[i];
int number = atoi(str.c_str());
cout << str;
The number show correctly as stored in the text file
However, I require the output to be an integer so that I could represent it in a loop to search for a value stored in a array. So this is where 'number' comes into play, which is the reason why I am asking for your help, when;
cout << number;
Whenever a new line is read it is represented as '0' how would I go about removing this? If your require my full code it is in several different .cpp files and to prevent anyone copying my work I can only email it you, im sure you have already guessed it is part of a University Assignment.
Using Member Adosi code I came up with this;
std::string str;
for(int i = 0; i < numberofvalues; i++)
{
str = cmemblock[i];
std::stol(str);
int number = std::stoi(str);
cout << number;
}
I get an error R6010. Have I done this wrong?
std::stoi(str)
Use this instead of atoi
C++11 has this and a few other functions such as std::stol() for longs, std::stof() for floats, etc.
http://en.cppreference.com/w/cpp/string/basic_string/stol
If you dont have C++11 for std::stoi but do have boost you could use lexical cast
#include <boost/lexical_cast.hpp>
int main()
{
std::string s = "100";
try
{
int n = boost::lexical_cast<int>(s);
std::cout << "n = " << n << std::endl;
}
catch (boost::bad_lexical_cast)
{
std::cout << "conversion failed" << std::endl;
}
}
This ensures a valid conversion can take place and throws an exception if it cannot
Regarding your Edit - This requires a C++11 Compiler to work
std::string str;
for(int i = 0; i < numberofvalues; i++)
{
str = cmemblock[i];
//std::stol(str); -> This line is unneeded as it converts string to a long
// Ideally you should check that str is valid here etc. before changing it to an int
int number = std::stoi(str);
cout << number;
}
Another option is to use std::stringstream:
#include <sstream>
#include <string>
int string_to_int(const std::string &string) {
std::stringstream s(string);
s >> number;
if (!s.good()) {
throw std::exception();
}
return s;
}
int main(int argc, const char* argv[]) {
int number = string_to_int(argv[1]);
return 0;
}
This doesn't require any external libraries or C++11, and should be compatible with any C++ compiler out there.
Edit
Fleshed out the example to show how you could write your own string_to_int function to simplify the use of std::stringstream.

Char* and While Loop is not working with eachother

Here is code which compare s2 with s1, if they are the same it returns 0 and some other options, but while loop is not end-able and I can not find its problem, the only thing I know if I convert char* s2 into const char* s2 it will work fine.
#include <iostream>
using namespace std;
int cmp(char*,char*);
int main()
{
char* s1;
cout << "Please Enter First Word: "; cin >> s1;
char* s2;
cout << "Please Enter Second Word: "; cin >> s2;
cout << "The Result is: " << cmp(s1,s2) << endl;
return 0;
}
int cmp(char* s1, char* s2)
{
int i=0;
while (*(s2+i)!=0)
{
if (*(s2+i)>*(s1+i)) return 1;
if (*(s2+i)<*(s1+i)) return -1;
i++;
}
return 0;
}
You have undefined behaviour. You aren't allocating any space to store the string (you're not initialising s1 or s2 to point at any memory).
I suggest using std::string instead; it manages its own memory issues.
Consider:
char* s1;
cout << "Please Enter First Word: "; cin >> s1;
How big is s1 ? The problem is that your char pointers doesn't point to any memory block. You need to allocate memory with new.
As above said by Oli and karlphillip, your code must allocate memory for strings.
And the compare function can be like....
int cmp(char* s1, char* s2)
{
int i=0;
while ( *(s1+i)!=0 & *(s2+i)!=0 )
{
if (*(s2+i)>*(s1+i)) return 1;
if (*(s2+i)<*(s1+i)) return -1;
i++;
}
if(*(s1+i)==0 & *(s2+i)==0 )
return 0;
else if (*(s1+i)!=0)
return -1;
else
return 1;
}
Because, your cmp function will return 0 whenever your str1 is greater in length that str2 and str1 is identical to str2 upto str2's length.