Page 1 of 3 123 Last
  • Jump to page:
    #1
  1. Banned ;)
    Devshed Supreme Being (6500+ posts)

    Join Date
    Nov 2001
    Location
    Woodland Hills, Los Angeles County, California, USA
    Posts
    9,612
    Rep Power
    4247

    Commonly Asked C/C++ Questions


    Here are some answers to commonly asked C/C++ questions on the forum. If you are new to the forum, please read this thread as your question may already be answered here. This guide is divided into many sections:
    0. Frequently Asked Newbie Questions (how do I pause output, compile my program etc.)
    1. Converting types
    2. Formatting Output
    3. String manipulation (copy, concatenate, replace etc.)
    4. File Manipulation (File size, dir contents, remove files etc.)
    5. Secure Programming Practices for Newbies.

    This guide is a work in progress, so feel free to PM me with your suggestions.

    CREDITS
    ---------------
    (in order of how they replied to the original thread)
    DaWei_M
    Deltron74
    grumpy
    movEAX_444
    mitakeet
    NetBSD
    User Name
    infamous41md

    Comments on this post

    • Maxium0CarMeX agrees : Thanks for sharing your knowledge with us
    Up the Irons
    What Would Jimi Do? Smash amps. Burn guitar. Take the groupies home.
    "Death Before Dishonour, my Friends!!" - Bruce D ickinson, Iron Maiden Aug 20, 2005 @ OzzFest
    Down with Sharon Osbourne

    "I wouldn't hire a butcher to fix my car. I also wouldn't hire a marketing firm to build my website." - Nilpo
  2. #2
  3. Banned ;)
    Devshed Supreme Being (6500+ posts)

    Join Date
    Nov 2001
    Location
    Woodland Hills, Los Angeles County, California, USA
    Posts
    9,612
    Rep Power
    4247

    0. Frequently Asked Newbie Questions (FNGFAQ)


    0. Frequently Asked Newbie Questions (FNGFAQ)
    ----------------------------------------------
    0.1. Where can I get a C or C++ compiler?
    Depends on your operating system. See the following links:
    http://www.compilers.net/Dir/Free/Compilers/CCpp.htm
    http://www.bloodshed.net/compilers/index.html
    http://www.openwatcom.org/ (Formerly Watcom/Sybase compiler)
    http://www.digitalmars.com/ (Formerly Symantec/Zortech compiler)
    http://community.borland.com/museum/ (Ancient Borland compilers)
    http://msdn.microsoft.com/visualc/vctoolkit2003/ (Free Visual C++ 2003 Toolkit)
    http://www.borland.com/products/down..._cbuilder.html (Borland C++ Builder Trial Version download)

    In general, people on this forum generally use the following:
    On Unix-like OS (Linux, FreeBSD, OpenBSD, NetBSD, Darwin etc.):
    gcc
    tendra (this is a relatively unknown compiler though :)).

    On Windows:
    Bloodshed Dev C++ (which uses gcc as the backend)
    Visual C++
    Borland C++ and Borland C++ Builder


    0.2 How do I compile my program?
    On unix-like systems:
    gcc -o exename myfile.c
    This will compile myfile.c to produce an executable file called exename. You can then run exename by typing ./exename

    On Windows systems, different compilers have different keys to compile a program.
    Bloodshed/Dev C++: Ctrl-F9 compiles, Ctrl-F10 executes.
    Visual C++: F7 compiles, F5 executes.
    Borland C++ Builder: Ctrl-F9 compiles, F9 executes.
    Turbo-C: F9 compiles, Ctrl-F9 executes.


    0.3 I cannot see my C compiler output. The window is closing too quickly for me.
    This is a common question that many newbie programmers on Windows have. See http://forums.devshed.com/t157960/s.html for many solutions.

    0.4 What are some handy C/C++ links?
    http://www.eskimo.com/~scs/C-faq/top.html
    http://www.parashift.com/c++-faq-lite/

    0.5 Why does my scanf/fscanf/sscanf stop working?
    Most C input is provided in a stream. That is, it is a series of characters made available one at a time. The scanf() function family are format-sensitive functions; they not only collect the characters for you, but attempt to convert them to a type (such as an integer) that you specify. They have great difficulty converting ZyGH4 to a meaningful number so they fail. The conversion attempt is governed by format specifiers that YOU provide. Since these may not match the input actually encountered, the family returns a value indicating the number of items successfully scanned AND assigned. If this value is zero, you have nothing. If this value is EOF, there was an end-of-file or other error. If you don't examine the return, how will you know? If an error occurs it will not be automatically cleared. Operations on the stream will continue to return an error until clearerr(), fseek(), fsetpos(), or rewind() is called. This means that a loop that is designed to pause for input will loop indefinitely.

    The characters that f/s/scanf attempt to convert as one value are all the characters up to the first whitespace character (space, tab, newline) or up to the specified field width, or up to the first character that cannot be converted. (Note: The [ and c format directives are not whitespace delimited, but we won't consider them for the explanation here). If a character conflicts with the format specification, the function terminates and the character is left in the stream as if it had not been read. You probably will not expect it to be there to serve as input for your next call, so your input will not behave as you expect.

    Example of proper usage:
    int status;
    status = scanf ("%s%d\n", name, &number);

    Check the value of 'status' after the scanf() call. If it is not what you expect (two, in this case), you didn't get all your fields. If it is EOF, your stream is broken and will remain so until you clear the error.

    0.6 Why does getline() not work correctly with Visual C++ (VC++)? Why do I have to type Enter twice for getline to process my input line?
    If you're reading this, you've probably noticed that getline() is not functioning the way your book says it should -- you need to hit <enter> twice for the program to read your input. For example:
    Code:
    #include <iostream>
    #include <string>
    
    using namespace std;
    
    int main()
    {
        string name;
        cout<<"Enter a name:\n";
        getline(cin, name);
        cout<<name<<endl;
    
        return 0;
    }
    This is because there's a known bug in Visual C++'s implementation of getline() (in the VC++ 6.0 Standard/Professional/Enterprise editions only, .NET has the fix). See the fix here: http://support.microsoft.com/default...;EN-US;q240015
    Further reading: getline(cin, text)

    Comments on this post

    • Maxium0CarMeX agrees : I was looking for this everywhere on the web! Thank you!
    Up the Irons
    What Would Jimi Do? Smash amps. Burn guitar. Take the groupies home.
    "Death Before Dishonour, my Friends!!" - Bruce D ickinson, Iron Maiden Aug 20, 2005 @ OzzFest
    Down with Sharon Osbourne

    "I wouldn't hire a butcher to fix my car. I also wouldn't hire a marketing firm to build my website." - Nilpo
  4. #3
  5. Banned ;)
    Devshed Supreme Being (6500+ posts)

    Join Date
    Nov 2001
    Location
    Woodland Hills, Los Angeles County, California, USA
    Posts
    9,612
    Rep Power
    4247

    1. FACQ - Frequently Asked Conversion Questions


    1. FACQ - Frequently Asked Conversion Questions
    =====================================
    1.1 How do I convert a char array to integer/double/long type?
    Use the atoi(), atof() or atol() functions. Also see question 1.3 below.
    Code:
    #include <stdlib.h>
    int main(void)
    {
         char *buf1 = "42";
         char buf2[] = "69.00";
         int i;
         double d;
         long l;
         i = atoi(buf1);
         l = atol(buf1);
         d = atof(buf2);
         return 0;
    }
    1.2. How do I convert an integer/float/double/long type variable to a char array?
    Use sprintf(). Many books/websites tell you to use itoa(), itol(), itof() etc., but these functions are compiler specific and are therefore non-portable. sprintf() is definitely the way to go.
    Code:
    #include <stdio.h>
    int main(void)
    {
        int i = 42;
        float f = 69.0;
        double d = 105.24;
        long l = 23;
        char buf[50];
     
        sprintf(buf, "%d", i);
        sprintf(buf, "%f", f);
        sprintf(buf, "%f", d);
        sprintf(buf, "%ld", l);
        sprintf(buf, "%d %f %ld", i, f, l);
        return 0;
    }
    C++ users may also use the stringstream or ostringstream class (the deprecated form was strstream class)
    Code:
    #include <sstream>
    #include <string>
    
    int main(void) {
        std::stringstream ss;
        int i = 42;
        double d = 105.24;
    
        ss << i << " " << d;
    
        // Convert to string or char array
        std::string s = ss.str();
        char buf[50];
        sprintf(buf, ss.str().c_str());
    }
    1.3. How do I convert a hex/octal/any-other-base value to a number?
    Use strtol() or sscanf().
    Code:
    #include <stdlib.h>
    #include <stdio.h>
    int main(void)
    {
      long l; int i;
      unsigned int ui;
      char *hexstr = "12FC3";
      char *octstr = "1245";
      char *binarystr = "1101";
    
      l = strtol(hexstr, NULL, 16);
      l = strtol(octstr, NULL, 8);
      l = strtol(binarystr, NULL, 2);
      sscanf("12", "%d", &i);
      sscanf("14", "%ld", &l);
      sscanf(hexstr, "%x", &ui);
      sscanf(hexstr, "%o", &ui);
    
      return 0;
    }
    C++ users may want to use stringstream instead (strstream is deprecated).
    Code:
    #include <sstream>
    #include <string>
    
    int main(void)
    {
      long l; int i;
      char *hexstr = "12FC3";
      char *octstr = "1245";
      std::stringstream ss;
    
      ss << std::hex << hexstr;
      ss >> l;
      ss.clear();
      ss << std::oct << octstr;
      ss >> i;
    
      return 0;
    }
    1.4. How do I convert an integer to hexadecimal (hex) /octal (oct)?
    Use sprintf().
    Code:
    #include <stdio.h>
    int main(void)
    {
        int i = 42;
        char buf[50];
        sprintf(buf, "%x", i); /* convert to hex */
        sprintf(buf, "%o", i); /* convert to octal */
        return 0;
    }
    C++ users may want to use stringstream instead (strstream is deprecated).
    Code:
    #include <sstream>
    #include <string>
    
    int main(void)
    {
      int i = 42;
      char buf[50];
      std::stringstream ss;
      ss << std::hex << i;
      ss >> buf;
    
      ss.clear();
      ss << std::oct << i;
      ss >> buf;
      return 0;
    }
    1.5 What's the equivalent of perl/pascal/vb/php's chr() and ord() functions in C/C++?
    There aren't any functions like this in C or C++ and they aren't needed anyway. You can get a char's ASCII value by simply assigning it to an integer variable.
    Code:
    char ch;
    int i;
    
    ch = 'A';
    i = ch; /* Assigns the ASCII value of 'A' (i.e.) 65 to i */
    printf("%d\n", i); /* Prints 65 */
    To do the reverse (i.e.) what the ord() function does, simply assign an integer to a char variable. You'll need to force a cast to avoid compiler warnings for some compilers though
    Code:
    int i;
    char ch;
    
    i = 65;
    ch = (char) i;
    /* some compilers don't warn you if you do:
    ch = i;
    and some will, hence the explicit cast to char type. The cast
    assures the compilers that warn you, that you know what you're doing. */
    printf("%c\n", ch); /* prints 'A' */
    Since characters and integers are treated somewhat alike in C/C++, you can perform arithmetic operations and comparision operations with char variables, just as you do with integer variables. For instance:
    Code:
    char ConvertToUpperCase(char ch) {
       if (ch >= 'a' && ch <= 'z')
          ch = ch - 'a' + 'A';
       return ch;
    }
    The above code takes a variable as input and checks if it is a lowercase letter by comparing its ASCII value to see if it is between the ASCII for 'a' and 'z'. If so, it subtracts the ASCII value of 'a' and adds the ASCII value of 'A', thereby converting it to an uppercase ASCII value.
    Up the Irons
    What Would Jimi Do? Smash amps. Burn guitar. Take the groupies home.
    "Death Before Dishonour, my Friends!!" - Bruce D ickinson, Iron Maiden Aug 20, 2005 @ OzzFest
    Down with Sharon Osbourne

    "I wouldn't hire a butcher to fix my car. I also wouldn't hire a marketing firm to build my website." - Nilpo
  6. #4
  7. Banned ;)
    Devshed Supreme Being (6500+ posts)

    Join Date
    Nov 2001
    Location
    Woodland Hills, Los Angeles County, California, USA
    Posts
    9,612
    Rep Power
    4247

    2. Frequently Asked Print Formatting Questions


    2. FREQUENTLY ASKED PRINT FORMATTING QUESTIONS
    ==========================================

    2.1 How do I print an integer/char/char array/float/double/long/long double/long long?
    Use appropriate formatting strings (%d, %ld, %f, %Lf, %lld) with your printf statements.
    Code:
    #include <stdio.h>
    
    int main(void)
    {
      int i = 23; long l = 42;
      float f = 105.23; double d = 69.05;
      long double ld = 55.23; long long ll = 92;
      char c='a'; char s[] = "This is a string";
    
      printf("int = %d\nlong = %ld\n", i, l);
      printf("float = %f\ndouble = %fd\n", f, d);
      printf("long double = %Lf\nlong long = %lld\n", ld, ll);
      printf("char = "%c\nString=%s\n", c, s);
    
      return 0;
    }
    C++ users can use cout and not worry about the format string types :D.

    2.2 How do I limit the precision/length of floating point, double numbers or char strings?
    Use the format strings to specify precision.
    Code:
    #include <stdio.h>
    
    int main(void)
    {
      float f = 105.2345;
      char buf[] = "This is a string";
    
      /* Limit to 2 decimals */
      printf("float = %.2f\n", f);
      /* Print 10 chars wide, limit to 2 decimals */
      printf("float = %10.2f\n", f);
      /* Print 10 chars wide, limit to 2 decimals and left-justify */
      printf("float = %-10.2f\n", f);
      /* Limit to 10 characters */
      printf("%.10s\n", buf);
    
      return 0;
    }
    C++ users may use the iomanip functions setprecision() and setw() to do this.
    Code:
    #include <iostream>
    #include <iomanip>
    
    int main(void)
    {
      float f = 105.2345;
      char buf[] = "This is a string";
    
      std::cout.setf(std::ios::fixed);
      /* Limit to 2 decimals */
      std::cout << std::setprecision(2) << f << endl; 
      /* Print 10 chars wide, limit to 2 decimals */
      std::cout << std::setw(10) << std::setprecision(2) << f << endl; 
      /* Right justify to 30 chars */
      std::cout << std::setw(30) << buf << endl; 
    
      return 0;
    }
    2.3 How do I control how many chars are read in a string when using scanf()?
    You can use the a format specifier in the scanf() function.
    Code:
    char buf[25];
    scanf("%20s", buf);
    The above code limits the length of the characters that will be read by scanf() to 20 characters maximum (note that the buffer can hold 25 characters though!)

    C++ Users can use either setw() or cin.get()
    Code:
    std::cin >> std::setw(20) >> buf;
    std::cin.get(buf, 20);
    Either statement does the same thing. Note that the above code will read 19 characters max and put \0 for the 20th character.


    2.4 How do I print a triangle, hourglass, sinewave or upside-down triangle?
    See this thread: http://forums.devshed.com/t137892/s.html and search this forum for more examples.
    Up the Irons
    What Would Jimi Do? Smash amps. Burn guitar. Take the groupies home.
    "Death Before Dishonour, my Friends!!" - Bruce D ickinson, Iron Maiden Aug 20, 2005 @ OzzFest
    Down with Sharon Osbourne

    "I wouldn't hire a butcher to fix my car. I also wouldn't hire a marketing firm to build my website." - Nilpo
  8. #5
  9. Banned ;)
    Devshed Supreme Being (6500+ posts)

    Join Date
    Nov 2001
    Location
    Woodland Hills, Los Angeles County, California, USA
    Posts
    9,612
    Rep Power
    4247
    Place holder for Chapter 3.
    Up the Irons
    What Would Jimi Do? Smash amps. Burn guitar. Take the groupies home.
    "Death Before Dishonour, my Friends!!" - Bruce D ickinson, Iron Maiden Aug 20, 2005 @ OzzFest
    Down with Sharon Osbourne

    "I wouldn't hire a butcher to fix my car. I also wouldn't hire a marketing firm to build my website." - Nilpo
  10. #6
  11. Banned ;)
    Devshed Supreme Being (6500+ posts)

    Join Date
    Nov 2001
    Location
    Woodland Hills, Los Angeles County, California, USA
    Posts
    9,612
    Rep Power
    4247
    Place holder for Chapter 4.
    Up the Irons
    What Would Jimi Do? Smash amps. Burn guitar. Take the groupies home.
    "Death Before Dishonour, my Friends!!" - Bruce D ickinson, Iron Maiden Aug 20, 2005 @ OzzFest
    Down with Sharon Osbourne

    "I wouldn't hire a butcher to fix my car. I also wouldn't hire a marketing firm to build my website." - Nilpo
  12. #7
  13. Banned ;)
    Devshed Supreme Being (6500+ posts)

    Join Date
    Nov 2001
    Location
    Woodland Hills, Los Angeles County, California, USA
    Posts
    9,612
    Rep Power
    4247
    5. Secure Programming Practices for Newbies
    --------------------------------------------
    Here's a FAQ put together by our very own mitakeet, with feedback from infamous41md. It covers several security issues, not just with C/C++ programming, but general practices to ensure the security of your applications. This article is a work in progress, so check back often:

    http://sol-biotech.com/code/SecProgFAQ.html
    Up the Irons
    What Would Jimi Do? Smash amps. Burn guitar. Take the groupies home.
    "Death Before Dishonour, my Friends!!" - Bruce D ickinson, Iron Maiden Aug 20, 2005 @ OzzFest
    Down with Sharon Osbourne

    "I wouldn't hire a butcher to fix my car. I also wouldn't hire a marketing firm to build my website." - Nilpo
  14. #8
  15. I'm Baaaaaaack!
    Devshed God 1st Plane (5500 - 5999 posts)

    Join Date
    Jul 2003
    Location
    Maryland
    Posts
    5,538
    Rep Power
    244
    I created a bit of a tutorial on performance programming at http://sol-biotech.com/code/PerformanceProgramming.html in case someone is interested.

    My blog, The Fount of Useless Information http://sol-biotech.com/wordpress/
    Free code: http://sol-biotech.com/code/.
    Secure Programming: http://sol-biotech.com/code/SecProgFAQ.html.
    Performance Programming: http://sol-biotech.com/code/PerformanceProgramming.html.
    LinkedIn Profile: http://www.linkedin.com/in/keithoxenrider

    It is not that old programmers are any smarter or code better, it is just that they have made the same stupid mistake so many times that it is second nature to fix it.
    --Me, I just made it up

    The reasonable man adapts himself to the world; the unreasonable one persists in trying to adapt the world to himself. Therefore, all progress depends on the unreasonable man.
    --George Bernard Shaw
  16. #9
  17. #10
  18. Last Day: May 29, 2005
    Devshed Novice (500 - 999 posts)

    Join Date
    Sep 2004
    Location
    elemental sphere
    Posts
    742
    Rep Power
    10

    win32


    also wanted to share some win32 links you might find useful:

    theForger's Win32 API Tutorial all win32 programmers know this one ;)
    Win32 Programming - FunctionX also a fairly complete list on the basics

    also:

    Al's Win32 programming page especially his first blank window tutorial
    Johnnie's Win32 API Programming Tutorial
  19. #11
  20. Lord of Dorkness
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2004
    Location
    Central New York. Texan via Arizona, out of his element!
    Posts
    8,524
    Rep Power
    3314

    A few ways to open and use files


    HOW TO OPEN AND USE A FILE

    Methods for opening files for reading and writing might be classified as C++, C stream, and C low-level methods. There are numerous variations, particularly with C++ streams; this post can in no way be considered exhaustive. CHECK YOUR DOCUMENTATION.

    A NOTE ABOUT MODE

    Unix/Linux have only one mode for file operations: binary. Windows has a text mode which is, unfortunately, the default. In text mode, content beyond what you supply is written to the file; it is stripped when you read the file. This makes the use of
    random access (seek, tell, etc.), problematic. Even worse, a 'soft' EOF, a special character, is written. This indicator is NOT MOVED if you do an append, so appended data is not reachable unless you reset the EOF indication. Consequently, I recommend always using binary mode. With 'fopen,' you can specify a read or write or other mode as "rb", "wb", etc. Unix/Linux will accept and ignore the 'b', so you can use it portably. You can also set the default mode in Windows with the global variable, _fmode.

    C++ USING FSTREAM

    VC++ 6.0, Windows XP
    Include iostream, fstream, and string for the following examples.

    FSTREAM
    OPENING FOR WRITE
    Code:
       // Example variables
       string sFileName = "test.txt";
       string sContents = "File data\n";
       string sToken;
       char   lineBuffer [256];
       int    nCount = 0;
    
       // Construct an fstream object and attempt to open
       // for output
       fstream ooFile;
       ooFile.open (sFileName.c_str (), ios::binary | ios::out);
    
       // Test for success
       if (!ooFile.is_open ()) return badHappenstance ("Couldn't open file for writing");
    
       // Write example
       ooFile << sContents;
    
       // Test the write for success
       if (!ooFile.good ()) return badHappenstance ("Write failed");
    
       // Close the file.  Note that the file will be closed automatically when
       // the object is destroyed (goes out of scope).
       ooFile.close ();
    OPENING FOR READ
    Code:
       // Open it for input
       ooFile.open (sFileName.c_str (), ios::binary | ios::in);
       if (!ooFile.is_open ()) return badHappenstance ("Couldn't open file for reading");
    
       // Read tokens until end of file or error
       while (ooFile.good ())
       {
          ooFile >> sToken;
          cout << "Token " << ++nCount << ": ";
          if (sToken.size ()) cout << sToken; else cout << "(null token)";
          cout << endl;
       }
       // Check some status for grins
       if (ooFile.eof ()) cout << "Reached EOF" << endl;
       else if (ooFile.fail ()) return badHappenstance ("Read failed for some reason");
    
       // Alternatively, read entire line
       ooFile.getline (lineBuffer, sizeof (lineBuffer));
    
       // Always the status
       if (!(ooFile.good () || ooFile.eof ()))
          return badHappenstance ("Failure reading line");
    
       cout << "This is the line: " << lineBuffer << endl;
    A SEEK EXAMPLE
    Code:
       // Position to beginning after clearing EOF or fail bits
       ooFile.clear ();
       ooFile.seekg (0, ios::beg);
       if (!ooFile.good ()) return badHappenstance ("Seek failed");
    
       ooFile.close ();
    Example output:
    Token 1: File
    Token 2: data
    Token 3: (null token)
    Reached EOF
    This is the line: File data
    C USING FOPEN

    VC++ 6.0, Windows XP
    Include stdio.h for this method.

    OPENING FOR WRITE
    Code:
       // Example variables
       FILE *ooFile;
       char  sFileName [] = "test.txt";
       char  sContents [] = "File data\n";
       char  sToken [32];
       char  lineBuffer [256];
       int   nCount = 0;
       int   status;
    
       // Attempt to open file for output
       ooFile = fopen (sFileName, "wb");
    
       // Test for success
       if (!ooFile) return badHappenstance ("Couldn't open file for writing");
    
       // Write the contents
       status = fputs (sContents, ooFile);
    
       // Test for success
       if (status == EOF) return badHappenstance ("Write failed");
    
       // Close the file
       fclose (ooFile);
    OPENING FOR INPUT
    Code:
       ooFile = fopen (sFileName, "rb");
       if (!ooFile) return badHappenstance ("Couldn't open file for reading");
    
       // Read tokens until end of file or error -- one method: fscanf
       // fscanf consumes whitespace, unlike some C++ methods
       // so there won't be a null token at the end.
       while (1)
       {
          if (fscanf (ooFile, "%s", sToken) != 1)
          {
             if (feof (ooFile)) 
             {
                printf ("Reached EOF\n");
                break;
             }
             else return badHappenstance ("Failed to read token");
          }
          printf ("Token %d: %s\n", ++nCount, sToken);
       }
    // REPOSITIONING EXAMPLE
    
       rewind (ooFile);
    
       // Read a line all in one swell foop
       // We'll either fill the buffer or have a newline
       // at the end of the buffer, or both.  If you don't
       // want the newline:
       //
       //    index = strlen (lineBuffer) - 1;
       //    if (lineBuffer [index] == '\n')
       //        lineBuffer [index] = '\0';"
       //
       if (fgets (lineBuffer, sizeof (lineBuffer), ooFile) == NULL)
          // Always the status; EOF is okay, error is not
          if (ferror (ooFile)) return badHappenstance ("Failed to read line");
    
       printf ("This is the line: %s", lineBuffer);
       fclose (ooFile);
    Example output:
    Token 1: File
    Token 2: data
    Reached EOF
    This is the line: File data
    C USING LOW LEVEL _open

    As far as I'm concerned, low level file operations are only good for reading large amounts of binary data, and are not necessary for that. One is far better off using the higher level functions.

    VC++ 6.0, Windows XP
    Include stdio.h, io.h, fcntl.h, sys\stat.h, ctype.h, and string.h for the following example.

    OPENING FOR READ/WRITE
    Code:
    typedef int fileHandle;
    extern int errno;
    
       // Example variables
       fileHandle ooFile;
       char  sFileName [] = "test.txt";
       char  sContents [] = "File data\n";
       char  sToken [32];
       char  sTrash [32];
       char  lineBuffer [256];
       int   nChars, nTokens;
       int   status;
    
       // Attempt to open file for input/output
       ooFile = _open ("test.txt", _O_CREAT | _O_RDWR | _O_TRUNC | _O_BINARY, _S_IWRITE);
    
       // Test for success
       if (ooFile == EOF) return badHappenstance (strerror (errno));
    WRITING
    Code:
       // Write the contents
       status = _write (ooFile, sContents, strlen (sContents));
    
       // Test for success
       if (status == EOF) return badHappenstance ("Write failed");
    SEEK AND READ OPERATION -- Far more complex than higher level methods
    Code:
       // Return to the beginning for input
       if (_lseek (ooFile, 0, SEEK_SET) == -1L)
          return badHappenstance ("Seek to beginning failed");
    
       // Read tokens until end of file or error
       nTokens = 0;
       while (1)
       {
          // Skip any whitespace
          while (status = _read (ooFile, sTrash, 1) == 1)
             if (!isspace (sTrash [0])) break;
          // Check for EOF or failure
          if (status < 0) return badHappenstance ("Failure to read data");
          else if (status == 0) break;
          sToken [0] = sTrash [0];
          for (nChars = 1; nChars < sizeof (sToken) - 1; nChars++)
          {
             status = _read (ooFile, &sToken [nChars], 1);
             // Check for EOF or failure
             if (status < 0) return badHappenstance ("Failure in reading data");
             else if ((status == 0) || (isspace (sToken [nChars])))
             {
                sToken [nChars] = '\0';
                break;
             }
          }
          // The token could be too long...
          if (nChars >= sizeof (sToken) - 1)
          {
             sTrash [0] = ' ';
             // Skip any remaining non-whitespace characters
             while (status = _read (ooFile, sTrash, 1) == 1)
                if (!isspace (sTrash [0])) break;
             // Check for EOF or failure
             if (status < 0) return badHappenstance ("Failure in reading data");
             else if (status == 0) break;
          }
          // Or we could have completed the token
          if (strlen (sToken) > 0) printf ("Token %d: %s\n", ++nTokens, sToken);
       }
       printf ("End of file\n");
    
       // Reposition to beginning
       if (_lseek (ooFile, 0, SEEK_SET) == -1L)
          return badHappenstance ("Seek to beginning failed");
    
       // Read one buffer's worth
       status = _read (ooFile, lineBuffer, sizeof (lineBuffer) - 1);
       if (status > 0) 
          lineBuffer [status] = '\0';
    
       printf ("This is the line: %s", lineBuffer);
       _close (ooFile);
    
       return 0;
    }
    Example output:
    Token 1: File
    Token 2: data
    End of file
    This is the line: File data
    Functionality rules and clarity matters; if you can work a little elegance in there, you're stylin'.
    If you can't spell "u", "ur", and "ne1", why would I hire you? 300 baud modem? Forget I mentioned it.
    DaWei on Pointers Politically Incorrect.
  21. #12
  22. Lord of Dorkness
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2004
    Location
    Central New York. Texan via Arizona, out of his element!
    Posts
    8,524
    Rep Power
    3314

    Pointers - A Quick View


    A short pointer tutorial can be found at this link .
    Functionality rules and clarity matters; if you can work a little elegance in there, you're stylin'.
    If you can't spell "u", "ur", and "ne1", why would I hire you? 300 baud modem? Forget I mentioned it.
    DaWei on Pointers Politically Incorrect.
  23. #13
  24. Left due to despotic ad-min
    Devshed Beginner (1000 - 1499 posts)

    Join Date
    Jun 2003
    Posts
    1,044
    Rep Power
    14

    Namespaces and the "using" directive


    This is a repost (with additions/corrections) of my response to a query about namespaces in the main forum. Some others suggested I add this to the FAQ, so....

    Namespaces and their close ally, the using directive, have a dubious distinction of being features of the C++ language that most programmers employ, while also being on the list of features that are most often misunderstood and misused.

    The following is a partial (and probably imperfect) attempt to describe what namespaces are in C++, and some forms of the "using" directive. Over time I may edit this post to make the discussion more complete (eg discuss the various gotcha's that arise from misunderstanding how namespaces work) or make corrections. If people pick up errors, or want to suggest additional material to include here, send me a private message.

    In simple terms, namespaces are a means of grouping the names of things..... by "things" I include type declarations, function names, type definitions, object names, etc etc. Consider an application that is built using several libraries that were written independently by other developers. In this case, the odds of two libraries using the same name for different things increases substantially. For example, a library concerned with multithreading might provide a class named Thread, which is responsible for creating an operating system thread and executing some function in the context of that thread. Now, let's consider an application that will do things multithreaded, but the actual purpose of that application is to control a set of sewing machines. The application therefore needs to use another library that also happens to define a class called Thread. Without namespaces, it would not be (easily) possible to use both libraries in the same application [there are techniques, but they are pretty arcane, particularly if our application developer cannot access source code for one or both libraries]. This is formally (according to the C++ standard) a violation of the "one definition rule" --- there should only be one definition of class Thread, not two. In practice, one might sometimes get lucky (eg our two hypothetical Thread classes might have all member functions with different names), but if both classes have a member function of the same name (eg both declare a non-static function of the form "void Initialise()") it is tricky even convincing the compiler and linker to build the application, let alone being able to run it.

    The purpose of namespaces is to reduce the odds that logically unrelated things wind up with exactly the same name. In our example, the developer of the multithreading library might define a namespace called Multithreading, while the developer of the other library may define a namespace named Cotton, viz.
    PHP Code:
    // in the header files and implementation of operating system theads ....
    namespace Multithreading
    {
        
    // all the definitions and declarations related to operating system threads
    }

    //   ... and in the header related to doing stuff with cotton ...

    namespace Cotton
    {
        
    // all the definitions and declarations related manipulating cotton threads

    The actual names of the namespaces don't matter, as long as they are different. The C++ standard defines a namespace named std, into which everything in the standard library exists (and application developers are not allowed to insert things into that namespace). Third party library developers pick the names of namespaces in various ways to reduce the odds of clashing with other libraries (eg by embedding their company name in the namespace name). Technically, this doesn't eliminate the possibility of duplicating names (eg two different library developers might happen to choose exactly the same name for their namespace), but the odds of it happening are substantially reduced.

    One nice thing about namespaces is they can be nested. For example, the Multithreading namespace I'm using in this example might include, within it, another namespace named Synchronisation which defines things related to mutexes and critical sections. Another feature is that everything within a class (or struct) definition appears in a namespace of the same name as the class. So the fully qualified (or fully scoped) name of a class related to critical sections might be something like "Multithreading::Synchronisation::CriticalSection", meaning that CriticalSection is a name within a namespace called Synchronisation, which is in turn within a namespace called Multithreading.

    This is all fine and dandy, but having to use the fully scoped name of an object or type gets inconvenient. For example, if we use the standard string class, every time we use a string, we have to name it std::string. Programmers are lazy souls (even worse than mathematicians, but mathematicians are taught to be deliberately lazy), so they whinge about having to do this in code where they don't use any other string class. This results in various forms of the "using" keyword.

    The most common one seen (and the one which I would argue should be used less) is.
    PHP Code:
    using namespace std
    takes everything that is declared or defined in namespace std, and allows them to be used without explicitly prefixing them with "std::".

    One (of many) problems with doing this is shown in this example;
    PHP Code:
    #include <string>
    // from another header ...
    namespace Foo
    {
         class 
    string
         
    {
              
    // whatever
         
    };
    }

    // now try to use our strings

    using namespace std;
    using namespace Foo;

    int main()
    {
         
    string   x;    // compiler complaint due to ambiguity
                          //   (not possible to decide what string to use).

    The string declaration within main() potentially resolves to either std::string or Foo::string. And there is no reason for the compiler to prefer one over the other....

    This is one reason (of several) that "using namespace" directives are often frowned upon.....they can give unintended effects such as code that can't be compiled because it is ambiguous. Putting a "using namespace" directive into any header file is bad practice, because it means every source file that #include's that header file has the chance of encountering this sort of ambiguity. And the only fix for such ambiguity is for the programmer to only use fully scoped names (eg "std::string" rather than "string" in the above example).

    Another form of a using directive is
    PHP Code:
    using std::string
    which basically allows definitions associated with std::string to be used, without pulling everything in namespace std along for the ride.

    Another use of the using keyword is to get around the "hiding rule", which is designed (deliberately, for reasons I won't go into here) to catch programmers out who do this;
    PHP Code:
    class Base
    {
         public:
              
    void Foo(int);
    };

    class 
    Derived: public Base
    {
         public:
              
    void Foo(double);
    };

    int main()
    {
         
    Derived x;
         
    x.Foo(1);     // will cause a compiler error, as Foo(int) is hidden

    If the intent in this example is for class Derived to supply both a Foo(int) and a Foo(double), the definition of Derived may be changed to....
    PHP Code:
    class Derived: public Base
    {
         public:
              
    using Base::Foo;
              
    void Foo(double);
    }; 
    Note that, in this case, the "using" directive is local to class Derived.

    A common misunderstanding of the using directive and namespaces is shown in the following example;
    PHP Code:
    #include <iostream>
    using namespace std;

    class 
    Foo
    {
         
    // various other details

         
    friend ostream operator<<(ostream &, const Foo &);
    };

    int main()
    {
         
    Foo x;
         
    cout << x;

    Most novices believe that the above will work, and output the object x to the standard stream std::cout. Even worse, some text books (which I won't name) encourage that belief. The result, however, is usually a compile time error. Worse still, some compilers also get it wrong, and don't complain---leaving a user mystified about why x is not output to standard output.

    This example is problematical because the "using namespace" directive does not interact with the friend declaration (except with some buggy compilers) in the "obvious" way. The friend declaration is actually equivalent to
    PHP Code:
        friend ::ostream &operator<<(::ostream &, const Foo &); 
    whereas the programmer (because they have used the "using namespace" directive) thinks it is "obviously" equivalent to;
    PHP Code:
        friend std::ostream &operator<<(std::ostream &, const Foo &); 
    The first form has actually (implicitly) declared a type named ostream in the (unnamed) global namespace, and then declared an operator<<() that works with that implicitly declared type. The problem is, the type ::ostream is completely distinct from std::ostream. When we come to use it, in the line
    PHP Code:
       cout << x
    the compiler realises that cout is actually std::cout (thanks to the using directive) and then looks for an implementation of the corresponding operator<<() that works with a std::ostream on the left hand side and a Foo on the right. Our function "::ostream &operator<<(::ostream &, const Foo &)" does not satisfy that search, so a compile time error occurs.

    In practice, to make the above example work, I would suggest never employing the "using namespace" directive in a header file or before any class declaration. Instead, I would do this;
    PHP Code:
    #include <iostream>

    // the following may be in a header file
    class Foo
    {
         
    // various other details

         
    friend std::ostream operator<<(std::ostream &, const Foo &);
    };

    //  OK, in our executing code we want to be lazy

    using namespace std;

    int main()
    {
         
    Foo x;
         
    cout << x;

    This form also (thankfully) works as intended, even with compilers out there that handle the first form incorrectly.
    It is only our bad temper that we put down to being tired or worried or hungry; we put our good temper down to ourselves."
    -- C.S. Lewis

    I like long walks, especially when they're taken by people who annoy me.
    --Fred Allen
  25. #14
  26. Banned ;)
    Devshed Supreme Being (6500+ posts)

    Join Date
    Nov 2001
    Location
    Woodland Hills, Los Angeles County, California, USA
    Posts
    9,612
    Rep Power
    4247

    Operator Overloading Tutorial for dummies


    Here is my attempt at writing a comprehensive C++ Operator Overloading Tutorial
    Up the Irons
    What Would Jimi Do? Smash amps. Burn guitar. Take the groupies home.
    "Death Before Dishonour, my Friends!!" - Bruce D ickinson, Iron Maiden Aug 20, 2005 @ OzzFest
    Down with Sharon Osbourne

    "I wouldn't hire a butcher to fix my car. I also wouldn't hire a marketing firm to build my website." - Nilpo
  27. #15
  28. I'm Baaaaaaack!
    Devshed God 1st Plane (5500 - 5999 posts)

    Join Date
    Jul 2003
    Location
    Maryland
    Posts
    5,538
    Rep Power
    244
    A little write-up on diagnosing and fixing buffer overflows (memory bounds violations): http://sol-biotech.com/code/BufferOverflows.html.

    My blog, The Fount of Useless Information http://sol-biotech.com/wordpress/
    Free code: http://sol-biotech.com/code/.
    Secure Programming: http://sol-biotech.com/code/SecProgFAQ.html.
    Performance Programming: http://sol-biotech.com/code/PerformanceProgramming.html.
    LinkedIn Profile: http://www.linkedin.com/in/keithoxenrider

    It is not that old programmers are any smarter or code better, it is just that they have made the same stupid mistake so many times that it is second nature to fix it.
    --Me, I just made it up

    The reasonable man adapts himself to the world; the unreasonable one persists in trying to adapt the world to himself. Therefore, all progress depends on the unreasonable man.
    --George Bernard Shaw
Page 1 of 3 123 Last
  • Jump to page:

IMN logo majestic logo threadwatch logo seochat tools logo