Hi, I've got a task to write a prototype of string class, but I'm stuck with the '>>' operator.
This is how it looks now:
1 2 3 4
std::istream& operator>>(std::istream& in, typeString& toload) {
in >> toload.content;
return in;
}
But of course, when I want to
1 2
typeString example;
std::cin >> example;
When I was debugging the problem occured in line with 'in >> toload.content'.
There is an error: "Exception thrown: write access violation." I don't know how to do this properly. What is wrong?
Thanks
You really need to give us more code. Based on the 6 lines you've shown us, I have the following questions:
1. What type is content?
2. Is content public, protected or private?
3. Is operator>> a friend of typeString?
4. What istream object did you pass to the 'in' argument?
5. How was the istream object created and initialized?
These questions all require additional code to answer.
It would be helpful to us is you created a program containing just enough code to reproduce the problem (strip out everything else that doesn't affect the problem) and post it here. Make sure the program compiles and runs to produce the problem.
Hi, thank you for answers. I didn't think about how little information I gave, sorry.
There is the part of the code which contains just enough to reproduce the problem:
#include <iostream>
#define N 100000
class typeString {
public:
int length;
char* content;
char& operator[](int index);
constchar& operator[](int index) const;
typeString& operator =(const typeString& source);
void swap(typeString& other);
friend std::ostream& operator <<(std::ostream& out, const typeString& towrite); //friend??
friend std::istream& operator >>(std::istream& in, typeString& toload);
typeString(const typeString& source);
typeString(constchar*);
typeString();
~typeString();
};
char& typeString::operator[](int index)
{
return content[index];
}
constchar& typeString::operator[](int index) const
{
return content[index];
}
typeString::typeString() {
content = 0;
length = 0;
}
typeString::~typeString() {
delete[] content;
}
typeString::typeString(const typeString& source) //copy
{
length = source.length;
content = newchar[length + 1];
for (int k = 0; k < length; k++)
content[k] = source.content[k];
content[length] = '\0';
}
void typeString::swap(typeString& other)
{
// ... swap the lengths and pointers ...
}
typeString& typeString::operator=(const typeString& other)
{
if (this != &other)
{
typeString temp(other);
swap(temp);
}
return *this;
}
int charLength(constchar* number) {
int c = 0;
while (*(number++)) c++;
return c;
}
typeString::typeString(constchar* number) {
length = charLength(number);
content = newchar[length + 1];
for (int k = 0; k < length; k++)
content[k] = number[k];
content[length] = '\0';
}
std::ostream& operator<<(std::ostream& out, const typeString& towrite) {
out << towrite.content;
return out;
}
std::istream& operator>>(std::istream& in, typeString& toload) {
in >> toload.content;
return in;
}
class numberData {
public:
int index = 0;
typeString thisNumber;
numberData* nextNumber = NULL;
};
numberData* createNext(typeString sentNumber)
{
numberData* newData = new numberData();
newData->thisNumber = sentNumber;
newData->nextNumber = NULL;
return newData;
}
void addNumber(numberData** myData, typeString thisNumber)
{
staticint index = 0;
numberData* newData = createNext(thisNumber);
newData->thisNumber = thisNumber;
newData->nextNumber = *myData;
newData->index = index++;
*myData = newData;
}
void readNumbers(numberData** myData)
{
std::cout << "How many numbers to read? : ";
int n;
do {
std::cin >> n;
if (n > 100000 || n < 1)
std::cout << "ERROR: value between 0 and 100 000. Load again. " << std::endl;
} while (n < 1 || n > N);
typeString number;
while (n-- > 0)
{
std::cin >> number;
addNumber(myData, number);
}
}
int main()
{
numberData* myData = NULL;
readNumbers(&myData);
return 0;
}
The problem appears when I want to cin a number. So, answering questions:
1 and 2. content is char* content to save number and it's public
3. Operator >> is friend of typeString, but to be honest I don't know why it should be a friend, but without it there is an error "too many parameters for this operator function".
4. I wanted to pass char* content to save it as a string
5. added code
OK.
myData is NULL in line 136.
You pass an address to myData (which contains NULL) to readNumbers.
You pass the same address (which still contains NULL) to addNumber.
In line 113 you dereference myData and try to assign newData to it. However, the contents of myData is NULL, so you are trying to assign to the NULL pointer. (Edit: there is no object at *myData to assign to.)
Instead, change line 113 to myData = &newData;
Even better, make myData a reference to a pointer.
Line 126 creates the object number where number.content is nullptr.
On Line 129/86 you try to write data to the nullptr which will crash. Before you execute line 86 you need to make sure that you have a sufficient large buffer/content to write the data to.
@coder777, but how to have a buffer large enough to write string of any length? I need it to work like std::cin >> std::string.
@doug4, I'm not sure if I get it fully, but if what I pass is NULL, should I pass instead not an address of myData but exactly myData to those functions?
When I change line 113 the same error occurs. I don't know if it matters, but when I used normal std::string from <string> library everything worked fine, I don't know where is the problem in class typeString.
The only way I know to do that is to have your class attempt to read from cin up to a fixed number of bytes and if it exceeds that, stop, reallocate more space, and read more.
I think this may be what you need (?)
std::cin.read(&buf, available_size);
but that isnt going to stop on whitespace the way cin does, you may need to dig into the lower level objects behind cin to see if you can find something that will read up to N bytes, whitespace delimited, and loop that increasing your memory as you go until its all worked out.
alternately, you can allocate some stupidly large thing that is as big as you want to support, read into it, get its length, allocate twice that to your object (or whatever, giving yourself a little room to grow/edit/etc), copy the data, toss the oversized buffer (or keep it forever as static to re-use for performance?) and call it good. Its simple, and it will work for most applications.
I can think of a number of ways to do what you want. Here are 5 of them. I prefer them in the order that I present them (number 1. is my most preferred).
Hey, I forgot to answer earlier, but somehow I managed to make everything work with your help... Probably there are still some bugs and problems, but what I need for now is okay. Thanks so much.