So I'm having a substantial amount of trouble with this one bit of code. I've included the whole program for context, but my issue lies in the cleanUp function, wherein I (attempt to) remove all characters that are not 'A' through 'Z'.
Any tips?
#include <iostream>
#include <cstdlib>
#include <string>
#include <stdio.h>
#include <ctype.h>
using namespace std;
bool again(string title); // Checks if you want to run again.
void makeUpper(char word[]);
void getReverse(char word[], char reversed[]);
char * find(char *str, char what);
bool equal(char word[], char reversed[]);
int size(char word[]);
char * cleanUp(char *str);
int main()
{
char word[256] = "Hello?? There!", reversedWord[256];
do
{
cout<<"Please enter the string to check: ";
makeUpper(word);
cout << word;
cleanUp(word);
getReverse(word,reversedWord);
if(equal(word, reversedWord))
cout<<"You have a palindrome!"<<endl;
else
cout<<"You do not have a palindrome!"<<endl;
} while(again("Do you want to do this again? "));
return 0;
}
bool again(string title)
{
string answer;
cout<<endl<<title;
getline(cin,answer);
return toupper(answer[0]) == 'Y';
}
void makeUpper(char word[])
{
char *ptr = word;
while (*ptr) {
*ptr = toupper(*ptr);
ptr++;
}
cout << "In uppercase:: " << word << endl;
}
char * cleanUp(char * astrid)
{
char *new_astrid;
for (*astrid; *astrid != '\0'; astrid++)
{
cout << "First loop";
if (isalpha(*astrid))
{
*new_astrid = *astrid;
new_astrid = ++new_astrid;
cout << "Here!";
}
}
cout << *new_astrid;
return *new_astrid;
}
void getReverse(char word[], char reversed[])
{
char *ptr_ind = find(word, '\0'), *ptr_ind_2 = reversed;
while(ptr_ind != word-1)
{
*ptr_ind_2 = *ptr_ind;
ptr_ind--;
ptr_ind_2++;
}
*ptr_ind_2 = '\0';
}
char * find(char *str, char what)
{
char *ptr = str;
while(*ptr != what && *ptr != '\0')
ptr++;
return *ptr == what ? ptr : NULL;
}
bool equal(char word[], char reverse[])
{
int total;
char * ptr;
ptr = word;
if((total = size(word)) != size(reverse))
return false;
for(char * ptr2 = reverse; *ptr != '\0' && *ptr == *ptr2; ptr++, ptr2++);
return *ptr == '\0';
}
int size(char word[])
{
int total = 0;
char * ptr = word;
while(*ptr != '\0') //while(!ptr)
{
ptr++;
total++;
}
return total;
}
There are several errors in your code.
new_astrid is not initialized and when you call *new_astrid = *astrid you try to copy a character to uninitialized memory, which will crash the program.
You also return the dereferenced pointer to new_astrid but the function prototype of cleanUp says that you return a pointer to char.
You should initialize new_astrid with new char[strlen(astrid)]. But then your code will result in memory leaks, since you increase the pointer (new_astid = ++new_astrid). So you should store the pointer first, so you can delete it later.
Instead of using raw pointers, i would suggest you use std::strings.
My suggestion for a palindrome tester would be:
#include <iostream>
#include <string>
#include <locale>
bool isPalindrome(std::string word)
{
std::locale loc;
for (std::string::size_type i = 0; i < word.length() / 2 + 1; ++i)
{
if (std::toupper(word[i],loc) != std::toupper(word[word.length() - i - 1],loc))
{
return false;
}
}
return true;
}
int main(int , char **)
{
std::string str = "Abba";
//Remove all non alpha values from string
str.erase(std::remove_if(str.begin(), str.end(), [](char const c){return !std::isalpha(c);}), str.end());
if (isPalindrome(str) == false)
{
std::cout << str << " is no palindrome" << std::endl;
}
else
{
std::cout << str << " is a palindrome" << std::endl;
}
return 0;
}
The erasion of non alpha values in the string is from this question.
Related
#include<iostream>
#include<string>
#include<sstream>
#include <typeinfo>
#include<cmath>
#include<vector>
#include <algorithm>
using namespace std;
class Mystring {
char *arr;
public:
Mystring(const char pointer[]) {
int i = 0;
while (pointer[i] != '\0') {
i++;
cout << pointer[i] << endl;
}
arr = new char[i];
i = 0;
while (pointer[i] != '\0') {
arr[i] = pointer[i];
i++;
}
}
friend ostream& operator<<(ostream& out, Mystring& str) {
int i = 0;
while (str.arr[i] != '\0') {
out << str.arr[i];
i++;
}
return out;
}
};
int main() {
Mystring string("Hello, world!");
cout << string << endl;
}
I'm trying to create my own string class. The length of "hello world!" is 13, but the length of arr turns out to be 17. It is filled with some strange chars for some reason I don't understand. When I'm trying to cout string it returns this: Hello, world!¤¤¤¤.
You forgot to add '\0' at the end of your arr[].
Moreover, the size or arrshould be increased to incorporate this \0, as noted in #user7860670's answer.
Moreover, using string as a variable name, in addition to using namespace std;, is confusing at least.
#include<iostream>
#include<string>
#include<sstream>
#include <typeinfo>
#include<cmath>
#include<vector>
#include <algorithm>
//using namespace std;
class Mystring {
char *arr;
public:
Mystring(const char pointer[]) {
int i = 0;
while (pointer[i] != '\0') {
i++;
std::cout << pointer[i] << std::endl;
}
arr = new char[i+1];
i = 0;
while (pointer[i] != '\0') {
arr[i] = pointer[i];
i++;
}
arr[i] = '\0';
}
friend std::ostream& operator<<(std::ostream& out, const Mystring& str) {
int i = 0;
while (str.arr[i] != '\0') {
out << str.arr[i];
i++;
}
return out;
}
};
int main() {
Mystring mstring("Hello, world!");
std::cout << mstring << std::endl;
}
Buffer size required to hold "Hello, world!" (including terminating null) is 14 while you only allocate space for 13 chars and completely omit terminating null. So during iteration inside of operator<< buffer index will go out of bounds which is Undefined Behavior.
You should allocate one extra byte and make sure that buffer ends with terminating null
arr = new char[i + 1];
i = 0;
while (pointer[i] != '\0')
{
arr[i] = pointer[i];
++i;
}
arr[i] = '\0';
Write and test your own function char * funct (char * str, int x) inverting (except for the character at position n) the string str and returning the modified str as the result. The use of the function funct could be:
This is main:
#include <iostream>
#include <cstring>
using namespace std;
char* funct(char *str, int x);
int main() {
char str1 [] = "Hello cpp";
cout << str1 << endl; // Hello cpp
cout << funct (str, 1) << endl; // pepC ollH // the character at position 1 ('e') stays in place
return 0;
}
This is my function:
char* funct(char *str, int x) {
int counter = 0;
do {
counter++;
str++;
} while (*str);
str--;
char *wskTmp = str;
for (int i = 0; i < counter ; i++) {
*wskTmp = *str;
str--;
wskTmp++;
}
*wskTmp = '\0';
wskTmp = wskTmp - counter;
for (int i = 0; i < counter - x -1; i++) {
wskTmp++;
}
char tmp;
for (int i = 0; i < counter-3; i++) {
tmp = *(wskTmp - 1);
*(wskTmp - 1) = *wskTmp;
*wskTmp = tmp;
wskTmp--;
}
return str;
}
Output:
Hello Cpp
Hello CppepC ollH
It should be:
Hello Cpp
pepC ollH
Why it gives me Hello Cp before "pepC ollH"?
Your code is very confusing and is a very roundabout way of accomplishing this task, so I restructured it a bit:
#include <cstring>
#include <iostream>
using namespace std;
char *funct(char *str, int x) {
// keep track of the original start
char *origStr = str;
// iterate through the string to find the end
do {
str++;
} while (*str);
// decrease the string so it's on the last byte, not the nullbyte
str--;
// create a start and end
char *start = origStr;
char *end = str;
if (start - origStr == x) {
start ++;
}
if (end - origStr == x) {
end--;
}
// if start >= end then we've finished
while (start < end) {
// swap values at start and end
char temp = *start;
*start = *end;
*end = temp;
// move the pointers closer to each other
start++;
end--;
// skip the index x
if (start - origStr == x) {
start++;
}
// skip the index x
if (end - origStr == x) {
end--;
}
}
// make sure to return the actual start
return origStr;
}
int main() {
char str1[] = "Hello cpp";
cout << str1 << endl; // Hello cpp
cout << funct(str1, 1) << endl; // pepC ollH // the character at position 1
// ('e') stays in place
return 0;
}
Return a pointer to the last appearance of c
appearing inside s and nullptr (0) if c does not appear inside s.
#include <string>
#include <iostream>
#include <cassert>
using namespace std;
const char* myStrRChr(const char* s, char c)
{
int curIdx = 0;
char last;
while (s[curIdx] != '\0')
{
if (s[curIdx] == c)
last = s[curIdx];
curIdx++;
}
if (s[curIdx] == c)
return last;
else
// return '\0', nullptr, NULL
return "";
}
int main()
{
char cstr[50] = "Abadabadoo!";
char buf[10];
const char * cat = "cat";
char dog[] = "Labradoodle";
cout << "\nmyStrRChr(cstr, 'a') expects adoo!" << endl;
cout << " -- " << myStrRChr(cstr, 'a') << endl;
return 0;
}
This code returns "adabadoo!". I can't wrap my mind around as to how to get the last instance of "char c."
You can do this by obtaining a pointer to the end of the string and decrementing down the string searching for the character c, and a pointer to the beginning of the string to know where to stop looping:
const char *mystrrchr(const char *str, char c)
{
int len = strlen(str);
char *p = const_cast<char *>(&str[len-1]);
char *stop = const_cast<char *>(&str[0]);
while(p>=stop)
{
if(*p==c)
{
return p;
}
p--;
}
return nullptr;
}
I decided to code all assignments from last semesters c++ class over summer in order to better prepare for c++ 3 but I don't understand how to pass through a String class or what steps are even needed in order to concatenate two strings and the display the result in the main cpp file.
In my Main.cpp:
#include <iostream>
using namespace std;
#include "String.h"
int main()
{
String Str1;
String Str2("this is a test");
String Str3(Str2);
String Str4("bruh");
int result;
cout << "Testing Display: " << endl;
Str2.Display();
cout << endl;
cout << "Testing displayLine: " << endl;
Str2.displayLine();
cout << endl;
result = Str2.Compare(Str3);
if (result < 0)
{
Str2.Display();
cout << " comes before " << endl;
Str3.Display();
cout << endl;
}
else
if (result > 0)
{
Str3.Display();
cout << " comes before " << endl;
Str2.Display();
}
else
{
Str3.Display();
cout << " is equal to " << endl;
Str2.Display();
}
cout << endl;
result = Str2.Compare("wxyz");
Str1.Copy(Str3);
cout << "Str1 contains " << Str1.length() <<" characters"<< endl;
cout << "Concatenation: ";
Str2.Concat(Str4);
cout << endl;
return 0;
}
In my String.cpp:
#include <iostream>
using namespace std;
#include <string.h>
#include "String.h"
#pragma warning(disable:4996)
String::String()
{
NumChars = 0;
MaxSlots = 0;
pChar = new char[NumChars+1];
pChar[0] = '\0';
}
String::String(const char Str[])
{
NumChars = strlen(Str);
pChar = new char[NumChars + 1];
strcpy(pChar, Str);
}
String::String(const String & Str)
{
NumChars = Str.NumChars;
pChar = new char[NumChars + 1];
strcpy(pChar, Str.pChar);
}
String::~String()
{
delete[] pChar;
}
int String::Compare(const String & Str) const
{
return strcmp(pChar, Str.pChar); //case sensitive
}
int String::Compare(const char Str[]) const
{
return strcmp(pChar, Str); //case sensitive
}
String& String::Copy(const String & Str)
{
if (this != &Str)
{
if (MaxSlots < Str.NumChars)
{
delete[]pChar;
MaxSlots = Str.NumChars;
pChar = new char[NumChars + 1];
}
else;
NumChars = Str.NumChars;
strcpy(pChar, Str.pChar);
}
else;
return *this;
}
String& String::Copy(const char Str[])
{
delete[] pChar;
NumChars = strlen(Str);
MaxSlots = NumChars;
pChar = new char[MaxSlots + 1];
return *this;
}
String& String::Concat(const String & Str)
{
pTemp = new char[NumChars+1];
strcpy(pTemp, pChar);
strcat(pTemp, Str.pChar);
delete[]pChar;
pChar = pTemp;
return *this;
}
String & String::Concat(const char Str[])
{
return *this;
/*
NumChars = strlen(Str);
MaxSlots = NumChars;
delete[] pChar;
MaxSlots = MaxSlots + NumChars;
NumChars = NumChars + strlen(Str);
pChar = new char[MaxSlots + 1]; */
}
void String::Display() const
{
cout << pChar;
}
void String::displayLine() const
{
cout << pChar;
}
In my String.h:
#ifndef STRING_H
#define STRING_H
class String
{
public:
String(); //default constructor
String(const char[]);
String(const String &); //copy constructor
~String();
int Compare(const String &) const;
int Compare(const char[])const;
String& Copy(const String&);
String& Copy(const char[]);
String& Concat(const String&);
String& Concat(const char[]);
void Display()const;
void displayLine() const;
int length() const;
private:
char * pChar;
char *pTemp;
int NumChars;
int MaxSlots;
};
inline int String::length() const
{
return NumChars;
};
#endif
You expect the length of the concatenated string to be the sum of the length of the two strings. Therefore:
String& String::Concat(const String & Str)
{
pTemp = new char[NumChars + Str.NumChars + 1];
strcpy(pTemp, pChar);
strcat(pTemp, Str.pChar);
delete[]pChar;
pChar = pTemp;
return *this;
}
You can optimize this further by not strcat()-ing but strcpy()-ing twice (with an offset added to pTemp second time), as you already know the string length.
I'm not sure to understand the use of your MaxSlots; it's the size of allocated pChar (minus 1)? If so, there are points in your code where you forget to set/update/use.
And I don't understand what do you mean with "how to pass through a String class", but regarding "what steps are even needed in order to concatenate two strings", you've forgotten to take in count the number of chars already present in the object.
First of all, I suggest to create e Reserve() method; something like [caution: code not tested]
String& String::Reserve (int n)
{
if ( n > MaxSlots )
{
MaxSlots = n;
pTemp = new char[MaxSlots+1];
strcpy(pTemp, pChar);
delete[]pChar;
pChar = pTemp;
}
}
Next, rewrite your Concat() methods in this way
String& String::Concat(const String & Str)
{
NumChars += Str.NumChars;
Reserve(NumChars);
strcat(pChar, Str.pChar);
return *this;
}
String & String::Concat(const char * Str)
{
if ( Str )
{
NumChars += strlen(Str);
Reserve(NumChars);
strcat(pChar, Str);
}
return *this;
}
p.s.: sorry for my bad English
I have this function: int split(char* str, char s), so how to split the str without using strtok() or other functions?
E.g: str = "1,2,3,4,5", s = ','
After split(str, s), output will be:
1
2
3
4
5
Sorry guys, the int return -1 if str == NULL and return 1 if str != NULL.
How about this? I'm not sure what the int return type means in the function so I made it the count of splits.
#include <stdio.h>
int split(char* str, char s) {
int count = 0;
while (*str) {
if (s == *str) {
putchar('\n');
count++;
} else {
putchar(*str);
}
str++;
}
return count;
}
I didn't write code for years, but that should do?
while (*str) // as long as there are more chars coming...
{
if (*str == s) printf('\n'); // if it is a separator, print newline
else printf('%c',*str); // else print the char
str++; // next char
}
string split(const char* str, char s) {
std::string result = str;
std::replace(result.begin(), result.end(), s, '\n');
result.push_back('\n'); // if you want a trailing newline
return result;
}
Another approach...
#include <iostream>
using namespace std;
void split(char* str, char s){
while(*str){
if(*str==s){
cout << endl;
}else{
cout << *str;
}
str++;
}
cout << endl;
}
int main(){
split((char*)"herp,derp",',');
}
and another one with iterator
#include <iostream>
using namespace std;
int main() {
string s="1,2,3,4,5";
char cl=',';
for(string::iterator it=s.begin();it!=s.end();++it)
if (*it == cl)
cout << endl;
else cout << *it;
return 0;
}
http://ideone.com/RPrls7