deceptikon 1,790 Code Sniper Team Colleague Featured Poster

@Deceptikon: Back in the days of Turbo C, I remember folks saying never put an array in the arguments, and instead use its pointer AND the same thing about struct's.

While it's true for struct instances, arrays have always been passed "by pointer", even in the prehistory of C. When you pass an array to a function, a pointer to the first element is created and sent by value, so the only thing that gets copied is an address. Note also that these three declarations of the parameter are completely identical in every functional way:

void foo(int *a);
void bar(int a[]);
void baz(int a[N]);

The latter two declarations are a convenience and under the hood will be treated as if they were the first. In the last declaration, the size of the first dimension is allowed syntactically, but ignored semantically. You can verify this with a simple program that would give at least a warning if the size were meaningful:

void foo(int a[10]) { }

int main(void)
{
    int arg[5];

    foo(arg); /* Size mismatch? */

    return 0;
}

The folks who were saying that an array parameter could be passed by value were mistaken.

I'm tempted to say that if you pass an array of specific size to a function expecting a specific size, it will pass by value, but I don't know.

That's quite impossible if we're talking about a conforming C compiler because passing by value would break the guaranteed …

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

Q1. Languagess are system software or application software?

Neither. Languages aren't software at all, they're abstractions designed to simplify the task of humans giving instructions to a computer. A programming language is nothing more than a set of grammatical rules that, when consumed by a compiler or interpreter, represent a consistent set of machine instructions.

Q2. In which software the languages are written? for example in which software the c++ language is written?

The answer to the previous question makes this question nonsensical.

Ancient Dragon commented: great answer :) +14
deceptikon 1,790 Code Sniper Team Colleague Featured Poster

set_union() assumes that the output iterator points to a collection with enough existing space to hold all of the results. If you're planning on using an empty vector or have set_union() grow the vector then you'll want to do it through a back inserter.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

Dani and I have been discussing it furiously for the last couple of days. Hopefully we'll have an idea of what's causing it soon.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

aren't you confusing them all the time when coding once in one language, and then in another ?

Only rarely, and only with languages I don't use on a regular basis.

Isn't it better to be splendid in 1 language than to be mediocre in 5 ?

There are some benefits to fluency, but they're vastly overwhelmed by the quality of the programmer. A good programmer doesn't become mediocre by using an unfamiliar language, and a mediocre programmer will still be mediocre regardless of fluency in a language.

I think it's more important to learn multiple languages for two reasons:

  1. A programmer who can hit the ground running (ie. already knows the implementation language) is far more marketable.
  2. Learning wildly different language families (Algol derivatives versus LISP variants, for example) gives you valuable insight by forcing you to change the way you think. In practice, I've found that the ability to think squiggly is mighty handy, and experience with different ways of going about the same thing is the best way to practice that skill.
deceptikon 1,790 Code Sniper Team Colleague Featured Poster

I'm writing it so that I don't have to worry about deleting anything everytime I allocate.

While writing your own smart pointer is a good exercise, it shouldn't be preferred over the ones already available in C++11 and Boost. I'd recommend studying the interface for those and how they work for ideas on ways to improve your own Memory class.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

The syntax for PHP is derived from the C family of languages, Ruby isn't. You'd feel more comfortable with PHP, but it's generally a good idea for programmers to have some familiarity with different language families.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

Is it possible to overload one operator more than once?

Yes, but only if the parameter types are unique. Operator overloading is no different from regular function overloading in that the signature (not including the return type) must be different for overload resolution to be unambiguous.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

9 times out of 10, a linker error means you failed to define something that was declared before it's usage. Very often this is due to a static class data member:

class foo
{
    static int bar;
};

int foo::bar; // This external definition is required somewhere (ideally in a separate implementation file)!

That's one thing to look for.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

I was able to reproduce the issue on Chrome Beta 20.0.1123.27. Clearing the cache corrected it. If you're affected, please try clearing your browser's cache and let us know if the problem persists.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

I think you're being overly sensitive here. I want to believe that it's an honest misunderstanding and not just an excuse to stir up trouble, so please take it up with him privately rather than derailing the topic of this thread.

Thank you.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

That was a serious question given that it came from left field and struck me as the ravings of a belligerent drunk, but I apologize if you were offended.

Since we're asking for apologies in name calling I'd ask you to apologize to Vernon for calling him an idiot, but I'll be satisfied if you create a new thread with your specific grievances so that this thread is no longer derailed.

Of course, you're still welcome to offer constructive suggestions as requested by Dani in the first post.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

This is the reason why people come and go! Over the years, it was bad but it gotten better that's why I sign up to become a member. I have doubts now

Could you specify what "this" refers to? I still have no clue what your beef is.

You are a developer at Daniweb, have you fixed Firefox?

Dani was working on that particular issue, you'll have to ask her what the status is.

Is that a threat?

Yes. Yes, it is. Our rules clearly state what's expected of you as concerns behavior. I couldn't care less who you are or what you do outside of Daniweb, here you follow the rules or suffer the consequences. Nobody is exempt.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

I'm all for calling it like you see it, LastMitch, so I'll ask: are you drunk? Where did all of that vitriol come from?

Anyway, now that you've insulted a valued member, a moderator, an administrator, and Dani herself, hopefully that vented the hate and we can return to a civil discussion. If not, well, the rules are very clear. ;) You may consider that your first and only warning, and as a sign of good will I won't edit or delete any of your posts in this thread thusfar.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

Your initial allocation loop iterates far too many times. The overall process looks fine though. I'd write it like this:

int rows = numCouples * 2;
int cols = numCouples;
int** ratings = malloc(rows * sizeof *ratings);

// Check if malloc() failed...

for (i = 0; i < rows; ++i)
{
    ratings[i] = malloc(cols * sizeof *ratings[i]);
}

// Populate the data...

for (i = 0; i < rows; ++i)
{
    free(ratings[i];
}

free(ratings);
deceptikon 1,790 Code Sniper Team Colleague Featured Poster

I'm going to go into pedantic mode for a bit. Apologies if either of you are offended in the process.

#include <conio.h>

C is a widely portable language, which means it's possible to take code and compile it on a multitude of operating systems and compilers without any changes. But that doesn't mean code is always portable; it's the job of the programmer to make sure that code is as portable as possible while still doing what needs to be done.

Now, that said, conio.h is not a portable library. Even if a compiler supports it, the functions that are supported within can vary greatly. One excellent example is the clrscr() function which is only supported (to the best of my knowledge) by Borland compilers, yet it's very commonly--and unnecessarily--included as a first step in many example programs:

#include <stdio.h>
#include <conio.h>

int main(void)
{
    clrscr(); /* Not needed and not portable! */

    printf("Hello, world!\n");

    return 0;
}

On a side note, I'll be happy to explain the issues with clrscr() in another reply if you're interested. The result is that these example programs are only compilable without change on the same compiler used to test them (assuming they were even tested). The closing getch() is another example shown in this thread:

#include <stdio.h>
#include <conio.h>

int main(void)
{
    printf("Hello, world!\n");

    printf("Press any key to continue . . .");
    fflush(stdout);
    getch(); /* Not portable and only conditionally needed! */

    return 0;
}

Using getch() …

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

numPerms[ii] = str;

str is a pointer, that pointer holds the address of word from main(). After RecursivePermute() runs to completion, every pointer in numPerms points to the same address.

Given that you've already allocated memory to each element in main(), you can fix both the problem and the obvious memory leak by copying the contents of str instead of assigning pointers:

strcpy(numPerms[ii], str);

One line changed, problem solved. :) There are other issues with the code, but I won't confuse things by pointing them out.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

As it stands right now, experienced programmers will only actively participate in DaniWeb if they want to spend all their time helping newbies.

Because the experienced programmers will typically have a host of favored ways to solve their own problems where asking for help on a forum is very low on the list. Case in point, I can count on one hand the number of times I've seriously sought help on a forum for something that had me stumped.

I do see a few more advanced questions, but you're right that they're overwhelmed by the beginner stuff. However, I disagree that we don't currently have a members-helping-members community because the beginner threads often have advanced tangents. Nothing is more instructive for two experts than getting into a debate about some topic, and a lot of good information gets churned out of such threads.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

The short answer is you can't. The long answer is you can if you aren't pedantic about it.

An array can be copied by value by wrapping the array in a structure and then passing an instance of that structure. When the structure instance is copied, the array goes with it as a data member. Technically you're not passing the array by value, you're passing the structure instance by value, but the effect is the same:

#include <stdio.h>

struct foo { int a[10]; };

void bar(struct foo arg)
{
    /* Notice how the sizeof trick works */
    for (int i = 0; i < sizeof arg.a / sizeof *arg.a; i++)
    {
        printf("%d ", arg.a[i]);
        ++arg.a[i]; /* Won't affect the original array in main() */
    }
}

int main(void)
{
    struct foo x =
    {
        {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
    };

    bar(x);
    putchar('\n');

    for (int i = 0; i < sizeof x.a / sizeof *x.a; i++)
    {
        printf("%d ", x.a[i]);
    }

    putchar('\n');

    return 0;
}
deceptikon 1,790 Code Sniper Team Colleague Featured Poster

I've wondered that as well, but if it were in Software Development I'm sure someone would ask why there's not a database subforum in Web Development. ;)

Anyway, my conclusion was that it's just an artifact of history where Dani simply chose to put that subforum there instead of somewhere equally valid.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

Some compilers have an option to rename the entry point, but I'd question its usefulness in all but the most niche cases.

And what, exactly, is the purpose of the main part, anyway?

To provide an entry point into the program. That's really it. The C++ runtime has to know how to call your code after initializing everything, and a function with a known signature is the simplest solution.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

Can you write a program in C++ and have another part written in C and compile them into a single executable file?

Yes. The two would be compiled into object code separately, then linked together. However, that's not the hard part. The hard part is making sure that the two can talk to each other, because you're very likely calling a C function from C++ or a C++ function from C. The specific tricks are getting your linkage right and exporting usable wrappers.

As concerns linkage, you need to make sure that any C++ functions intended for use in a linked C program must have C linkage. Likewise, any C functions intended for use in a linked C++ program must also be declared with C linkage. Note that this is all on the C++ side. For example:

extern "C" void foo(); // Basically disables C++'s name mangling

Since C++ has a bunch of stuff that C won't recognize, you need to write wrappers and proxies that C will recognize. So if you want to use a class in C, the functionality would need to be wrapped up in a function with C linkage because C can't instantiate the object. If you want to use std::string as parameters or a return type then a wrapper is needed to convert that object into a C-style string that C can use.

Further reading: http://www.parashift.com/c++-faq-lite/mixing-c-and-cpp.html

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

Well, you could take advantage of the way the numbers are patterned. Notice how your triangle fits perfectly if you replace everything less than or equal to N with asterisks, where N starts at 6:

int j;
int x = 6;

for (int i = 1; i < 6; i++, x--)
{
    for(j = 1; j < 5; j++)
    {
        if (j >= x)
        {
            System.out.print("*");
        }
        else
        {
            System.out.print(j);
        }
    }

    for(int k = j; k > 0; k--)
    {
        if (k >= x)
        {
            System.out.print("*");
        }
        else
        {
            System.out.print(k);
        }           
    }

    System.out.println();
}

Obviously this won't work without the incrementing and decrementing number pattern.

pritish.kamath commented: Awesome!!! +0
deceptikon 1,790 Code Sniper Team Colleague Featured Poster

When I use Chromium, I am unable to login.
Today I tried my luck with Firefox and it worked.
But I am not sure what the problem with Chromium is..

This is mostly for my own curiosity, but it could also benefit troubleshooting: have you tried Chrome and gotten the same results?

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

I wouldn't call it a debate at all, more like some know-it-all being pwned by someone who actually knew what she was talking about. By the way, this thread is 6 years old...

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

setw() is an absolute field width, not something based on tab stop boundaries, so you'd need to calculate the correct field widths for even alignment. You can also use the '\t' escape character to print a tab that will adhere to tab stop boundaries:

cout << setw(23) << left << "Loan amount:" << "\t$" << principle << endl;
cout << setw(23) << left << "Monthly Interest Rate:" << "\t" << monthlyIntRate << "%" << endl;
cout << setw(23) << left << "Number of Payments:" << "\t" << numPayments << endl;
cout << setw(23) << left << "Monthly Payment:" << "\t$" << monthlyPayment << endl;
cout << setw(23) << left << "Total Amount Paid:" << "\t$" <<totalAmt << endl;
cout << setw(23) << left << "Interest Paid:" << "\t$" << intPaid << endl;
deceptikon 1,790 Code Sniper Team Colleague Featured Poster

"isDuplicate" is declared in "getScores", so it should be defined first.

I think you're confused. Can you point out exactly what you're referring to?

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

Shouldn't the boolean "isDuplicate" go before the integer "getScores", so there aren't initialization errors?

The only requirement is that it's declared before use. The given code was only a snippet, which suggests that something along the lines of the following was assumed:

bool isDuplicate(int* student_ids, int head_count, int id);
int getScores(int* student_ids, int* scores, int max_students);

...

int getScores(int* student_ids, int* scores, int max_students)
{
    ...
}

bool isDuplicate(int* student_ids, int head_count, int id)
{
    ...
}
deceptikon 1,790 Code Sniper Team Colleague Featured Poster

What's the logic for the path? Is it the shortest path between A and B? Longest? Ad hoc based on input?

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

Once again it depends. If I'm only ever planning on using a compiler where getch() is supported, it's silly to write something custom. I'd favor separating it out into a wrapper so that porting would be easier should it be needed though. So first a header with a portable definition:

// raw_input.h
#ifndef RAW_INPUT_H
#define RAW_INPUT_H

int raw_input();

#endif

Then an implementation that uses the non-portable library:

// raw_input.cpp
#include "raw_input.h"
#include <conio.h>

int raw_input()
{
    return getch();
}

This way I could use raw_input() in the main application, and if the time comes where getch() is no longer suitable, I can simply replace the implementation of raw_input() instead of replacing every instance of getch() throughout the entire program. For cases such as this where the wrapper is trivial, there's a good cost to benefit ratio even if the likelihood of porting is fairly low.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

Thanks for the input nikita, but was it really worth bumping a 7 year old thread that already had working example code?

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

I would recommend that moderators get more involved with thier members, not only in answering questions, but also in the voting and commenting process.

I'd be shocked if most or all of the moderators didn't already participate heavily in this way. One of the reasons mods attracted attention for becoming mods is being highly active members.

In addition, for those questions that have clearly been answered, they should be marked as answered if the original poster has abandoned the thread.

This is also already done to the best of our ability. Sometimes it's not obvious that the thread has been solved though.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

I read its bad to use conio.h, and i use getch() from that header. If i have a new project that needs such function, is it good i to write it on my own? What would the mass of programmers do?

getch() is "bad" because it's non-portable. Whether it's actually bad in a practical sense depends on why you use it. For example, one of the classic clueless programmer red flags is using getch() to pause the program:

#include <iostream>
#include <conio.h>

int main()
{
    std::cout << "Hello, world!\n";
    getch();
}

On top of being only conditionally necessary[1], this destroys portability by limiting the code to compilers that support both conio.h and getch(). It's generally seen as stupid by clueful people to decrease portability without good reason. Another fine example of unnecessary loss of portability (and also conveniently another clueless programmer red flag) is the supremely arrogant and idiotic concept of starting a program with clrscr():

#include <iostream>
#include <conio.h>

int main()
{
    clrscr();
    std::cout << "Hello, world!\n";
}

However, if you're using getch() to legitimately accept raw input where the functionality of the program depends on not buffering said input and cannot be suitably replaced with a portable solution, that's fine. One example would be a password input function where you replace each typed character with an asterisk. There's no way to portably create that effect, so when you have no choice but to use a non-portable solution, the portability criticism goes away.

WaltP commented: Excellent explanation... +14
deceptikon 1,790 Code Sniper Team Colleague Featured Poster

I'm not sure I understand the requirement. It looks like start and finish are related, in which case sorting by finish time would be more meaningful like this:

#include <stdio.h>
#include <stdlib.h>

struct ElapsedTime
{
    int start, finish;
};

int compare_elapsed(void const* a, void const* b)
{
    struct ElapsedTime const* pa = a;
    struct ElapsedTime const* pb = b;

    return pa->finish - pb->finish;
}

int main(void)
{
    struct ElapsedTime times[] = 
    {
        {1, 5},
        {5, 11},
        {3, 4},
        {1, 2},
        {5, 9},
    };
    int n = sizeof times / sizeof *times;

    qsort(times, n, sizeof(times[0]), compare_elapsed);

    for (int i = 0; i < n; ++i)
    {
        printf("%d, %d\n", times[i].start, times[i].finish);
    }

    return 0;
}

The difference being that it's an array of structs where each struct has only a single pair of times, then the array is sorted according to the finish time. This design strikes me as more reasonable, but I am making an assumption based on experience rather than what your actual requirements are.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

Just a quick correction: line 6 should read

if (argc == 1)

It's a nitpick, but I wouldn't recommend that because argc can indeed be 0. If you're expecting one actual argument then I'd make the test argc < 2. This accounts for all cases where insufficient arguments are provided. Whether the program name (stored in argv[0]) is available or not, actual parameters will begin at argv[1]. So there's no case where argv[0] will represent anything except for a null pointer or the program name.

So the test argc < 2 covers all of the possible cases:

  • argc is 0 (program name is not available, no parameters)
  • argc is 1 (program name is available or simulated, no parameters)
  • argc is 2 or more (parameters provided, program name available or simulated)

On a side note, it's not safe to assume that argv[0] represents anything meaningful. It could be NULL in the case where argc is 0, or it could be an empty string. Even if it's not an empty string, the value is a completely implementation-defined representation of the program name.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

Don't post working answers.

No worries, bakabozza didn't post a working answer. There are a number of problems with the posted Init() function such that it's completely unusable without fixing some fundamental errors. And this is excluding the required addition of scaffolding to make it compile.

WaltP commented: True, but he DID offer working code -- which is cheating. +0
deceptikon 1,790 Code Sniper Team Colleague Featured Poster

Vertical tab and form feed are exactly what you'd think, and they really only apply to things like line printers or ancient hardcopy terminals. Note that those were part of the language way back in the 60s where such things were far more common than now. You're not likely to use either of them in modern code.

Concerning vertical tab, the standard says that the following is unspecified:

The behavior of the display device if a vertical tab character is written when the active position is at or past the last defined vertical tabulation position (5.2.2).

However, and this is important to recognize: horizontal tab has the same unspecified behavior:

The behavior of the display device if a horizontal tab character is written when the active position is at or past the last defined horizontal tabulation position (5.2.2).

Notice how the wording is identical with the only difference being an exchange of "vertical" with "horizontal". Essentially the same wording is used for printing any character at the end of a line, backspace, horizontal tab, and vertical tab. Ultimately this implies that the behavior is unspecified if you produce any output at all. :D In other words, don't worry about it.

sunfutbol commented: Ok thnx :) +0
deceptikon 1,790 Code Sniper Team Colleague Featured Poster

I'm not familiar with Github. Can you give an example?

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

some one correct my program and let me continue my execution .............

I did take a look at the code, and you're clearly dereferencing null pointers. Here's one example:

a=a->next;
a=malloc(sizeof(struct node));      
a->name=c;
a->next=NULL;

The first a = a->next makes a a null pointer. Why? Because a is equivalent to g from main(), and while g is a valid node object, g->next is NULL. So what you need to do is allocate memory to a->next, then move to the new node.

But this still doesn't fix the problem because you're basically throwing away all references to the objects you're creating by modifying a directly and then returning it to be assigned to g.

The following gins() at least allows the program to run to completion for a very simple test.

struct node* gins(struct node* a)
{
    struct node* p = a;
    char c;

    do
    {     
        printf("\n enter  vertex else a space\n");     
        scanf("%c", &c);         
        fflush(stdin);

        if (c != ' ')
        {
            p->next = malloc(sizeof(struct node));      
            p = p->next;
            p->name = c;
            p->next = NULL;
        }
    }
    while(c != ' ');

    return a;
}

Learn to do that yourself. It's very important, and I'm not going to do it for you a second time. You strike me as exceptionally lazy and helpless, and your presumptuous attitude about deserving freebies is irritating as well.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

The only problem I have with it is that confusing instant preview, makes me think I have double vision problems :)

I'm thinking that the live preview is good, but not when the editor has the same look and feel. I'm always clicking on the live preview to edit my posts instead of the editor. :P But Dani is against raw unhighlighted Markdown in the editor and a live preview with the end result, because that defeats the purpose of the editor we're using, which was chosen for its highlighting features in lieu of spell checking.

Why isn't it as wide as the posts in a thread?

Probably something to do with difficulties in dynamically resizing the editor to match the post div. I honestly don't know why it's that way, but we can certainly look into making the editor and live preview adjust according to your screen width.

True, but why is it only about 2-3 lines high to begin with? Why not 8-10 lines for example?

I'm not sure. There might be a user interface design reason, or maybe too large of a box was distracting if you didn't want to post, or too large of a box could have hidden the live preview such that it wasn't used. That's more of a Dani question since she's the gatekeeper for the UI design. ;)

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

When you display $num_result to the page, what's the value?

echo var_dump($num_result), '<br />';
deceptikon 1,790 Code Sniper Team Colleague Featured Poster

According to the documentation, the first parameter represents the previous result of the function. In the case of the first call, you'd seed it to "null":

unsigned long checksum = /* Saved checksum */
FILE* fp = fopen("file.txt", "r");

if (fp)
{
    unsigned long sum = adler32(0, 0, 0);
    char buf[BUFSIZ];

    while (fgets(buf, sizeof buf, fp))
    {
        sum = adler32(sum, buf, strlen(buf));
    }

    fclose(fp);

    if (sum != checksum)
    {
        panic("Invalid checksum");
    }
}
deceptikon 1,790 Code Sniper Team Colleague Featured Poster

Here's an example of serializing non-POD types:

#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>

#include <ctime>

using namespace std;

struct Info
{
    string description;
    int quantity;
    double wholesale_cost;
    double retail_cost;
    string date_added;

    Info() {}

    Info(string const& s) { deserialize(s); }

    string serialize() const
    {
        ostringstream oss;

        oss << description << '|' << quantity << '|' << wholesale_cost << '|' << retail_cost << '|' << date_added;

        return oss.str();
    }

    void deserialize(string const& s)
    {
        istringstream iss(s);

        // No error checking for brevity
        getline(iss, description, '|');
        iss >> quantity; iss.get();
        iss >> wholesale_cost; iss.get();
        iss >> retail_cost; iss.get();
        getline(iss, date_added);
    }
};

bool user_menu(string& option)
{
    cout << "1. Add Inventory\n2. View Inventory\n3. Load Inventory\n4. Save Inventory\n5. Quit\n> ";

    return getline(cin, option) && option.front() >= '1' && option.front() <= '4';
}

string now()
{
    // No error checking for brevity
    time_t t = time(0);
    tm* info = gmtime(&t);
    char buf[1024];

    strftime(buf, sizeof buf, "%Y-%m-%d", info);

    return string(buf);
}

int main()
{
    vector<Info> inventory;
    string option;

    while (user_menu(option))
    {
        switch (option.front())
        {
        case '1':
            {
                Info item;

                cout << "Description: "; getline(cin, item.description);
                cout << "Quantity: "; cin >> item.quantity;
                cout << "Wholesale Cost: "; cin >> item.wholesale_cost;
                cout << "Retail Cost: "; cin >> item.retail_cost;

                cin.get(); // Trim the newline

                item.date_added = now();

                inventory.push_back(item);

                break;
            }
        case '2':
            for (vector<Info>::size_type i = 0; i < inventory.size(); ++i)
            {
                cout << inventory[i].serialize() << '\n';
            }

            break;
        case '3':
            {
                ifstream in("test.txt");
                string line;

                if (in)
                {
                    while (getline(in, line)) …
deceptikon 1,790 Code Sniper Team Colleague Featured Poster

I'm not sure the first parameter is needed unless it refers to the modulus, but that's a fixed number, IIRC. What library are you using? Do you have the source code? If so, what does the body of that function look like?

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

The editor resizes as you edit your post. I've found that it's not perfect and you may end up scrolling a bit in some cases, but it does at least attempt grow and shrink to fit the content.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

You can post directly to the Software Development category if there's not a sub-category that fits your needs.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

void foo(string & s = "default");

Make it a const reference:

void foo(string const& s = "default");

It's really no different from just calling a function taking a reference with a string literal:

#include <string>

using namespace std;

void foo(string&) {}

int main()
{
    foo("test"); // Error, "test" is an rvalue
}
deceptikon 1,790 Code Sniper Team Colleague Featured Poster

alright now where would i put this?

Anywhere except the header. It's a definition, which means it can only be defined once.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

static const char *Error[];

This is only a declaration, you still need to define Error:

class Inventory
{
    static const char *Error[];

    ...
};

const char *Inventory::Error[100];

100 in this case is an arbitrary number, but since it's an array you need to pick something.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

You would need to push_back() each element after creating a new vector with push_back():

while (!done)
{
    // Somehow populate inputs with an unknown number of elements (23 or less)

    int n = /* Number of actual elements in inputs */

    data.push_back(vector<int>()); // Append a new vector

    // Populate the newly appended vector with the contents of inputs
    for (int i = 0; i < n; ++i)
    {
        data.back().push_back(inputs[i]);
    }
}