Thread: Another n00b with pointer problems!

  1. #1
    Registered User
    Join Date
    Dec 2003
    Posts
    11

    Another n00b with pointer problems!

    This is the first program that I'm writing that uses pointers (and overall the second I'm writing in C++).

    I want DrivesToDo (a 26-digit boolean) to be filled by ExistingDrives. Every bit stands for a drive letter, so DrivesToDo[2] will be TRUE if a C-partition exists. I'm doing some stuff wrong though I can't figure out what it is. It worked when I first wrote it without using pointers. The program is written in MSVC6.0 and I guess it won't compile under any other compiler. The errors I get are the following:

    loc.cpp(9) : error C2664: 'ExistingDrives' : cannot convert parameter 1 from 'bool (*)[26]' to 'bool *[]'
    Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
    loc.cpp(16) : error C2059: syntax error : '{'
    loc.cpp(16) : error C2143: syntax error : missing ';' before '{'
    loc.cpp(16) : error C2143: syntax error : missing ';' before '}'


    It's probably a very stupid error I made, but I'm so newbie-ish I just can't figure it out... Help would be appreciated! Here's the code:


    Code:
    #include <direct.h>
    #include <iostream.h>
    
    
    void ExistingDrives(bool *Drives[26]);
    
    int main(void)
    {	bool DrivesToDo[26];  
    	ExistingDrives(&DrivesToDo);
    	return(0);
    }
    
    
    void ExistingDrives(bool *Drives[26])
    {	int c=2;
    	*Drives = {false, false};
    	
    	while (c < 26)
    	{	cout << endl << char(97+c) << ":";
    		if (_chdrive(c+1) != NULL) { *Drives[c] = false; cout << " doesn't exist"; }
    		else { *Drives[c] = true; cout << " exists"; }
    		c++;
    	}
    }

  2. #2
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    Code:
    char s[1024];
    char * sp = s;
    
    An array gets passed like a pointer because function(char * s) and function(char s[]) are identical. Both can be invoked as function(s) or function(sp) using the above arrays.
    
    >> *Drives = {false, false};
    
    Which two elements were you clearing - why?
    
    >> *Drives[c] = true;
    
    Drop the pointer dereferencing here. 
    
    >>if(_chdrive(c+1) != NULL)
    
    chdrive returns 'zero' on success, and 'NULL' implies a pointer, use:
    
    if(chdrive(c+1) != 0)
    
    or 
    
    if(chdrive(c+1))
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  3. #3
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    Welcome the boards......n00b!!
    J/K

    >> bool *Drives[26]
    This is an array of 26 pointers that point to type bool. What you want is an array of 26 bools: "bool Drives[26]"

    >> *Drives = false, false (left off curleys)
    If you want A: and B: to always be false, the use
    > Drives[0] = false;
    > Drives[1] = false;

    >> if (_chdrive(c+1) != NULL)
    You should compare with 0 instead of NULL. Or since _chdrive() returns -1 on failure, just check for that.

    >> *Drives[c]
    Get rid of the *

    >> char(97+c)
    Or char('A' + c)

    Don't try to compress the format of you code either, just makes less readable.
    Code:
    void ExistingDrives(bool Drives[26])
    {   
        int c = 2;
        Drives[0] = false;
        Drives[1] = false;
        
        while (c < 26)
        {   
            cout << endl << char('A' + c) << ":";
    
            if (_chdrive(c+1) == -1) 
            { 
                Drives[c] = false; 
                cout << " doesn't exist"; 
            }
            else 
            { 
                Drives[c] = true; 
                cout << " exists"; 
            }
            c++;
        }
    }
    Now what you should be using is GetLogicalDrives(). The method you are using will not work for drives that don't have any media. CD-ROM drives will not show up unless there is a CD in the drive.

    GetLogicalDrives() returns of a bitmask where the first 26 bits indicate if the drive exists or not. If pointers are new to you then bit twiddling may be too. Give another post if you have any questions.

    Code:
    #include <windows.h>
    #include <iostream>
    using namespace std;
    
    int main()
    {	
        DWORD mask = GetLogicalDrives();
        if (mask == 0)
        {
            cerr << "GetLogicalDrives() failes, last error = " 
                 << GetLastError() << endl;
            return 1;
        }//if
    
        for (int bit = 0; bit < 26; bit++)
        {
            cout << (char)('A' + bit) << ": ";
            if (mask & (1 << bit))
                cout << "exists" << endl;
            else
                cout << "doesn't exist" << endl;
        }//for
    
        return 0;
    }//main
    gg

  4. #4
    Registered User
    Join Date
    Dec 2003
    Posts
    11

    got it

    Thanks for the help, I understand what I did wrong and altered the file and it's now working.

    The only question I've got left is this:
    I now use
    Code:
    Drives[0]=false; Drives[1]=false;
    so my program knows drive A and B (your floppy drives) don't exist (cause checking their existence takes too much time). But why can't I write this like this:
    Code:
    Drives = {false,false};
    How should I write this correctly by just using one statement?

    Thanks for the help again, it's much appreciated.

  5. #5
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    >> How should I write this correctly by just using one statement?

    You can't. Though you could do:

    Drives[0]= Drives[1]=false;
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  6. #6
    Registered User
    Join Date
    Dec 2003
    Posts
    11
    Also thanks to you CodePlug.
    The program I'm making is a "locate" (from the UNIX shell) for DOS. The function I'm writing will be called when the user wants a complete disks-contents database to be created, but doesn't specify any drives (what a lazy bastard!). Hence, drives without media (like your CD-ROM player) shouldn't be indexed. I actually don't want the CD-ROM drive to be indexed at all (not even when a disk is in there), but I don't know how I can check if a specified drive is a CD-ROM drive. A possible way to do this is to check the time it takes to access the drive, but that would also exclude slow harddisks.

    But that's why I'm sticking to my algorithm instead of the one with GetLogicalDrives()

  7. #7
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    Use GetLogicalDrives() along with GetDriveType().

    gg

  8. #8
    Registered User
    Join Date
    Dec 2003
    Posts
    11
    Those are both declared in windows.h, they won't work with DOS.

  9. #9
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981

    Re: Another n00b with pointer problems!

    Originally posted by Bastaard
    The program is written in MSVC6.0 ...
    You're not making a DOS application. If you want it to work correctly and efficiently under any Win32 platform, then use the functions I've shown.

    gg

  10. #10
    Registered User
    Join Date
    Dec 2003
    Posts
    11
    Can't I make an app that will work under DOS AND Windows??? I'm sure the code I've written so far does...

  11. #11
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    Do not confuse "DOS application" with "console application".

    There is no difference in the code you've written and the code that I've shown in terms of "what it will run under". Both compile into Windows 32bit applications.

    To drive the point home, here's the actual Microsoft implementation of the _chdrive() function:
    Code:
    int __cdecl _chdrive (int drive)
    {
        char  newdrive[3];
    
        if (drive < 1 || drive > 31) {
            errno = EACCES;
            _doserrno = ERROR_INVALID_DRIVE;
            return -1;
        }
    
        _mlock(_ENV_LOCK);
    
        newdrive[0] = (char)('A' + (char)drive - (char)1);
        newdrive[1] = ':';
        newdrive[2] = '\0';
    
        /*
         * Set new drive. If current directory on new drive exists, it
         * will become the cwd. Otherwise defaults to root directory.
         */
    
        if ( SetCurrentDirectory((LPSTR)newdrive) ) {
            _munlock(_ENV_LOCK);
            return 0;
        }
        else {
            _dosmaperr(GetLastError());
            _munlock(_ENV_LOCK);
            return -1;
        }
    }
    SetCurrentDirectory() is another Win32 API out of <windows.h> just like GetLogicalDrives() and GetDriveType().

    Functions like _chdrive() are provided for backwards compatibility for older source code that was originally written for DOS. That way, these applications can simply be recompiled into true Win32 console applications.

    In VC++ 6.0, if you go to the Project -> Settings menu, then the Link tab under General Category, look in the Project Options edit box - in there you will see "/subsystem:console". This tells the linker that your app is going to need a console for interacting with stdin and stdout (among other things).

    Feel free to ask questions if anything is unclear.

    gg

  12. #12
    Registered User
    Join Date
    Dec 2003
    Posts
    11
    Okay, I see. This means it's impossible to write a pure DOS program using the headerfiles I'm using right now, right?

  13. #13
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    Need a different compiler and headers/libraries.

    DJGPP is a compiler for true DOS applications.

    Are you sure you want to make a true DOS application? Most folks are running some version of Windows if they aren't runing a flavor of Linux.

    gg

  14. #14
    Registered User
    Join Date
    Dec 2003
    Posts
    11
    No, I'll write a "pure" win32 app then.

    Thanks for all the tips and help, I greatly appreciate it.
    *over and out*

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Struct Pointer Problems. (Warning: Long Post.)
    By Phoenix940 in forum C Programming
    Replies: 1
    Last Post: 11-30-2008, 10:04 PM
  2. Problems passing a file pointer to functions
    By smitchell in forum C Programming
    Replies: 4
    Last Post: 09-30-2008, 02:29 PM
  3. pointer problems
    By subflood in forum C Programming
    Replies: 8
    Last Post: 06-17-2005, 11:18 AM
  4. Request for comments
    By Prelude in forum A Brief History of Cprogramming.com
    Replies: 15
    Last Post: 01-02-2004, 10:33 AM
  5. base class pointer problems
    By ... in forum C++ Programming
    Replies: 3
    Last Post: 11-16-2003, 11:27 PM