I'm getting this error hence I am new to c++ I could not understand
please help me!!!
I am writing a palindrome code
This is the code given below:.............
I am basically here using some extra concepts not doing in-direct fashion.
if anyone can post the correct code he/she is most welcome...
//palindrome
#include <cstring> //or use #include <string.h>
#include <iostream>
using namespace std;
void Palindrom(string& );
void Palindrome(string& word)// same as (const string& word)
{
int n = word.length();
string word2;
char reverse[n];
for(int i = 0; i <=n; i++){
word[i]=tolower(word[i]);
}
word2=word; //now both are small
for(int i = n-1; i >=0; i--){
reverse[n-1-i]=word2[i];
cout<<reverse[n-1-i];
}
for(int i =0; i >n; i++){ //printing reversed
cout<< " Reverse: "<<reverse[i]<<endl;
}
// word is ok and word2 gets reversed
for (int i = 0; i <= n; i++){
if(word[i]==reverse[i])
{
cout<<"\nit is palandrome ";
}
cout<<"\nit is not a palindrome ";
}
}
int main()
{ string k="YuUuy";
void Palindrome(k);
return 0;
}
Correct syntax for calling a function is Palindrome(k); without the void.
Few remarks:
Get a good c++
book.
// same as (const string& word) is not true.
You did not include <string> header.
It's good practice to use std::size_t for indices, but beware of unsigned>=0 condition being always true.
char reverse[n]; is wrong, n must be a compile-time constant, VLA are not part of the C++ standard.
Function calls should not have return type. Change void Palindrome(k); in main() function to Palindrome(k);
While declaring array, the expression should have constant value. So you can't use char reverse[n];. Change it to char *reverse = new char[n]; and deallocate it using delete[] reverse; after you are done using it.
I would recommend you to use smart pointer. You should also take a look at std::string instead of using stream of char.
Related
I have a routine function process_letter_location(const char& c, string &word).
Inside my main I have declared a series of string variables like so:
string sf_1 = "something", sf_2 = "something", sf_3 = "something",
sf_4 = "something";
And i have a string word and i call my routine function as so
process_letter_location(word[0], sf_1);
process_letter_location(word[1], sf_2);
process_letter_location(word[2], sf_3);
process_letter_location(word[3], sf_4);
This does look a bit messy but i know i can use a loop to call the routine like
for(int i=0; i < 4; i++) {
process_letter_location (word[i], ?)
}
But I'm not so sure how i would go about assigning the second argument. The variables have 'sf_' in common and the only thing that change are the numbers. Is there anyway that i can incorporate this routine call in the loop? If not are there better ways of implementing this code?
Any help would be appreciated.
Thanks
You can use an array:
string sf[4] = { "something1", "something2", "something3", "something4"};
Then loop:
for(int i=0; i < 4; i++) {
process_letter_location (word[i], sf[i]);
}
You should use an array. Your use case screams it should be an array.
But if you can only change how you process the variables, you can use a variadic template function as well.
#include <iostream>
#include <string>
#include <type_traits>
using namespace std;
void process_letter_location(char c, string const& str)
{
cout << str << '\n';
}
void process_strings(char* buf, string const& str)
{
process_letter_location(*buf, str);
}
template<typename... Args>
auto process_strings(char* buf, string const& str, Args... args)
-> typename enable_if<sizeof...(Args)>::type
{
process_letter_location(*buf, str);
process_strings (++buf, args...);
}
int main() {
string sf_1 = "something1",
sf_2 = "something2",
sf_3 = "something3",
sf_4 = "something4";
char buff[10];
process_strings(buff, sf_1, sf_2, sf_3, sf_4);
return 0;
}
Which is just a fancy way to unroll the loop. See here
You can start with this refactoring: replace string with string * const
in the function process_letter_location. (Adjust the function definition
accordingly).
Then you can fill your favourite container with the string pointers
and loop on it.
I think you can learn a lot of C++ from this refactoring.
Let me show how you could write the loop:
std::vector<std::string*> strings = {&sf_1,
&sf_2,
&sf_3,
&sf_4};
for(int i=0; i < 4; i++) {
process_letter_location (word[i], strings[i]);
}
then you may consider using iterators rather than a C-style loop.
I created a function to store a string in an array without spaces and punctuation:
int main()
{
char arr[1];int b,i=0;
bool newl = false;
for(;!newl;)
{
arr[i]=cin.get();
b = arr[i];
if(b>=65&&b<=90) i++;
else if(b>=97&&b<=122) i++;
if(arr[i]=='\n') newl =true;
}
for(int j=0;j<i;j++)
cout << arr[j];
}
it seemed pretty logic to me but when i tested it, its behaviour didnt turn out as i expected like with 1 character its ok but more than that its just really wrong.Is it because of the cin.get? Sorry im newb.
Thanks.
You allocated only one element to arr, so accessing arr[1] or further is forbidden.
std::vector is useful as variable-length array.
Also I suggest you should use isalpha() from library cctype instead of the comparation against magic numbers that are relatively hard to understand and dependent on the character code.
#include <iostream>
#include <vector>
#include <cctype>
using std::cin;
using std::cout;
int main()
{
std::vector<char> arr;int b,i=0;
bool newl = false;
for(;!newl;)
{
b = cin.get(); // store the input directly into b
if(isalpha(b)) arr.push_back(b);
if(b=='\n') newl = true;
}
for(size_t j=0;j<arr.size();j++)
cout << arr[j];
}
I need to pass a char pointer to function, then change the value that it points to inside the function and print values outside the function.
The problem I have is that I'm losing it when I leave function and try to print it outside. What can I do to avoid this?
This is an code example:
char array[] = "Bada boom";
char *pText = array;
reverseText(pText);
cout << (pText);
cout should print
moob adaB
When I print inside the function, everything is fine(it prints reversed).
My task is to print It out outside the function (as you can see in a 4th line of code)
This is the full of code which have the bug (printing inside func works, outside didn't work)
#include <iostream>
#include <string>
#include <string.h>
using namespace std;
char reverseText(char *text);
int main(){
char array[] = "Bada boom";
char *pTekst = array;
reverseText(pTekst);
cout << (pTekst); //in here it doesn't work
}
char reverseText(char *text){
char befRev[100]; int lenght=-1;
/*until *text doesn't meet '\0' */
for(int i=0;*text!='\0';i++){
befRev[i]=(*text);
text++;
lenght++;
}
/*reversing*/
int j=0;
for(int i=lenght;i>=0;i--){
*(text+j)=befRev[i];
j++;
}
for(int i=0;i<=lenght;i++) //in here it does print the right value
cout << text[i];
};
Just re-arrange the array in-place. The pointer itself doesn't need to change:
#include <cstring>
#include <algorithm>
void reverseText(char* array)
{
auto len = std::strlen(array);
std::reverse(array, array+len);
}
int main()
{
char array[] = "Bada boom";
char *pText = array;
reverseText(pText);
std::cout << pText << std::endl;
}
Output:
moob adaB
If you really wanted to provide a pointer that points to a different address to the caller, you could simply return it:
char* foo(char* stuff)
{
char* tmp = ....;
...
// do some stuff
...
return tmp;
}
Alternatively, you could pass the pointer by reference, but the intent is less clear than in the previous version:
void foo(char*& stuff)
{
stuff = something_else;
}
But in both cases, you must make absolutely sure the thing the new pointer points to is valid outside of the function. This might require some dynamic memory allocation. For your case, it seems the best and simplest option is to re-arrange the array in place.
To answer your question, you have an error in logic. Notice that in your first loop in reverseText you increment the local pointer text. In your second loop you did not reset text to it's original value so beforeRev is being copied over starting at location text+offset.
If you were to look at pText on return from call to reverseText you would find it contains:
"Bada boom\0moob adaB"
Your reverseText should be renamed palindrome :)
This is pretty straightforward. Some points to note:
An array decays to a pointer when you pass it to a function.
You are passing in a null terminated string. So the length of the char array you are passing in is the length of the string (including white space) +1.
Because you are using a pointer there is no need to assign a temp variable to hold everything.
Here is some code in C that is easy to translate to C++. Working out the actual reverse algorithm is left for you as an exercise.
#include<stdio.h>
void reverseText(char* text)
{
// Hint: It can be done in one loop!
int i;
for(i = 0; i < 9; i++)
{
// Your algorithm to reverse the text. I'm not doing it for you! ;)
*(text + i) = 'r';
}
}
int main()
{
char array[] = "Bada boom";
reverseText(array);
printf("The text reversed: %s\n", array);
return 0;
}
My final code:
#include <iostream>
void reverseText(char* text){
int length=-1; char tmp;
/*Length = sign from 0 to 8 without counting explicit NUL terminator*/
for(int i=0;*(text+i)!='\0';i++){
length++;
}
int j=0; int i=length;
while(j<i){
tmp=*(text+j); //tmp=first
*(text+j)=*(text+i); //first=last
*(text+i)=tmp; //last=tmp
j++;
i--;
}
}
int main(){
char array[] = "Bada boom";
char *pText = array;
reverseText(pText);
std::cout << pText;
}
I should have read more about pointers before I started this exercise.
You can either return a pointer or pass a pointer to pointer as a function argument.
//pointer to pointer
void reverseText(char** textPtr) {
char* newText = ...; //initialize;
...
*textPtr = newText; //assign newText
}
//return pointer
char* reverseText(char* text) {
char* newText = ...; //initialize
return newText;
}
Remember that if you allocate memory in this function you must do it dynamically (with new or malloc) and you have to free it afterwards (with delete or free respectively). Memory allocation in a function like this is probably a bad practice and should be avoided.
I'm making a class to delete repeated character from a random word. For example if the input is "aabbccddeeff", it should output "abcdef". However my output contains strange characters after "abcdef". The main.cpp file already exists as the requirements for creating the class. Please see the following codes:
main.ccp
#include <iostream>
#include "repeatdeletion.h"
using namespace std;
int main()
{
char* noRepeats;
int length;
string s;
cout<<"Enter a random word with repeating characters: ";
cin>>s;
RepeatDeletion d;
length=s.length();
noRepeats=d.deleteRepeats(s, length);
cout<<"Your word without any repeating characters: ";
for (int k=0; k<length; k++){
cout<<noRepeats[k];
}
cout<<endl;
delete [] noRepeats;
noRepeats=NULL;
return 0;
}
repeatdeletion.h
#ifndef REPEATDELETION_H
#define REPEATDELETION_H
#include <iostream>
using namespace std;
class RepeatDeletion
{
char* c;
char arr[128]={};
bool repeated;
bool isRepeated(char);
public:
RepeatDeletion();
~RepeatDeletion();
char* deleteRepeats(string, int);
};
#endif // REPEATDELETION_H
repeatdeletion.cpp
#include "repeatdeletion.h"
RepeatDeletion::RepeatDeletion()
{
repeated=false;
}
RepeatDeletion::~RepeatDeletion()
{
delete [] c;
c=NULL;
}
bool RepeatDeletion::isRepeated(char c){
bool repeated=false;
if (arr[c]>=1){
repeated=true;
arr[c]++;
}else{
arr[c]++;
}
return repeated;
}
char* RepeatDeletion::deleteRepeats(string str, int len){
c=new char[len];
int j=0;
for (int i=0; i<len; i++){
if (isRepeated(str[i])==false){
c[j]=str[i];
j++;
}
}
return c;
}
Your return character array is not null terminated.
The length function of string does not include \0.
You have two choices
Add null at the end of returned character array, and std::cout the char array directly (instead of char by char)
Output the final length of your char array, and use that as range to print it char by char
Your printing loop loops using the old and unmodified string length. That means you will go outside the characters you added to memory returned by deleteRepeats.
The easiest solution to handle this is to terminate the data as a proper string, and check for the terminator in the loop.
If you want to use a C-string array, they have a null terminator at the end. That means you'll want to (in deleteRepeats) define your character array one character larger than the length:
c=new char[len+1];
And, after the for loop, ensure you put that null terminator in:
c[j] = '\0';
Then, in your calling function, you can just do:
cout << noRepeats;
Even if you don't want to use C strings, you'll need to communicate the new length back to the caller somehow (currently, you're using the original length). The easiest way to do that is (IMNSHO) still using a C-style string and using strlen to get the new length (a).
Otherwise, you're going to need something like a reference parameter for the new length, populated by the function and used by the caller.
(a) But I'd suggest rethinking the way you do things. If you want to be a C++ coder, be a C++ coder. In other words, use std::string for strings since it avoids the vast majority of problems people seem to have with C strings.
That's because in your code you write the following:
cout<<"Your word without any repeating characters: ";
for (int k=0; k<length; k++){
cout<<noRepeats[k];
}
cout<<endl;
Here, length refers to the length of the original string (which you, by the way shouldn't pass to your deleteRepeats method). I would suggest you make deleteRepeats return a string and write something like this:
std::string noRepeats = d.deleteRepeats(s);
std::cout << "Your word without any repeating characters: ";
std::cout << noRepeats << std::endl;
C-style string (char *, if you insist) follow the convention that the last character is '\0', indicating that the string ends. You could also change deleteRepeats by appending '\0', i.e.
char* RepeatDeletion::deleteRepeats(string str){
c = new char[str.size() + 1];
int j = 0;
for (int i = 0; i < str.size(); i++){
if(isRepeated(str[i]) == false){
c[j] = str[i];
j++;
}
}
c[j] = '\0';
return c;
}
and in your main
std::cout << noRepeats << std::endl;
instead of the for loop. But really, you should use std::string, and if possible not mix it with char *. Hope that helps.
for(k=0;k<length;k++)
Here length should be the exact length of noRepeats, but not of s
so :
char* RepeatDeletion::deleteRepeats(string str, int len)
should return the length-after too
use std::unique it does what you want:
std::string s{};
std::cin>>s;
auto it = std::unique(std::begin(s), std::end(s));
s.resize(std::distance(std::begin(s),it));
std::cout << s;
the way it works is to go through the range begin to end and move all the remaining elements forward if the current element is equal to the next. It returns the position of the end of the new string (it in this example) but does not actually shorten the string so on the next line we shorten the string to the length equal to the distance of begin() to it.
see live at http://ideone.com/0CeaHW
I can't figure out how to do this.
The question: Implement the function
int count_matches(const string arr[], int size, string query);
Return the number of strings in the array that are equal to query or
-1 if size if less than 0.
My answer:
#include <iostream>
#include <cmath>
#include<string>
using namespace std;
int count_matches(const string arr[], int size, string query){
int i = 0;
int numMatches;
for (;i<size;i++) {
if (string[i] == (string[i]+1)){
numMatches++;
}
}
return numMatches;
}
int main(){
string selection;
const string array[4]={"dog", "cat", "dog", "dog"};
cout<<"which animal do you want?"<<endl;
cin>> selection;
cout<< "there are " << count_matches(array, 4, selection)<< " matches"<<endl;
return 0;
}
What is wrong?
int count_matches(const string arr[], int size, string query){
int numMatches(0);
for (int i=0; i<size; ++i)
{
if (arr[i] == string)
{
++numMatches;
}
}
return numMatches;
}
This should be a solution to your problem but you will never learn anything from gaining the answer this way. I'd advise reading this tutorial on arrays and loops to better understand how to tackle the problem next time.
Once you get your code to compile, you need to look carefully at this block:
if (string[i] == (string[i]+1)) {
numMatches++;
}
What do you actually want to compare here? string is a type. Take another look at the arguments that you pass into the function and that should make it clear.
Then, once you have a match, you increment numMatches. But what value does this have to start with? What value should it have to start with?
Note that std::count() does exactly what your count_matches() function should do:
std::count(array, array + 4, selection)
This will probably not statisfy whomever marks your homework, but it is worth playing with and learning if you want to advance your C++ skills.
Good luck!