Narue 5,707 Bad Cop Team Colleague

Can anyone explain -in simple words as possible- what happens in the first code so that it prints the result that way?

Undefined behavior.

Narue 5,707 Bad Cop Team Colleague
#include <cstdlib> // I'm needed for rand() and srand()
#include <ctime>   // I'm needed for time()
#include <iostream>

int main()
{
    // Put me at the start of the program
    srand((unsigned)time(0));
    
    const int N = 100;
    
    // Watch as random numbers between 0 and N are generated
    for (int i = 0; i < 10; i++)
        std::cout << rand() % N << '\n';
}
Narue 5,707 Bad Cop Team Colleague

the job offered do not focus mainly about c++

It doesn't have to focus mainly on C++. If getting the job depends on answering a question, you don't deserve to get the job if you can't answer the question. This is simple common sense.

NathanOliver commented: amen to that +10
Narue 5,707 Bad Cop Team Colleague
pStu= new (nothrow) student pStu[i];

Should be this:

pStu= new (nothrow) student[i];

You also need to include <cstdlib> because that's where system() is declared.

Narue 5,707 Bad Cop Team Colleague

Wow! I never knew it was a C function. Thanks for sharing that, now onward i will not use that.

The fact that it's a function inherited from C is largely irrelevant. The important piece of information is that gets() is quite literally impossible to use safely. There's always a chance of buffer overflow, and you cannot avoid it. You can create the same problem using cin and C-style strings:

char buf[N];

cin >> buf; // No better than gets()

But at least here there's a fix for it:

char buf[N];

cin >> setw(N) >> buf; // All better

Of course, in C++ you should prefer to use the string class over C-style strings because they're easier to get right.

Narue 5,707 Bad Cop Team Colleague

I compiled it on Dev C++ and that is exactly the output i got. Please tell me what is wrong about it?

It doesn't matter what result your compiler gives you. Allow me to summarize since you're reading-impaired (ie. the following has been said multiple times already in this thread): The behavior is undefined, and thus, completely unpredictable. Your mistake is assuming that test results from Dev-C++ will be consistent on all other compilers, which is wrong.

Narue 5,707 Bad Cop Team Colleague

Obviously I have some wrong assumptions, because this prints "strsize = 8" no matter what.

Good call. buff is a pointer to char, so sizeof(buff) will always tell you what the size of a pointer to char is, not the length of the string it points to (if it points to a string at all, which isn't a safe assumption). What you want is the strlen() function, not sizeof.

Also note that strcat() expects the destination to be a valid string, which means you code is broken. This will fix it:

char* buff = malloc(sizeof(command)+42);

buff[0] = '\0'; /* Make buff a valid string */

strcat(buff, "notify-send \"notif finished\" \"Command: '");

Finally, it's good practice to check malloc() for failure. Otherwise you'll attempt to dereference a null pointer.

Bladtman242 commented: Solved my (initial) problem :) +3
Narue 5,707 Bad Cop Team Colleague

getcwd() returns the current working directory. That's the directory to which you can expect relative paths to resolve. Thus, it certainly explains why your relative path isn't finding the file if the current working directory is different. An easy solution would be using chdir() to force the current directory you want rather than using whatever happens to be the default.

Narue 5,707 Bad Cop Team Colleague

Since it is a pointer, what you are doing is printing the address of the pointer, not the contents.

Pointers are confusing for many people, so you should be especially precise with your phrasing. The address of a pointer is not the same as the address stored by a pointer. The contents of a pointer is the address stored.

The question was why is the address stored by a pointer to member not equivalent to the expected format of a memory address when printed. And the answer was a pointer to member does not store a memory address, it stores sufficient information to provide an offset into the target class when applied to an object of that class.

Try "cout << *ptr << endl;" instead.

Note that the discussion is about pointers to members, not regular pointers. They're most certainly not the same thing, hence the wildly different (and awkward, in my opinion) syntax.

Narue 5,707 Bad Cop Team Colleague

Well it is undefined in gcc compiler.

It's undefined in the C language specification. Compilers can do anything they damn well please when it comes to undefined behavior.

...but in Dev C++ or Turbo C++

It's still undefined. Just because you can pick out the method used in a specific compiler doesn't make the code any less broken.

Narue 5,707 Bad Cop Team Colleague

Yes, i want the space to be inserted when you press enter, without jumping to the next line. And when the maximum number of columns in a row is reached, it should jump on to the next line ie. the new row....

Assuming you want the console to auto-format itself according to the size of your matrix, this cannot be done without taking control of the console in a non-standard way. It's not terribly difficult, but I'd question the practicality of replacing the console with your own custom shell for the sole purpose of formatting matrix input.

Here's a very naive example of the concept:

#include <cctype>
#include <iostream>
#include <sstream>
#include <string>
#include <conio.h>

using namespace std;

string raw_gets()
{
    string result;
    int ch;
    
    // Naive algorithm, use at your own risk
    while (!isspace(ch = getch())) {
        result += (char)ch;
        cout << (char)ch;
    }
    
    return result;
}

int main()
{
    int mat[2][4];
    
    cout << "Enter the matrix:\n";
    
    for (int i = 0; i < 2; i++) {
        for (int j = 0; j < 4; j++) {
            stringstream conv(raw_gets());
            int x;
            
            conv >> x;
            mat[i][j] = x;
            
            cout << (j < 3 ? ' ' : '\n');
        }
    }
    
    for (int i = 0; i < 2; i++) {
        for (int j = 0; j < 4; j++)
            cout << mat[i][j] << ' ';
            
        cout << '\n';
    }
}
PrimePackster commented: Thank U very much +3
Narue 5,707 Bad Cop Team Colleague

Exit code 0xC0000005 is an access violation. Your code is broken, but you can search for places where you're accessing an array out of bounds or an uninitialized pointer. Those are the two most common causes of an access violation.

Narue 5,707 Bad Cop Team Colleague

But......The thing is, i am the only active one there.....

Yes, IRC hasn't grown much because every new person joins and then leaves in disgust at how inactive it is, thus continuing the vicious cycle. :icon_rolleyes:

Narue 5,707 Bad Cop Team Colleague

I guess the reputation feature must have been removed

It wasn't removed, it just looks different. On every post you'll find an up and down arrow along with a counter. The counter is the number of people who have clicked the arrows to vote on a post (positive and negative votes correspond to up and down arrows, respectively). When you choose to vote on a post, you have the option of also giving reputation and including a comment, this is where you'll find the reputation feature now.

So rather than removing a feature, Daniweb added one. :) Votes are a way of saying you like or dislike a post without being forced to give out reputation, and reputation can still be given out if you also want to leave feedback in the form of a comment.

Narue 5,707 Bad Cop Team Colleague

Yes but i tried learning opengl and it is pain in the ass to make it work!

If you're going to give up as soon as it gets hard, then programming isn't for you.

What were u saying about double buffering?

Double Buffering.

Narue 5,707 Bad Cop Team Colleague

This code is compile without any errors in my Visual Studio 2010 Ultimate.

C++ is not defined by Visual Studio 2010 Ultimate. For example, on GCC your code fails with two errors:

main.cpp:6:3: error: 'ptr' was not declared in this scope
main.cpp:29:16: error: 'system' was not declared in this scope

Comeau agrees with this assessment:

"ComeauTest.c", line 6: error: identifier "ptr" is undefined
                ptr=this;

Given only that out of three compilers, two of them[1] fail to compile your code, I'd lean toward Visual Studio being wrong. Please provide chapter and verse from the C++ standard that proves GCC and Comeau are broken.

if the compiler is bugged you wouldn't be so stupid

Please provide chapter and verse from the C++ standard before calling other people stupid.


[1] One of those compilers, Comeau, is also widely accepted as the best conforming compiler available as far as standard C++ goes.

Narue 5,707 Bad Cop Team Colleague

I'm guessing with gcc there will be no optimization, unless called with -O or similar parameters?

It's best not to guess. GCC is very aggressive when it comes to optimization, so a test using assembly output would be the better approach.

Bladtman242 commented: This is great :) +3
Narue 5,707 Bad Cop Team Colleague

No user-defined function can run outside main().

Assuming you mean that no user-defined function can run before main (ignoring that you seem to have misunderstood the OP), consider this:

#include <iostream>

class foo {
public:
    foo() { std::cout << "Me first!" << std::endl; }
} obj;

int main()
{
    std::cout << "In main()" << std::endl;
}
LRRR commented: Whenever I read your post, I always learn something new. +2
PrimePackster commented: Can't resist adding reps... +0
Narue 5,707 Bad Cop Team Colleague
for (char **curr_point = parr, **bound_point = parr + maxStrings;
curr_point < bound_point; ++curr_point)

Please someone correct me, if I am wrong but, I don't think it is safe to use such addition :
**bound_point = parr + maxStrings; maxStrings = 5 it's an int.

The size of a char is 1 byte, but if it was an int (4 byte), this method wouldn't work. In the end of the loop, it would be pointing to the memory area of the second element of the ""array""(int) instead of the desired bound point. (The bound point would be pointing in the second int.)

I believe you're trying to say that addition on a pointer will always use a step size of one byte, which isn't how pointers work. The step size of a pointer depends on the size of the pointed to type, so p + n under the hood is more along the lines of (char*)p + (n * sizeof *p) .

Narue 5,707 Bad Cop Team Colleague

1- element of a vector/array can "share" same address with the vector/array it was put into. (Well, I always thought each value has its own address)
(reference = 2)

The address of the array and the address of the first element are the same. This makes sense when you think of array indexing as an offset from a base address. (base + 0) == base , right? So &base[0] == base as well.

2- from what I learned, when we setup an array, the pointer will referred to the first element automatically, and that's what (I thought) happen on the pointer's pointer's value(**parr and **curr_points)
(reference = 5 / 7)

That's what happens. Though **parr will always produce the same result because you're always accessing parr[0][0] .

3- based on '2-', can anyone give an idea on how to iterate through the pointer's pointer's value? (does ++**curr_point works?) :P

If I understand your question, you still need some form of iterator. You can't use *curr_point directly, but you can use it as a base:

for (char *p = *curr_point; *p != '\0'; p++)
    std::cout << *p << '\n';

The reason you can't use *curr_point directly is somewhat subtle. If it's an actual array then the pointer isn't modifiable and your code will fail. If it's a simulated array as in your example then modifying it will break subsequent code that relies on parr . This is because curr_point is referencing parr , so changes to …

Narue 5,707 Bad Cop Team Colleague

I would like to know the best beginner book for C++.

The best book is the one you understand that makes the fewest mistakes. I (and most clueful C++ programmers) recommend Accelerated C++ as a first book due to quality, but that doesn't mean it will be a good fit for you.

My teacher has referred Robert Lafore and The Complete Reference.

This suggests that your teacher isn't very good. My condolences. While Robert Lafore doesn't write horrible books, they're still bottom shelf quality-wise. And Herbert Schildt's books have been the butt of jokes for decades.

Narue 5,707 Bad Cop Team Colleague

As you can see that this code is accessible in turbo C but not in Dev C++

That's because Dev-C++ is properly disallowing a language constraint violation. The address-of operator may only be used on an lvalue. You can use offsetof() to avoid the very hackish calculations that your awful book is encouraging:

#include <stdio.h>
#include <stddef.h>

struct a {
    struct b {
        int i;
        float f;
        char ch;
    } x;
    struct c {
        int j;
        float f;
        char ch;
    } y;
} z;

void fun(struct c *p)
{
    /* Find the offset of the struct c member */
    size_t offset = offsetof(struct a, y);
    
    /* 
        Find the base address of the struct b member 
        since we know it precedes the struct c member
    */
    struct b *address = (struct b*)((char*)p - offset);
    
    /* Hope and pray that what we "know" about struct a is correct */
    address->i = 400;
    address->f = 3.14;
    address->ch = 'c';
}

int main(void)
{
    fun(&z.y);
    printf("\n%d %f %c", z.x.i, z.x.f, z.x.ch);

    return 0;
}

It's still silly and unsafe, but at least the code should build and run on a modern compiler.

Ancient Dragon commented: Learned something new today :) +17
Narue 5,707 Bad Cop Team Colleague

Java is designed for the web.

Actually, it was designed for the early 90s concept of mobile devices and later tweaked to fit the web paradigm when the original target didn't seem marketable anymore.

C on the other hand is for interaction with the hardware.

C is a general purpose programming language that allows low level access to the hardware. Restricting your definition of what a programming language is or isn't will surely blind you to the possibilities that don't fit your definition.

You CANNOT write an operating system in Java.

You should tell the people who have done it so that they can adjust their view of reality accordingly. Also note that an OS written in XYZ doesn't mean only written in XYZ. For example, you'll find that the bootstrapping parts of an OS are typically written in assembly language. But if all other code uses XYZ then it's not incorrect to say the OS is written in XYZ.

Narue 5,707 Bad Cop Team Colleague

this is just an example..but i can't compile it.is there any mistakes in these codes?

If it doesn't compile, there are mistakes. That's axiomatic. If it doesn't compile, there are also compilation errors. Use them to fix the mistakes or post the errors so that others can help you fix the mistakes if you're incapable of doing so by yourself.

Narue 5,707 Bad Cop Team Colleague

I don't know what happened and I'm sure that reason is scanf().

Then let's start by using scanf() correctly. When your choice variable is a short int, the correct format specifier is %hd . Fix that and return if the problem persists.

Narue 5,707 Bad Cop Team Colleague

If you understand, you can figure out now why I'm naming the title "nested pointer", right?

I was pretty confident that I knew why just from reading the title.

I'm thought of this "timeline" of process happen in my code...

note: see my attachment for better picture of each explanation.
 
a. '1000' assigned to "value_1"
 
b. "pointer_1" become a point to "value_1" content, where:-
        - *pointer_1 == value_1's content
        -  pointer_1 == value_1's address
 
c. "pointer_2" become a point to "pointer_1" content, where:-
        - **pointer_2 == value's content
        -  *pointer_2 == pointer's content == value_1's address
        -   pointer_2 == pointer_1's address

If I were your teacher, I'd give you perfect marks for this.

The references operator, usually known as, "& == address of"... At first, I thought the equation is literally descriptive, but then I discover I'm wrong. When this operator assigned to the pointer, it will return address to the "standard variable", but not only that, it return the whole content of the address.

Now you're getting into nonsensical territory. The address-of operator is literal. It evaluates to the address of an object, and a pointer object isn't treated differently. The problem with pointers and addresses is people get confused because a pointer is both an object with an address and an object that stores an address. So for an initialized pointer there are two addresses and two values involved:

  • &ptr : The ptr object's address.
  • ptr : The ptr object's value (the pointed-to …
mike_2000_17 commented: great +14
Narue 5,707 Bad Cop Team Colleague

Let me know, if you think its not correct.

It's not correct. Let's ignore that unistd.h isn't a standard header (you don't use anything from it anyway) and go right to the first real error. Boiled down, it looks like this:

char *no;

cin >> no;

int len = strlen(no);

First, you forgot to include <cstring> for strlen(). Second, you clearly don't understand how pointers work because an uninitialized pointer does not point to infinite memory. A pointer must be initialized to memory that your process owns before it can be used.

C++ is not just C with cin and cout, there are many more things that can make your life easier:

#include <algorithm>
#include <iostream>
#include <string>
 
using namespace std;
 
int main()
{
    string line;
    
    while (true) {
        cout << "Enter a number (EOF to quit): ";
        
        if (!getline(cin, line))
            break;
        
        bool not_num = any_of(line.begin(), line.end(), [](char c) { return !isdigit(c); });
        
        cout << "'" << line << "' is" << (not_num ? " not " : " ") << "a number\n";
    }
}

Notice how you don't have to worry about pointers with the std::string class. That's one of the key benefits for people who are low level programming challenged. ;)

All of this is assuming that the need for a "number" means a series of digits rather than a value suitable for conversion to one of the integer or floating-point types. If you need to convert to a numeric type, the naive algorithm …

Narue 5,707 Bad Cop Team Colleague

When you encode something you have to decode it with the same username and password again, otherwise it will give you a very strange character text.

It's called symmetric key cryptography, and I don't recommend inventing your own algorithm as it's more likely to be woefully insecure than decent in any way. As one example, your key isn't unique (actually, it's VERY not unique) due to the chance of unsigned integer wrap around with arbitrarily long text strings.

We're going to use this for our website, and I thought it might be nice to share this with others!

If you're going to show it off on your website, fine. If you're doing this for fun and education, fine. If you're planning on using this algorithm for your website's security, I strongly suggest that you reconsider and instead use .NET's built-in cryptography algorithms. The following is much better (not to mention more concise):

using System;
using System.IO;
using System.Text;
using System.Security.Cryptography;

public class Program {
    public static void Main() {
        // Test driver for the Encryption class
        //
        var crypt = new Encryption("QNHMKh4HTJnTxzDsorGvL5IZxfPgvagA", "21Z8CmgIDQEB9Khm7fs8aw==");
        string cipherText = crypt.Encrypt("this is a test");
        string plainText = crypt.Decrypt(cipherText);

        Console.WriteLine("{0}\n{1}", cipherText, plainText);
    }
}

public sealed class Encryption {
    private byte[] _key; // Symmetric key used for both encryption and decryption
    private byte[] _iv;  // Initialization vector for the encryption algorithm

    /// <summary>
    /// Initialize an object of the Encryption class with specified key and IV.
    /// </summary>
    /// <param name="key">Base 64 representation …
darkagn commented: Consice answer with great coding example +10
Narue 5,707 Bad Cop Team Colleague

what am I doing wrong ?

You're using feof() as the loop condition. feof() won't return true until after a request for input from the file fails, but by then it's too late and you'll continue processing the result of failed input. Given that fgetcsv() returns false on end-of-file, you can use it directly as the loop condition and forget about feof() entirely:

while ($buffer = fgetcsv($file_handle, 4096))
{
    echo "<br>";

    ...
}
Narue 5,707 Bad Cop Team Colleague

So i'm wondering how 162 and 12 are converted to 3234?

Don't forget that the 12 is your second byte, so it needs to be appropriately shifted: (12 << 8) | 162 == 3234 .

Narue 5,707 Bad Cop Team Colleague

i am don't know what median is ?
or strdDevition ?

Do you know what Google is?

Narue 5,707 Bad Cop Team Colleague

Is it possible to know what is the undefined behavior?

Undefined behavior is by definition undefined. Anything can happen. I've heard cases of undefined behavior frying hardware, or corrupting system files, so it's far from harmless. And I suspect that's why people always look for descriptions of what might happen, they want to weigh the risks.

iamcreasy commented: Woo! +3
Narue 5,707 Bad Cop Team Colleague

What means, "only defined on output streams"?

Here's what the standard says:

#include <stdio.h>
int fflush(FILE *stream);

Description
If stream points to an output stream or an update stream in which the most recent
operation was not input, the fflush function causes any unwritten data for that stream
to be delivered to the host environment to be written to the file; otherwise, the behavior is
undefined.

Note that input streams and update streams where the most recent operation was input fall into the "otherwise" part of the definition. stdin is an input stream, so fflush(stdin) invokes undefined behavior.

Narue 5,707 Bad Cop Team Colleague

Just because you don't personally use a language doesn't make it unimportant.

/thread

Moschops commented: So true, and needs saying more often. Although this is the first time I've seen someone suggest Java as a replacement for C. +8
Narue 5,707 Bad Cop Team Colleague

Is this compilable? (i.e without the white space)

Yes, that particular annoyance was removed in C++11. The OP's compiler (Visual C++ 2010) supports the new feature.

frogboy77 commented: Thank you. Need a new compiler. +6
Narue 5,707 Bad Cop Team Colleague

So can you please explain how to use this std::vector?

Certainly. Here's a rough facsimile of your code using std::vector:

#include <iostream>
#include <vector>

using namespace std;

int main()
{
    int a, b;
    
    cout << "Enter the size for the 2D array: ";
    
    if (cin >> a >> b) {
        vector<vector<int>> vec(a, vector<int>(b));
        int k = 0;
        
        for (int i = 0; i < a; i++) {
            for (int j = 0; j < b; j++)
                vec[i][j] = k++;
        }
        
        for (int i = 0; i < a; i++) {
            for (int j = 0; j < b; j++)
                cout << vec[i][j] << ' ';
                
            cout << '\n';
        }
    }
}

The only real difference is in the constructor where you need to build up both dimensions. This is the proper way to do it if you already know the sizes, but you can grow the vector dynamically as you go if necessary, that's where the real power lies:

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

using namespace std;

int main()
{
    vector<vector<int>> vec;
    string line;
    
    cout << "Enter a table (EOF to finish):\n";
    
    while (getline(cin, line)) {
        // Insert a new row to the vector
        vec.push_back(vector<int>());
        
        istringstream iss(line);
        int x;
        
        while (iss >> x)
            vec.back().push_back(x);
    }
    
    for (int i = 0; i < vec.size(); i++) {
        for (int j = 0; j < vec[i].size(); j++)
            cout << vec[i][j] << ' ';
            
        cout << '\n';
    }
}
PrimePackster commented: Thank U very much. That helps a lot +0
Narue 5,707 Bad Cop Team Colleague

I'd recommend this one, but I'm also just a little biased, having written it. ;)

Narue 5,707 Bad Cop Team Colleague

@Narue: Is there a way I can use toupper() with a string then?

Yes, the way you do everything with each character of a string: use a LOOP!

int i;

for (i = 0; line[i] != '\0'; i++)
    line[i] = toupper(line[i]);
Narue 5,707 Bad Cop Team Colleague
printf("%s\n", "hai welcome..." + 3);
Narue 5,707 Bad Cop Team Colleague

Since this isn't an assignment, the correct answer is to ditch that piece of shit compiler and get something from the current decade. You'd have no end of troubles using a 16-bit compiler on a modern 32 or 64-bit OS anyway (the environment 99.99% of Turbo C folks are trying to run under), so this would be an exercise in unnecessary frustration.

Narue 5,707 Bad Cop Team Colleague
fscanf(fp, "%d", &temp);
if(temp!='\n')

This is an impossible case unless one of the numbers happens to match the numeric value of '\n', and if that happens you'll get unpredictable behavior. You told scanf() to read integers, and it will discard all whitespace in the process.

What you need to do is read the file line by line, then split up each line into fields for your array:

#include <stdio.h>

int main(void)
{
    FILE *in = fopen("test.txt", "r");
    
    if (in != NULL) {
        char line[BUFSIZ];
        
        while (fgets(line, sizeof line, in) != NULL) {
            char *start = line;
            int field;
            int n;
            
            while (sscanf(start, "%d%n", &field, &n) == 1) {
                printf("%d ", field);
                start += n;
            }
                
            puts("");
        }
        
        fclose(in);
    }
    
    return 0;
}

Be mindful of the sscanf() loop in that example, because it uses a somewhat tricky way of stepping through the string. If you don't save the number of characters that were extracted and move forward accordingly, the loop will be infinite. For example, this is the wrong way:

while (sscanf(line, "%d", &field) == 1) {
    printf("%d ", field);
}

sscanf() isn't smart enough to use anything but the string you give it as the source, so this loop will continually extract the first field in line . Contrast this with something like std::istringstream in C++, where the buffer is updated internally to reflect extractions.

An alternative is to avoid sscanf() entirely and do the conversions yourself. This is more of a manual parse:

zeroliken commented: well said +3
Narue 5,707 Bad Cop Team Colleague
int[] b = new int[0];
int[] c = new int[0];

Arrays of size zero...sounds useful. :icon_rolleyes:

Antenka commented: :D And how fast! +7
Narue 5,707 Bad Cop Team Colleague

Attention: rtrim could modify memory outside string range

While you're correct, the bug report is unhelpful because you haven't specified when this would happen or suggested a fix. The problem stems from an unchecked decrement of original , which can drop below string if it's empty of contains nothing but junk characters.

If whatever memory prior to string also contains junk characters, the loop will continue and modify memory outside the bounds of the array. If memory prior to string doesn't contain junk characters, at least one element beyond the array will be accessed, which is still undefined behavior.

Trimming away the entire string is the special case that needs to be considered here, with awareness of three potential cases at original[0]:

  • original[0] is '\0': The string was empty, so nothing needs to be done.
  • original[0] is junk : The string is trimmed to nothing and must end at original[0] .
  • original[0] neither '\0' nor junk : The string must end after original[0] , as in the original algorithm.

Once the potential cases are discovered, it's a simple matter to account for them:

char *rtrim(char *string, char junk)
{
    char *original = string + strlen(string);

    while (original != string && *--original == junk)
        ;
    
    if (*original != '\0')
        original[*original == junk ? 0 : 1] = '\0';

    return string;
}
~s.o.s~ commented: Nice follow-up; can't believe I missed Melando's post :-) +17
Narue 5,707 Bad Cop Team Colleague

@Narue, if that be the case, why have you decided to be a bad cop? You should be a good one.....lol:)

I figure there's enough good karma in helping people that I can afford to be an ass while doing it. ;)

Nick Evan commented: Hahaha, nice one +0
Narue 5,707 Bad Cop Team Colleague

What I came to know from google is that Bit shifting allows for compact storage of similar data as a single integral value.

It's not just shifting, and that's not the only use of the bitwise operators. Since a byte is the smallest addressable unit in C#, that's typically the smallest object one works with. But bytes are comprised of bits, and the bitwise operators allow you to work at an even smaller granularity than bytes when it makes sense to do so.

Compact storage of flags is one such use. A flag is either on or off, so there are really only two values. Rather than have an array or list of N bool objects (which still consume one byte of storage each), you can use an object with a sufficient number of bits, and then use each bit as a flag. For example with eight flags:

using System;

class Program {
    static void Main()
    {
        bool[] flagList = new bool[8] { true, false, true, true, false, true, true, false };
        byte flagByte = 0xB6;

        Console.WriteLine("flagList size: " + flagList.Length * sizeof(bool));
        Console.WriteLine("flagByte size: " + sizeof(byte));

        // List the flags in flagList
        foreach (bool flag in flagList)
            Console.Write(Convert.ToInt32(flag));

        Console.WriteLine();

        // List the flags in flagByte
        for (int bit = 7; bit >= 0; bit--)
            Console.Write((flagByte >> bit) & 0x1);

        Console.WriteLine();
    }
}

Notice how the same information was stored in 1/8th of the space using bitwise operators in the above program. This is a significant savings, …

Narue 5,707 Bad Cop Team Colleague

Here's a user control that does what you want. You can use it directly or as a template for your own ad hoc collection of controls:

using System;
using System.Drawing;
using System.Windows.Forms;
using System.Collections.Generic;

public class SelectionList: UserControl {
    #region UI Controls
    private TableLayoutPanel tableLayoutPanelControl = new TableLayoutPanel();
    private ListBox listBoxLeft = new ListBox();
    private ListBox listBoxRight = new ListBox();
    private TableLayoutPanel tableLayoutPanelButtons = new TableLayoutPanel();
    private Button buttonAddAll = new Button();
    private Button buttonAddSelected = new Button();
    private Button buttonRemoveSelected = new Button();
    private Button buttonRemoveAll = new Button();
    #endregion

    #region UI Initialization
    private void InitializeComponent()
    {
        tableLayoutPanelControl.SuspendLayout();
        tableLayoutPanelButtons.SuspendLayout();
        SuspendLayout();

        tableLayoutPanelControl.ColumnCount = 3;
        tableLayoutPanelControl.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50F));
        tableLayoutPanelControl.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 45F));
        tableLayoutPanelControl.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50F));
        tableLayoutPanelControl.Controls.Add(listBoxLeft, 0, 0);
        tableLayoutPanelControl.Controls.Add(listBoxRight, 2, 0);
        tableLayoutPanelControl.Controls.Add(tableLayoutPanelButtons, 1, 0);
        tableLayoutPanelControl.Dock = DockStyle.Fill;
        tableLayoutPanelControl.Location = new Point(0, 0);
        tableLayoutPanelControl.Name = "tableLayoutPanelControl";
        tableLayoutPanelControl.RowCount = 1;
        tableLayoutPanelControl.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
        tableLayoutPanelControl.Size = new Size(178, 106);
        tableLayoutPanelControl.TabIndex = 0;
            
        listBoxLeft.Dock = DockStyle.Fill;
        listBoxLeft.FormattingEnabled = true;
        listBoxLeft.Location = new Point(3, 3);
        listBoxLeft.Name = "listBoxLeft";
        listBoxLeft.Size = new Size(60, 100);
        listBoxLeft.TabIndex = 0;
            
        listBoxRight.Dock = DockStyle.Fill;
        listBoxRight.FormattingEnabled = true;
        listBoxRight.Location = new Point(114, 3);
        listBoxRight.Name = "listBoxRight";
        listBoxRight.Size = new Size(61, 100);
        listBoxRight.TabIndex = 1;
            
        tableLayoutPanelButtons.ColumnCount = 1;
        tableLayoutPanelButtons.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
        tableLayoutPanelButtons.Controls.Add(this.buttonAddAll, 0, 1);
        tableLayoutPanelButtons.Controls.Add(this.buttonAddSelected, 0, 2);
        tableLayoutPanelButtons.Controls.Add(this.buttonRemoveSelected, 0, 3);
        tableLayoutPanelButtons.Controls.Add(this.buttonRemoveAll, 0, 4);
        tableLayoutPanelButtons.Dock = DockStyle.Fill;
        tableLayoutPanelButtons.Location = new Point(69, 3);
        tableLayoutPanelButtons.Name = "tableLayoutPanelButtons";
        tableLayoutPanelButtons.RowCount = 6;
        tableLayoutPanelButtons.RowStyles.Add(new RowStyle(SizeType.Percent, 50F));
        tableLayoutPanelButtons.RowStyles.Add(new RowStyle(SizeType.Absolute, 25F));
        tableLayoutPanelButtons.RowStyles.Add(new RowStyle(SizeType.Absolute, 25F));
        tableLayoutPanelButtons.RowStyles.Add(new RowStyle(SizeType.Absolute, 25F));
        tableLayoutPanelButtons.RowStyles.Add(new RowStyle(SizeType.Absolute, 25F));
        tableLayoutPanelButtons.RowStyles.Add(new RowStyle(SizeType.Percent, 50F));
        tableLayoutPanelButtons.Size = new Size(39, 100);
        tableLayoutPanelButtons.TabIndex = 2; …
Narue 5,707 Bad Cop Team Colleague

How can I print it from the main? I know it sounds stupid, but I am still a beginner to the language.

There are three conventional options for accessing the calculated result in a function from the calling function:

  1. Return the result from your function:
    #include <stdio.h>
    #include <math.h>
    
    float round2int(float test)
    {
        return floor(test + 0.5);
    }
    
    int main (void)
    {
        float x;
        
        while (1) {
            printf("Enter a number (Enter zero (0) to quit program): ");
            scanf("%f", &x);
            
            if (x == 0)
                break;
                
            printf("%f\n", round2int(x));
        }
        
        return 0;
    }
  2. Pass a pointer to the destination object as an argument:
    #include <stdio.h>
    #include <math.h>
    
    void round2int(float test, float *result)
    {
        *result = floor(test + 0.5);
    }
    
    int main (void)
    {
        float x, result;
        
        while (1) {
            printf("Enter a number (Enter zero (0) to quit program): ");
            scanf("%f", &x);
            
            if (x == 0)
                break;
            
            round2int(x, &result);
            printf("%f\n", result);
        }
        
        return 0;
    }
  3. (not recommended) Use a global variable:
    #include <stdio.h>
    #include <math.h>
    
    float result;
    
    void round2int(float test)
    {
        result = floor(test + 0.5);
    }
    
    int main (void)
    {
        float x;
        
        while (1) {
            printf("Enter a number (Enter zero (0) to quit program): ");
            scanf("%f", &x);
            
            if (x == 0)
                break;
            
            round2int(x);
            printf("%f\n", result);
        }
        
        return 0;
    }
terence193 commented: Well given examples +2
Narue 5,707 Bad Cop Team Colleague

Consider four cases given an array, a start index, and an end index:

  1. The base case where the start index passes the end index: terminate recursion.
  2. There's a vowel at the start index: recurse and increment the start index.
  3. There's not a vowel at the end index: recurse and decrement the end index.
  4. There's a vowel at the end index: swap the characters at the two indices and recurse while both incrementing the start index and decrementing the end index.
Narue 5,707 Bad Cop Team Colleague
#include <stdio.h>

void foo(int *p)
{
    printf("%p: %d\n", (void*)p, *p);
}

int main(void)
{
    int i = 12345;
    int *p = &i;
    
    foo(p);
    
    return 0;
}
Narue 5,707 Bad Cop Team Colleague

There are multiple ways of doing it, but in my opinion the most instructive is with a level order traversal, since checking for a complete binary tree is a pretty specific operation. By generalizing the problem a bit, you can get more out of the exercise. So here's an updated problem for you:

Q: Given a binary tree of the following definition:

struct node {
    int data;
    struct node *left;
    struct node *right;
};

Write a function that will perform a level order traversal and convert the tree into an array using heap indexing rules. Heap indexing rules state that for each node (numbered 0 to N in level order) the left child is at index 2 * i + 1 and the right child is at 2 * i + 2 .

As an example, given the following degenerate binary tree:

1
        -                      2
   -         -             -        3
 -   -     -   -         -   -    -   4
- - - -   - - - -       - -  - - - - - 5

The array you are to return might look like this:

1-2---3-------4---------------5

Once you have this array, determine if it represents a complete binary tree by testing for null nodes in between non-null nodes. A complete binary tree will have all non-null nodes strictly adjacent to each other. For example, here is a complete binary tree and the array representation:

5
  2         7
1   3     6   -
527136-

Note: The size …

N1GHTS commented: Your effort deserves credit +6