Reversing a cstring array in a function using pointers c++ - 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];
}
}

Related

Find all substring in a given string c++

I've got a problem with a program which finds all substring in a given string.
I've tried to make variable "found", which would contain a position of a previously found substring and then start searching from the position.
Here's my code:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string str;
string str1;
cin >> str >> str1;
int i = 0;
int found = -1;
while(found < str1.size()){
found = str1.find(str, found + 1);
cout<<str1.find(str, found)<<endl;
i++;
}
}
for the following input: "ab
aabb"
it doesn't print anything.
Could you help?
So a little bit of theory first:
substr(a,b) -> returns cut out of the string from position a to position b
find(a) -> returns the position of found character or set of characters 'a'. returns -1 if NOT found.
Let's examine your code:
#include <iostream>
#include <string> //not really needed here. string should already be usable
using namespace std; //in small programs is ok but with big programs this could lead to problems with using specific things that could have the same names in std and other library. So its best to avoid this and or any other using namespace you use.
int main()
{
string str; // you should really name your variables better
string str1;
cin >> str >> str1; // your variable names are unreadable at first glance
int i = 0; // iterator cool but why is it needed if you're just using find()
int found = -1; // good variable although the name "pos" would probably be better as to further explain to the programmer what the variable does
while(found < str1.size()){ //not really sure what you were going for here
found = str1.find(str, found + 1); // this could have been your while logic above instead
cout<<str1.find(str, found)<<endl; // this finds the exact same position again using more resources. your variable found stores the position so doing cout << found << here would be better
i++;
}
}
Now let's see why your code doesn't show anything on console:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string str;
string str1;
cin >> str >> str1; //you input ab as str and abbb as str1
int i = 0;
int found = -1;
while(found < str1.size()){ //first iteration is while(-1 < 4)
found = str1.find(str, found + 1); //<-- find needs just 1 parameter. heres your problem
cout<<str1.find(str, found)<<endl;
i++;
}
}
str1.find("ab); -> function find searches for "ab" in string str1. You don't need to add where it's meant to search for. Also the fact that your while loop is dependant on found < str1.size() and not anything to do with your iterator means your loop will go on forever. whenever this happens most IDE's crash your program giving you nothing cout'ed.
Fix:
#include <iostream>
using namespace std;
int main()
{
string str;
string str1;
int pos;
cin >> str >> str1;
for(int i = 0; i < str1.size(); i++) // this or could be while(true)
{
pos = str1.substr(i).find(str); //finds your string in the rest of the line
if (pos == -1)
{
//NOT FOUND
break; //stops
}
else
{
//FOUND
cout << pos + i << endl; //pos is position in the cut out after adding i we get global position
i += pos; // skip characters after we found them to NOT be found again
}
}
}
Another possible solution would be:
Walk the input string until the point you know the substring cannot fit anymore.
For each input string position, check if each substring starts with the substring (starts_with only since C++20).
[Demo]
#include <iostream>
#include <string>
int main() {
std::string str{ "ab aab" };
std::string sub{ "ab" };
int count{};
size_t last_index{ str.size() > sub.size() ? str.size() - sub.size() : 0 };
for (size_t i{0}; i <= last_index; ++i) {
if (str.substr(i).starts_with(sub)) {
count++;
}
}
std::cout << count;
}
// Outputs: 2
int find_substr(string substr, string str) {
int postion = 0;
auto beginning = str.c_str();
int i = 0;
char* p = (char *)beginning;
while (p && '\0'!=p)
{
p = strstr(p, substr.c_str());
if (!p)
break;
cout << "A substring is at index:" << p - beginning << "\n";
p++;
};
return 0;
}
void test()
{
string substr, str;
{
substr = "ab"; str = "aabb";
cout << "Finding " << substr << " in " << str << "\n";
find_substr(substr, str);
cout << "\n";
}
{
substr = "ab"; str = "abab";
find_substr(substr, str);
cout << "\n";
}
{
substr = "a"; str = "11111111111111111111111a";
find_substr(substr, str);
cout << "\n";
}
}

Insert a character into a string

I need to insert a character into a string at every instance of that character. For example if my string was, "This is a test" and my character was 's' then my output would need to look like this: "Thiss iss a tesst"
any idea why this isn't working? Here's what I have so far. I am not supposed to add any extra preprocessor instructions or anything, just using what's here I need to figure this out.
#include <iostream>
#include <string>
using namespace std;
int main(){
string userString;
char userChar;
cin >> userString;
cin >> userChar;
for (int i = 0; i < userString.size(); i++){
if(userString.at(i) == userChar){
userString.insert(userString.begin() + i, userChar);
}
}
cout << userString;
return 0;
Update:
Here's the solution I worked out.
#include <iostream>
#include <string>
using namespace std;
int main(){
string userString;
char userChar;
cout << "enter a string" << endl;
getline(cin, userString);
cout << "enter a character" << endl;
cin >> userChar;
for (int i = userString.size()-1; i >= 0; i--){
if(userString.at(i) == userChar){
userString.insert(userString.begin() + i, userChar);
}
}
cout << userString;
return 0;
}
I don't know why you want to go through the string backwards. Anyway. Your problem is that once you insert a character at some position, your loop will encounter the inserted character again in the next iteration and insert another. Ad infinitum.
#include <cstddef> // std::size_t, the correct type for indexes and sizes of objects in mem
#include <string>
#include <iostream>
int main()
{
std::cout << "Enter a string: ";
std::string userString; // define variables as close
std::getline(std::cin, userString);
std::cout << "Enter a character: ";
char userChar; // to where they're used as possible
std::cin >> userChar;
for (std::size_t i{}; i < userString.size(); ++i) {
if (userString[i] == userChar) { // no need to use std::string::at() 1)
userString.insert(userString.begin() + i, userChar);
++i; // advance the index to not read the same character again.
}
}
std::cout << userString << '\n';
}
1) since it is allready sure that the index will be in a valid range.
Your first solution probably ends up looping infinitely if you ever find one of the chosen character because you always insert one more copy ahead and keeps finding the same char ever after.
std::basic_string has a find function. It's always better to use code offered by a library than self made code. Here's my proposed solution:
std::string& duplicate_char(std::string& str, char val)
{
using std::string;
auto pos = str.find(val); // finds first index of character val or npos if unsuccessful
while (pos != string::npos)
{
str.insert(pos, 1, val); // insert at pos one character val
pos = str.find(val, pos + 2); // find the next occurence of val starting after the newly inserted character
}
return str;
}
You may use this function like this:
int main()
{
std::string testStr{"Thiss iss a tesst"};
duplicate_char(testStr, 's');
std::cout << testStr << std::endl;
}

Trying to temporarily convert entire string to lowercase and remove spaces

So my program is a palindrome checker function using only the string library and C++ sting objects. In order to check if the string input by the user is a palindrome, I need to convert the entire string to lowercase and remove the spaces to check if the string and its reverse are equal. I've tried looking up solutions but I've only found answers using different libraries and creating new functions. This is the code I have so far.
#include <iostream>
#include <string>
using namespace std;
string checkPalin();
int main()
{
string result = checkPalin();
cout << "The palindromes are: " << result;
}
string checkPalin()
{
int stringNum, time = 0;
string list;
string str1;
string reverse;
cout << "How many strings? " << endl;
cin >> stringNum;
cout << "Enter the strings: " << endl;
do
{
getline(cin, str1);
int size = str1.length();
for (int i = size - 1; i >= 0; i--)
reverse += str1[i];
if ((str1.compare(reverse)) == 0)
{
list += str1;
}
time++;
} while (time <= stringNum);
return list;
}
How about something like this
std::string inputString = "WhatEver", cleanString;
for (char & c : inputString)
if (c != ' ')
cleanString += std::tolower(static_cast<unsigned char>(c));
std::tolower is undefined if the char value is not representable as unsigned char, hence the cast.

C++ print string one word at a time, count characters, and average of characters

how can I print a single word from a string in each line with the number of characters right next to it and the average of the characters together? I'm suppose to use a string member function to convert the object into a c string. The function countWords accepts the c string and returns an int. The function is suppose to read in each word and their lengths including the average of characters. I have done how much words are in the string except I don't know how continue the rest.
For example: super great cannon boys
super 5
great 5
cannon 6
boys 4
average of characters: 5
This is my program so far:
#include <iostream>
#include <string>
#include <cstring>
using namespace std;
int countWords(char *sentence);
int main()
{
const int size=80;
char word[size];
double average=0;
cout<<"Enter words less than " <<size-1<<" characters."<<endl;
cin.getline(word, size);
cout <<"There are "<<countWords(word)<<" words in the sentence."<<endl;
return 0;
}
int countWords(char *sentence)
{
int words= 1;
while(*sentence != '\0')
{
if(*sentence == ' ')
words++;
sentence++;
}
return words;
}
Unless this is something like homework that prohibits doing so, you almost certainly want to use std::string along with the version of std::getline that works with a std::string instead of a raw buffer of char:
std::string s;
std::getline(std::cin, s);
Then you can count the words by stuffing the line into a std::istringstream, and reading words out of there:
std::istringstream buffer(s);
auto word_count = std::count(std::istream_iterator<std::string>(s),
std::istream_iterator<std::string());
To print out the words and their lengths as you go, you could (for example) use std::for_each instead:
int count = 0;
std::for_each(std::istream_iterator<std::string>(s),
std::istream_iterator<std::string>(),
[&](std::string const &s) {
std::cout << s << " " << s.size();
++count;});
This should not be far from you requirements - I only did minimal modification to your present code.
Limits :
you'd better use
string line;
getline(cin, line);
to read the line to be able to accept lines of any size
my present code assumes
no spaces at beginning or end of line
one single space between 2 words
it should be improved to cope with extra spaces, but I leave that to you as an exercise :-)
The code :
#include <iostream>
#include <string>
#include <cstring>
using namespace std;
int countWords(char *sentence, double& average);
int main()
{
const int size=80;
char word[size];
double average=0;
cout<<"Enter words less than " <<size-1<<" characters."<<endl;
cin.getline(word, size);
cout <<"There are "<<countWords(word, average)<<" words in the sentence."<<endl;
cout << "Average of the sentence " << average << endl;
return 0;
}
int countWords(char *sentence, double& average)
{
int words= 1;
int wordlen;
char *word = NULL;
while(*sentence != '\0')
{
if(*sentence == ' ') {
words++;
wordlen = sentence - word;
average += wordlen;
*sentence = '\0';
cout << word << " " << wordlen<< endl;
word = NULL;
}
else if (word == NULL) word = sentence;
sentence++;
}
wordlen = sentence - word;
average += wordlen;
cout << word << " " << wordlen<< endl;
average /= words;
return words;
}
For input : super great cannon boys
Output is :
Enter words less than 79 characters.
super great cannon boys
super 5
great 5
cannon 6
boys 4
There are 4 words in the sentence.
Average of the sentence 5
You can inspire here. Basically use std::getline to read from std::cin to std::string.
#include <iostream>
#include <string>
#include <cctype>
inline void printWordInfo(std::string& word) {
std::cout << "WORD: " << word << ", CHARS: " << word.length() << std::endl;
}
void printInfo(std::string& line) {
bool space = false;
int words = 0;
int chars = 0;
std::string current_word;
for(std::string::iterator it = line.begin(); it != line.end(); ++it) {
char c = *it;
if (isspace(c)) {
if (!space) {
printWordInfo(current_word);
current_word.clear();
space = true;
words++;
}
}
else {
space = false;
chars++;
current_word.push_back(c);
}
}
if (current_word.length()) {
words++;
printWordInfo(current_word);
}
if (words) {
std::cout << "AVERAGE:" << (double)chars/words << std::endl;
}
}
int main(int argc, char * argv[]) {
std::string line;
std::getline(std::cin, line);
printInfo(line);
return 0;
}
Going along the lines of what you already have:
You could define a countCharacters function, like your countWords:
int countCharacters(char *sentence)
{
int i;
char word[size];
for(i = 0; sentence[i] != ' '; i++) //iterate via index
{
word[i] = sentence[i]; //save the current word
i++;
}
cout <<word<< <<i<<endl; //print word & number of chars
return i;
}
which you can call inside your countWords function
int countWords(char *sentence)
{
int words = 1;
for(int i; sentence[i] != '\0';) //again this for loop, but without
//increasing i automatically
{
if(sentence[i] == ' ') {
i += countCharacters(sentence[++i]); //move i one forward to skip
// the space, and then move
// i with the amount of
// characters we just counted
words++;
}
else i++;
}
return words;
}

How do I get a part of the a string in C++?

How do I get a part of a string in C++? I want to know what are the elements from 0 to i.
You want to use std::string::substr. Here's an example, shamelessly copied from http://www.cplusplus.com/reference/string/string/substr/
// string::substr
#include <iostream>
#include <string>
using namespace std;
int main ()
{
string str="We think in generalities, but we live in details.";
// quoting Alfred N. Whitehead
string str2, str3;
size_t pos;
str2 = str.substr (12,12); // "generalities"
pos = str.find("live"); // position of "live" in str
str3 = str.substr (pos); // get from "live" to the end
cout << str2 << ' ' << str3 << endl;
return 0;
}
You use substr, documented here:
#include <iostream>
#include <string>
using namespace std;
int main(void) {
string a;
cout << "Enter string (5 characters or more): ";
cin >> a;
if (a.size() < 5)
cout << "Too short" << endl;
else
cout << "First 5 chars are [" << a.substr(0,5) << "]" << endl;
return 0;
}
You can also then treat it as a C-style string (non-modifiable) by using c_str, documented here.
If the string is declared as an array of characters, you can use the following approach:
char str[20];
int i;
strcpy(str, "Your String");
// Now let's get the sub-string
cin >> i;
// Do some out-of-bounds validation here if you want..
str[i + 1] = 0;
cout << str;
If you mean std::string, use substr function as Will suggested.
Assuming you're using the C++ std::string class
you can do:
std::string::size_type start = 0;
std::string::size_type length = 1; //don't use int. Use size type for portability!
std::string myStr = "hello";
std::string sub = myStr.substr(start,length);
std::cout << sub; //should print h
use:
std::string sub_of_s(s.begin(), s.begin()+i);
which create a string sub_of_s which is the first i-th the element in s.