deceptikon 1,790 Code Sniper Team Colleague Featured Poster

&& is bitwise AND operator.

&& is the logical AND operator.

& is refrencing operator.

& is an overloaded operator in C, but in this case it's the bitwise AND operator.

& cannot be used instead of &&.

It can in some places, but you're limited by the type restriction of bitwise operators and the lack of short circuiting. It's strongly recommended that one not mix the two, lest one be surprised by the resulting behavior.

Performance doesn't enter the picture, especially when micromanaging performance at such a low level is the wrong place 9 times out of 10.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

Then use getchar instead of scanf to read each digit as a character. Much easier:

#include <ctype.h>
#include <stdio.h>

int main(void)
{
    int ch;

    while (isdigit(ch = getchar()))
    {
        switch (ch)
        {
        case '0': fputs("zero ", stdout); break;
        case '1': fputs("one ", stdout); break;
        case '2': fputs("two ", stdout); break;
        case '3': fputs("three ", stdout); break;
        case '4': fputs("four ", stdout); break;
        case '5': fputs("five ", stdout); break;
        case '6': fputs("six ", stdout); break;
        case '7': fputs("seven ", stdout); break;
        case '8': fputs("eight ", stdout); break;
        case '9': fputs("nine ", stdout); break;
        }
    }

    putchar('\n');

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

rundll32.exe is a Windows application that executes shared stuff from DLLs. It's totally legit, so no worries about malware, but if it regularly eats CPU like that while idle you may be looking at a poorly developed DLL that's eating more CPU than it should.

You can find out what DLL rundll32 is running by opening Task Manager, selecting the Processes tab, and making sure the Command Line column is visible. That column will show what argument rundll32 was given.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

So Now I have 2 infraction points. I don't see which rule i broke.

You've been here long enough to know we have a C forum and that C questions go in the C forum. I had to move this thread from Community Center, and thus felt justified in giving you an infraction for Keep It Organized.

If you read the PM that was sent automatically with my reason comment, you'd know this though.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

"better" requires creativity, originality and so on...

Only in situations where creativity, originality, and so on are required. "Better" is subjective, and it's prefectly reasonable to say that a code monkey can get "better" without being more creative or original.

when you are experienced you tend to avoid trials and go strait to results.

When you're experienced, your trials just become that much more complex. ;)

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

What are you passing as width and stop? So what values do argv[2] and argv[3] have? That's somewhat important in replicating your results. ;)

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

An exclusion scanset (the %[^ specifier) won't extract any of the excluded characters, so the stream still contains a comma after HuffOriginal is extracted. The simple answer is this:

sscanf(buffer, "%[^,],%[^\n]", HuffOriginal[i], HuffSymbol[i]);
billkas commented: Thanks! +0
deceptikon 1,790 Code Sniper Team Colleague Featured Poster

gcc -o test test.c from command line , i am compling with the old gcc compiler right ? so if the code has long long int in there , which isnt supported before c99 , shouldnt i get a compile time error ?

The default mode for gcc is -std=gnu89, which IIRC does include support for a form of long long.

i tried to compile from pelles 's command line using the cc /Ze test.c command i found in here, but it gave me a lot of errors .

Those are all from Kernel32.lib. Pelles C should just work right out of the box, so I'm not sure why you're getting those errors as they're an internal detail. Check your linker settings to ensure that all of the Win32 libraries are included.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

Barring the obvious issue of not properly handling the last span of characters unless they're exactly width length, I don't see any problems. I'd do a few things differently, but the way you're doing it is functional.

Can you provide a sample file as well as an invokation string so that we can see what you're seeing?

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

POLINK: error: Unresolved external symbol 'WinMain'.

You're trying to compile the project as a Windows application rather than a console application. Windows applications use a different entry point called WinMain. This is an easy one to fix, just change the appropriate setting for your project to build a console application.

somjit{} commented: thanks :) +3
deceptikon 1,790 Code Sniper Team Colleague Featured Poster

Honestly, I don't have any links anymore since it's all been internalized. However, I would be shocked if you couldn't find some good articles with the search engine of your preference. Alternatively, if you ask a specific question (ideally in a new thread) I can probably answer it. If not, I can do a good job faking an answer. ;)

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

You want some variant of getch(). However, note that raw input is not portable, so you'll be using something specific either to your compiler or operating system.

This may help, since I don't particularly feel like writing a raw input example for the umpteenth time. ;)

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

Each node is just an anonymous variable that the pointer points to. It seems like your confusion is more about self-referential structures than anything. So let's take a look at a simple linked list:

#include <iostream>

struct node {
    int data;
    node *next;

    node(int data, node *next = nullptr): data(data), next(next) {}
};

int main()
{
    node *head = nullptr;

    for (int i = 0; i < 5; i++) {
        head = new node(i, head);
    }

    for (node *x = head; x != nullptr; x = x->next)  {
        std::cout << x->data << '\n';
    }
}

Your question is about why all of those next pointers don't overwrite each other, but conceptually the list looks like this if you unroll the loop and name each anonymous variable:

#include <iostream>

struct node {
    int data;
    node *next;

    node(int data, node *next = nullptr): data(data), next(next) {}
};

int main()
{
    node *head = nullptr;
    node a{0}, b{1}, c{2}, d{3}, e{4};

    head = &e;
    e.next = &d;
    d.next = &c;
    c.next = &b;
    b.next = &a;

    for (node *x = head; x != nullptr; x = x->next)  {
        std::cout << x->data << '\n';
    }
}

Each pointer points to a unique entity in both cases, the first case simply hides that from you by using anonymous objects versus named variables.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

If I ever feel strongly enough about a downvote to give a reason, I make sure to provide a comment and it becomes negative rep.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

You need to decide whether you want to use C-style strings or C++ std::string. If you want a C-style string, it's called like this:

int main()
{
    char s[] = "apples";
    char a = 'p';
    char b = 'd';

    cout << "Before swap of Char : " << s << endl;
    substitute(s, a, b);
    cout << "After swap of Char : " << s << endl;
}
deceptikon 1,790 Code Sniper Team Colleague Featured Poster

it is my opinion, may be i am wrong in this

As far as Daniweb's rules go, RJ wasn't even close to breaking the Keep It Pleasant rule. If the moderators or long time members don't call someone on their behavior, chances are that it's acceptable within the community.

atleast we must filter these words when anyone try to write these words.

We do filter such things (so if it's not filtered, it's OK), and also have rules in place to deal with excessively bad behavior. If you feel someone is being excessively rude, report the post and let a moderator deal with it. If it's not worth reporting, the problem is on your end. I think you're being too sensitive, which could very well be the overall problem that prompted this thread in the first place. Grow some thicker skin, dude.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

Although possibly questionable ethically and technically, there is some mileage in the reasoning behind being the only one who understands your coding.

True, it's usually perceived as job security. However, I find that attitude so repulsive I'd be willing to fire an employee for it and give the new employee bonuses for the pain and suffering of figuring out or rewriting the obtuse code. A programmer that writes bad code as job security isn't the type I want to employ.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

how are they better at selling themselves ?

That's impossible to answer.

what does that exactly means ? :(

Google for "selling yourself". There are tons of resources, but ultimately it's about being likable and making yourself look like the person the interviewer wants.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

what the hell the problem is ?

They're better at selling themselves, and probably good at bullshitting too.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

it didn't get this line.. can you explain it ?

It was a somewhat joking way of saying that your expectations are too high, and there's no reason to be depressed about your results so far.

what to do ? :(

There's nothing you can do other than keep trying. Rejection is part and parcel of looking for a job. However, there's absolutely nothing wrong with reaching out to your contact at the company after a rejection and asking for advice on what you can do to improve your marketability.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

If one can write an algorithm that is significantly faster than a brute-force one, that is better.

Is it? What if the brute force algorithm was fast enough already? What if the faster algorithm is so godawful complicated that the original author barely understood it and left the company? One of the first things I try to teach college grads is cost benefit analysis for code. It may be cool, or theoretically superior, but if the cost exceeds the benefit, it's an inferior solution.

But all my peers and companies that recruit interns look for people who can write algorithms that are fast.

Obviously you shouldn't intentionally write slow code, but fast has a price, and if an employer doesn't understand that, they're not worth working for.

I just fail to see the wonderful patterns that arise out of the better(faster) algorithms.

Studying algorithm and data structure design would be a good start. Without a strong foundation in the theory, I'm not sure you'd suddenly start seeing those wonderful patterns just because you're under a time or resource crunch.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

Define "better". Do you want to win contests or be a good programmer in general? Do you want to write professional quality code or code that just solves the problem as quickly as possible, and maintainability be damned?

That's the difference between competition and software development. Most of the time, code that should be in contests would miserably fail a code review. Likewise, good production code will general lose a contest consistently.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

i have got 3 rejections yet in directi (second-last round), AMZON(last round) and facebook (first round). how to make myself confident ?

Here's a bit of perspective: I wouldn't be surprised if Amazon or Facebook rejected me (and I'm not familiar with Directi). Since you seem to hold me in some regard, what does that say about your expectations? ;)

first of all: get realistic. 3 rejections are about equal to nothing. most sollicitants these days get dozens, or some even hundreds of rejections before actually finding a job, welcome to modern day economics, I'm afraid.

And that's with the folks who have experience. A newbie fresh out of school is a big risk, so you're more likely to get rejected.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

What about it?

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

Order of operations, my friend. (int*)a + 1 converts a to a pointer to int, then increments it as a pointer to int. What you wanted, according to your expected output, was to increment a first, then convert to a pointer to int:

static int *p[] = {(int*)a, (int*)(a + 1), (int*)(a + 2)};

Notice the parentheses around a + 1 and a + 2.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

Check your errors. For example, whenever opening a file fopen() returns NULL on failure:

FILE *f=fopen(file,"w");

if (f == NULL) {
    perror("Error opening output file");

    /* Whatever exit or recovery strategy you choose here */
    exit(EXIT_FAILURE);
}

If nothing else you may get more useful information in the way of first knowing that fopen() failed and also what the exact error was.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

How can I do that?

You could actually read this thread instead of guessing at what people are saying. I posted how to do it with std::string.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

How can I do it with sprintf()? Before I posted here, I scoured the internet all over, and all the explanations for sprintf were to complicated. I couldn't understand.

If AD's example above was too complicated, I'm not sure what to tell you, because that's as simple as it gets. For your specific needs:

double n = 1.23456;
char s[10];

sprintf(s, "%.2f", n);

In C++ there are many more options, but I suspect those will confuse you as well. The usual solution involves stringstreams:

double n = 1.23456;
ostringstream oss;

oss.precision(2);
oss << fixed << n;

string s = oss.str();
deceptikon 1,790 Code Sniper Team Colleague Featured Poster

My guess is that you shouldn't use delete to deallocate the string's memory which was allocated with strdup (which is not a standard function, btw).

Good catch, I totally brain farted on that one. ;)

why did you use const?

Why not? Defaulting to const is safer, and in this case there's no reason to have write access to the object being copied.

what's up with the double reference?

That's an rvalue reference from C++11.

How are they enabled using "= delete" ?

I don't understand the question. Using the C++11 =delete syntax tells the compiler not to provide implicit implementations of the member function. In the case of a copy constructor, if you don't write one explicitly, one is provided for you with a shallow copy. Since you don't want a shallow copy, the two options are to write a copy constructor or disable copy construction.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

i was solving a problem which didn't have specification to create them

If it's a school assignment then you don't need to go out of your way, just be aware of the issues. In real code, I'd prefer in most cases where shallow copy is a problem to either implement all of those member functions, or implement a subset of them and disable the rest. For example if you didn't want your class to be copyable, movable, or assignable:

class CObject
{
    char *mName;
public:
    CObject(char *name) : mName(strdup(name)) {}
    CObject(const CObject& rhs) = delete;
    CObject(CObject&& rhs) = delete;
    ~CObject() { delete[] mName; }

    CObject& operator=(const CObject& rhs) = delete;
    CObject& operator=(CObject&& rhs) = delete;

    const char *Name() const { return mName; }
};

The workaround to such behavior prior to C++11 was to make the member functions in question private:

class CObject
{
    char *mName;
public:
    CObject(char *name) : mName(strdup(name)) {}
    ~CObject() { delete[] mName; }

    const char *Name() const { return mName; }
private:
    // Noncopyable. Move semantics were added with C++11, so not necessary to deal with here
    CObject(const CObject& rhs) {}
    CObject& operator=(const CObject& rhs) {}
};
deceptikon 1,790 Code Sniper Team Colleague Featured Poster

I tried this, but i get debug assertion failed. From what i've read, it's because my object are destructed for a multiple number of times.

If you're calling the destructor multiple times, something is very wrong with how you're using the class. Perhaps you're trying to delete the object pointer twice?

std::string is STL? because we are not allowed to use it.

Technically std::string isn't a part of the STL, but it is part of the extensive standard library of which the STL is a subset. If you aren't allowed to use "the STL", std::string is very likely to be implied in that restriction.

@deceptikon, why do i have to implement a copy constructor and to overload the assignement operator when creating a destructor?

Because if you use the default copy constructor and assignment operator, you'll have two objects that refer to the same block of memory. This is a very risky situation that would end up in trying to delete the pointer multiple times (on the destructor call of each object).

This is the rule of 3 (and more recently the rule of 5) intended to handle the management of resources owned by a class as safely and completely as possible.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

why is mName char* instead of std::string?

From previous threads, I can safely conclude that the OP isn't allowed to use such convenient classes yet.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

Also keep in mind that if you need a destructor, you probably also need a copy constructor and copy assignment operator (and possibly a move constructor and move assignment operator for C++11). I'd also avoid a protected data member in favor of a private data member and public const getter. That way CObject absolutely controls mName, and can make assumptions about its integrity (ie. assuming that it's always safe to delete the pointer). For example:

class CObject
{
    char *mName;
public:
    CObject(char *name) : mName(strdup(name)) {}
    CObject(const CObject& rhs) : mName(strdup(rhs.mName)) {}
    CObject(CObject&& rhs) : mName(rhs.mName) { rhs.mName = nullptr;  }
    ~CObject() { delete[] mName; }

    CObject& operator=(const CObject& rhs)
    {
        if (&rhs != this)
        {
            mName = strdup(rhs.mName);
        }
    }

    CObject& operator=(CObject&& rhs)
    {
        mName = rhs.mName;
        rhs.mName = nullptr;
    }

    const char *Name() const { return mName; }
};
deceptikon 1,790 Code Sniper Team Colleague Featured Poster

This would be a short version of my code:

You created CLibrary using the default constructor. mA is a null pointer.

@deceptikon
You may want to read an intro level tutorial to CPP
http://www.learncpp.com/cpp-tutorial/121-pointers-and-references-to-the-base-class-of-derived-objects/

Good. Now go to the next chapter and read about virtual functions, genius. I'd also appreciate if you reversed your negative rep on me when you eventually realize I'm right.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

You must be high, at run-time the container object won't know which object is a derived type (versus being a base type) unless he defines the type within the class and casts the base class pointer to the derived class pointer.

The OP is storing pointers to a base class, not objects of the base class. Read up on how polymorphism and dynamic binding work in C++ and then look at my code again, because you're clearly confused.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

@deceptikon
Your solution is wrong.
In your solution, when he calls print() it will treat all of the pointers as articles no matter what they are.

You might want to educate yourself a bit more before trying to correct people who actually know what they're talking about.

I also tried this, using an overloaded assignement operator defined for each one of the classes CArticle,CBook,CMagazine, but it breaks somewhere.

The overloaded assignment operator is irrelevant here because you're working with pointers at the container level. Please post a small but complete program that exhibits your problem and I'll see if I can locate the error.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

Is there any reason why the Controller can't own the objects and then dole out references to them on request? Since you're storing pointers, and from the previous discussion, I'm assuming the objects aren't owned by the Controller, just loosely contained. Is that the case?

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

I would add one change to the structures/classes/members shown by decepticon, and that is to use a std::vector<CArticle> for the _articles member in the CLibrary class.

I would too, but given that the description of the actual classes suggests a dynamic array of pointers, I matched my example to that.

Also, it is STRONGLY recommended by standards to NOT use leading underscores for local/class/static variables as that is reserved for internal use by system libraries, etc.

Identifiers starting with two underscores or an underscore followed by an upper case letter are always reserved, period. An identifier starting with an underscore followed by a digit or a lower case letter is not reserved except in the global namespace. My data member names are perfectly legal and conforming.

However, with that said, it couldn't hurt to always avoid leading underscores as a general best practice. The only reason I do it is because I'm confident in my understanding of the rules and restrictions.

In decepticon's example, you would have to resize it manually in your addArticle() method if the size of the array has reached its previous limit.

Once again, my example wasn't intended to be a full solution. I assumed that the OP's classes were already otherwise feature complete since he didn't ask about anything except adding polymorphic items in the interface.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

I see that a lot of people are already familiar with C++11 to the point that they don't think about it when they use its features. Is it now considered 'best practice' to use the new features?

Best practice depends on your needs. If you don't need to conform to legacy code or tools, then I'd say go for it. Otherwise, you really have no choice but to follow the supported standard. Note though, that C++11 isn't likely to go the way of C99. There's a huge demand for it (and also C++14 already) as well as a huge push to get conforming implementations shipped. It won't be long before most of the new example code out there is dependent on at least C++11.

Those Turbo C++ folks will just have to suffer and learn how to convert C++11 to pre-standard C++.

I am mainly concerned due to the lack of universal support for it and the fact that some C++ programmers have yet to learn the changes so I fear that C++11 code may not be understood.

Universal support is close enough at this point, with the majority of the major features supported by all popular compilers and the rest on the horizon. As far as not understanding code because one hasn't learned the changes...now is a good time to start. ;)

Is there some macro that can tell you if C++11 is supported (so that you can make a header work in C++03, …

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

I can't figure out what type of parameter should my addArticle() function have in order to work for this main. I would like to let the compiler choose if the object passed is a CBook or a CMagazine. Is that possible?

Perhaps I'm missing something, but if you want polymorphism, you should use polymorphism rather than trying something tricky and dangerous:

#include <iostream>

class CArticle {
public:
    virtual void print() const = 0;
};

class CBook: public CArticle {
    int _x;
public:
    CBook(int x) : _x(x) {}

    virtual void print() const override
    {
        std::cout << "CBook: " << _x << '\n';
    }
};

class CMagazine: public CArticle {
    int _x;
    int _y;
public:
    CMagazine(int x, int y) : _x(x), _y(y) {}

    virtual void print() const override
    {
        std::cout << "CMagazine: " << _x << ' ' << _y << '\n';
    }
};

class CLibrary {
    CArticle **_articles;
    int _size;
public:
    CLibrary() : _articles(new CArticle*[10]), _size(0) {}

    ~CLibrary()
    {
        delete[] _articles;
    }

    void addArticle(CArticle *article)
    {
        _articles[_size++] = article;
    }

    void print() const
    {
        for (int i = 0; i < _size; i++) {
            _articles[i]->print();
        }
    }
};

int main()
{
    CLibrary L1;
    CArticle *A1 = new CBook(1000);
    CArticle *A2 = new CBook(1001);
    CArticle *A3 = new CMagazine(1002, 3);
    CArticle *A4 = new CMagazine(1003, 6);
    CArticle *A5 = new CMagazine(1004, 8);

    L1.addArticle(A1);
    L1.addArticle(A2);
    L1.addArticle(A3);
    L1.addArticle(A4);
    L1.addArticle(A5);

    L1.print();
}
deceptikon 1,790 Code Sniper Team Colleague Featured Poster

Option 1 would be preferred in this case. In option 2 you're allocating a whole new data structure to hold the filtered results and also iterating the original list in its entirety once followed by the filtered results once.

In option 1 you have what essentially boils down to a lazy evaluated yielding iterator. So it doesn't allocate any new data structures and only traverses the original list once (filtering out items that fail your predicate as it goes).

I'd expect option 1 to be faster as well as less wasteful of resources. But the compiler may optimize things such that the resulting difference is negligible.

ddanbe commented: Great! +14
deceptikon 1,790 Code Sniper Team Colleague Featured Poster

There's a way to systematically convert a recursive algorithm to an iterative one, but unless you're dealing strictly with tail recursion, some form of stack data structure is still required. Do your contest requirements exclude the high probability of virtual memory on the machine being sufficient to contribute to the definition of "infinite"?

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

What problem are you having such that you need help? Simply saying "Any help is appreciated" is very broad. For example, I'd do something completely different; does throwing away your code and starting over constitute "help"?

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

Besides, it is not part of the standard and your code might not work with other compliers. Before each scanf(), put fflush(STDIN); to make sure the input stream is empty.

Um...I hate to break it to you, but 1) C++ is case sensitive and STDIN is not a valid alias for stdin, and 2) fflush() isn't defined for input streams. So in one sentence you attacked non-standard code and then in the next sentence advocated non-standard code. ;)

Another thing to do is check the return value of scanf() which will tell you how many good values were read. If it does not match the number of variables that you were expecting, something went wrong; probably the user entered bad data.

Failure to check the return value of scanf() is probably one of the most common problems I see in beginner code.

David W commented: no need to be bashful ... it all needed to be corrected +0
deceptikon 1,790 Code Sniper Team Colleague Featured Poster

I thought that any change in pointer was reflected in main().

You can pass a reference to achieve that behavior.

Is same behaviour expected in C?

Yes.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

how it is used and why we use it

In theory you would use it just like char, and the purpose is to support extended character sets. The char type for character usage was really designed and intended for character sets (and language alphabets) that can fit into a single byte, such as ASCII or EBCDIC.

In practice, conforming to larger character sets such as Unicode means you're targeting internationalization as a goal, which is quite a bit more complex than just swapping char for wchar_t. Even when you stick to a single locale, conversion between char and wchar_t is often necessary.

And also what is the difference between char and wchar_t.

char is guaranteed to be a single byte. wchar_t is a typedef for one of the integer types, and it may be multiple bytes so that it can represent any value in a large character set. You can't assume any specific size for wchar_t.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

Consider this simple example of clearing the input line on an invalid conversion:

#include <ios>
#include <iostream>
#include <limits>

using namespace std;

int main()
{
    int num;

    while (true)
    {
        cout << "Enter a number: ";

        if (cin >> num)
        {
            break;
        }

        cerr << "Invalid input\n";

        // Clear the stream state so we can read again
        cin.clear();

        // Extract everything remaining on the line
        cin.ignore(numeric_limits<streamsize>::max(), '\n');
    }

    cout << "You entered " << num << '\n';
}

When a conversion by the >> operator fails, it puts cin into an error state where it won't read anymore data. Also, the bad data is left on the stream. So you need to clear the error state and then discard the bad data before trying again.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

I am guessing however that the pointer in the while loop is always pointing to string data, until it
iterates on the final drive, and hits another \0 character, which causes the while test to be false.

Good guess. However, there's a bit of a trick here because the pointer you're using points to potentially multiple strings pasted next to each other. For example, the string might be: "C:\0D:\0E:\0\0". So what happens is the body of the loop will use strlen() + 1 to push the pointer over the first null character. When it reaches the extra null character at the end, the loop stops for the reason you guessed. But it won't stop on the previous null characters because of stepping the pointer by strlen() + 1 characters.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

Whew, a lot of questions. ;) I'll answer them, but before doing that I'll strongly recommend that you consider memory mapping your files if you go the route of file lists. That way you only need to manage the organization of the files themselves as well as the memory maps, and after that your code can just pretend to be working with really large arrays. So the meat of your code that exists now won't need to be modified much, if at all.

My first question then is: is it okay to keep the file open and still use it as large storage?

Yes, but keep in mind that there's a limit to the number of files you can have open at one time. Usually both a system and a stream library limit will be imposed and they may or may not match. In the C stdio library, the limit is defined in the FOPEN_MAX macro.

is there any way to NOT have to re-open those files every time I need them?

You need some sort of way to access the files, whether it be keeping them open or re-opening them.

is there any way to get the file name out of a FILE structure in stdio.

Not portably, no. You'll need to maintain a map of the file with its path.

fstream IS an option, except that I definately need speed and as far as I know I can get more of …

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

There are good tutorials out there if you search for them. I started writing a cryptography library a couple of years ago and abandoned it, so all of my supplementary bookmarks and references are gone, unfortunately. However, I can at least offer you a basic implementation. :)

I wrote it using the standard definition, and the test driver uses the test cases from that document. It's as simple as I could make it while maintaining core functionality, but please do keep in mind that this isn't a finished project, just a work in progress. As such the comments are lacking and the design is a first draft.

Here's the test driver:

#include <iostream>
#include <iomanip>
#include <string>
#include <vector>
#include "aes_provider.h"

using namespace encryption;
using namespace std;

#define length(a) (sizeof (a) / sizeof *(a))

void display_bytes(const std::string& message, vector<unsigned char> output)
{
    cout << message;

    for (vector<unsigned char>::size_type i = 0; i < output.size(); i++)
        cout<< setw(3) << hex << left << (unsigned)output[i];

    cout <<'\n';
}

int main()
{
    unsigned char key_init[] = {
        // 128-bit key
        /*
        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
        0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
        */
        // 192-bit key
        /*
        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 
        0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17
        */
        // 256-bit key
        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
        0x10, 0x11, 0x12, 0x13, …