Tom Gunn 1,164 Practically a Master Poster

However, my integer to hex function gets stuck in an infinite loop and I have no clue why.

You never change the value of number inside the loop. The algorithm should be dividing it by 16 and storing the result, right? Also, 0 and '0' are two completely different values. Be sure to double check whether you are working in a string context or a numeric context and use the right constants.

n = number;

This will probably give you problems as well. The expression should be the other way around because number is the variable you are trying to initialize.

Tom Gunn 1,164 Practically a Master Poster

If the array is the last one in the struct, you are probably seeing the struct hack. Prior to C99 it is an unportable trick for allocating arrays in a struct:

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

typedef struct
{
    char s[1];
} String;

int main()
{
    /* allocate 15 extra bytes for the string */
    String *s = malloc(sizeof *s + 15);

    strcpy(s->s, "test string");
    puts(s->s);
    free(s);

    return 0;
}

The idea is that by tacking on extra memory and accessing it by overflowing the last array member, you can save an extra call to malloc:

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

typedef struct
{
    char *s;
} String;

int main()
{
    String *s = malloc(sizeof *s);

    s->s = malloc(15);
    strcpy(s->s, "test string");
    puts(s->s);
    free(s->s);
    free(s);

    return 0;
}

C99 makes the struct hack a legal feature of the language, but I do not think it is a good idea even then because it makes the code less clear. ;)

ashok.g15 commented: Thanks for the reply . Now I got the answer. +0
Tom Gunn 1,164 Practically a Master Poster

then it would be like if-else if internally.

but here it is given as it uses jump tables

I think compilers commonly use jump tables for a tight range of cases and compares for wider ranges. This switch would probably use a jump table:

switch (condition)
{
    case 0:
        //...
        break;
    case 1:
        //...
        break;
    case 2:
        //...
        break;
    case 3:
        //...
        break;
    case 4:
        //...
        break;
    case 5:
        //...
        break;
}

But this switch would probably use compares and be close to the same result as the equivalent if statement because a jump table would be too big and too sparse:

switch (condition)
{
    case 0:
        //...
        break;
    case 10000:
        //...
        break;
    case 5000:
        //...
        break;
    case 40:
        //...
        break;
    case 900:
        //...
        break;
    case 123456:
        //...
        break;
}

I have heard about compilers using a jump table and binary search for switches that have a large number of cases and the range is wide.

then what is the advantage of using switch

If a switch is more intuitive then it makes the code clearer. Compilers are good at optimization, so you should not worry about which statement is more efficient and write code that is easy to read. The biggest performance changes come from whole algorithms anyway.

Tom Gunn 1,164 Practically a Master Poster

1. Concept of Late binding can be acheived by Function pointers or indirect calls - This is due to the fact that compiler cannot simply substitute the address of the function when it encounters a function pointer, instead it needs to dereference it at a later stage.

That is my understanding too.

2. But in case of c++ compiler will associate a VPTR which points to a VTable while declaring a class when it encounters a virtual function.

Yes. The C++ compiler can generate and assign vtable addresses at compile time, but in C I did it manually for the vtable implementation and picking the vtable for new objects. The virtual method implementation was meant to show that even in C++ there is nothing special about methods. Internally they will probably be nothing more than regular functions with a special naming scheme that ties them to the class, like __Base_void_ToString_void corresponding to void Base::ToString() . If it is a virtual function, instead of using an inline definition, it just makes a call into the vtable using the index of the actual method definition.

My virtual method definition is the end result after an imaginary C++ compilation phase. Think of the original as this:

struct Base
{
    int _x;

    virtual void ToString()
    {
        //...
    }
};

First the method is hoisted out of the struct and made a traditional function with the mangled name and taking this as the first argument:

struct Base
{
    int _x;
}; …
Tom Gunn 1,164 Practically a Master Poster

Anyone who has a good understanding of operating systems in addition to Windows, generally won't use Windows. Oh, they may repair it for other people, but they won't use it for themselves, except possibly for gaming.

Can you prove this without any weasel tricks like claiming that anyone who prefers Windows is ignorant? ;)

And no, it's not only hobbyists who "can afford to be extreme" about such things. Business owners like myself

So we're talking about business owners now and not IT professionals? My comment was about people who are forced to follow the rules of a client or employer, not people who make their own rules. If you have the option to choose your favorite tool, more power to you. Most of us are not so lucky.

So when you put things into their proper perspective, Unix, being the older operating system, should have a lot more problems.

Predictably, you missed the point and tried to twist it into a straw man for your Windows bashing. :)

Intolerant? Everything I've said has been accurate. If being right is intolerance, I hadn't heard that.

Yes, intolerant. You cannot be right about an opinion, because opinions are subjective. In your opinion Microsoft products are garbage, and you have a few bullet points that justify your opinion. Not respecting different opinions, like those of the people who prefer Windows, is intolerant.

William Hemsworth commented: excellent responce +0
jasimp commented: Beautiful post +0
Tom Gunn 1,164 Practically a Master Poster

Here is a simple example of one way to implement vtables in C:

#include <stdio.h>

/* class definitions */
typedef struct Base
{
    void (**vtable)();
    int _x;
} Base;

typedef struct Child
{
    void (**vtable)();
/* begin base class slice */
    int _x;
/* end base class slice */
    int _y;
} Child;

/* class method implementations */
void Base_ToString(Base const* obj) { printf("Base: (%d)\n", obj->_x); }
void Child_ToString(Child const* obj) { printf("Base: (%d,%d)\n", obj->_x, obj->_y); }

/* vtable implementation */
enum { Call_ToString };
void (*Base_Vtable[])() = { &Base_ToString };
void (*Child_Vtable[])() = { &Child_ToString };

/* virtual method implementation */
void ToString(Base const* obj)
{
    obj->vtable[Call_ToString](obj);
}

int main()
{
    /* pick the vtable for objects at compile time */
    Base base = {Base_Vtable, 123};
    Child child = {Child_Vtable, 456, 789};

    Base* a = &base;
    Base* b = (Base*)&child;

    /* call the virtual methods */
    ToString(a);
    ToString(b);
}

I did not include any code for handling multiple inheritance. That is harder to do. The implementation does not matter as long as the end result is the effect of late binding. Even vtables are not required, but it is a common implementation in C++ compilers.

Note: This example is not completely portable, but neither is a compiler. ;)

Tom Gunn 1,164 Practically a Master Poster

In my book book there is a similar kind of problem where it's mentioned that the input value should be less than 32767.

The range of signed int is only assured to be at least[-32,767..+32,767]. If you want your code to be maximally portable, do not assume anything outside that range, or use signed long instead, where the range is assured to be at least [-2,147,483,647..+2,147,483,647].

and the second thing is if i choose any number less than 32767, still i'm not geting the answer.

I get the right answer when I run this program, but the last printf() does not print a line break character, so my guess would be that this is your problem. If you do not print a line break, the output stream might not be flushed before the call to getch(), and you will not see the output. Replace that printf() call with this one and see if it fixes the problem:

printf("The desired value is:%d\n", total);
Tom Gunn 1,164 Practically a Master Poster

Well, real geeks don't run Windows. Real geeks don't run any Microsoft products, because we understand enough about operating systems and application programs, to know that Microsoft products are total, absolute, pieces of garbage.

I guess you can tweak your definition of 'geek' to mean what you want, but in my opinion a real geek would not limit his options by making generalizations. There are Microsoft products that are garbage, but there are also Microsoft products that are very good. The only company I know of that has been completely successful with every production so far is Pixar. ;)

Many of us 'geeks' are IT professionals, and banning Microsoft products would put us on the fast track to being out of work. Only hobbyists can afford to be extremist about these kind of things.

Even Microsoft admits that Windows was not designed to be secure.

Windows was also designed in the mid 1980s, when OS security was not exactly the buzzword that it is now. Couple that bad decision with the good decision of maintaining extensive backward compatibility and it is easy to see the dilemma of securing Windows without breaking functionality. I am not defending the insecurity, just putting things in perspective.

Maybe Windows 7 will be their successful attempt to hit that mark. I have not tried it yet, but soon my PC will be upgraded at work and I will also move to Windows 7.

I could continue - but you should have …

tux4life commented: First post in this thread which makes sense. +0
Tom Gunn 1,164 Practically a Master Poster
if first % 2 == 0;

Your syntax is close. Do not forget the parentheses, and lose the semicolon:

if (first % 2 == 0)
Tom Gunn 1,164 Practically a Master Poster

Please post your code and the errors.

Tom Gunn 1,164 Practically a Master Poster

I have problems understanding the code quickly whenever I need to go back to it after some time.

That is normal, and it is why code should be written as simply as possible without sacrificing functionality, and why comments that describe why you wrote something the way you did are critically important.

I started about a month ago , without planning much , and now I am struggling to understand the logic.

You should plan enough to understand how the application is supposed to work. The details can be ironed out during development, but the overall vision should not change much. Planning is even important for conversions because the target language might have better ways of designing the code. The result will probably be completely different from the original even though they both do the same thing. A straight line by line conversion of VB6 to C# is not a good idea, if you get my drift. ;)

Today I had a talk with a user and things cleared up much more .

I always make sure that clients are involved in the development process from start to finish, both to keep myself informed about their needs and to keep them informed about what I am doing. That way things do not get too far off track and everybody understands the vision of the final product.

I don't feel confident in my programming abilities because I can't predict when I'll finish a project .

Nobody can predict …

majestic0110 commented: Good answer! +6
Tom Gunn 1,164 Practically a Master Poster

it was what I did when I first learned about recursion

Yes, me too. Those examples are fine for learning how recursion works, but not for how it can be best used in real code. I think that is what the question was about, and that is why I replied the way I did.

I also wrote a function involving the fibonacci number sequence.

The best thing I learned from a recursive Fibonacci generator is how seemingly innocent code can be criminally inefficient. ;)

Grn Xtrm commented: Your 100% right :) +1
Tom Gunn 1,164 Practically a Master Poster

The seed for each thread is independent. You need to call srand() in the Draw() function to reseed for each thread.

hmortensen commented: Simple and accurate, information. :) +1
Tom Gunn 1,164 Practically a Master Poster

This is how i call the function:

char * answer= cString('e',"Hello");

That is your problem then. :) String constants are read only. Trying to modify one through a pointer to non-const char will likely throw an access violation. If you plan to pass string constants to a function, it is best to make those pointers point to const data:

char const* cString (char letter, char const* string)

And if the function is designed to modify one of the strings passed, make sure it is not pointing to const data, and be careful to make copies of string constants first:

char * cString (char letter, char * string)
char source[] = "Hello";
char * answer= cString('e', source);
KonkaNok commented: nice solve ;) +1
Tom Gunn 1,164 Practically a Master Poster

(which will ensure a cast to an unsigned long, the biggest unsigned integral type)

Unless size_t is unsigned long or integral promotion makes it an unsigned long, the only thing you ensure is undefined behavior because the type of the value and the type of the format string do not match. The convention is to use an explicit cast:

printf("%lu\n", (unsigned long)sizeof(something));

to make sure that the size will always be displayed correctly on the screen.

If you are lucky. size_t is only guaranteed to be unsigned. It might be an extended type, where there is risk of the value being truncated by casting to unsigned long. The ideal solution is C99's %z modifier:

printf("%zu\n", sizeof(something));

But for C89 compilers the best we can do is cast to the largest possible unsigned type that printf() supports and hope for the best. :)

tux4life commented: Thanks for the very useful addition :) +23
Tom Gunn 1,164 Practically a Master Poster

1) Using the getchar() function, you need to flush the input buffer to get rid of the newline character

As a corollary, fflush(stdin) is not the way to flush the input buffer because fflush() is only defined to work on output buffers. A portable way to flush is getchar() in a loop:

while (getchar() != '\n')
{
    /* no work to do */
}

If EOF is possible, add that to the condition:

{
    int c;

    while ((c = getchar()) != '\n' && c != EOF)
    {
        /* no work to do */
    }
}

The only problem with this loop strategy is when the buffer is empty, the loop will block until some characters are buffered. The end user will have to type an extra [Enter] before getting past the loop, and that can be surprising. I like to fix it by dipping into the stream internals, but that is not a portable fix. Use it with caution:

#if defined(_MSC_VER)
/* Visual C and derivatives */
#define FLUSH_STDIN() stdin->_cnt = 0;
#else
#define FLUSH_STDIN() while (getchar() != '\n')
#endif

2) In your original code posting, you used void main() - this is bad, very bad.

I have only seen one OS mentioned that fails when void main() is used, and both compilers in that article warn about it. Not recommended, definitely. void main() is not portable and technically undefined when the compiler does not support it, so it should be avoided on all hosted …

kvprajapati commented: Thanks Tom to share your knowledge. Good suggestion but I still recomend int main() +17
tux4life commented: I still prefer to use the standard about the return type of main, but you're right about the void main() :) +23
Tom Gunn 1,164 Practically a Master Poster

but i dont understand how can we ensure a binary tree is strict just by checking only root and its children .

That was my mistake. I posted an incomplete example. That function is supposed to be recursive. I will try again:

int IsStrictRoot(struct node* root)
{
    return !((root->left && root->left->dat >= root->dat) ||
             (root->right && root->right->dat <= root->dat));
}

int IsStrictBst(struct node* root)
{
    if (root)
    {
        return IsStrictBst(root->left) && 
               IsStrictBst(root->right) && 
               IsStrictRoot(root);
    }
    else return 1;
}

The rule for a strict binary search tree is that the left node has a smaller value than the root and the right node has a larger value than the root. That is assuming no duplicate values are allowed in the tree. The comparison can be changed to support that duplicates easily. :)

for the tree to be strict does it must be a BST?

For a tree to be strict you need to define what strict is. A BST has a node order requirement, but if you have a binary tree that is not a BST, there has to be some ordering that makes it strict, or the design of the tree allows more than one child node and you want to allow only up to two at run time.

but you checked it reverse.

It is a reverse test for failure. Here is the truth table for that comparison:

I = Invalid
V = Valid
* = NULL

   | * | V | I | …
tux4life commented: Is there maybe something you don't know? :P +22
Tom Gunn 1,164 Practically a Master Poster

Good start! C is different in a few ways though. Declarations need to be the first thing in a block unless you are compiling under C99, so your C code will not compile with most compilers.

printf("N %2.2f, factorial %2.2f \n" ,i,factorial(i));

You need to be very careful with printf() and scanf() format strings because mixing up types can give weird results. In this one, the first modifier should be %d, not %2.2f, because i is an int.

char wait;
printf("Enter to exit");
scanf(&wait);

scanf() is just like printf() in that it requires a format string. Your code will compile because &wait is the right type, but anything could happen because &wait does not point to a string. The whole thing should look like this:

/* unnamed block so wait can be declared */
{
    char wait;

    printf("Enter to exit");

    /* flush the stream if you do not print '\n' */
    fflush(stdout);
    scanf("%c", &wait);
}

But in both your C and C++ code, that whole wait thing is more verbose than it needs to be. In C++ you can do cin.get(); and in C you can do getchar(); for the same effect as a char variable and operator>> or scanf().

Using the same style, I would write the code like this:

#include <stdio.h>

double factorial(int n);

int main()
{
    int i;

    printf("N          Factorial\n");
    printf("--------------------\n");

    for(i = 15; i > 0; --i)
    {
        printf("%-11d%.2f\n", i, factorial(i));
    }

    printf("Enter to exit");
    fflush(stdout);
    getchar();

    return 0;
}

double …
Grn Xtrm commented: Thanks for the help +1
Tom Gunn 1,164 Practically a Master Poster

return *nodePtr->data;

Unless data is a pointer to a pointer, this either returns data or throws an indirection error. To get the address of an object you use the & operator:

return &nodePtr->data;
mrnutty commented: Always get there before others, huh? +4
Tom Gunn 1,164 Practically a Master Poster

This is an example of how to turn numbers into words. 1473 would get translated to "one thousand four hundred seventy three", for example. The class has a simple interface and can handle any value representable by unsigned int. The implementation recursively processes groups of 3 digits using table lookups for the word strings.

Note to cheaters: The code was written so that a teacher can tell if you try to steal it and turn it in for a homework grade.

tux4life commented: Incredibly nice! +21
Nick Evan commented: That's just awesome. Took a while to figure out ;) +31
amrith92 commented: Must've taken some thought!! I like it :) +2
Tom Gunn 1,164 Practically a Master Poster

Dave Sinkula's idea is good, but I think it is easier to see what goes on by printing the intermediate results too, but in binary instead of hex:

#include <iostream>
#include <limits>
#include <bitset>

int main()
{
    using namespace std;

    //int tmp = 0xff000000 | ((int)(val) << 16 | (int)(val ) << 8 | (int)(val));

    // breaking the expression down into component parts
    unsigned char val = 0xA5;
    unsigned tmp = 0xff000000;
    unsigned shift1 = (unsigned)(val);
    unsigned shift2 = (unsigned)(val) << 8;
    unsigned shift3 = (unsigned)(val) << 16;
    unsigned paste1 = (shift3 | shift2 | shift1);
    unsigned paste2 = tmp | paste1;

    cout << bitset<numeric_limits<unsigned>::digits>(tmp) << '\n'
         << bitset<numeric_limits<unsigned>::digits>(shift1) << '\n'
         << bitset<numeric_limits<unsigned>::digits>(shift2) << '\n'
         << bitset<numeric_limits<unsigned>::digits>(shift3) << '\n'
         << bitset<numeric_limits<unsigned>::digits>(paste1) << '\n'
         << bitset<numeric_limits<unsigned>::digits>(paste2) << '\n';
}
Dave Sinkula commented: Danke. +28
Tom Gunn 1,164 Practically a Master Poster

Seems a good text, but I wonder about the choice of using main() as opposed to int main() ?

C++ evolved from C89, and C89 supports a feature called implicit int. If the type is not explicitly stated, int is assumed. These two definitions were the same in C89:

main()
{
    return 0;
}
int main()
{
    return 0;
}

C99 and standard C++ removed that feature, so newer compilers are starting to disallow it completely.

Whats the deal? Why would the author recommend that?

C++ went for a long time before it was standardized. A lot of compilers and books were written before implicit int was removed. Your book was probably written before 1998. That is the risk of using newer compilers with code from older books, but it helps you learn to manage legacy code. :D

Tom Gunn 1,164 Practically a Master Poster

but what if I want the hexadecimal 199 to be displayed in binary?

printf() does not have a conversion to binary. The C++ library has a bitset<> class that will indirectly do it for you, but you need to use cout to print directly, or manually convert to a string for printf():

#include <iostream>
#include <limits>
#include <bitset>

int main()
{
    std::cout << std::bitset<std::numeric_limits<int>::digits>(0x199) << '\n';
}

The other alternative is manually converting the number to a binary string. If you search this forum you can find tons of threads about how to do it that way.

kvprajapati commented: I appreciate your knowledge. +13
tux4life commented: Great post, keep up the good work Tommy ! :) +21
Tom Gunn 1,164 Practically a Master Poster

The forum is buzzing with questions about tokenizing a C++ string. This is a short function that does it and returns a vector of the tokens. As an option, the delimiter string can represent either a multichar delimiter or a collection of single char delimiters:

// multichar delimiter == "^^"

"aa^^bb^c^^d"

becomes

"aa"
"bb^c"
"d"
// single char delimiter list == "^,"

"aa^^b,b^c^^d"

becomes

"aa"
""
"b"
"b"
"c"
""
"d"

A test driver is not included because that confused people with my last snippet.

Tom Gunn 1,164 Practically a Master Poster

CSV is more than just comma delimited fields. There are quoting and white space rules too. This is a short function as an example of a complete way to read CSV records line by line.

Tom Gunn 1,164 Practically a Master Poster

1)What is a NULL Macro? What is the difference between a NULL Pointer and a NULL Macro?

The NULL macro is a symbolic name for a null pointer constant. It is defined something like this:

#define NULL ((void*)0)

or this:

#define NULL 0

2)What is the difference between the functions rand(), random(), srand() and randomize()?

rand() returns a pseudo random number between 0 and RAND_MAX. srand() seeds the random number generator that rand() uses so that the same sequence is not generated each time. Under the hood rand() and srand() work something like this:

static int __seed;

void srand(int seed)
{
    __seed = seed;
}

int rand()
{
    int r = {cool math using __seed};

    ++__seed;

    return r;
}

random() and randomize() are not part of the C library, but if a compiler supports them they probably work similarly to rand() and srand().

Tom Gunn 1,164 Practically a Master Poster
int c_hrs1 , c_hrs2 , c_hrs3 , c_hrs4;
    float gpa_1 , gpa_2 , gpa_3 , gpa_4;

    int total_c_hrs= c_hrs1+c_hrs2+c_hrs3+c_hrs4;
    float cgpa= ((c_hrs1*gpa_1)+(c_hrs2*gpa_2)+(c_hrs3*gpa_3)+(c_hrs4*gpa_4))/total_c_hrs;

This will not work because all of those variables used in initializing total_c_hrs and cgpa have not been initialized. You should move the second two lines to after all of the input.

cout<<"Please enter you GPA in course 4: ";
    cin>>gpa_4;
    cout<<"Please enter the credit hours for course 4:";
    cin>>c_hrs1;

Copy/paste coding can be dangerous. ;) You forgot to change c_hrs1 to c_hrs4, which leaves c_hrs4 uninitialized in the calculation of total_c_hrs and cgpa.

It doesnt even display the last cout>>

If you are using cin.get() to keep the console window open then the last cout would happen too fast for you to see. But a terminating line break is a good idea anyway.

operator<< trims leading white space and stops reading on white space by default, so there will be a '\n' character still sitting in the stream for cin.get() to read, like firstPerson said. But another cin.get() is just a hack to fix this specific problem. If there is more than one character at the end of the stream, the same thing will happen. You can fix the problem generically like this:

cin.ignore(1024, '\n');

This reads and discards up to 1024 characters or until '\n' is found. It should clear the stream out so that the next cin.get() will block. 1024 is an arbitrary number though, numeric_limits<streamsize>::max() is a better …

Salem commented: Many fine points +36
Tom Gunn 1,164 Practically a Master Poster

You have the right idea, but there are a few problems in the details:

vector <string > string;
vector <int> int;

Naming your variables the same as types is not a good idea. Most of the time it will not work the way you want.

tranform(string.begin(), string.end(), int.begin(), atoi);

First, atoi() does not work on C++ string objects. You need to define another function that does. Second, transform() does not insert new items onto the destination. This call will fail because the int vector does not have room.

Compare your code with this:

#include <algorithm>
#include <stdexcept>
#include <iostream>
#include <iterator>
#include <string>
#include <sstream>
#include <vector>
#include <cstdlib>

int StrToInt(std::string const& s)
{
    std::istringstream iss(s);
    int value;

    if (!(iss >> value)) throw std::runtime_error("invalid int");

    return value;
}

int main()
{
    std::vector<std::string> vs;
    std::vector<int> vi;

    vs.push_back("1");
    vs.push_back("2");
    vs.push_back("3");
    vs.push_back("4");
    vs.push_back("5");

    std::transform(vs.begin(), vs.end(), std::back_inserter(vi), StrToInt);

    std::vector<int>::const_iterator x = vi.begin();
    int sum = 0;

    while (x != vi.end()) sum += *x++;

    std::cout << "Sum: " << sum << '\n';
}

String streams are a good way to convert between strings and other types because most of the work is already done for you. And when you want transform() to add new items, the back_inserter uses a call to push_back() instead of just assigning to an index.

Dave Sinkula commented: This will be a good post to refer to in the future (but I've come to expect that). +26
mrnutty commented: Good job +2
Tom Gunn 1,164 Practically a Master Poster

Most of the time when a programmer prints a char*, he wants a string to be printed, not the address. cout assumes that is what you want and to get around it, you need to cast to a different pointer type. void* is a good choice because an object pointer can be cast to void* safely:

#include <iostream>

int main()
{
    char const* p = "string";

    std::cout << p << '\n'
              << (void*)p << '\n';
}

On a side note, this is the same as how printf works with the %p modifier. To be 100% safe, the pointer should be cast to void* because that is the type %p expects:

#include <cstdio>

int main()
{
    char const* p = "string";

    std::printf("%s\n%p\n", p, (void*)p);
}
Salem commented: Nice, so few people get the %p thing right. Though the C++ would have been better with a reinterpret_cast +36
Tom Gunn 1,164 Practically a Master Poster

qsort() what your looking for.

But be careful with the example from that page. Subtracting ints like that without any kind of underflow test has some risk. The safe way is easier to understand too:

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

int Compare(void const* a, void const* b)
{
    int const* first = a;
    int const* second = b;

    if (*first == *second) return 0;
    else if (*first < *second) return -1;
    else return 1;
}

int main()
{
    int a[] = {0,4,6,2,8,7,1,6,8,4,3,2,8,5,9};
    size_t const sz = sizeof a / sizeof *a;
    size_t x;

    for (x = 0; x < sz; ++x) printf("%2d%s", a[x], x < sz - 1 ? "" : "\n");
    qsort(a, sz, sizeof *a, Compare);
    for (x = 0; x < sz; ++x) printf("%2d%s", a[x], x < sz - 1 ? "" : "\n");

    return 0;
}
Salem commented: Nice +36
Tom Gunn 1,164 Practically a Master Poster

Now you can get the username by using scanf like this:

scanf("%s", username);

More info about character arrays and the scanf-function can be found at the links which are at the bottom* of this post.

I have not seen any references that talk about reading strings the right way with scanf(). It's always the same "%s" format string, even though making it overflow safe is super easy:

scanf("%49s", username);

I think a big reason why fgets() is recommended is because everyone teaching scanf() uses it unsafely. I'm sure fgets() would be evil too if everyone learned and used it like this:

char username[50];

/* Unsafe code */
fgets(username, INT_MAX, stdin);

it's like using a chainsaw with no safety guards.

Welcome to C. :D There are no safety guards here, and scanf() is kind of low on the list of great ways to screw yourself over.

use "fgets()" instead.

That is not much better than saying void main is evil without explanation. Using fgets() to replace scanf() is good advice to avoid scanf() pitfalls, but then the same people who give the advice go on to recommend sscanf() for parsing the string... Imagine how confusing that would be to a beginner since scanf() and sscanf() are so similar. ;)

tux4life commented: Some other interesting stuff about C :P +20
jephthah commented: bork bork bork :) +15
Nick Evan commented: - that's another bookmark +27
Tom Gunn 1,164 Practically a Master Poster

In general, passing by value means that a copy of variable is made with the same value and passing by reference means the variable object itself is passed. You can change the value all you want with pass by value, but the original object is not changed. With pass by reference any changes to the passed variable also change the original. C does not support passing by reference, but you can fake it with pointers:

#include <stdio.h>

void CallByValue(int x)
{
    x = 123;
}

void CallByFakeReference(int* x)
{
    *x = 123;
}

int main()
{
    int x = 0;

    printf("Before CallByValue: %d\n", x);
    CallByValue(x);
    printf("After CallByValue: %d\n\n", x);

    printf("Before CallByFakeReference: %d\n", x);
    CallByFakeReference(&x);
    printf("After CallByFakeReference: %d\n", x);

    return 0;
}

Faking call by reference is done by passing the address of an object and then accessing the value through indirection. That way you can get to the original object and make changes, but the address is still passed by value.

tux4life commented: I appreciate you for taking the time to answer this question in a more correct way than I did :P +20
Tom Gunn 1,164 Practically a Master Poster

In case of main function, if i forgot to write return 0; at the last, GCC compiler generates no error

If you rely on the compiler to point out every problem in your code, you will spend more time with the debugger than if you know the problem areas that go undiagnosed by compilers and always write code with your brain switched on. :) Coding in C takes more work because the compiler does not try to protect you from every possible mistake.

But in case of main function if return 1; or other would have some meaningful sense, but return 0; has no sense.

A return value of 0 from main means success. Unless you compile with the std=c99 switch in gcc, omitting the return statement invokes undefined behavior because main has to return an int. If you do not explicitly return a value, the value that gets returned is what we call indeterminate. The value cannot be predicted and the resulting behavior of the calling process in turn cannot be predicted.

If you compile with std=c99, you can omit the return statement because C99 implicitly returns 0 if execution falls off the end of main without an explicit return statement. Otherwise, return 0; is a very good idea. If it still makes no sense to you, try return EXIT_SUCCESS; and include <stdlib.h>. That might look like more work is being done. ;)

Salem commented: Wise words indeed, there is no safety netting. +36
Tom Gunn 1,164 Practically a Master Poster
main(int ac, char *argv[])

Even when you do not specify a return type, main returns int, but your main does not have a return value. If you do not return a value from main, a junk value is returned to the OS. Also, C99 does not support implicit int anymore, so you should be typing it explicitly to futureproof your code.

if(ac>1)
    {
          printf("Invalid number of arguments /n");
          exit(1);
    }

The test is backwards. :) If ac is greater than 1, it means there is an argument available.

else
    {
        int newpid;
        newpid=atoi(argv);
    }

newpid is declared in the else block, so it does not exist outside of that block. Whatever you do with newpid, it will go away when execution gets to the end curly brace for the else block. Also, argv is an array, so you need to specify which item in the array you want to convert to an int.

This code should help you get started. It is always a good idea to start with something small and test that it works before adding more complexity. Like a program to print the arguments and make sure you got that right before trying to spawn processes which is harder to debug:

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

int isInt(char const* p);

int main(int argc, char *argv[])
{
    int nProcesses = 0;
    int x;

    if (argc < 2)
    {
        fputs("usage: $prog {number of processes}\n", stderr);
        exit(EXIT_FAILURE);
    }

    if (!isInt(argv[1]))
    {
        fputs("integer argument expected\n", …
MentallyIll5150 commented: Thanks! +1
iamthwee commented: Good explanation and carefully thought out. +22
Tom Gunn 1,164 Practically a Master Poster

You know how to use 1D arrays, right? 2D arrays are 1D arrays where every item is an array. C has arrays of arrays instead of true multidimensional arrays:

int a[5] = {1,2,3,4,5};

[0] -> [1][2][3][4][5]

int b[3][2] = 
{
    {1, 2},
    {3, 4},
    {5, 6}
};

[0] -> [1][2]
[1] -> [3][4]
[2] -> [5][6]
#include <stdio.h>

#define ASIZE 5
#define BXSIZE 3
#define BYSIZE 2

int main()
{
    int a[ASIZE] = {1,2,3,4,5};
    int b[BXSIZE][BYSIZE] = 
    {
        {1, 2},
        {3, 4},
        {5, 6}
    };
    int x, y;

    for (x = 0; x < ASIZE; ++x)
    {
        printf("%d%s", a[x], x < ASIZE - 1 ? " " : "\n");
    }

    for (x = 0; x < BXSIZE; ++x)
    {
        for (y = 0; y < BYSIZE; ++y)
        {
            printf("%d%s", b[x][y], y < BYSIZE - 1 ? " " : "\n");
        }
    }

    return 0;
}

A string variable is a char array, right? So an array of strings is an array of char arrays, and instead of using name to get the string variable, you use name[x] . Everything else is the same:

#include <stdio.h>
#include <string.h>

#define NAME_CNT 5
#define NAME_LEN 20

int main()
{
    /* 5 names up to 19 chars each */
    char name[NAME_CNT][NAME_LEN];
    size_t x, y, n;

    printf("Enter %d names\n", NAME_CNT);

    for (x = 0; x < NAME_CNT; ++x)
    {
        printf("Name #%d: ", x + 1);
        fflush(stdout);

        if (!fgets(name[x], NAME_LEN, stdin)) break;

        /* trim any trailing line break */
        n = strlen(name[x]);
        if …
yellowSnow commented: An excellent and informative reply. +4
Nick Evan commented: seconded +24
Tom Gunn 1,164 Practically a Master Poster

The order of cin.clear() and cin.ignore() is backward. cin.ignore() is just as much a read as cin.get() , so if the stream is in an error state, nothing will be read. The code needs to clear first, then ignore:

if (!cin)
{
    name.clear();
    cin.clear();
    cin.ignore(256, '\n');
}

I also added '\n' to the call because the delimiter defaults to EOF. That turns cin.ignore() into a blocking read because it waits for up to 256 characters or EOF.

tux4life commented: Perfect! +19
Tom Gunn 1,164 Practically a Master Poster

But what is he honestly going to do with it? Look at it, compile it, get his results. Then what?

I like to give examples because I think everyone learns better with code. If I have to post code that is too advanced because of unreasonable restrictions by you people, then he will just have to go the extra mile to learn from it.

I have already seen what happens when I try to give examples at the right level. Everybody attacks me for giving away code. If you want to be useful, show me how to post helpful code without everyone having a hissy fit. Otherwise your criticism is unconstructive will be ignored.

nav33n commented: Agree! +11
Tom Gunn 1,164 Practically a Master Poster

Old C meaning the latest standard will not allow it. If you compile as C89, the implicit int works, but if you compile as C99, it will throw an error. gcc supports both standards, so it depends on your compiler settings.

tux4life commented: Clean, sweet, and solid! +18
Tom Gunn 1,164 Practically a Master Poster

this thread was not put here to make anyone mad

Wow maybe i should stop this thread befor everyone starts to hate me.

I do not see where anyone got mad. Challenging your idea is not the same as hating you. ;)

Tom Gunn 1,164 Practically a Master Poster

There is also cout.width(...).

cout.width() is not sticky. You need to call it for every object that gets printed, so code like this will only right justify the first string:

cout.width(30);
cout << "right justified\n"
     << "left justified\n";

To justify both strings, you need to split the output into two statements because cout.width() does not return a reference to the stream and cannot be chained:

cout.width(30);
cout << "right justified\n";
cout.width(30);
cout << "left justified\n";

The manipulator lets you do it all in one statement:

cout << setw(30) << "right justified\n"
     << setw(30) << "right justified\n";

So while cout.width() exists, I do not think there is much reason to use it unless you really hate including <iomanip> for the parameterized manipulators. ;)

necrolin commented: Agreed +1
Tom Gunn 1,164 Practically a Master Poster

Daniweb probably has to comply with certain information archival laws. If any threads are physically deleted from the database, that could be grounds for heavy fines or even complete shutdown of the site. Or the information could be used to prosecute spammers, but physical deletion makes coming up with a case harder.

I mean no offense, but I have been part of the administration for a forum before. Most of the complaints and suggestions I got were too narrow minded. They focused on one aspect of the big picture and did not consider all of the other factors. Big forums like Daniweb do not get popular by having arbitrary rules and processes. We should be confident that there is a good reason for everything, even if it does not make sense to those of us without inside information. :)

lllllIllIlllI commented: Hahah nice. i was going to say that. but a lot less nice. I get sick of constant b**tching :P +4
Tom Gunn 1,164 Practically a Master Poster

It's not because you quickly want to test out some code that you may use bad coding styles.
Bad coding styles are considered: bad, so you don't have to use them, under any circumstances.

That rationalization might work when you preach to the choir, but everyone else needs a better reason. :) The better reason is that you are not just a tutor but a role model too. If you use bad coding practices then those practices will be emulated. If you use good coding practices then *those* practices will be emulated. Set a good example because you do not need to create more questions by training weak programmers. There are already plenty. ;)

tux4life commented: The better example is in place here :) +18
Tom Gunn 1,164 Practically a Master Poster

You can do it, but I think a better way is to have a Clone() method in the Animal class that the child classes override. Then all you need to do is this:

foreach (Animal d in AnimalBufferList)
{
    Add(d.Clone());
}
sknake commented: Thats what I would do +6
Tom Gunn 1,164 Practically a Master Poster

I am not using any features of .NET as I know of. So, why does Visual Studio always ask me to target a Framework in my project.

Make sure you do not have the /clr switch anywhere in your compiler command line options. C++/CLI compiles native C++ to a CLR assembly, so you might be targeting .NET without knowing it. I think /clr is a default switch for empty projects, if that is how you started.

Creator07 commented: Thanks buddy +1
Tom Gunn 1,164 Practically a Master Poster

That would happen if you do this:

C:\> tcc Sample1.c
C:\> tcc Sample2.c

The linker errors because those two calls to tcc are separate. They both try to compile and link the file, but there is no definition of f1 when compiling and linking just Sample2.c. To get the definition, you need to be able to link Sample1.c to Sample2.c. To do both at once and link them together, you do it with one call:

C:\> tcc Sample1.c Sample2.c

Or you compile the Sample1.c to an object file and link it with the object file of Sample2.c, but it is not as convenient as doing it all in one line:

C:\> tcc -c Sample1.c
C:\> tcc Sample2.c Sample1.obj

or

C:\> tcc -c Sample1.c
C:\> tcc -c Sample2.c
C:\> tcc Sample1.obj Sample2.obj

Please excuse any mistakes, I am going on memory of Turbo C. ;)

Before someone else attacks you about your choice of compiler, Turbo C/C++ is very old. There are better options now, like Code::Blocks or Visual C++ Express. Newer compilers make better use of recent improvements in CPUs and compiler design, and your code can only benefit from those improvements. :)

Also, if you want to move from C to C++, a compiler released after 1998 is a must because that is when C++ was standardized. If you use Turbo C++, you will miss out on most of the best stuff from standard C++.

jephthah commented: attack thwarted +14
Tom Gunn 1,164 Practically a Master Poster

NRU is a caching algorithm based on time. Cache some data and when the data is used set a flag bit. At regular intervals, check the flag bits and deallocate the memory for any of the data where the bit is not set. NRU means not recently used inside the time interval.

The code can be as simple as this:

const THRESHOLD = [I]{some seconds}[/I]

let start = time()

while true do
    // do stuff
    // load data into cache if not there
    // set flag bit when cache data is used

    if diff(time(), start) >= THRESHOLD then
        for x = 0 to sz
            if isset(cache[x].flag) then
                release(cache[x])
                remove(cache[x])
            end if
        loop
    end if
loop
tux4life commented: I don't know how you keep doing it, but your replies are always excellent :) +17
Tom Gunn 1,164 Practically a Master Poster

First I get attacked for not being perfect right out of the gate. Now I get attacked for fitting in. What do you want from me? :confused:

Tom Gunn 1,164 Practically a Master Poster

3) wrong, you only create a pointer of type char, this can't hold a string.

The next line assigns the pointer to a string constant:

char *abc;
abc="xyz";

There is no problem here, and the string is read only. It is the same to initializing directly:

char *abc = "xyz";

In fact, the compiler will probably reduce both ways to the same machine code.

tux4life commented: Thanks for the correction :) +16
Tom Gunn 1,164 Practically a Master Poster

Why not change the locale to something that uses ',' as the radix character? Then you don't have to do any mumbo jumbo with strings:

#include <iostream>
#include <locale>
#include <sstream>

using namespace std;

int main()
{
    istringstream is("12,34");
    double a = 0;

    is.imbue(locale("german_germany.1252"));

    is >> a; // will recognize ',' as a radix
    cout << a << '\n';
}
jephthah commented: sweet. i lernt something today. +13
Nick Evan commented: as did I. +22
Tom Gunn 1,164 Practically a Master Poster

>>char EVENT_NAME;

That only declares a single character. you need an array, such as char EVENT_NAME[255]; or better yet string EVENT_NAME;

Please remember that if you use an array with operator>>, you also need to lock the upper limit so that cin does not overflow the array:

char EVENT_NAME[255];

// setw() is declared in the <iomanip> header
// the size for setw includes a null character for the array
while (in >> setw(255) >> EVENT_NAME)
{
    cout << EVENT_NAME << "\t"  << endl;
}

The string class is better because it grows dynamically. You do not need to worry about array overflow or how to deal with extra long strings.

Ancient Dragon commented: Thanks for the correction :) +36
tux4life commented: Nice one here :) +16