0
ifstream file ("../file.csv");
string test;
unsigned counter = 0;
   while(counter<10){
        getline(file,test,'"');
        cout<<test<<endl;
        counter++;
    }

I am essentially trying to recreate this in c++ but without using the string class. I am trying to figure out a way to not use the string class and still use this same function. Any thoughts?

For some clarification I will be delimeting with a '"' and then I will be a comma after that, so there is a text surrounded in '"', and a conclusion that is seperated from the text by a comma.

This is my custom class

class customString {
    char* myStr;
    int length;
public:
    customString();
    customString(char enb);
    customString(const customString& source);
    customString(customString&& source);
    ~customString(){delete myStr;}
    
    
};

customString::customString(){
    str = new char[1];
    str[0] = '\0';
}
customString::customString(char enb) {
    length = 1;
    myStr= new char(enb);

}
customString::customString(const customString &source) {
    length = source.length;
    myStr = new char[length];

    for (int i = 0; i < length; i++){
        myStr[i]=source.myStr[i];
    }
}
customString::customString(const char* val){
    if(val!= nullptr){
        int counter = 0;
        while(val[counter]!='\0')counter++; //Find length of the char array
        length = counter;
        myStr = new char[counter];
        for(int i =0;i<counter;i++){
            myStr[i]=val[i];
        }


    }else{
        length = 1;
        myStr = new char[length];
        myStr[0] = '\0';
    }
}
customString::~customString(){
    delete[] myStr;
}```

  • 2
    It's not clear to me how the code you are trying to copy manages to read a csv file. There's no special treatment of commas for instance, which is kind of essential in reading Comma Separated Values. – john Sep 02 '20 at 05:50
  • 1
    Unless all values are double-quoted within the fields and you take odd number of inputs... – David C. Rankin Sep 02 '20 at 05:52
  • Anyway writing your own string class that emulates the parts of `std::string` that you need seems the only correct solution. – john Sep 02 '20 at 05:53
  • @DavidC.Rankin That never occurred to me. I suspect you're right. – john Sep 02 '20 at 05:55
  • @john I have a custom string class I am trying to use it with getline but thought there might be another option. can you give me an example of how to use getline with a custom string. I will upload my custom string to the original thread. –  Sep 02 '20 at 05:57
  • @john chuckling.... not something you see every day, but at least in theory it would work. Though you would expect to see the modulo operator somewhere (or at least an AND `1` check) – David C. Rankin Sep 02 '20 at 05:58
  • @ConnerMorton Your custom string class isn't powerful enough to do the job. You need to add something to your string class that lets you add one character to the end of an existing string (like `push_back` in `std::string`), then you can write a function that loops, reading one character at a time, and if it isn't `"` adds it to the end of the string. – john Sep 02 '20 at 06:24

2 Answers2

1

you can use std::basic_istream<CharT,Traits>::getline:

basic_istream& getline( char_type* s, std::streamsize count, char_type delim );
Oblivion
  • 7,176
  • 2
  • 14
  • 33
  • 2
    I think the OP would need to `basic_istream& getline( char_type* s, std::streamsize count, char_type delim );` form at that same link to search for `'"'` as a delimiter? – David C. Rankin Sep 02 '20 at 05:50
  • 1
    Also, some kind of iteration to mimic the behavior of `std::getline`, perhaps pushing back into a `vector`. – jxh Sep 02 '20 at 05:52
  • 1
    Sure. Other thought, if the OP can't use `std::string`, then `std::vector` is out, so they would probably need to allocate a block of pointers and then allocate a block for each string, copy to the allocated block and assign each block to a pointer in turn... (reallocing as needed) – David C. Rankin Sep 02 '20 at 05:56
0

There isn't much to your custom class, but as it is implemented, you need to define an assignment operator, otherwise an assignment could result in both a memory leak and a double free bug. Follow the Rule of Three.

If you must use a pointer, you should at least use a std::unique_ptr<char[]> instead of a bare pointer. However, it is simpler to use a std::vector<char> instead.

class customString {
    std::vector<char> myStr;
    friend std::ostream & operator << (std::ostream &ost, const customString &s) {
        return ost.write(&s.myStr[0], s.myStr.size());
    }
    friend std::istream & getline (std::istream &ist, customString &s,
                                   char delim = '\n') {
        //...
        return ist;
    }
public:
    customString() {}
    customString(char enb) : myStr(enb) {}
    customString(const char *val, int len = -1)
        : myStr(val, val + (len < 0 ? strlen(val) : len))
        {}
};

Note that your code was missing the const char * constructor. Also, since std::vector knows its length, the length member is no longer required. For convenience, I included a method to emit the contents into an std::ostream.

For your getline replacement, you could also implement that as a friend function inside your custom class, and I included a stub above. When you implement it, you have to pay attention to how std::getline is defined to make sure you follow all of its behaviors.

My advice is to actually extract one character at a time (e.g., with std::istream::get) and check it against the delimiter. Then, make sure you set failbit in the std::istream if you encounter one of the failure conditions.

  • str.max_size() characters have been stored
  • If no characters were extracted for whatever reason

Reference: cppreference.com

Good luck, and hope this helps!

jxh
  • 69,070
  • 8
  • 110
  • 193