Thread: Relatively noob question regarding #include and .h files.

  1. #1
    Registered User
    Join Date
    Apr 2010
    Posts
    88

    Relatively noob question regarding #include and .h files.

    Hello,

    It's been a while since I programmed, and I've gotten rusty on some of the main points. I've made a simple example to try to refresh my memory.

    Basically, I have the source files attached below. They are the actual implementation of some csv functions, the corresponding header, and a main program trying to use them. I'm trying to compile main.cpp to use the code from krs_csv.cpp with the following g++ call:

    g++ main.cpp krs_csv.cpp

    However, I keep getting the following error messages:
    Code:
    krs_csv.cpp:1:1: error: ‘string’ in namespace ‘std’ does not name a type
    krs_csv.cpp:13:1: error: ‘string’ in namespace ‘std’ does not name a type
    The source files are below:

    main.cpp
    Code:
    #include<iostream>
    #include<string>
    #include "krs_csv.h"
    
    
    int main( int argc, char ** argv){
    
      int n=1;
      std::string buf;
      std::fstream file;
      file.open( "data.csv", std::ios::in );
    
      buf = get_nth_line( file, 4 );
      
      buf = get_nth_entry(buf, 0, " "); 
      
      std::cout<<"2nd entry of 2nd line is: "<<buf<<"\n";
      
      return 0;
    }
    krs_csv.cpp
    Code:
    #include "krs_csv.h"
    
    std::string get_nth_line( std::fstream & file, int n){
      
      std::string buffer;
    
      file.seekg( 0, std::ios::beg );
      
      for( int i=0; i < n ; i++)
        getline( file, buffer, '\n' );  
    
      return buffer;
    }
    
    std::string get_nth_entry( std::string line, int n , std::string sep){
    
      int l=-1;
      int r=0;
    
      //find preceding occurrence of sep
      for( int i=0; i < (n-1); i++)
        l = line.find( sep, l+1 );
      
      r = line.find( sep, l+1);
      
      if( r == -1){
        return line.substr( l+1, std::string::npos);
      }
      else{
        return line.substr( l+1, r-l-1 );
      }
    
    }
    krs_csv.h
    Code:
    #ifndef _STRING_INCLUDED
    #define _STRING_INCLUDED
    #include<string>
    #endif
    
    #ifndef _FSTREAM_INCLUDED
    #define _FSTREAM_INCLUDED
    #include<fstream>
    #endif
    
    #ifndef _FUNC_H
    #define _FUNC_H
    std::string get_nth_line( std::fstream & file, int n);
    std::string get_nth_entry( std::string line, int n , std::string sep);
    #endif /*_FUNC_H */
    Can you please critique this "way" of using the #include command and the way I've organized the files? Is there a smarter way to do something like this?

    I understand this is contrived, and there is error-checking and other things that should be added to the code, I'm just wondering if I've roughly set up the source files and include dependencies okay.
    Last edited by Ocifer; 04-29-2013 at 08:52 AM.
    W7, Ubuntu -- mingw, gcc, g++, code::blocks, emacs, notepad++

  2. #2
    [](){}(); manasij7479's Avatar
    Join Date
    Feb 2011
    Location
    *nullptr
    Posts
    2,657
    Remove the guards around <string> and <fstream>.
    They have their own guards.

  3. #3
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Your krs_csv.h really should be written like this:
    Code:
    #ifndef OCIFER_FUNC_H
    #define OCIFER_FUNC_H
    
    #include<string>
    #include<fstream>
    
    std::string get_nth_line( std::fstream & file, int n);
    std::string get_nth_entry( std::string line, int n , std::string sep);
    
    #endif /* OCIFER_FUNC_H */
    Notice that I got rid of those conditional inclusions of the standard headers and move the header inclusions to within the header inclusion guards. Notice also that I changed the header inclusion guard name: names like _FUNC_H that begin with an underscore followed by an uppercase letter (or that contain consecutive underscores) are reserved to the implementation for any use, so you should not use them unless you are writing the compiler/standard library implementation.

    Next, your krs_csv.cpp should start with:
    Code:
    #include<string>
    #include<fstream>
    #include "krs_csv.h"
    Granted, the first two should have been included in krs_csv.h, but it is good practice not to rely on that. Also, I expect that your use of the unqualified getline should work because of argument dependent lookup, but you should be aware of why it works (the compiler sees that file and/or buffer belong to the std namespace, so it searches the std namespace for the name getline and finds std::getline).

    In main.cpp, you likewise should #include<fstream>.
    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

  4. #4
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by ZuK
    then your main file needn't #include <string> and <iostream> but it wouldn't do any harm
    #include <iostream> is required since std::cout is used. Well, okay, by chance some other header may have included that, but to rely on such a fact is a very bad practice.

    Quote Originally Posted by ZuK
    I have no idea what could cause your error messages if the order of includes is as in the code you have posted.
    It could be that _STRING_INCLUDED happens to be the actual header inclusion guard name used in <string> or a header file it includes. In that case, the #define _STRING_INCLUDED means that the contents of the standard header won't get included, thus std::string would not have been declared.
    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
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Firstly, standard headers (like <string> and <fstream>) are required to work even if they are #include'd multiple times in a compilation unit. You do not need to wrap them #include directives for standard headers in constructs like this.
    Code:
    #ifndef _STRING_INCLUDED
    #define _STRING_INCLUDED
    #include<string>
    #endif
    In this case, all you need to do is "#include <string>". The guarding macros are not necessary.

    Second, identifiers (including macro names) that start with a leading underscore and an uppercase letter, or that contain a double underscore, are reserved for any use by the implementation. All identifiers that start with a leading underscore are reserved for use by the implementation as names within the global namespace. Code that uses such identifiers - which your header file does - yields undefined behaviour according to the standards. You need to ensure your naming of identifiers does not have that form. That is probably the reason for the error messages from your compiler (although some other compilers might let the code through, the code is still incorrect).

    Third, using #include guards in your own headers is often a good idea (to prevent problems with multiply defined types or variables), but typically protect EVERYTHING in the file. There are exceptions to that statement, but your code - as it stands - does not need to be one of them.

    Fourth, you need to #include other headers (<iostream> comes to mind).
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  6. #6
    Registered User
    Join Date
    Aug 2005
    Location
    Austria
    Posts
    1,990
    Quote Originally Posted by laserlight View Post
    #include <iostream> is required since std::cout is used. Well, okay, by chance some other header may have included that, but to rely on such a fact is a very bad practice.
    I said so because the header "ksc_csv.h" is the only header in that small program and that already #includes <iostream> but you're right one should alwais #include any dependent header
    BTW: You were very fast, I deleted my reply within 15 seconds afer posting.

  7. #7
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by grumpy
    Fourth, you need to #include other headers (<iostream> comes to mind).
    Quote Originally Posted by ZuK
    I said so because the header "ksc_csv.h" is the only header in that small program and that already #includes <iostream>
    Hmm... are you two sure? It looks like Ocifer only included <iostream> in main.cpp, which is fine.

    Quote Originally Posted by ZuK
    You were very fast, I deleted my reply within 15 seconds afer posting.
    Thanks, I try to be fast and bright, like laserlight
    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
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by ZuK View Post
    BTW: You were very fast, I deleted my reply within 15 seconds afer posting.
    Don't forget that moderators can see deleted replies, as well
    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.

  9. #9
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    If it were deleted then I would have no interest in addressing it.
    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
    Registered User
    Join Date
    Aug 2005
    Location
    Austria
    Posts
    1,990
    Quote Originally Posted by laserlight View Post
    Hmm... are you two sure? It looks like Ocifer only included <iostream> in main.cpp, which is fine.
    You are right. Didn't read the code properly.

    Kurt

  11. #11
    Registered User
    Join Date
    Apr 2010
    Posts
    88
    Hello all,

    Thanks for the responses. I've updated the source files, and they compile
    without any warnings or errors. I've attached them below in code tags.

    I would also like to make sure I understand all of your comments and
    suggestions.

    1) I've updated the implementation (.cpp) and the header (.h) files, they now both include <fstream> and <string>. Laserlight wrote that I should include these libraries in both source files for good measure. Why is this necessary? Am I wrong in thinking that the krs_csv.cpp file will always be used in conjunction with the .h file (it includes it)? Why do I need to include it in both? Furthermore, I've noticed that it compiles without warnings if I include <fstream> and <string> in one or the other, or both. What is the "correct" way? Any thoughts?

    2) The comment about getline() is a bit unclear to me (due to my ignorance, not the phrasing). Did you mean that I should "qualify" it by using this kind of call:

    file.getline( --args --)

    ------------------------------------------------------------

    krs_csv.h
    Code:
    #ifndef INC_KRS_CSV
    #define INC_KRS_CSV
    
    #include<fstream>
    #include<string>
    
    std::string get_nth_line( std::fstream & file, int n);
    std::string get_nth_entry( std::string line, int n , std::string sep);
    
    #endif /* INC_KRS_CSV */
    krs_csv.cpp
    Code:
    #include<string>
    #include<fstream>
    #include "krs_csv.h"
    
    std::string get_nth_line( std::fstream & file, int n){
      
      std::string buffer;
    
      file.seekg( 0, std::ios::beg );
      
      for( int i=0; i < n ; i++)
        getline( file, buffer, '\n' );  
    
      return buffer;
    }
    
    std::string get_nth_entry( std::string line, int n , std::string sep){
    
      int l=-1;
      int r=0;
    
      //find preceding occurrence of sep
      for( int i=0; i < (n-1); i++)
        l = line.find( sep, l+1 );
      
      r = line.find( sep, l+1);
      
      if( r == -1){
        return line.substr( l+1, std::string::npos);
      }
      else{
        return line.substr( l+1, r-l-1 );
      }
    
    }
    main.cpp
    Code:
    #include<iostream>
    #include<string>
    #include<fstream>
    #include "krs_csv.h"
    
    
    int main( int argc, char ** argv){
    
      std::string buf;
      std::fstream file;
      file.open( "data.csv", std::ios::in );
    
      buf = get_nth_line( file, 2 );
      
      buf = get_nth_entry(buf, 2, " "); 
      
      std::cout<<"2nd entry of 2nd line is: "<<buf<<"\n";
       
      return 0;
    }
    compilation command:
    Code:
    g++ main.cpp krs_csv.cpp -Wall
    W7, Ubuntu -- mingw, gcc, g++, code::blocks, emacs, notepad++

  12. #12
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by Ocifer View Post
    1) I've updated the implementation (.cpp) and the header (.h) files, they now both include <fstream> and <string>. Laserlight wrote that I should include these libraries in both source files for good measure. Why is this necessary? Am I wrong in thinking that the krs_csv.cpp file will always be used in conjunction with the .h file (it includes it)? Why do I need to include it in both?
    Perhaps you remove <string> from the header in the future. Perhaps you create an entirely new header. Then your source file will stop working all of a sudden.
    You don't need to. It's just good practice.

    Furthermore, I've noticed that it compiles without warnings if I include <fstream> and <string> in one or the other, or both. What is the "correct" way? Any thoughts?
    Always include all headers your code is using. Since file streams and strings reside in different headers--always include them both. Some implementation may include another one behind the scenes, but that's an implementation detail. Some compilers might, some don't, which makes your code compile on some compilers and not others.

    2) The comment about getline() is a bit unclear to me (due to my ignorance, not the phrasing). Did you mean that I should "qualify" it by using this kind of call:
    No, it means you should write

    std::getline(...);
    instead of
    getline(...);

    Avoid file.getline. It's evil™.
    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.

  13. #13
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by Ocifer
    2) The comment about getline() is a bit unclear to me (due to my ignorance, not the phrasing). Did you mean that I should "qualify" it by using this kind of call:

    file.getline( --args --)
    No, what I mean is that you should understand why it works. If you are not sure, then it is better to qualify it, i.e.,
    Code:
    std::getline( file, buffer, '\n' );
    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

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 1
    Last Post: 11-06-2011, 06:20 PM
  2. noob question regarding #include
    By Ace Rockolla in forum C++ Programming
    Replies: 14
    Last Post: 03-06-2010, 11:31 AM
  3. Multiple Source Files, make files, scope, include
    By thetinman in forum C++ Programming
    Replies: 13
    Last Post: 11-05-2008, 11:37 PM
  4. about #include files and header files
    By bulletbutter in forum C++ Programming
    Replies: 9
    Last Post: 04-18-2008, 10:24 AM
  5. #include header files or .cpp files?
    By DoctorX in forum C++ Programming
    Replies: 3
    Last Post: 12-23-2006, 12:21 PM