creating a simple C++ string class - c++

I'm writing a program where I create my own string class. The program is supposed to instruct the user to write a sentence, copy the input, and then display how many characters it contains.
Although it did build and compile (using Visual Studio Express 2013), it would copy the sentence the user is instructed to write down, not display the amount of characters, and then crash.
I'm guessing is has something to do with how the memory is dynamically allocated or how *character and _String is passed between functions. But some help on how to fix this or improve my code would be very helpful.
Header: String.h
class String
{
private:
char *characters[50]; // 50 is just a placeholder to get it to work
int size;
public:
// Constructors and Destructors
String();
String(char*);
~String();
// Other functions
void stringAssign(char*);
void printString(char*);
int stringSize(char*) const;
};
Implementation: String.ccp
#include "String.h"
#include <iostream>
#include <cstring>
String::String()
{
size = 0;
* characters = 0;
}
String::String(char* _String)
{
size = stringSize(*characters + 1);
_String = new char[size];
}
String::~String()
{
delete [] *characters;
}
void String::stringAssign(char* _String)
{
_String = characters[size];
}
void String::printString(char* _String)
{
for (int i = 0; _String[i] != '\0'; i++)
std::cout << _String[i];
}
int String::stringSize(char* _String) const
{
int size;
size = strlen(*characters);
return size;
}
Test: Main.ccp
#include "String.h"
#include <iostream>
int main()
{
char string[50];
String s;
std::cout << "Enter a sentence that is less than 50 characters\n\n";
std::cin.getline(string, 50);
s.printString(string);
std::cout << s.stringSize(string);
return 0;
}
Solved:
I got the program working. Literally all I did was replace the two *character arguments with _String in the implementation. I knew it had something to do with function passing, and I did get a little help for that. But one person gave no helpful input (and practically insulted me) and both said that there were "too many things to fix". Some elaboration on the "so many things" I had to fix would be nice.

In almost all functions, you do something with the argument of the function, _String, and not with the member field characters that is supposed to hold the string internally. So your functions do not change the string at all, but rather try to mess with something you passed them.
An example
struct Foo {
char internal[42];
void bar(char *external) { external[0] = 'X'; }
void qux(char *external) { internal[0] = 'Z'; }
};
int main() {
Foo foo;
char something[6] = "Hello";
foo.qux(something); // Did something to the member variable foo.internal; variable something is unchanged.
foo.bar(something); // Now something reads "Xello", foo.internal was not changed.
}
Your code does almost as the function bar while it should work like qux.
There is indeed too much to fix in this code.
Just in case you were mistaken... Unlike some other languages, say Python or Smalltalk, C++ passes a pointer to the current object implicitly via this.

Related

char * not returned correctly from overloaded operator or memory managment issue

I try to read a file decompress it and parse it to a tree in C++. Everything works fine with one excaption: For some reason I can construct a char[] string and use a pointer on it to output it with the help of cout inside a befriended overloaded <<-operator, but can't use the pointer returned by the operator to cout the string. I was thinking it might have to do with visibility of the string-memory, but that makes no sense to me since with "new" allocated memory should be visible to everyone since its on the heap of the program and not somekind of object or class heap. This all sounds rather confusing, let me show you a striped down version of the source and I'm pretty sure everything becomes clear (probably some really stupid mistake on my end... but I try since two days and don't find the mistake):
main:
#include "dekompstream.h"
#include <iostream>
int main(void) {
char *testString;
DekompStream ds(nullptr, 0);
std::cout << "TEST" << std::endl;
testString << ds;
std::cout << "Outside operator: " << testString << std::endl; // Fails misarably. Some weird randome memory-slice looking output
//delete [] testString;
return 0;
}
dekompstream.cpp:
#include "dekompstream.h"
DekompStream::DekompStream(uint8_t *kompDaten, unsigned int anzahlBytes) {
}
DekompStream::~DekompStream() {
}
uint8_t *DekompStream::dekompremieren() {
char *test = new char[4];
test[0] = 'A';
test[1] = 'B';
test[2] = 'C';
test[3] = '\0';
return (uint8_t *)test;
}
char *operator<<(char *zeichenkette, DekompStream &dekompStream) {
zeichenkette = (char *)dekompStream.dekompremieren();
std::cout << "Inside operator: " << zeichenkette << std::endl; // Works fine
return zeichenkette;
}
dekompstream.h:
#ifndef DEKOMPSTREAM_H
#define DEKOMPSTREAM_H
#include <cstdint>
#include <iostream>
class DekompStream {
public:
DekompStream(uint8_t *kompDaten, unsigned int anzahlBytes);
~DekompStream(void);
friend char *operator<<(char *zeichenkette, DekompStream &dekompStream);
private:
uint8_t *dekompremieren();
};
#endif
Thanks in advance :-)
testString << ds doesn't do what you think it does.
If we take a look at the code for operator<<:
char *operator<<(char *zeichenkette, DekompStream &dekompStream) {
zeichenkette = (char *)dekompStream.dekompremieren();
return zeichenkette;
}
The function reassigns the char* argument to a new value, then returns the new value. Fine. OK. But how does the compiler use this?
When we write:
testString << ds;
The compiler turns it into:
operator<<(testString, ds);
See the error?
You returned a new value, but because the operator overload was turned into a function call, the allocated pointer was lost. In addition, because the char* argument was simply reassigned, the original pointer value wasn't changed, meaning you got whatever was on the stack previously.
If we look at the declarations for the STL functions for iostream, we'll see the way to fix it:
ostream& operator<< (ostream& os, const char* s);
Notice the first parameter is passed by reference - this ensures any modifications to the stream made by the function persist in the calling context.
Simply change your function definition to:
char *operator<<(char *&zeichenkette, DekompStream &dekompStream){
...
}
and the issue will disappear.

Pointer Array outputting integer variables without issue, but strings are all empty

I am a C++ novice and have an assignment using Oldie McOldSchool arrays and pointers. I have looked at this specific problem for about 8-12 cumulative hours now, kind of want to shove my face into a brick wall and don't really know what to think at this point. I am hoping from help from the experts here at SO!
I have the following class
#include <iostream>
#include <string>
using namespace std;
#include "mainclass.h"
#include "mysubobject1.h"
const string dataString[] =
{
"stringvalue,stringvalue,stringvalue,stringvalue,19,51,36,41,STUFF1",
"stringvalue,stringvalue,stringvalue,stringvalue,19,52,37,44,STUFF2",
"stringvalue,stringvalue,stringvalue,stringvalue,19,53,38,46,STUFF3",
"stringvalue,stringvalue,stringvalue,stringvalue,19,54,39,49,STUFF1",
"stringvalue,stringvalue,stringvalue,stringvalue,19,55,30,38,STUFF2",
};
MyObject* myObjectArray[5];
const string* dataArray[5];
int delimiterPositionArray[5][9];
string tokenArray[5][9];
Stuff stuff;
void main()
{
MainClass* mainClass = new MainClass();
dataArray[0] = &dataString[0];
dataArray[1] = &dataString[1];
dataArray[2] = &dataString[2];
dataArray[3] = &dataString[3];
dataArray[4] = &dataString[4];
/*Parse the contents of string into Token array. I have this working and can share if necessary but trimmed it out to keep this easy to look at */
for (int i = 0; i < 5; i++)
{
/* Logic to set the value of stuff goes here - it's very simple and trimmed for ease of reading */
mainClass->add(tokenArray[i][0], tokenArray[i][1], tokenArray[i][2], tokenArray[i][3], stoi(tokenArray[i][4]), stoi(tokenArray[i][5]), stoi(tokenArray[i][6]), stoi(tokenArray[i][7]), stuff);
}
cout << "TEST" << endl;
cout << mainClass->myObjectArray[0] << endl;
}
void MainClass::add(string string1, string string2, string string3, string string4, int int1, int int2, int int3, int int4, Stuff stuff)
{
MyObject myObject;
if (stuff == STUFF2) {
MySubObject1 myObject;
myObject.SetStuff(stuff);
}
myObject.SetString1(string1);
myObject.SetString2(string2);
myObject.SetString3(string3);
myObject.SetString4(string4);
myObject.SetInt1(int1);
int* intArray[] = { &int2, &int3, &int4 };
myObject.SetIntArray(intArray);
//Awful temporary array filling logic (which doent work properly, but works for the purpose of testing this problem)
if (myObjectArray[0] == nullptr)
{
myObjectArray[0] = &myObject;
}
else
{
if (myObjectArray[1] == nullptr)
{
myObjectArray[1] = &myObject;
}
/* ….until the array is filled */ }
}
And the question:
When I inspect this line of code from the main method in the mainclass.cpp in the VB debugger, all looks perfect. Token array contains what I expect:
mainClass->add(tokenArray[i][0], tokenArray[i][1], tokenArray[i][2], tokenArray[i][3], stoi(tokenArray[i][4]), stoi(tokenArray[i][5]), stoi(tokenArray[i][6]), stoi(tokenArray[i][7]), stuff);
I keep stepping through the code and get through the end of the add method. I see that everything looks fine by the time I reach the end of the add method. The strings and integers all appear to get set perfectly. I inspect the following line after the debugger runs over it and see everything looks great. Each array field has the data I expect in it. (the logic sucks and the data is the same for each array index, but that is for a later troubleshooting session :D)
myObjectArray[0] = &myObject;
After the add method runs, execution is deferred back to the main method and the following code outputs the results to the screen:
cout << "TEST" << endl;
cout << mainClass->myObjectArray[0] << endl;
This is where the problem is.... mainClass->myObjectArray[0] has empty values in all string properties and nothing is outputted for them (they contain "").... but the int properties have the proper output for some reason!
If anyone would have any insight into why the ints are available and the strings don't appear to be, I would be eternally grateful!
Thanks again!
Given you really didn't post all of your code, the code you did post shows one major issue, and could be the reason why your program behaves as it does.
In your MainClass::add() function, you're storing the addresses of local variables in the MainClass::myObjectArray array, and attempting to access these addresses from outside the add() function.
A synopsis of the code:
int main()
{
MainClass* mainClass = new MainClass();
//...
mainClass->add(...);
//...
cout << mainClass->myObjectArray[0] << endl; // <-- index 0 points to a garbage value
}
void MainClass::add(string string1, string string2, string string3, string string4, int int1, int int2, int int3, int int4, Stuff stuff)
{
MyObject myObject;
if (stuff == STUFF2) {
MySubObject1 myObject; // <-- Local variable
//...
int* intArray[] = { &int2, &int3, &int4 }; // <-- Another local variable
//...
myObject.SetIntArray(intArray); // <-- Storing address of local
//...
myObjectArray[0] = &myObject; // <-- Storing address of local
//...
}
When add() returns, those addresses will not be pointing to valid variables, since those variables no longer are valid since they are local variables.
So the fix is that you have to ensure that whatever pointers you place in your myObjectArray array, the lifetimes (scope) of those variables that are pointed to will last as long as myObjectArray.
A better solution to use an array of a type that stores "any" value such as an array of std::any.
In addition to this, you should attempt to reduce the unnecessary calls to new. For example, your main function starts off on the wrong foot:
int main()
{
MainClass* mainClass = new MainClass();
This could have simply been:
int main()
{
MainClass mainClass;

How can I access an array stored in an object?

I'm quite new to C++. I've been trying to figure this out for days - there'll be an easy solution no doubt but I haven't been able to find it (after much googling)! My problem is this:
I'm trying to create a class with a member function that reads in characters from a file and stores them in an array. I want to be able to create multiple objects (not sure how many - decided by the user), each with their own arrays filled with characters taken from different files. I think I've managed to do that. How would I then go about accessing the object's array in main?
The code I'm working on is long and messy but something along these lines (char.txt contains simply '12345' in this case):
#include <iostream>
#include <fstream>
using namespace std;
class Something{
public:
void fill_array(char array_to_fill[]){
char next;
ifstream input;
input.open("chars.txt");
input.get(next);
while(!input.eof())
{
for(int i = 0; i < 6; i++)
{
array_to_fill[i] = next;
input.get(next);
}
}
}
};
int main()
{
Something* something = new Something[1];
char array_to_fill[5];
something->fill_array(array_to_fill);
//I'd like to be able to access the array here; for example - to cout the array.
return 0;
}
Apologies if a) my terminology is wrong b) my code is rubbish or c) my question is stupid/doesn't make sense. Also I should add I haven't learnt vectors yet and I'm not supposed to use them for the program I'm making. Any help would be much appreciated. Cheers!
Your class does not store the array at all. It is simply a holder for a method. You probably want something like this, where each instance of the class holds the array. (I changed it to std::string since they are nicer to work with.)
class Something
{
private:
std::string data;
public:
void fill_data( const std::string& filename )
{
ifstream file( filename );
file >> data;
file.close();
}
std::string get_data() const
{
return data;
}
}
int main()
{
std::vector<Something> my_things;
my_things.push_back( Something() );
my_things[0].fill_data( "chars.txt" );
cout << my_things[0].get_data() << std::endl;
my_things.push_back( Something() );
my_things[1].fill_data( "another_file.txt" );
cout << my_things[1].get_data() << std::endl;
}
Since you are using C++, not C, get used to writing C++ code instead of C. (std::vector instead of C arrays (for unknown length arrays), std::string instead of char*, etc).
I think your question is too general for the format of stack overflow, but what you want in this case is to either create a public member, or create a private member with setters and getters.
class Something
{
public:
std::string m_string;
}
int main()
{
Something A;
A.m_string = "toto";
cout << A.m_string;
return 0;
}
Put a string for convenience (you could use a const char* but you will have to understand what is the scope to know when it will not be accessible anymore and you are not quite there yet) and there may be typos since I typed this from a phone.
If you really want to access the chars themselves, pass a char* with a size_t for the length of the array or use std::array if possible.
Right now the method fill_array is creating a local copy of array_to_fill, so any changes that you make to array_to_fill only happen in the local method. To change this, pass by pointer. This way the pointer gets copied instead of the whole array object. I didn't test this but it should look more like this:
void fill_array(char* array_to_fill){
...
}
You don't need to change anything in the main method.
To actually access the elements you can use [] notation. I.e. cout << array_to_fill[0] in the main method.
Edit: I think that change should work.

C++ Using Class to Define New Type

I am working on an operating system right now. However, I had to create the type "String" for developers.
I've tried typedefs and enumerations but they all didn't fit my need. I wanted to make the type string work like Windows's VB.Net.
Like this:
string a
a = "Hello, "
a.CombineString ("World")
int a = a.NumberOfChars ()
so I came up with this (in c++)
class string {
char * value = NULL; //My Operating System's Kernel's Printf Function Uses Char Pointers
bool CompareString (char *);
int NumberOfChars () {return (!value);}
void CombineString (char *);
}
bool string::CompareString(char * string_to_compare_with) {
int return_prototype = 0;
return_prototype = strcmp(string::value, string_to_compare_with); //The strcmp () function returns 0 if the char*s are the same and 1 if different.
if(return_prototype == 0) {
return true;
} else {
return false;
}
}
void string::CombineString(char * string_to_add) {
value = strcpy(value, string_to_add);
}
int main() {
string a;
a.value = "Hello, ";
a.CombineString("World!!");
Printf(a);
}
This prints the string "Hello, World!!" on the console screen in my Operating System. BUT I want to just go
string a = "Hello, ";
NOT
string a;
a.value = "Hello, ";
What should I do?
Defining a constructor that takes a const char* as parameter and a copy constructor should do it. Having a copy constructor there also means you'd need a copy assignment operator and a destructor. You should also decide whether your objects assume ownership of the strings. In your example - a.value = "Hello, "; - just makes that member point to that string literal. You won't be able to modify it afterwards - perhaps make a copy there?
However, I must point out the existing std::string implementation that exists in <string>.
I'm Simple Fellow. I am working on an operating system called "Windows" right now. It runs on its own filesystem, the NTFS filesystem, and supports user mode, execution of applications, memory management, and other awesome stuffs.
Besides having a copy constructor, you also need assignment operator overload:
const string& operator=(const string& arg){
delete[] value;
value = new char[arg.NumberOfChars()+1];
CombineString(const_cast<char*>(arg));
return reinterpret_cast<string&>(*this);
}
string(const string& arg):value(NULL){
value = new char[arg.NumberOfChars()+1];
CombineString(arg);
return reinterpret_cast<string&>(*this);
}

Guaranteed valid string as function parameter

I was wondering whether there is a way in C++ that a "string" (in whatever representation) that get's passed into a function can be assumed to be a valid string by that function.
I'm very new to C/C++ but so far as I can see, in C that question is answered by default because there is no other way und you just know that you have to check:
#include <stdio.h>
void foo(const char *str)
{
if (str)
printf("%s\n", str);
}
int main()
{
char *name = "Jack";
foo(name);
return 0;
}
But since C++ offers additional stuff like references I was wondering whether one could write foo() in such a way that it doesn't have to check. I tried it like this:
#include <iostream>
#include <string>
void foo(const std::string &str)
{
std::cout << str << std::endl;
}
int main(void)
{
std::string name = "Jack";
foo(name);
std::string *str = NULL;
foo(*str);
return 0;
}
But as you can see I can fool foo() to run into a SegFault. So, I guess you just always have to check, no matter what?
EDIT #1:
Okay, first of all thanks for all your answers and future answers, they are all much appreciated!
So to sum up what I learned so far:
There is no syntactic way in C++ to write a function defintion to
eliminate misuse by the actual function call.
Is that correct? If so, I see my original question as answered.
So now I trying to write foo() as defensive as possible, so that no matter how much you treat foo() like a dog, it just won't produce a SegFault.
In C I would now write it like this (assuming short-circut evaluation):
#include <stdio.h>
void foo(const char *str, const size_t len)
{
if (str && (str[len - 1] == '\0'))
printf("%s\n", str);
}
int main()
{
char *name = "Jack";
foo(name, 5);
/* possible mistakes, but foo can handle them */
foo(name, 4);
foo(name, -1);
foo(NULL, 5);
return 0;
}
And in C++ I'm trying this:
#include <iostream>
#include <string>
void foo(const std::string &str)
{
if (&str)
std::cout << str << std::endl;
}
int main(void)
{
std::string name = "Jack";
foo(name);
std::string *str = NULL;
foo(*str);
return 0;
}
...but I'm not sure if that is in any approriate or what one would, could or should do with exceptions in this case.
What do you think? If you can't prevent misuse by syntax you gotta increase the precautions?
std::string *str = NULL;
foo(*str);
This is undefined behavior, on the part of the caller. Not your problem. So no, you(the writer of foo) don't have to check.
Even in C, with the pointer, you don't necessarily have to check. You just have to document. "The argument must point to a valid null-terminated string. If it is not, the call is undefined behavior." -- If the user passes a NULL, that is, again, their problem. This is done all the time. If it wasn't, you'd have wasteful call chains checking the validity of the pointer at every level like this:
void foo(const char * s)
{
if (s)
printf("%s", s);
}
void bar(const char * s)
{
if (s)
foo(s);
}
void baz(const char * s)
{
if (s)
bar(s);
}
No, you're not right.
In the second code, undefined behaviour happens when you dereference your pointer, before you ever get to your function.
This is not a problem of your function. Inside your function, with the second signature you can always assume that you have a valid string, which makes it superior to the first one.