Random ascii char's appearing - c++

I was trying to write a program that stores the message in a string backwards into a character array, and whenever I run it sometimes it successfully writes it backwards but other times it will add random characters to the end like this:
input: write this backwards
sdrawkcab siht etirwˇ
#include <iostream>
#include <string>
using namespace std;
int main()
{
string message;
getline(cin, message);
int howLong = message.length() - 1;
char reverse[howLong];
for(int spot = 0; howLong >= 0; howLong--)
{
reverse[spot] = message.at(howLong);
spot++;
}
cout << reverse;
return 0;
}

The buffer reverse needs to be message.length() + 1 in length so that it can store a null termination byte. (And the null termination byte needs to be placed in the last position in that buffer.)

Since you can't declare an array with a length that is only known at runtime, you have to use a container instead.
std::vector<char> reverse(message.length());
Or better, use std::string. The STL also offers some nice functions to you, for example building the reversed string in the constructor call:
std::string reverse(message.rbegin(), message.rend();

Instead of reversing into a character buffer, you should build a new string. It's easier and less prone to bugs.
string reverse;
for(howlong; howLong >= 0; howLong--)
{
reverse.push_back(message.at(howLong));
}

Use a proper C++ solution.
Inline reverse the message:
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int main() {
string message;
getline(cin, message);
//inline reverse the message
reverse(message.begin(),message.end());
//print the reversed message:
cout << message << endl;
return 0;
}
Reverse a copy of the message string:
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int main() {
string message, reversed_message;
getline(cin, message);
//reverse message
reversed_message = message;
reverse(reversed_message.begin(), reversed_message.end());
//print the reversed message:
cout << reversed_message << endl;
return 0;
}
If you really need to save the reversed string in a C string, you can do it:
char *msg = (char *)message.c_str();
but, as a rule of thumb use C++ STL strings if you can.

Related

Managing Strings In C++

So I make an array of string pointers and put a string in at position 0 of the array. If I don't know the length of the string in word[0] how do I find it? How do I then manage that string, because I want to remove the "_." and "." part of the string so I will be left with "apple Tree".How do I resize that string? (functions like strcpy,strlen, or string.end() didn't work, I get errors like "can't convert string to char*" etc)
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <string>
using namespace std;
int main()
{
int counter=0;
string* word = new string[0];
word[0] = "apple_.Tree.";
return 0;
}
Edit:what i want to do is make a dynamic array of strings(not using vector) and then edit the strings inside
string is a class, so you can use its member functions to manage it. See the documentation.
To remove characters, use std::erase (see this answer).
#include <iostream>
#include <string>
#include <algorithm>
int main() {
// Create array of 10 strings
std::string array[10];
array[0] = "apple_.Tree.";
std::cout << array[0].size() << "\n";
array[0].erase(std::remove(array[0].begin(), array[0].end(), '.'), array[0].end());
array[0].erase(std::remove(array[0].begin(), array[0].end(), '_'), array[0].end());
std::cout << array[0];
return 0;
}

Character Array of dynamic length

I have written a C++ Function which can be represented as below:
All it does is take a string (this is where it crashes) and reverse it.
#include <iostream>
#include <string.h>
#include <stdio.h>
using namespace std;
int main()
{
cout<<"Enter a string: "<<endl;
char *str;
gets(str);
cout<<"Reversed String is: ";
for(int i=strlen(str)-1;i>=0;i--)
cout<<(str[i]);
return 0;
}
I guess there's some kind of memory access violation.
Any clue why this doesn't work?
Error: Segmentation fault (core dumped)
In c++ there is way more easier and less error prone solution to this problem via std::reverse from algorithm. Also its easier to use std::string.
#include <iostream>
#include <algorithm>
int main ()
{
std::string input;
std::cout << "Enter string to reverse: ";
std::cin >> input;
std::reverse(input.begin(),input.end());
std::cout << "Reversed string: " << input << std::endl;
return 0;
}
If you have to do it via char arrays, try this (you dont even need dynamic memory allocation)
#include <iostream>
#include <algorithm>
#include <cstring>
int main ()
{
char input[1024];
puts("Enter string to reverse: ");
fgets(input, 1024, stdin);
std::reverse(input, input + strlen(input));
printf("Reversed string: %s", input);
return 0;
}
Your code isn't c++ style and I recommend you take a look at the answer from Filip (https://stackoverflow.com/a/45903067/4386427)
I'll just address what goes wrong with your code.
When you do
char* str;
all you get is a pointer that can point to a char. You don't get any memory for holding a char. Further the value of the pointer variable str is uninitialized.
So when you do
strlen(str)
you read an uninitialized variable and try to treat this uninitialized value as a C-style string. That is undefined behavior and is very likely to cause a program crash.
You need to make sure that str is initialized before using it. As you want dynamic memory, you could do:
char *str;
str = new(char[100]); // Initialize str to point to a dynamic allocated
// char array with size 100
...
...
delete(str);
But again - I wouldn't use this style in c++ code

Using strtok/strtok_r in a while loop in C++

I'm getting unexpected behavior from the strtok and strtrok_r functions:
queue<string> tks;
char line[1024];
char *savePtr = 0;
while(true)
{
//get input from user store in line
tks.push(strtok_r(line, " \n", &savePtr)); //initial push only works right during first loop
char *p = nullptr;
for (...)
{
p = strtok_r(NULL, " \n", &savePtr);
if (p == NULL)
{
break;
}
tks.push(p);
}
delete p;
savePtr = NULL;
//do stuff, clear out tks before looping again
}
I've tried using strtok and realized that during the second loop, the initial push is not occurring. I attempted to use the reentrant version strtok_r in order to control what the saved pointer is pointing to during the second loop by making sure it is null before looping again.
tks is only correctly populated during the first time through the loop - subsequent loops give varying results depending on the length of line
What am I missing here?
Just focusing on the inner loop and chopping off all of the stuff I don't see as necessary.
#include <iostream>
#include <queue>
#include <string>
#include <cstring>
using namespace std;
int main()
{
std::queue<std::string> tks;
while(true)
{
char line[1024];
char *savePtr;
char *p;
cin.getline(line, sizeof(line));
p = strtok_r(line, " \n", &savePtr); // initial read. contents of savePtr ignored
while (p != NULL) // exit when no more data, which includes an emtpy line
{
tks.push(p); // got data, store it
p = strtok_r(NULL, " \n", &savePtr); // get next token
}
// consume tks
}
}
I prefer the while loop over the for loop used by Toby Speight in his answer because I think it is more transparent and easier to read. Your mileage may vary. By the time the compiler is done with it they will be identical.
There is no need to delete any memory. It is all statically allocated. There is no need to clear anything before the next round except for tks. savePtr will be reset by the first strtok_r.
There is a failure case if the user inputs more than 1024 characters on a line, but this will not crash. If this still doesn't work, look into how you're consuming tks. It's not posted so we can't troubleshoot that portion.
Wholeheartedly recommend changing to a string-based solution if possible. This is a really simple, easy to write, but slow, one:
#include <iostream>
#include <queue>
#include <string>
#include <sstream>
int main()
{
std::queue<std::string> tks;
while(true)
{
std::string line;
std::getline(std::cin, line);
std::stringstream linestream(line);
std::string word;
// parse only on ' ', not on the usual all whitespace of >>
while (std::getline(linestream, word, ' '))
{
tks.push(word);
}
// consume tks
}
}
Your code wouldn't compile for me, so I fixed it:
#include <iostream>
#include <queue>
#include <string>
#include <cstring>
std::queue<std::string> tks;
int main() {
char line[1024] = "one \ntwo \nthree\n";
char *savePtr = 0;
for (char *p = strtok_r(line, " \n", &savePtr); p;
p = strtok_r(nullptr, " \n", &savePtr))
tks.push(p);
// Did we read it correctly?
for (; tks.size() > 0; tks.pop())
std::cout << ">" << tks.front() << "<" << std::endl;
}
This produces the expected output:
>one<
>two<
>three<
So your problem isn't with the code you posted.
If you have the option to use boost, try this one out to tokenize a string. Of course by providing your own string and delimeters.
#include <vector>
#include <boost/algorithm/string.hpp>
int main()
{
std::string str = "Any\nString\nYou want";
std::vector< std::string > results;
boost::split( results, str, boost::is_any_of( "\n" ) );
}

string s = "hello" vs string s[5] = {"hello"}

#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int main() {
string s = "hello";
reverse(begin(s), end(s));
cout << s << endl;
return 0;
}
prints olleh
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int main() {
string s[5] = {"hello"};
reverse(begin(s), end(s));
cout << *s << endl;
return 0;
}
prints hello
Please help me understand why is such difference. I am newbie in c++, I am using c++ 11.
Ok, I corrected to s[5]={"hello"} from s[5]="hello" .
The first is a single string. The second is an array of five strings, and initializes all five string to the same value. However, allowing the syntax in the question is a bug (see the link in the comment by T.C.) and should normally give an error. The correct syntax would have the string inside braces, e.g. { "hello" }.
In the second program you are only printing one string of the five anyway, the first one. When you dereference an array, it decays to a pointer and gives you the value that pointer points to, which is the first element in the array. *s and s[0] are equivalent.
I think that what you are looking for is this:
int main() {
char s[] = "hello";
reverse(s, s + (sizeof(s) - 1));
cout << string(s) << endl;
return 0;
}
With char[6] you have an C-style string. Remember that theses strings must be terminated with '\0'. Therefore there is a 6th element.

Function that takes a String parameter and reverses it C++

I want to create a function that takes a string parameter, reverses it and returns the reversed string. There have been some answers, but none work fully.
Here is my code:
#include <iostream>
#include <string>
using namespace std;
string revStr(string word){
string reversed = "";
if(word.size() == 0)
{
return reversed;
}
for (int i = word.length()-1; i>=0; i--){
reversed = reversed+word[i];
}
return reversed;
}
int main(){
string strin;
cout << "enter string;" << endl;
cin>> strin;
cout << revStr(strin);
}
This works only for strings that do not contain a space. When I type in Hello World, it return olleH.
basic_string::operator>>:
2) Behaves as an FormattedInputFunction. After constructing and checking the sentry object, which may skip leading whitespace, first clears str with str.erase(), then reads characters from is and appends them to str as if by str.append(1, c), until one of the following conditions becomes true: [...]
std::isspace(c,is.getloc()) is true for the next character c in is (this whitespace character remains in the input stream).
The method you use by definition reads until a white-space, so you read only Hello into strin. You should use another method for reading like getline or stringstream.
You need to use std::getline to input strings with a space.
For reversing your std::string, consider using std::reverse from <algorithm>, although your algorithm is correct too.
Code:
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int main()
{
string strin;
cout << "enter string;" << endl;
getline(cin,strin);
reverse(strin.begin() , strin.end() );
cout << strin;
}
See, cin halts the input at any occurrence of a space or a newline character. So, to input a string with spaces, you'd have to use cin.getline() and that can be done by using the following snippet:
string S;
cin.getline(1000,'\n');
This would take input till the newline character into string S and then we just have to reverse the string, and that can be done in two ways.
Method 1:
Using std::reverse from <algorithm> header file. This function works with all containers and takes iterators as parameters.
#include <bits/stdc++.h>
using namespace std;
int main()
{
ios_base::sync_with_stdio(false);
string S;
getline(cin,S);
reverse(S.begin(), S.end());
return 0;
}
Method 2:
You can create your function which swaps the characters at positions equidistant from end and start, and you get what you need in O(n) time-complexity.
#include <bits/stdc++.h>
using namespace std;
string myfunc(string S)
{
int l = 0;
int r = S.size()-1;
while(l<r)
{
swap(S[l],S[r]);
l++;
r--;
}
return S;
}
int main()
{
ios_base::sync_with_stdio(false);
string S;
getline(cin,S);
S = myfunc(S);
cout<<S;
return 0;
}
What I think is you could do fine with your revStr() but you need to get a whole line input, but using cin considers space as a delimiter, hence you get only Hello out of Hello World.
Replace cin >> strin with getline(cin,strin).