Thread: How do I create a filename with multiple variable types

  1. #1
    Registered User
    Join Date
    Dec 2008
    Posts
    38

    How do I create a filename with multiple variable types

    I have a set of text files where the titles coorespond to the date they were written (such as 01-31-12, where 01 is january, 31 is the thrity first, and 12 is the year). In my C++ code, I have an array with different variables allocating different numbers to different blocks in the array to check different files for a comparison to a keyword. Problem is, the dashes are a char, and the numbers are, well, numbers. Is there an easy workaround for this problem, or do I have to restructure my filenames?

    I'm teaching myself programming, so please don't presume a college level education.

  2. #2
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    sscanf() ought to work:

    Code:
    #include <cstdio>
    
    char *filenameExample = "01-31-12";
    int month, day, year;
    
    std::sscanf(filenameExample, "%d-%d-%d", &month, &day, &year);
    (For those about to complain that I used a C function, have your C++ version ready for comparison)
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  3. #3
    Registered User
    Join Date
    Dec 2008
    Posts
    38
    Good enough. Thanks.

  4. #4
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by brewbuck
    (For those about to complain that I used a C function, have your C++ version ready for comparison)
    Not too difficult:
    Code:
    int month, day, year;
    std::stringstream ss("01-31-12");
    ss >> month >> literal('-') >> day >> literal('-') >> year;
    // or:
    ss >> month >> '-' >> day >> '-' >> year;
    if only we had continued working on getting an input matching manipulator standardised, or getting the formatted read to ignore literals added to the standard I/O streams
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  5. #5
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    [hangs head in shame]
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  6. #6
    Registered User
    Join Date
    Oct 2006
    Posts
    3,445
    care to explain the head hanging? aside from trying to read directly into literals, I see nothing wrong with laserlight's example.

  7. #7
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    We were working on a project to allow one or the other to work as part of the C++ standard library, but brewbuck decided that he did not have the time to see it through.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  8. #8
    [](){}(); manasij7479's Avatar
    Join Date
    Feb 2011
    Location
    *nullptr
    Posts
    2,657
    Quote Originally Posted by laserlight View Post
    Not too difficult:
    Code:
    int month, day, year;
    std::stringstream ss("01-31-12");
    ss >> month >> literal('-') >> day >> literal('-') >> year;
    // or:
    ss >> month >> '-' >> day >> '-' >> year;
    if only we had continued working on getting an input matching manipulator standardised, or getting the formatted read to ignore literals added to the standard I/O streams
    How can the second one be implemented ?
    (The first one, I think, can just be a templated function, taking and returning a reference to the istream involved, plucking out the argument passed into it. Am I right ?)

  9. #9
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by manasij7479
    How can the second one be implemented ?
    By overloading operator>> in the std namespace (for argument dependent lookup) to have two parameters: a non-const reference to std::basic_istream and a const reference to char.

    Quote Originally Posted by manasij7479
    (The first one, I think, can just be a templated function, taking and returning a reference to the istream involved, plucking out the argument passed into it. Am I right ?)
    No, it is not as simple as that because the function call does not involve the istream. One way out is for the function call to create an object that has operator>> overloaded for basic_istream. This object then contains the argument provided as an argument to the input manipulator, and then its operator>> uses that value to perform the input manipulation.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  10. #10
    [](){}(); manasij7479's Avatar
    Join Date
    Feb 2011
    Location
    *nullptr
    Posts
    2,657
    Quote Originally Posted by laserlight View Post
    No, it is not as simple as that because the function call does not involve the istream. One way out is for the function call to create an object that has operator>> overloaded for basic_istream. This object then contains the argument provided as an argument to the input manipulator, and then its operator>> uses that value to perform the input manipulation.
    After simplifying a little and abstracting the work of the >> in the () operator, here is my try:
    Code:
    template<typename T>
    class literal
    {
        T t;
    public:
        literal(T t_):t(t_){};
        istream& operator()(istream& is)
        {
            T temp;
            is>>temp;
            if(temp!=t)is.setstate(ios_base::failbit);
            return is;
        }
    };
    template<typename T>
    istream& operator>>(istream& is,literal<T> lt)
    {
        return lt(is);
    }
    Example use:
    Code:
    int main()
    {
        int x,y;
        cin>>x>>literal<char>('+')>>y;
        cout<<x<<endl<<y;
        return 0;
    }
    Doe this fall short anywhere ?
    Last edited by manasij7479; 02-11-2012 at 02:21 PM.

  11. #11
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by laserlight View Post
    By overloading operator>> in the std namespace (for argument dependent lookup) to have two parameters: a non-const reference to std::basic_istream and a const reference to char.
    Hrm. That causes an ambiguous overload for me: the compiler cannot decide between std::stringstream::operator >> (int&) and std::operator > (std::stringstream&, const char&).
    Last edited by Elysia; 02-11-2012 at 04:24 PM.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  12. #12
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    O_o

    This:

    Code:
    namespace std
    {
        istream & operator >>
        (
            istream & fLHS
          , const char & fRHS
        );
    }
    not this:

    Code:
    namespace std
    {
        stringstream & operator >>
        (
            stringstream & fLHS
          , const char & fRHS
        );
    }
    Soma

  13. #13
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Just for the sake of it, I made an attempt at implementing the first method:

    Code:
    #include <sstream>
    #include <iostream>
    #include <assert.h>
    
    template<typename StreamT>
    class XLiteral
    {
    public:
    	XLiteral(char c): m_c(c) {}
    	void SetStream(std::basic_istream<StreamT>& stream) { m_stream = &stream; }
    	template<typename T> XLiteral& operator >> (T& rhs) { assert(m_stream); *m_stream >> rhs; return *this; }
    	char GetChar() const { return m_c; }
    
    protected:
    	std::basic_istream<StreamT>* m_stream;
    	char m_c;
    };
    
    template<typename StreamT>
    XLiteral<StreamT> & operator >> (std::basic_istream<StreamT>& lhs, XLiteral<StreamT>& rhs) 
    {
    	char tmp;
    	lhs >> tmp;
    	assert(tmp == rhs.GetChar());
    	rhs.SetStream(lhs);
    	return rhs;
    }
    
    template<typename StreamT>
    XLiteral<StreamT> literal(StreamT c) { return XLiteral<StreamT>(c); }
    
    int main()
    {
    	int month, day, year;
    	std::stringstream ss("31-01-12");
    	ss >> day >> literal('-') >> month >> literal('-') >> year;
    }
    (Also took the liberty to fix the date format.)

    It compiles and works fine under Visual Studio, but not with Comeau. Dunno why. I am probably missing something trivial.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  14. #14
    [](){}(); manasij7479's Avatar
    Join Date
    Feb 2011
    Location
    *nullptr
    Posts
    2,657
    Quote Originally Posted by Elysia View Post
    Dunno why. I am probably missing something trivial.
    a.cpp: In function ‘int main()’:
    a.cpp:36:26: error: no match for ‘operator>>’ in ‘ss.std::basic_stringstream<char>::<anonymous>.std ::basic_iostream<char>::<anonymous>.std::basic_ist ream<_CharT, _Traits>:perator>> [with _CharT = char, _Traits = std::char_traits<char>]((* & day)) >> literal [with StreamT = char](45)’
    What does that <anonymous > mean, though ?

    (Also, why are you templating it w.r.t to the stream type ? ... shoudn't choosing the base class... i.e istream or basic_istream be enough ?)

  15. #15
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    It complains there is no match for operator >> (basic_istream<T>, XLiteral). But the WHY is what I don't understand.
    basic_istream is a template class and istream is a typedef for basic_istream<char>. This way, you can use either char or wchar_t.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Overloading a variable with multiple data types
    By CPlus in forum C++ Programming
    Replies: 18
    Last Post: 02-13-2010, 04:25 PM
  2. Creating multiple files with string as filename
    By jmayer in forum C++ Programming
    Replies: 2
    Last Post: 01-25-2008, 09:55 AM
  3. Using a variable for a filename
    By Unlockitall in forum C++ Programming
    Replies: 4
    Last Post: 12-15-2007, 10:41 AM
  4. I/O--Using a variable as a filename
    By jedo in forum C++ Programming
    Replies: 7
    Last Post: 09-06-2005, 10:57 AM
  5. Variable filename
    By Azmeos in forum C++ Programming
    Replies: 7
    Last Post: 06-09-2003, 02:42 PM

Tags for this Thread