Thread: Fun vector project not doing what I want!!!

  1. #1
    Registered User
    Join Date
    Jul 2013
    Location
    Germany
    Posts
    499

    Fun vector project not doing what I want!!!

    Really glad your guys are here. I sent this issue to my professor and he told me to worry about completing the graded assignments. However if I don't fully understand something, why move on?

    Ok first of all when ever run the program it always returns the addContact() then stops. I want to it keep running so I would assume I need a while statement, which I tried in main() but it didn't work. Furthermore I do not understand why my if and ifelse statements are failing!


    Code:
    #include <iostream>
    #include <vector>
    #include <string>
    
    using namespace std;
    
    void userPrompt();
    char getPrompt(char);
    void accessPrompt();
    void addContact();
    void deleteContact();
    void CountContact();
    
    
    vector<string> contacts;  
    
    void userPrompt()
    {
        char prompt;
        
        cout<<"Enter [a] to add a contact, [d] to delete a contact, [c] to count the contacts"<<endl;
        cin >> prompt;
        
        getPrompt(prompt);
        
    }
    char getPrompt(char prompt)
    {
        return prompt;
        
    }
    void accessPrompt()
    {
        char prompt = '\0';
        char user_request = getPrompt(prompt);
        
        if (user_request == 'a' || 'A') {
            addContact();
        }
        else if (user_request == 'd'|| 'D')
            deleteContact();
        else if (user_request == 'c' || 'C')
            CountContact();
    }
    
    void addContact()
    {
        string contact;
        cout<<"Add the name of your contact below"<<endl;
        getline(cin, contact);
        
        contacts.push_back(contact);
        
    }
    void deleteContact()
    {
        int position;
        
        cout<<"Where is the contect located that you want to delete?"<<endl;
        cin>>position;
        cin.ignore();
        
        contacts.erase(contacts.begin() + position); //contacts.begin=0 so position will find the contact
    
    }
    void CountContact()
    {
        cout<<"You have"<<contacts.size()<<" contact(s)."<<endl;
        
        for (int i=0; i<contacts.size(); i++) {
            cout<<i<<"."<<contacts.at(i)<<endl; //just another way to way to write contacts[i]
        }
            
    }
    
    
    int main(int argc, const char * argv[])
    {
        
        userPrompt();
        accessPrompt();
            
        return 0;
    }

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Your getPrompt function does not do anything useful: it just returns what was passed to it. As such, in accessPrompt, this code:
    Code:
    char prompt = '\0';
    char user_request = getPrompt(prompt);
    can be simplified to:
    Code:
    char user_request = '\0';
    That is, the user_request has nothing to do with what the user actually requested.

    To fix this, I suggest that you get rid of getPrompt. Instead, have userPrompt return the prompt. I would then get rid of accessPrompt: instead, that code can be moved to the main function. In the main function, you start by assigning the value returned from the call to userPrompt to the user_request variable.
    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

  3. #3
    Internet Superhero
    Join Date
    Sep 2006
    Location
    Denmark
    Posts
    964
    Code:
    if (user_request == 'a' || 'A') {
            addContact();
        }
        else if (user_request == 'd'|| 'D')
            deleteContact();
        else if (user_request == 'c' || 'C')
            CountContact();
    This is your problem right here. This needs to be:

    Code:
    if (user_request == 'a' || user_request == 'A') {
            addContact();
        }
        else if (user_request == 'd'|| user_request ==  'D')
            deleteContact();
        else if (user_request == 'c' || user_request ==  'C')
            CountContact();
    How I need a drink, alcoholic in nature, after the heavy lectures involving quantum mechanics.

  4. #4
    Registered User
    Join Date
    Jul 2013
    Location
    Germany
    Posts
    499
    Now it runs but just quits right away.

    I did the useless function because my book did that in classes. I thought it was good programing practice to name what you were doing for every step. Now that I think about it, it was most likely breaking it down dummy style.

    Code:
     #include <iostream>
    #include <vector>
    #include <string>
    
    using namespace std;
    
    void userPrompt();
    char getPrompt(char);
    void accessPrompt(char);
    void addContact();
    void deleteContact();
    void CountContact();
    
    
    vector<string> contacts;  
    
    void userPrompt()
    {
        char prompt;
        
        cout<<"Enter [a] to add a contact, [d] to delete a contact, [c] to count the contacts"<< endl;
        cin >> prompt;
        
        accessPrompt(prompt);
        
    }
    
    void accessPrompt(char user_request)
    {
        user_request = '\0';
        
        if (user_request == 'a' || user_request == 'A') {
            addContact();
        }
        else if (user_request == 'd'|| user_request == 'D')
            deleteContact();
        else if (user_request == 'c' || user_request == 'C')
            CountContact();
    }
    
    void addContact()
    {
        string contact;
        cout<<"Add the name of your contact below"<<endl;
        getline(cin, contact);
        
        contacts.push_back(contact);
        
    }
    void deleteContact()
    {
        int position;
        
        cout<<"Where is the contect located that you want to delete?"<<endl;
        cin>>position;
        cin.ignore();
        
        contacts.erase(contacts.begin() + position); //contacts.begin=0 so position will find the contact
    
    }
    void CountContact()
    {
        cout<<"You have"<<contacts.size()<< " contact(s)."<<endl;
        
        for (int i=0; i<contacts.size(); i++) {
            cout<<i<<"."<<contacts.at(i)<<endl; //just another way to way to write contacts[i]
        }
            
    }
    
    
    int main(int argc, const char * argv[])
    {
        char name = '\0';
        
        userPrompt();
        accessPrompt(name);
            
        return 0;
    }

  5. #5
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    I will point out 3 things:

    >>for (int i=0; i<contacts.size(); i++)
    Beware that .size() does not return an int. It returns std::vector<your_type>::size_t, often commonly written as std::size_t since they are often the same types. Problem is that .size() return an unsigned type and you use a signed type. Don't want to go there. Keep away from mixing signed and unsigned or you'll be sorry later.

    >>cout<<i<<"."<<contacts.at(i)<<endl; //just another way to way to write contacts[i]
    I will point out that it is not the same. The index operator and at() function have different semantics. It is a programming error to access non-existent elements using the index operator. It will cause undefined behavior, though some implements actually catches these kinds of errors before they happen. The at() function throws an exception if you access a non-existent element. Therefore, it is well defined. I would recommend you to use at() though, because it will often stop undefined behavior from corrupting your program later, leading to a simpler bug to fix.

    Finally, I would get rid of accessPrompt in main (and name) because the userPrompt function already does everything and your call in main doesn't make any sense (because it doesn't read any action and just passes an "invalid" response to the function).
    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.

  6. #6
    Registered User
    Join Date
    Jul 2013
    Location
    Germany
    Posts
    499
    Code:
    I have added in a while statement so the user can keep adding data until they want to stop. Sadly its a never ending loop. I added { to the if else statements because I seen they were missing. Still do not think it worked because now it just says "you did not enter a correct value" over and over until I quit the program.
    Code:
     #include <iostream>
    #include <vector>
    #include <string>
    
    using namespace std;
    
    void userPrompt();
    void accessPrompt(char);
    void addContact();
    void deleteContact();
    void CountContact();
    
    
    vector<string> contacts;  
    
    void userPrompt()
    {
        char prompt;
        
        cout<<"Enter [a] to add a contact, [d] to delete a contact, [c] to count the contacts and to [e]Exit"<< endl;
        cin >> prompt;
        cin.ignore();
        
        accessPrompt(prompt);
        
    }
    
    void accessPrompt(char user_request)
    {
        user_request = '\0';
        bool running = true;
        
        while (running == true) {
            
        if (user_request == 'a' || user_request == 'A')
        {
            addContact();
        }
        else if (user_request == 'd'|| user_request == 'D')
        {
            deleteContact();
        }
        else if (user_request == 'c' || user_request == 'C')
        {
            CountContact();
        }
        else if (user_request == 'e' || user_request == 'E')
        {
            running = false;
        }
        else
            cout<<"You did not enter a correct value"<<endl;
        }
        
    }
    
    void addContact()
    {
        string contact;
        cout<<"Add the name of your contact below"<<endl;
        getline(cin, contact);
        
        contacts.push_back(contact);
        
    }
    void deleteContact()
    {
        int position;
        
        cout<<"Where is the contect located that you want to delete?"<<endl;
        cin>>position;
        cin.ignore();
        
        contacts.erase(contacts.begin() + position); //contacts.begin=0 so position will find the contact
    
    }
    void CountContact()
    {
        cout<<"You have"<<contacts.size() << " contact(s)."<<endl;
        
        for (size_t i = 0; i<contacts.size(); i++) {
            cout<< i <<". "<< contacts.at(i) <<endl; //just another way to way to write contacts[i]
        }
            
    }
    
    
    int main(int argc, const char * argv[])
    {
        
        userPrompt();
        
        return 0;
    }

  7. #7
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    I would get rid of the global variable and pass the vector by reference or const reference to each function that should access it

    for example

    Code:
    void CountContact(const std::vector<std::string>& contacts)
    {
        std::cout << "You have " << contacts.size() << " contact(s)."<< std::endl;
         
        for (auto it = contacts.begin(); it != contacts.end() ; ++it) 
        {
            std::cout << std::distance(contacts.begin(), it) << ". " << *it << std::endl; 
        }
             
    }
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  8. #8
    Registered User
    Join Date
    Jul 2013
    Location
    Germany
    Posts
    499
    Vart:

    Really like the use of auto, I will remember to use that in the future. Thank you for the introduction of distance.

    Pass by Reference in this case is good because it saves memory, prevents over head, or is it just good programing practice?

  9. #9
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    when you need to modify object the pass by reference is only reasonable choice.

    When you do not need to modify object - you can pass by const reference or by value...

    For small types (let's say upto 2-4 ints) without complex copy constructors - you can easily pass variables by value.
    For complex types it is not so much the memory usage consideration now days but the cost of copying the data to the temporary storage and then destructing of this temporary storage...

    So I would say it more or less the question of performance issue. And only secondarily the memory usage
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  10. #10
    Registered User
    Join Date
    Jul 2013
    Location
    Germany
    Posts
    499
    I am having a real issue passing by reference and I really want to know how to do it. Do I need to declare it in main first, call all the functions there and pass it at that point. I can pass by value until I get to the addContact, deleteContact or CountContact right?

    It great you brought that up because I just entered into pass by reference with points in my book. However it just uses arrays and when when passed with functions it just changes the value passed to it as an example.

  11. #11
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    Here is the whole code that I used to test the CountContact function
    Code:
    #include <iostream>
    #include <string>
    #include <vector>
    
    void CountContact(const std::vector<std::string>& contacts);
    
    int main()
    {
        std::vector<std::string> contacts;
        contacts.push_back("one");
        contacts.push_back("two");
        contacts.push_back("three");
    
        CountContact(contacts);
    
        return 0;
    }
    
    
    
    void CountContact(const std::vector<std::string>& contacts)
    {
        std::cout << "You have " << contacts.size() << " contact(s)."<< std::endl;
         
        for (auto it = contacts.begin(); it != contacts.end() ; ++it) 
        {
            std::cout << std::distance(contacts.begin(), it) <<". " << *it << std::endl; 
        }
             
    }
    So basically - yes - you declare the contacts variable in main and then pass it to each function that needs to use it
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  12. #12
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by jocdrew21 View Post
    It great you brought that up because I just entered into pass by reference with points in my book. However it just uses arrays and when when passed with functions it just changes the value passed to it as an example.
    First off, the book does not pass by reference.
    Now, first you must separate C arrays and C++ arrays, because they behave differently. Avoid C arrays if you can.
    C arrays are declared like

    T myarray[size];

    When you pass such an array to a function, you can either pass it by address or by reference. You cannot pass it by-value. Consequently, if you declare the function as accepting an array by-value, you are accepting it as pass-by-address. Confusing? Yeah, you can thank the designers of C for that. Example:

    void foo(int myarray[]);
    // Equivalent to: void foo(int* myarray);

    int myarray[10];
    foo(myarray); // Passes by address
    // Equivalent to: foo(&myarray[0]);

    You can also pass by reference, which is done like so:

    void foo(int (&myarray)[10]);

    int myarray[10];
    foo(myarray);

    Note that the size is not optional. In the first, it works whatever the size of your array. In the second, it ONLY works with an array of 10 elements.
    C++ arrays comes in the form of std::array, which is like std::vector. It follows normal copy semantics. Pass it by-value and you get a copy. You can also pass it by-reference with the normal syntax:

    void foo(std::array<int, 10>& myarray);

    std::array<int, 10> myarray;
    foo(myarray);

    You can read more here.
    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. Replies: 4
    Last Post: 08-02-2013, 06:45 PM
  2. Replies: 4
    Last Post: 07-05-2013, 02:30 AM
  3. Replies: 5
    Last Post: 02-23-2013, 03:37 PM
  4. Second project, some errors (A set as a vector)
    By ferenczi in forum C++ Programming
    Replies: 3
    Last Post: 01-28-2010, 12:27 PM
  5. your 11th & 12th grade c++ project or similar project
    By sleepyheadtony in forum A Brief History of Cprogramming.com
    Replies: 12
    Last Post: 01-13-2002, 05:14 PM