I'm trying to avoid using a pointer for an assignment
When I avoid using a pointer, my code doesn't work, so I'm not really sure what to do.
How would I change this code to not use a pointer?
char* removeVowels(char* userInput) {
int j = 0;
char* noVowels = new char[100];
for (int i = 0; i < strlen(userInput); i++) {
char character = userinput[i];
switch (character) {
case 'a':
case 'A':
case 'E':
case 'e':
case 'i':
case 'I':
case 'o':
case 'O':
case 'U':
case 'u':
continue;
default:
noVowels[j++] = character;
}
}
noVowels[j] = '\0';
return noVowels;
}
To avoid pointers you need to change the interface.
You cannot avoid pointers if you don't change the function declaration because it obviously uses pointers.
The function should probably take a const std::string& and return a std::string (requires #include<string>):
std::string removeVowels(const std::string& userInput) {
std::string noVowels;
for(char character : userInput) {
//...
// use `noVowels.push_back(character)` to append `character` to `noVowels`
//...
}
return noVowels;
}
This will then also require appropriate changes at the call site.
If you don't know what const and/or & means, then use just std::string instead of const std::string&.
Related
I am trying to make a program that will use a switch statement and see if an element of a char array is a vowel and which one, but i am stuck at how to check the elements:
int prob2() {
char uName[25] = "";
int voCo = 0;
cout<<"Enter you first and last name, under 25 chars please: ";
cin>>uName;
int i = 0;
while(i <= 25){
switch(i){
case 1:
voCo++;
break;
case 2:
voCo++;
break;
case 3:
voCo++;
break;
case 4:
voCo++;
break;
case 5:
voCo++;
break;
default:
break;
}
i++;
}
cout<<"Your first and last name have: "<<voCo<<" vowels in them."<<endl;
return 0;
}
It seems you mean the following
#include <iostream>
#include <cctype>
using namespace std;
//...
size_t prob2()
{
const size_t N = 25;
char uName[N] = "";
size_t voCo = 0;
cout<<"Enter you first and last name, under " << N << " chars please: ";
cin.getline( uName, N );
for ( char *p = uName; *p != '\0'; ++p ) *p = toupper( ( unsigned char )*p );
for ( const char *p = uName; *p != '\0'; ++p )
{
switch( *p )
{
case 'A':
voCo++;
break;
case 'E':
voCo++;
break;
case 'I':
voCo++;
break;
case 'O':
voCo++;
break;
case 'U':
voCo++;
break;
default:
break;
}
}
cout<<"Your first and last name have: "<<voCo<<" vowels in them."<<endl;
return voCo;
}
You could try something like this:
const std::string vowels = "aeiou";
const std::string name = "martin luther king, jr.";
const unsigned int name_length = name.length();
unsigned int vowel_count = 0U;
for (unsigned int i = 0U; i < name_length; ++i)
{
if (vowels.find(name[i]) != std::string::npos)
{
++vowel_count;
}
}
No need for switch statement. This is one of many possible algorithms or implementations.
Edit 1: An array of counts
You could also use an array of counts:
unsigned int counts[26] = {0};
for (unsigned int i = 0U; i < name_length; ++i)
{
const c = std::tolower(name[i]);
if (isalpha(c))
{
counts[c - 'a']++;
}
}
const unsigned int vowel count =
counts['a'] + counts['e'] + counts['i']
+ counts['o'] + counts['u'];
First of all decouple user interaction from the logic solving your requirement. I think we can safely assume you can collect the input in this case and save it into an string. So we will not waste our time with that.
We will focus on developing and testing the code that solves the requirement. In a standard C++. Now here is the deep end of the pool. The code.
// mike.h
#pragma once
// std::string view requires C++17
#include <string_view>
// always use namespace,to avoid name clashes
namespace mike {
// make 'sv' the string_view literal available
using namespace std::string_view_literals;
// declare and define compile time
// string view literal
// 'constexpr' guarantees compile time
// notice the use of 'sv'
constexpr auto vowels = "eaiouEAIOU"sv;
// compile time function to count literals
// again 'constexpr' guarantees compile time
// inline gurantees we can include this header many times
// without making accidental duplicates of `count_vowels`
// 'in_' argument has 'std::string_view' passed by value
// pass by value is preferred standard C++ method
// of functions arguments passing
// 'std::string_view' is standard C++ preferred type
// to pass strings into functions
inline constexpr size_t
count_vowels(std::string_view in_)
{
// return type is size_t
// we can count very large number of vowels
// but all at compile time
size_t rezult{};
// this is C+17 'range for'
// we cast implicitly references to input elements
// from, `char const &` to `int const &`
// cost of that is very likely 0
for (int const & ch_ : in_)
for (int const & v_ : vowels)
// there is no if() here
// we simply add 0's or 1's, to the rezult
// false is 0, true is 1
// the correct by the book way of coding that is
// static cast from bool to int
// rezult += static_cast<int>( v_ == ch_ ) ;
rezult += v_ == ch_ ;
return rezult;
}
// runtime speed of this call is 0 (zero)
// all happens at compile time
// notice how we pass normal string literal
// no need to create string_view
constexpr size_t r1
= count_vowels("abra ca dabra");
// no runtime tests necessary
// `static_assert()` is compile time assert
// failure message is optional
static_assert(r1 == 5,
"compile time calculation failed, 'abra ca dabra', must contain 5 vowels");
} // mike ns
Hopefully there are a lots of comments. Solution does not use switch() statement or if() statements. Thanks to standard C++ constructs, code is very simple, resilient and probably very fast when compiled by modern optimizing compilers.
Solution works at compile time too. That is not stopping you to use it in your run-time scenario. Although, I would advise again using native char array. std::string might be a perfect match here.
std::string input_ = collect_user_input() ;
int rezult = count_vowels(input_);
Enjoy the standard C++ ...
I'm fairly new to c/c++ programming and currently I'm working on some basic programms to get in touch with the language. My newest programm is a simple hex_xor function, that follows the instruction of Cryptopals Challenge 2. But I'm already getting errors and I'm assuming I am doing something horribly wrong with the pointers I am using.
Here is a part of my programm:
const char* hex_char_to_bin(char c)
{
switch(toupper(c))
{
case '0': return "0000";
case '1': return "0001";
case '2': return "0010";
case '3': return "0011";
case '4': return "0100";
case '5': return "0101";
case '6': return "0110";
case '7': return "0111";
case '8': return "1000";
case '9': return "1001";
case 'A': return "1010";
case 'B': return "1011";
case 'C': return "1100";
case 'D': return "1101";
case 'E': return "1110";
case 'F': return "1111";
}
}
const char* hex_binary(const char* c){
std::string result = "";
for(int i = 0; i < strlen(c); i++){
result += hex_char_to_bin(c[i]);
}
return result.c_str();
}
int main(){
std::string s1 = "1c0111001f010100061a024b53535009181c";
std::string s2 = "686974207468652062756c6c277320657965";
const char* bin1 = hex_binary(s1.c_str());
const char* bin2 = hex_binary(s2.c_str());
std::cout << bin1 << "\n" << bin2 << std::endl;
return 0;
}
The output is the following:
011010000110100101110100001000000111010001101000011001010010000001100010011101010110110001101100001001110111001100100000011001010111100101100101
011010000110100101110100001000000111010001101000011001010010000001100010011101010110110001101100001001110111001100100000011001010111100101100101
In both variables (bin1/2) is the binary conversion of the second hex-string. My aim is (obviously) to have both binary-strings saved in different variables, so I can proceed with my xor-function. Can someone point out where I am failing to achieve my goal and why? Other hints are welcome aswell!
You can't use result of c_str() when main string object is no longer alive. So, you're referencing already freed resources and facing undefined behavior.
If I were you, I'd change hex_binary() to return std::string and just return result back without using c_str()
#pragma once
# include <iostream>
# include <string>
# include <cstring>
using namespace std;
const int err=404;
class longMath{
protected:
char* str;
int size;
protected:
//void create(int len);
public:
inline longMath();
inline longMath(longMath &a);
inline longMath(char* s);
inline longMath(string &s);
~longMath(){delete [] str;}
void print();
};
//-------------------------------------------------------------//
longMath::longMath(){size=0;}
longMath::longMath(longMath &a){
str = new char [a.size];
strncpy(str,a.str,a.size);
size= a.size;
}
longMath::longMath(char* s){
size = (sizeof s)/(sizeof s[0]);
str = new char [size+1];
strncpy_s(str,size+1,s,size);
}
void longMath::print(){
for (int i=0;i<size;i++){
cout<<*(str+i);
}
cout<<endl;
}
longMath::longMath(string &s){
str = new char [s.length()];
for (int i=0;i<size;i++){
*(str+i)=s[i];
}
size = s.length();
}
longMath longMath::operator= (const longMath &a){//оператор присвоения
if (this==&a) return *this;
delete [] str;
str = new char [a.size];
strncpy(str,a.str,a.size);
size = a.size;
return *this;
}
//----------additional function--------------------//
int switcher(char &c){
switch (c){
case '1': return 1; break;
case '2': return 2; break;
case '3': return 3; break;
case '4': return 4; break;
case '5': return 5; break;
case '6': return 6; break;
case '7': return 7; break;
case '8': return 8; break;
case '9': return 9; break;
case '0': return 0; break;
default: return err;
}
}
And another main file
# include <iostream>
# include "longMath.h"
using namespace std;
int main(){
char* s("regw");
longMath h,n(s);
n.print();
system("PAUSE");
return 0;
}
This program doesn't want to compile, it returns exception in 0x0f8657aa (msvcr100d.dll)
Help me with this please. Program seems like not too complicated.
There is a problem in constructor, initialized with char*.
This could be the problem
(sizeof s)/(sizeof s[0]);
This trick only works with arrays, not with pointers to arrays.
You should add a length parameter and pass it in during construction. Or use strlen to find the length of the string, if it is null terminated.
I think you are doing the following: sizeof(char*, a pointer) is usually 4 (on 32-bit machines), sizeof(s[0]) is just like sizeof(char) (1 byte on 32-bit machines), so you always get 4 bytes.
And if your string is longer than 3 bytes, the program will crash.
Use strlen(s) to get the length of char* s. Try it.
In your default constructor, you haven't allocate memory for str but you call delete [] str in destructor. Set str to NULL in default constructor should fix crash issue:
longMath::longMath() : str(NULL), size(0)
{
}
The program won't compile, because you didn't declare operator= in longMath class but defined it. you need to add below declaration in class:
longMath& operator= (const longMath &a);
I want to write a cpp function something similar to this, where outVal should accept data of the corresponding type returned from the respective functions in each case.
void ReadFieldByType(char fieldType, string content, string& outStr, **unknown**& outVal){
unsigned int ifield;
char cField;
string sField;
double dField;
switch (fieldType)
{
case 'c':
ReadChar(content, content, cField);
outVal = cField;
break;
case 'd':
ReadInteger(content, content, ifield);
outVal = ifield;
break;
case 'f':
ReadDouble(content, content, dField);
outVal = dField;
break;
case 's':
ReadString(content, content, sField);
outVal = sField;
break;
default:
break;
}
outStr = content;}
I don't know how to set datatype for outVal. Can this be improved or is there any other choice to accomplish this task?
Take a look at boost::variant.
In your case you would use something like:
typedef boost::variant<char, int double, std::string> out_t;
You could probably do it with templates and the typeid operator:
template<class T>
void ReadField(string content, string& outStr, T& outVal)
{
if (typeid(T) == typeid(int))
ReadInteger(content, content, outVal);
else if (typeid(T) == typeid(char))
ReadChar(content, content, outVal);
else if (typeid(T) == typeid(double))
ReadDouble(content, content, outVal);
else if (typeid(T) == typeid(std::string))
ReadString(content, content, outVal);
outStr = content;
}
Although I have to admit that I don't like the solution.
Use union, it allows to choose type of variable;
union
{
unsigned int ifield;
char cField;
string sField;
double dField;} outVal;
void ReadFieldByType(char fieldType, string content, string& outStr, **unknown**& outVal){
switch (fieldType)
{
case 'c':
ReadChar(content, content, cField);
outVal.cField = cField;
break;
case 'd':
ReadInteger(content, content, ifield);
outVal.ifield = ifield;
break;
case 'f':
ReadDouble(content, content, dField);
outVal.dField = dField;
break;
case 's':
ReadString(content, content, sField);
outVal.sField = sField;
break;
default:
break;
}
outStr = content;}
I wrote a little structure for getting certain time information. This structure is a helper,
for my logging class im planning to write. Here is the code:
struct UTime
{
char Month [4];
char DayOfMonth [3];
char DayOfWeek [4];
char Year [5];
char Time [9];
char Full [25];
UTime()
{
this->refresh();
}
void refresh()
{
char TimeBuffer[26] = {};
time_t RawTime = 0;
time(&RawTime);
ctime_s(TimeBuffer, 26*sizeof(char), &RawTime);
this->DayOfWeek[0] = TimeBuffer[0];
this->DayOfWeek[1] = TimeBuffer[1];
this->DayOfWeek[2] = TimeBuffer[2];
this->DayOfWeek[3] = 0;
this->Month[0] = TimeBuffer[4];
this->Month[1] = TimeBuffer[5];
this->Month[2] = TimeBuffer[6];
this->Month[3] = 0;
this->DayOfMonth[0] = TimeBuffer[8];
this->DayOfMonth[1] = TimeBuffer[9];
this->DayOfMonth[2] = 0;
this->Time[0] = TimeBuffer[11];
this->Time[1] = TimeBuffer[12];
this->Time[2] = TimeBuffer[13];
this->Time[3] = TimeBuffer[14];
this->Time[4] = TimeBuffer[15];
this->Time[5] = TimeBuffer[16];
this->Time[6] = TimeBuffer[17];
this->Time[7] = TimeBuffer[18];
this->Time[8] = 0;
this->Year[0] = TimeBuffer[20];
this->Year[1] = TimeBuffer[21];
this->Year[2] = TimeBuffer[22];
this->Year[3] = TimeBuffer[23];
this->Year[4] = 0;
memcpy(this->Full, TimeBuffer, 25);
this->Full[24] = 0;
}
}; // struct UTime;
Now Id like to add a function wich returns a formatted version of the time information.
For example:
std::string formatted = utime.get(Year, Month)
This function should return something like: "2011 Nov", or another example:
std::string formated = utime.get(DayOfWeek, Time);
This function should return something like: "Mon 20:43:24". Can anyone please point me in the most effecient way to do this? Im just not sure about effeciency because in a logger this function might get called alot. Thank you very much.
You can use strftime. It supports lots of format
std::string utime::get(char* format) {
std::string formatted;
formatted.reserve(30);
for( ; *format!='\0'; ++format) {
if (*format != '%')
formatted.append(*format);
else {
++format;
switch (*format) {
case 'a': formatted.append(DayOfWeek); break;
case 'b': formatted.append(Month); break;
case 'd': formatted.append(DayOfMonth); break;
case 'H': formatted.append(Time, 2); break;
case 'M': formatted.append(Time+3, 2); break;
case 'S': formatted.append(Time+6, 2); break;
case 'x': formatted.append(Month);
formatted.append(' ');
formatted.append(DayOfMonth);
formatted.append(' ');
formatted.append(Year);
break;
case 'X': formatted.append(Time); break;
case 'y': formatted.append(Year+2); break;
case 'Y': formatted.append(Year); break;
case '%': formatted.append('%'); break;
default: throw std::logic_error("Unsupported string format");
};
}
}
return formatted;
}
This should be fairly fast since it reserves a fair amount of space, and simply appends chacters to the end of the already allocated buffer most of the time. I highly recommend matching a standard formatting scheme like strftime as parapura rajkumar suggested.