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
Related
I wrote this code to remove all occurrences of x from the string using recursion
#include <bits/stdc++.h>
using namespace std;
void removex(string str)
{
if (str.length()==0)
{
return;
}
if (str[0] != 'x')
{
removex(str.substr(1,str.length()));
}
int i = 1;
for (; str[i] != '\0'; i++)
{
str[i-1]=str[i];
}
str[i - 1] = str[i];
removex(str);
// cout<<"strq"<<str<<endl;
}
int main()
{
int t;
cin >> t;
while (t--)
{
string str;
cin >> str;
removex(str);
cout << str << endl;
}
return 0;
}
however it's pass by value and If I try using pass by reference it gives an error as
initial value of reference to non-const must be an lvalueC. which means I need to make the reference constant which is not suitable for rest of the code. I tried pass by pointer and using arrow operator however unable to get value at index and not sure how to make recursion call. to pass address or ponter? can someone modify it accordingly?
Doing this with std::string and recursion is a formidable template for insanity. The erase/remove idiom exists for just this purpose, functions iteratively, and is highly efficient. Best of all, it already exists; all you have to do is set up the calls.
That said, if you're bent on doing this recursively (and inefficiently) you need to convey the result back to the caller (including the recursive calls) somehow. The following does that using the function return type, which is std::string. This also uses the global free operator + that allows concatenation of a char + std::string to return a new string:
#include <iostream>
#include <string>
std::string removex(std::string str)
{
if (!str.empty())
{
if (str[0] == 'x')
str = removex(str.substr(1));
else
str = str[0] + removex(str.substr(1));
}
return str;
}
int main()
{
std::string str = "Remove all x chars from this string.";
std::cout << "Before: " << str << '\n';
std::cout << "After: " << removex(str) << '\n';
return 0;
}
Output
Before: Remove all x chars from this string.
After: Remove all chars from this string.
That said, that isn't the way I'd do this. I'd use the erase/remove idiom which would be much faster, and much more memory efficient.
Given that you are using C++, I would use the features of the standard library. I believe this problem can be easily solved with a single line of code. Assuming that the string variable is called line, you would just need to do something like:
line.erase(remove(line.begin(), line.end(), 'x'), line.end());
Following is a complete example:
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
std::string line = "12djd V x jhrf h58HSFH HUHFuhfdhkdh uhdfvygh 234 fhj xxx";
std::cout << "Line before removing the x character: " << line << std::endl;
line.erase(remove(line.begin(), line.end(), 'x'), line.end());
std::cout << "Line after removing the x character: " << line << std::endl;
return 0;
}
The example above would produce the following output:
Line before removing the x character: 12djd V x jhrf h58HSFH HUHFuhfdhkdh uhdfvygh 234 fhj xxx
Line after removing the x character: 12djd V jhrf h58HSFH HUHFuhfdhkdh uhdfvygh 234 fhj
An example that you can run is available here: https://onlinegdb.com/4wzMXTXP5
I want to delete characters of a string that are in a vector, starting from an index inputted by the user up until the end of that string. For example if in index 0, my vector has the string "hello" and index 1 has the string, "goodbye", I want to erase the characters "llo" in the first string and "dbye" in the second string. So the result will be "he" in index 0 and "goo" in index 1. In my code that I am posting, I did not add the part of getting input from the user for the index. But just pretend, it is index 4 and beyond. How would I do this? Thank you.
I tried putting a '\0' character at the index that I want to start the deletion at, but that does not work.
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main()
{
int maxSize;
cin >> maxSize;
string usrInput;
vector<string> myArray;
for(int i = 0; i < maxSize; i++)
{
cin >> usrInput;
myArray.push_back(usrInput);
}
myArray[0][4] = '\0';
cout << myArray[0];
return 0;
}
You can combine the std::string method substr with the standard algorithm std::for_each to apply your cutting function to all strings in the vector.
#include <algorithm> // std::for_each
std::cout << "cut at length: ";
if(size_t cutpoint; std::cin >> cutpoint) {
std::for_each(myArray.begin(), myArray.end(), [&cutpoint](std::string& str) {
str = str.substr(0, cutpoint);
});
}
the std::string class provides a method substr which do the job.
Example:
int main()
{
int maxSize;
cin >> maxSize;
string usrInput;
vector<string> myArray;
for(int i = 0; i < maxSize; i++)
{
cin >> usrInput;
myArray.push_back(usrInput);
}
for ( auto& s: myArray )
{
s = s.substr(0,4);
std::cout << s << std::endl;
}
return 0;
}
http://www.cplusplus.com/reference/string/string/substr/
or
https://en.cppreference.com/w/cpp/string/basic_string/substr
Or you may want use resize which let the resulting string to be at a fixed size, if needed, filled up by a char which you can add as parameter.
https://en.cppreference.com/w/cpp/string/basic_string/resize
What you did is simply replacing a character inside the string. So if you have a string "abcdef" you will get "abcd\0e" which is not what you expect. You can see that yourself by printing out each of the chars like this:
myArray[0][4]='\0';
for ( auto&c: myArray[0] )
{
std::cout << (int) c << std::endl;
}
If you print it as a c-string, the output looks like the string is shorted, but it is really not! This one looks well but is wrong:
myArray[0][4]='\0';
std::cout << myArray[0].c_str() << std::endl;
Why?:
Quite simple: std::cout uses for printing std::string a different method than for printing c-style strings.
If you know where you want to cut, this is why substr function exist. Its a method from string, look at the documentation http://www.cplusplus.com/reference/string/string/substr/.
Hope it helps.
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];
}
}
#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
Ok guy i had to make a program to split elements of a string. And after that print those words.
there are some problems i am facing:
1) the array prints more than the size of the words in string i want that it should end printing as soon as last word is printed. i tried to prevent that but it always gives runtime error when i try to break at the last word.
2)is there any other efficient way to split and print ???
#include <sstream>
#include <iostream>
#include<cstdio>
#include<cstdlib>
#include <string>
using namespace std;
int main()
{
std::string line;
std::getline(cin, line);
string arr[1000];
int i = 0;
int l=line.length();
stringstream ssin(line);
while (ssin.good() && i < l)
{
ssin >> arr[i];
++i;
}
int size = sizeof(arr) / sizeof(arr[0]);
for(i = 0; i <size; i++){
cout << arr[i] << endl;
}
return 0;
}
int size = sizeof(arr) / sizeof(arr[0]);
That is a compile time value, and it's always going to be the number of elements in your array (1000). It has no idea how many strings you assigned to in your loop. You stored the number of successfully read strings (plus 1) in the i variable, so you could do this instead:
int size = i - 1;
But if it were up to me, I would just use a growable structure, like vector (#include <vector>)
std::vector<std::string> arr;
std::string temp;
while (ssin >> temp)
{
arr.push_back(temp);
}
for (auto const & str : arr)
{
std::cout << str << std::endl;
}
/* If you're stuck in the past (can't use C++11)
for (std::vector<std::string>::iterator = arr.begin(); i != arr.end(); ++i)
{
std::cout << *i << std::endl;
}
*/
For general purpose character based splitting, I would much prefer boost::split (I know you can't use it, but for future reference)
std::vector<std::string> arr;
boost::split(arr, line, boost::is_any_of(".,;!? "));
Read up on the function strtok. It is old school but very easy to use.
1) there are a couple of changes you should make to your program:
#include <sstream>
#include <iostream>
#include <string>
using namespace std;
int main()
{
std::string line("hello string world\n");
string arr[1000];
int i = 0;
stringstream ssin(line);
while (ssin.good() && i < 1000)
{
ssin >> arr[i++];
}
int size = i-1;
for(i = 0; i < size; i++){
cout << i << ": " << arr[i] << endl;
}
return 0;
}
namely, you don't want to print sizeof(arr)/sizeof(arr[0]) (i.e. 1000) elements. There is no point in the condition i < l
2) stringstream is fine if you just want to separate the single strings; if more is needed, use boost/tokenizer for splitting strings. It's modern c++, once you try it you'll never come back!
this is the best method i think no worry now
#include <sstream>
#include <iostream>
#include<cstdio>
#include<cstdlib>
#include <cstring>
#include <string>
using namespace std;
int main ()
{
std::string str;
std::getline(cin, str);
string arr[100];
int l=0,i;
char * cstr = new char [str.length()+1];
std::strcpy (cstr, str.c_str());
// cstr now contains a c-string copy of str
char * p = std::strtok (cstr,".,;!? ");
while (p!=0)
{
//std::cout << p << '\n';
arr[l++]=p;
p = strtok(NULL,".,;!? ");
}
for(i = 0; i <l; i++)
{
cout << arr[i] << endl;
}
delete[] cstr;
return 0;
}