Question about the efficiency of using an array or individual variables

AI Thread Summary
The discussion centers on the efficiency of using arrays versus individual boolean variables in programming. It suggests that individual variables may offer faster access due to direct addressing, while arrays may benefit from memory caching. The initialization of an array with multiple values is clarified, explaining that using a single initializer only sets the first element, leaving others at zero. Additionally, the conversation highlights the limitations of fixed-size arrays, advocating for dynamic arrays or vectors for user-defined sizes. The complexities of user input handling for dynamic arrays are also addressed, suggesting the use of sentinel values for easier input management.
yungman
Messages
5,741
Reaction score
294
I have two questions here. In the program, I have two different boolean expressions, one using array A[10], the other just using individual variablesB(0..9). They both do the same thing as in the program. My question which one is faster in real life hardware? My guess is B(0..9) is faster even though it looks stupid. I think each variable use individual address, so it's one step access. The one using array has to take the starting address, add the index to get the address before accessing the value. I put a lot more emphasis on efficiency than make the code looks "nice".

Also, in the process of declaring the bool A[10], I found out I had to initialize with {1, 1, 1, 1, 1, 1, 1, 1, 1, 1} INSTEAD of {1} for all 10 elements. Why?

C++:
//Efficiency
#include <iostream>
using namespace std;

int main()
{
    bool A[10] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
    bool B0 = true, B1 = true, B2 = true, B3 = true, B4 = true, B5 = true,
        B6 = true, B7 = true, B8 = true, B9 = true;
    bool An, Bn; // result of AND

    An = A[0] && A[1] && A[2] && A[3] && A[4] && A[5] && A[6] && A[7] && A[8] && A[9];
    Bn = B0 && B1 && B2 && B3 && B4 && B5 && B6 && B7 && B8 && B9;
    cout << " An = " << An << "    Bn = " << Bn << "\n\n";
    return 0;
}

Thanks
 
Technology news on Phys.org
This is a hard and implementation dependent question. My guess would be arrays would be faster from a memory caching point of view with prefetch of data for the cache.
 
  • Like
Likes yungman
I have another question on array
I just went through the chapter on array, when initialization of an array int A[size]. The size has to be a constant, it cannot be a variable programmed by program later. I even tried to declare const int size = sz; where sz is variable. Still C++ doesn't like it.

The only other way is to use vector(dynamic array) initiated with undersize vector and use push_back to make the size variable and get to the size needed.

Any other suggestion?
 
yungman said:
I even tried to declare const int size = sz; where sz is variable. Still C++ doesn't like it.
A variable declared as const has to have its value known at compile time. Since sz is a variable, your declaration won't work.
 
  • Like
Likes yungman
Mark44 said:
A variable declared as const has to have its value known at compile time. Since sz is a variable, your declaration won't work.
Yeh, it's one thing to learn and write the notes, it's when the rubber hits the road by writing a complete program that one really see the details and the limitations. That's why I am NOT following the book on all the search and sorts, I read the flow and logic to understand what they are trying to do, the method, but I then close the book, just get the question and write totally on my own. I am doing the bubble sort right now, I need an array of boolean to keep track of the steps of comparisons. Then I realize the limitations of using array. I have to use vector now in order to leave the choice for user input the number of numbers for sorting. The example of the book use a fixed array of numbers, that's too easy. I want user to be able to enter the amount of numbers as they want and sort.

It's fun to actually write a complete program.
 
yungman said:
Also, in the process of declaring the bool A[10], I found out I had to initialize with {1, 1, 1, 1, 1, 1, 1, 1, 1, 1} INSTEAD of {1} for all 10 elements. Why?
If you declare you array this way, bool A[10] = {1};, the 0-index element is initialized to 1, and the other 9 are initialized to 0. If you want all of the elements to be 1, you have to supply an initializer list that does this. (Or you could assign values to the array in a for loop.)
jedishrfu said:
This is a hard and implementation dependent question. My guess would be arrays would be faster from a memory caching point of view with prefetch of data for the cache.
I would say the opposite -- that accessing a scalar variable is faster than accessing an array element. With an array element, the run time has to calculate the address of the array element, based on the starting address of the array, to which is added the offset to the element in question. With a scalar variable, the run time merely needs to access the memory address to get the value.

Edit:
On an x86 Windows machine, here is what the Visual Studio C++ compiler generates. All variables are of type int.
First, a scalar variable is accessed and its value is assigned to variable, x.
Code:
// x = num;
mov eax, dword ptr[num]
mov dword ptr[x], eax
The assembly code above copies the value in num to the EAX register, and then copies it to the variable x.

Next, an element of an array is accessed, and its value is assigned to a variable, y.
Code:
// y = Arr[3]
mov eax, 4
imul ecx, eax, 3
mov edx, dword ptr Arr[ecx]
mov dword ptr [y], edx
The first two lines of assembly set the EAX register to 4 (the size of an int), and then multiply it by 3 (the index in the array), storing the value 12 in the ECX register. The number we're looking for is at an offset of 12 bytes from the beginning of the array. The last two lines copy the value at that location to the EDX register, and then copy it to the variable y.
 
Last edited:
  • Like
Likes sysprog
yungman said:
Then I realize the limitations of using array. I have to use vector now in order to leave the choice for user input the number of numbers for sorting. The example of the book use a fixed array of numbers, that's too easy. I want user to be able to enter the amount of numbers as they want and sort.

It's fun to actually write a complete program.
The arrays your are using are allocated at compile time on the stack. If you want to use an array that is allocated dynamically at run time, or whatever size the user wants, you can do that in C using malloc(), or in C++ using the new operator in its array form.

These are probably a bit ahead of where you are in the book.
 
  • Like
Likes .Scott
Mark44 said:
The arrays your are using are allocated at compile time on the stack. If you want to use an array that is allocated dynamically at run time, or whatever size the user wants, you can do that in C using malloc(), or in C++ using the new operator in its array form.

These are probably a bit ahead of where you are in the book.
No, I have not learn that. I'll wait.

I already experimented using vector and I can do it using vector. But I have a more pressing question now.

In normal situation when we use cin or cin.get, we enter a number, then we have to hit ENTER. If I want to enter any number of integers as I want and want to stop whenever I want, I don't know how to make it easier.

Right now, I can ask user to enter a number, hit enter. Then I ask user to hit any key to enter another number or hit ENTER to quit. But that's a lot of trouble as you enter a number then hit enter, then hit any key follow by enter to repeat. So it takes 4 steps to enter one number as shown in the program:
C++:
//Efficiency
#include <iostream>
#include <vector>
using namespace std;

int main()
{
    vector<int> Av;
    int num;
    char key = 'A';
    while (key != '\n')
    {
        cout << " Enter an integer to be store in the dynamic array Av "; cin >> num;
        Av.push_back(num);
        cout << "\n\n Hit any key to enter another integer, hit ENTER to quit ";
        cin.ignore(255, '\n');
        cin.get(key);
    }
    int x = Av.size();
    cout << " You enter these number into dynamic array Av\n\n";
    cout << " {";
    for (int i = 0; i < x; i++)
        cout << Av[i] << " ";
    cout << "} \n\n";
    return 0;
}

Is there any way to simplify that? Something like number1-spacebar-number2-spacebar...until hit enter to quit? I just want to make it easier to enter numbers. I am sure the chapters I studied so far don't have anything like this.

Thanks
 
yungman said:
I have two questions here. In the program, I have two different boolean expressions, one using array A[10], the other just using individual variablesB(0..9). They both do the same thing as in the program. My question which one is faster in real life hardware? My guess is B(0..9) is faster even though it looks stupid. I think each variable use individual address, so it's one step access. The one using array has to take the starting address, add the index to get the address before accessing the value. I put a lot more emphasis on efficiency than make the code looks "nice".

Also, in the process of declaring the bool A[10], I found out I had to initialize with {1, 1, 1, 1, 1, 1, 1, 1, 1, 1} INSTEAD of {1} for all 10 elements. Why?

C++:
//Efficiency
#include <iostream>
using namespace std;

int main()
{
    bool A[10] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
    bool B0 = true, B1 = true, B2 = true, B3 = true, B4 = true, B5 = true,
        B6 = true, B7 = true, B8 = true, B9 = true;
    bool An, Bn; // result of AND

    An = A[0] && A[1] && A[2] && A[3] && A[4] && A[5] && A[6] && A[7] && A[8] && A[9];
    Bn = B0 && B1 && B2 && B3 && B4 && B5 && B6 && B7 && B8 && B9;
    cout << " An = " << An << "    Bn = " << Bn << "\n\n";
    return 0;
}

Thanks
Hi Yungman, I am writing you from the future, to warn you to watch out for std::vector< bool >. It isn't what it appears to be.
 
  • Like
  • Haha
Likes sysprog, pbuk and jedishrfu
  • #10
yungman said:
Right now, I can ask user to enter a number, hit enter. Then I ask user to hit any key to enter another number or hit ENTER to quit. But that's a lot of trouble as you enter a number then hit enter, then hit any key follow by enter to repeat. So it takes 4 steps to enter one number as shown in the program:
It's a problem when you mix different types of input; i.e., numbers for the vector, and characters to signal the loop to stop. Perhaps a better way is to use a sentinel value -- a value that wouldn't be expected for valid input. In the loop below, I'm assuming that valid numbers are positive, so if the user enters a negative number, the input loop exits.

If that's not feasible, you could ask the user how many numbers will be input, and then run the loop that many times.

Some comments:
  1. The user doesn't care that the vector is named Av, or even that you are using a dynamic array. Don't include that extraneous information in the user prompt.
  2. Try to come up with better variable names. Av and x are just about useless, as these names don't convey to the reader (another programmer who is reviewing or maintaining your program).
  3. It's better to use separate using std::xxx statements, rather than bringing in the whole very large std namespace. I gave an example in another thread of what can go wrong. It's especially bad practice to put such a statement into a header file.
Here's my version of your code.
C++:
#include <iostream>   
#include <vector>       
using std::cout;
using std::cin;
using std::vector;

int main()
{
    vector<int> List;
    int num;
    
    while (true)
    {
        cout << " Enter a nonnegative integer, or a negative number to quit "; 
        cin >> num;
        if (num < 0) break;
        List.push_back(num);        
    }

    int listSize = List.size();
    cout << " You entered these numbers\n\n";
    cout << " {";
    for (int i = 0; i < listSize; i++)
        cout << List[i] << " ";
    cout << "} \n\n";    
}
 
  • Like
Likes pbuk and yungman
  • #11
Jarvis323 said:
Hi Yungman, I am writing you from the future, to warn you to watch out for std::vector< bool >. It isn't what it appears to be.
Can you explain, it's not in the book. Doing a little guessing here, it works! Maybe, I am too much ahead of myself, wanting to do too much for what I know.
thanks
 
  • #12
yungman said:
Can you explain, it's not in the book. Doing a little guessing here, it works! Maybe, I am too much ahead of myself, wanting to do too much for what I know.
thanks
In the early days of C++, they wanted to make vector< bool > more memory efficient. A bool is just true or false, so it can be represented with a single bit. So they specialzed vector< bool > so that it doesn't contain actual bools, it contains bits. This violates some rules about what a vector is supposed to be. And note that memory is addressed and operated on by the machine at the resolution of bytes.

Normally, it's safe to write to different vector elements from different threads. But not in this case.

So a parallel for loop like below,

C:
const size_t END = vb.size();
#pragma omp parallel for
for( size_t i = 0; i < END; ++i )
{
    vb[ i ] = something(i);
}

is a bug if vb is a vector<bool>, whereas it would be fine for any other type of vector. I once spent a few days perplexed why my code was giving wrong results, and then learned this was why.

There are some other issues with vector< bool > as well, and you can find a lot of blog posts about them. It's considered by most to have been a mistake to add this kind of special case for vector< bool >, but for backwards compatibility it's a mistake the C++ committee needs to live with. Nowdays, there is std::bitset as well. If you can help it, I think it's best to just treat vector< bool > as depreciated.
 
Last edited:
  • Like
Likes pbuk and yungman
  • #13
Jarvis323 said:
In the early days of C++, they wanted to make vector< bool > more memory efficient. A bool is just true or false, so it can be represented with a single bit. So they specialzed vector< bool > so that it doesn't contain actual bools, it contains bits. This violates some rules about what a vector is supposed to be. And note that memory is addressed and operated on by the machine at the resolution of bytes.

Normally, it's safe to write to different vector elements from different threads. But not in this case.

So a parallel for loop like below,

C:
const size_t END = vb.size();
#pragma omp parallel for
for( size_t i = 0; i < END; ++i )
{
    vb[ i ] = something(i);
}

is a bug if vb is a bool, whereas it would be fine for any other type of vector. I once spent a few days perplexed why my code was giving wrong results, and then learned this was why.

There are some other issues with vector< bool > as well, and you can find a lot of blog posts about them. It's considered by most to have been a mistake to add this kind of special case for vector< bool >, but for backwards compatibility it's a mistake the C++ committee needs to live with. Nowdays, there is std::bitset as well. If you can help it, I think it's best to just treat vector< bool > as depreciated.
Thanks for taking the time to explain, bottom line is one cannot write one bit at a time......BUT, you might give me a new idea.....If I just use char 'T' for true, 'F' for false or something similar. Something along with this idea:
C++:
//Bytewise logic
#include <iostream>
using namespace std;

int main()
{
    short int a, b, c, d, e, f;
    a = 0x00FF;
    b = 0x0000;
    d = 0x00AA;
    e = 0x0055;

    c = a | b;
    cout << " c = " << c << "\n\n";
    c = a & b;
    cout << " c = " << c << "\n\n";

    f = d ^ e;
    cout << " f = " << f << "\n\n";

    return 0;
}

Idea is if I can find a 1byte char or int and set True=0xFF and False=0x00. I can do AND and OR with that. That, I can simulate a vector of boolean, each 1byte...Hell, if I have to use 2bytes short int, so be it. I can create my "boolean" vector or array.

I need to think about this more.

The reason I need this is because I am writing the bubble sort, I need to keep track each pair whether I have to flip them or not, so I need a parallel vector so I can use the same index to access, and check whether all are true, then I know the sort is complete.

I am doing it my own way, I want to write my own bubble sort BEFORE I even look at the book how they do it. If I keep looking at the book first, I'd never learn.
 
Last edited:
  • #14
yungman said:
Thanks for taking the time to explain, bottom line is one cannot write one bit at a time......BUT, you might give me a new idea.....If I just use char 'T' for true, 'F' for false or something similar. Something along with this idea:
C++:
//Bytewise logic
#include <iostream>
using namespace std;

int main()
{
    short int a, b, c, d, e, f;
    a = 0x00FF;
    b = 0x0000;
    d = 0x00AA;
    e = 0x0055;

    c = a | b;
    cout << " c = " << c << "\n\n";
    c = a & b;
    cout << " c = " << c << "\n\n";

    f = d ^ e;
    cout << " f = " << f << "\n\n";

    return 0;
}

Idea is if I can find a 1byte char or int and set True=0xFF and False=0x00. I can do AND and OR with that. That, I can simulate a vector of boolean, each 1byte...Hell, if I have to use 2bytes short int, so be it. I can create my "boolean" vector or array.

I need to think about this more.

The reason I need this is because I am writing the bubble sort, I need to keep track each pair whether I have to flip them or not, so I need a parallel vector so I can use the same index to access, and check whether all are true, then I know the sort is complete.

I am doing it my own way, I want to write my own bubble sort BEFORE I even look at the book how they do it. If I keep looking at the book first, I'd never learn.
Yeah, for writing in parallel, you might try using a vector of char or uchar instead of bool. Or maybe you could just be careful that more than one thread cannot write to the same byte and use a bitset?

You'll probably be doing sequential programming for quite a while before you have to worry about it. It's only when you have multiple threads where it becomes unsafe.
 
  • #15
Mark44 said:
Edit:
On an x86 Windows machine, here is what the Visual Studio C++ compiler generates. All variables are of type int.
Next, an element of an array is accessed, and its value is assigned to a variable, y.
Code:
// y = Arr[3]
mov eax, 4
imul ecx, eax, 3
mov edx, dword ptr Arr[ecx]
mov dword ptr [y], edx
The first two lines of assembly set the EAX register to 4 (the size of an int), and then multiply it by 3 (the index in the array), storing the value 12 in the ECX register. The number we're looking for is at an offset of 12 bytes from the beginning of the array. The last two lines copy the value at that location to the EDX register, and then copy it to the variable y.
This is in debug mode. in release mode, you get just:
Code:
//static array, the compiler can compute the adress of Arr[3] at compile time.
 move edx, [Arr + 12] for a static array
move [y], edx 
//array on the stack. The data will be at a known offset from ebp 
//ebp = previous value of the stack pointer, used for all local variables and parameters.
move edx, [ebp + offset] 
move [y], edx

And there is no difference between an array, and ordinary local variables
 
  • Like
Likes pbuk
  • #16
willem2 said:
This is in debug mode.
willem2 said:
And there is no difference between an array, and ordinary local variables
I'll have to take your word for this. If I compile in Release mode in VS, the debugger shows only some of the assembly code that is generated.
 
  • #17
Mark44 said:
I'll have to take your word for this. If I compile in Release mode in VS, the debugger shows only some of the assembly code that is generated.
The code was probably optimized away. It's not uncommon to see your entire test program optimized into
Code:
mov eax, 0
ret
you could make the declaration of the array volatile
volatile int arr[10];
that should keep the compiler from optimizing code that uses the array.

You should be able to see all the disassembly that's actually generated and let the debugger step through it.
 
  • #18
Jarvis323 said:
In the early days of C++, they wanted to make vector< bool > more memory efficient. A bool is just true or false, so it can be represented with a single bit. So they specialzed vector< bool > so that it doesn't contain actual bools, it contains bits. This violates some rules about what a vector is supposed to be. And note that memory is addressed and operated on by the machine at the resolution of bytes.

Normally, it's safe to write to different vector elements from different threads. But not in this case.

So a parallel for loop like below,

C:
const size_t END = vb.size();
#pragma omp parallel for
for( size_t i = 0; i < END; ++i )
{
    vb[ i ] = something(i);
}

is a bug if vb is a vector<bool>, whereas it would be fine for any other type of vector. I once spent a few days perplexed why my code was giving wrong results, and then learned this was why.

There are some other issues with vector< bool > as well, and you can find a lot of blog posts about them. It's considered by most to have been a mistake to add this kind of special case for vector< bool >, but for backwards compatibility it's a mistake the C++ committee needs to live with. Nowdays, there is std::bitset as well. If you can help it, I think it's best to just treat vector< bool > as depreciated.
Actually from your response, I came up with this to achieve taking a boolean input and store in a vector of programmable length and perform AND function ( I can do others also, but that's what I need). basically I use a vector <short int>, store 0x00FF for true, 0x0000 for false. I can perform boolean as shown:

C++:
//Bytewise logic
#include <iostream>
#include <vector>
using namespace std;

int main()
{
    vector<short int> Bo;
    int i = 0, index=0, andF; 
    char temp, temp1 ;
    cout << " This program creates a vector of boolean and AND them together\n\n";
    do
    {
        cout << " Enter t for True, f for False and any other key to quit "; cin >> temp;
        if (temp == 't')        Bo.push_back(0x00FF);
        else if (temp == 'f')    Bo.push_back(0x0000);
    } while ((temp == 't') || (temp == 'f'));

    cout << " You entered " << Bo.size() << " elements\n\n";
    index = Bo.size() - 1;
    cout << " You entered {";
    for (int i = 0; i <= index; i++)
    {
        if (temp1 = 't') Bo[i] == 0x00FF;
        else if (temp1 = 'f') Bo[i] == 0x0000;
        cout << temp1 << " ";
    }
    cout << "}\n\n";
    for (int j = 0; j <= index; j++)
        cout << Bo[j] << " ";
    cout << "}\n\n";
    cout << " Index = " << index << "\n\n";
    i = 0;
    do //AND all the elements together
    {
        andF = Bo[i] & Bo[i+1];
        Bo[i + 1] = andF;
        i++;
        cout << " i = " << i << ",  Bo[" << i << "] = " << Bo[i] << ",  andF = " << andF << "\n\n";
    } while (i < index);
    cout << " The result of all the elements of Bo AND together is " << andF << "\n\n";
    return 0;
}
 
  • #19
yungman said:
Actually from your response, I came up with this to achieve taking a boolean input and store in a vector of programmable length and perform AND function ( I can do others also, but that's what I need). basically I use a vector <short int>, store 0x00FF for true, 0x0000 for false. I can perform boolean as shown:

C++:
//Bytewise logic
#include <iostream>
#include <vector>
using namespace std;

int main()
{
    vector<short int> Bo;
    int i = 0, index=0, andF;
    char temp, temp1 ;
    cout << " This program creates a vector of boolean and AND them together\n\n";
    do
    {
        cout << " Enter t for True, f for False and any other key to quit "; cin >> temp;
        if (temp == 't')        Bo.push_back(0x00FF);
        else if (temp == 'f')    Bo.push_back(0x0000);
    } while ((temp == 't') || (temp == 'f'));

    cout << " You entered " << Bo.size() << " elements\n\n";
    index = Bo.size() - 1;
    cout << " You entered {";
    for (int i = 0; i <= index; i++)
    {
        if (temp1 = 't') Bo[i] == 0x00FF;
        else if (temp1 = 'f') Bo[i] == 0x0000;
        cout << temp1 << " ";
    }
    cout << "}\n\n";
    for (int j = 0; j <= index; j++)
        cout << Bo[j] << " ";
    cout << "}\n\n";
    cout << " Index = " << index << "\n\n";
    i = 0;
    do //AND all the elements together
    {
        andF = Bo[i] & Bo[i+1];
        Bo[i + 1] = andF;
        i++;
        cout << " i = " << i << ",  Bo[" << i << "] = " << Bo[i] << ",  andF = " << andF << "\n\n";
    } while (i < index);
    cout << " The result of all the elements of Bo AND together is " << andF << "\n\n";
    return 0;
}
Why use two bytes instead of one? Also, in C and C++, 0 treated as false, and not zero is treated as true. You can do this for example:

C:
std::vector<uchar> vb;
while( 1 )
{
    char input = getUserInput();
    if(      input == 't' ) vb.push_back( true );
    else if( input == 'f' ) vb.push_back( false );
    else break;
}

if( vb.size() > 1 )
{
    for( size_t i = 1, end = vb.size(); i < end; ++i )
    {
        vb[ i ] = vb[ i ] && vb[ i - 1 ];
    }
    vb[ 0 ] = vb[ 1 ];
}

Also, be careful with code like index = v.size() - 1 You can print out v.size() -1 when v is empty to see what I mean.
 
Last edited:
  • Like
Likes yungman
  • #20
I have quite a lot to say, so here goes:

yungman said:
I have two questions here. In the program, I have two different boolean expressions, one using array A[10], the other just using individual variablesB(0..9). They both do the same thing as in the program. My question which one is faster in real life hardware?

Any sensible compiler on any hardware will pre-compute the address of a[10] and access it just as fast as b10. Actually most modern processors (and certainly any 32+ bit x86) have an instruction that makes accessing a[k] (where k is an integer variable) just as fast as b10.

You should learn about Premature Optimization.

You also need to know (but not now) that if you did need to write faster code you need to stay away from std::vector (and for that matter std::string and the other STL classes) because these do a lot of work behind the scenes managing memory allocation for you. With an array you have to do this yourself.

In summary at this stage in your learning about C++ you need to forget about making your code faster, it's like trying to improve your lap times in a car around a race circuit when you haven't even learned how to change gear (C++ is a race car so it has a clutch and a stick shift).

jedishrfu said:
This is a hard and implementation dependent question. My guess would be arrays would be faster from a memory caching point of view with prefetch of data for the cache.
As was pointed out later in the thread a[10] and b10 compile to the same code so even if there was a hardware level user memory prefetch it wouldn't differentiate between them.

yungman said:
In normal situation when we use cin or cin.get, we enter a number, then we have to hit ENTER. If I want to enter any number of integers as I want and want to stop whenever I want, I don't know how to make it easier.
...
Is there any way to simplify that? Something like number1-spacebar-number2-spacebar...until hit enter to quit? I just want to make it easier to enter numbers. I am sure the chapters I studied so far don't have anything like this.
Use std::getline, or if you don't want to learn something new use a sentinel value as @Mark44 suggested.

yungman said:
The reason I need this is because I am writing the bubble sort, I need to keep track each pair whether I have to flip them or not, so I need a parallel vector so I can use the same index to access, and check whether all are true, then I know the sort is complete.

I am doing it my own way, I want to write my own bubble sort BEFORE I even look at the book how they do it. If I keep looking at the book first, I'd never learn.
A bubble sort doesn't need a vector to keep track of anything, just a single boolean.

yungman said:
...
I think you can write better code than in this post, and it will make your life (and ours) much easier if you get into the habit of writing code that is easier to read.

C++:
    // Don't use PascalCase for variables, and pick better names (unless 'bo' really
    // does mean something you will remember in 2 years time).
    vector<short int> Bo;

    // Don't leave variables unitialized. Be consistent with your spacing around '='.
    int i = 0, index=0, andF;

    // You must be able to thing of better names than these - and initialize them.
    char temp, temp1 ;

        // Use constants or even macros  something like TRUE_VALUE and FALSE_VALUE
        // instead of typing literal values each time; you should be able to think of two
        // obvious reasons why, but there are some non-obvious ones too.
        if (temp == 't')        Bo.push_back(0x00FF);
        else if (temp == 'f')    Bo.push_back(0x0000);

    // The name index is usually used to loop over the elements of an array, we would
    // usually call a variable representing the number of elements 'length' or 'size',
    // and we would not reduce it by 1.
    index = Bo.size() - 1;

    // So this line would be for (int i = 0; i < length; i++) - notice we use < instead of <=
    // rather than subtracting 1 from the number of elements.
    for (int i = 0; i <= index; i++)

        // I think you need to revise what '=' and '==' do.
        if (temp1 = 't') Bo[i] == 0x00FF;
        else if (temp1 = 'f') Bo[i] == 0x0000;

    // Why a new variable j, this makes it look like an inner loop - what's wrong with i?
    for (int j = 0; j <= index; j++)

        // Omitting { } around this line is a fast route to a maintenance and debugging nightmare.
        cout << Bo[j] << " ";

    // This time you _have_ resused i!
    i = 0;

        // Why are you changing the values of the array?
        Bo[i + 1] = andF;
 
  • Like
Likes Mark44 and Jarvis323
  • #21
Jarvis323 said:
C:
std::vector<uchar> vb;
while( 1 )
{
    char input = getUserInput();
    if(      input == 't' ) vb.push_back( true );
    else if( input == 'f' ) vb.push_back( false );
    else break;
}

I don't recall I've seen uchar in the book. It can take true or false? You can perform Boolean operation on each element?

Also, what is while( 1 )?

Jarvis323 said:
C++:
if( vb.size() )
{
    for( size_t i = 1, end = vb.size(); i < end; ++i )
    {
        vb[ i ] = vb[ i ] && vb[ i - 1 ];
    }
    vb[ 0 ] = vb[ 1 ];
}

Also, be careful with code like index = v.size() - 1 You can print out v.size() -1 when v is empty to see what I mean.

I don't follow this part:
What is if( vb.size() ) ? Is it if vb.size() = 0, it's false, or else it's true?

Also: for( size_t i = 1, end = vb.size(); i < end; ++i ) , what is size_t? Is it something I have not learn? I only know for(i=0; i<vb.size(); i++) {} type expression.

I am only on chapter 8 of Gaddis' book.

thanks
 
  • #22
yungman said:
I don't recall I've seen uchar in the book. It can take true or false? You can perform Boolean operation on each element?
Also, what is while( 1 )?
uchar is an 8 bit unsigned int. Like I said, in C and C++, 0 is treated as false and not 0 is treated as true.

size_t is an unsigned integer that represents the maximum size that a container can have. This is the type of the value that .size() returns. You might have seen compiler warnings when you assigned .size() to an int. It warns you because size() may be larger than an int can hold without overflowing. If your container had more than 2,147,483,647 elements, then the int would wrap around, for example becoming negative. It's critical to understand the implications of the types you are using. You can play around and try to see what happens when you exceed their limitations, when you use multiple types in a single expression, etc.

https://en.cppreference.com/w/c/types/size_t
 
Last edited:
  • Like
Likes yungman
  • #23
Jarvis323 said:
uchar is an 8 bit unsigned int. Like I said, in C and C++ 0 is treated as false and not 0 is treated as true.
I see. thanks
 
  • #24
pbuk said:
You also need to know (but not now) that if you did need to write faster code you need to stay away from std::vector (and for that matter std::string and the other STL classes) because these do a lot of work behind the scenes managing memory allocation for you. With an array you have to do this yourself.

That's not necessarily true. There is no performance overhead using a vector instead of a raw dynamic array. The only issue is reallocation, which vector will do if it runs out of space while you are pushing new elements. But if you made your own version of a vector, you would need to do the same anyways. Maybe for a custom use case, you can use a better reallocation strategy. That would be the only improvement I can imagine you might make. With vector you can initialize with a specific size, reserve a certain amount of space, etc. If using these features to avoid the vector reallocating memory is enough, then you will gain nothing from using your own vector implementation.

And other STL classes like map, unordered_map, and list are perfectly fine implementations of the corresponding data structures. You can implement your own hash map, but do you really need to, and why should you expect to get a performance benefit?
 
  • #25
Jarvis323 said:
Also, be careful with code like index = v.size() - 1 You can print out v.size() -1 when v is empty to see what I mean.
How about
index = v.size()

Then in the later lines I use (i < (index - 1)) instead of (i < index)
 
  • #26
yungman said:
How about
index = v.size()

Then in the later lines I use (i < (index - 1)) instead?
The point I was making is that v.size() has type size_t, which is an unsigned integer type. If you subtract 1 from an unsigned integer 0, then what happens is that it wraps around to the maximum value. So if subtracting from an unsigned type, you have to consider what happens if the value goes below zero, especially in loop conditions, because in this case subtraction can yield a larger (very large) value where a smaller value was intended.

What you proposed is fine, because index is a signed int, so it can go below zero to end the loop.
 
  • #27
yungman said:
I have two questions here. In the program, I have two different boolean expressions, one using array A[10], the other just using individual variablesB(0..9). They both do the same thing as in the program. My question which one is faster in real life hardware? My guess is B(0..9) is faster even though it looks stupid. I think each variable use individual address, so it's one step access. The one using array has to take the starting address, add the index to get the address before accessing the value. I put a lot more emphasis on efficiency than make the code looks "nice".

Also, in the process of declaring the bool A[10], I found out I had to initialize with {1, 1, 1, 1, 1, 1, 1, 1, 1, 1} INSTEAD of {1} for all 10 elements. Why?

C++:
//Efficiency
#include <iostream>
using namespace std;

int main()
{
    bool A[10] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
    bool B0 = true, B1 = true, B2 = true, B3 = true, B4 = true, B5 = true,
        B6 = true, B7 = true, B8 = true, B9 = true;
    bool An, Bn; // result of AND

    An = A[0] && A[1] && A[2] && A[3] && A[4] && A[5] && A[6] && A[7] && A[8] && A[9];
    Bn = B0 && B1 && B2 && B3 && B4 && B5 && B6 && B7 && B8 && B9;
    cout << " An = " << An << "    Bn = " << Bn << "\n\n";
    return 0;
}

Thanks

I think that in the future, when you've learned about structs and classes, then you will probably want to implement a series of related variables like B0-10 as a struct if not an array. An example would be a mathematical vector.

C:
struct Vec3
{
    float x;
    float y;
    float z;
} vec3;
//or
float vec3[3];

In that case, they should be basically equivalent under the hood. Both are guaranteed to be contiguous in memory. There isn't any reason I can think of why a compiler should generate different code when either of them are used. Being contiguous can be good for the performance, because a single machine instruction can load multiple at once, or even operate on multiple at once, or cache a large chunk of them.In most cases, don't worry about these kind issues you brought up when it comes to performance. Worry about the algorithms and data structures, worry about making unnecessary copies of large objects (pass them by reference instead of by value), then worry about parallelism and vector instructions or maybe using the GPU, then worry about caching issues and so forth. Focus on the slow parts. After you've gone through all of the serious optimization strategies, then you can worry about these type of issues you brought up. When you do that, you need to do trial and error, maybe look at the assembly, and don't expect it to be the same for a different compiler or machine, or when the whole program has changed.
 
Last edited:
  • #28
yungman said:
I don't recall I've seen uchar in the book.
Jarvis323 said:
uchar is an 8 bit unsigned int. Like I said, in C and C++, 0 is treated as false and not 0 is treated as true.
uchar appears to be a Microsoft thing. I didn't remember seeing it before, so I did a Google search for "c++ uchar" and came up with this from Stackoverflow:

If you try to find definition of uchar (which is pressing F12 if you are using Visual Studio), then you'll end up in OpenCV's core/types_c.h:

#ifndef HAVE_IPL
typedef unsigned char uchar;
typedef unsigned short ushort;
#endif

When I tried to compile a simple test program that declares a uchar variable, using g++, I got this:

Code:
% g++ -std=c++11 uchartest.cpp
uchartest.cpp:5:5: error: unknown type name 'uchar'
    uchar foo;
    ^
1 error generated.
yungman's textbook probably sticks to standard C++.
 
  • Informative
Likes Jarvis323
  • #29
jtbell said:
uchar appears to be a Microsoft thing. I didn't remember seeing it before, so I did a Google search for "c++ uchar" and came up with this from Stackoverflow:
When I tried to compile a simple test program that declares a uchar variable, using g++, I got this:

Code:
% g++ -std=c++11 uchartest.cpp
uchartest.cpp:5:5: error: unknown type name 'uchar'
    uchar foo;
    ^
1 error generated.
yungman's textbook probably sticks to standard C++.

Oh, thanks for pointing that out. I usually use uint8_t so I didn't realize this. I only used uchar when using OpenCV since it's the type OpenCV loads an image as. I just naively thought it was standard, and it compiles fine for me with g++ when using OpenCV, but it turns out that's only because OpenCV defines it in its header.
 
Last edited:
  • #30
With respect to the array vs single variable issue, there’s a scheme called cache prefetch where sequential memory locations as in instructions or an array can be loaded ie prefetched for use when the processor gets to those steps.

https://en.wikipedia.org/wiki/Cache_prefetching

it can be either hardware, software or a mix of the two schemes to improve program performance. In this instance, arrays in loops can be processed faster than via memory addressing.
 
  • #31
I just want to update everyone, It is correct I DO NOT need the boolean array, just one boolean variable is good enough. I am on the bubble sort now. I am stuck on some other things that the program got hung up. I want to spend some time before I cry for help. I need to learn to solve my own problem...at least give it a real try.

Thanks.
 
  • Like
Likes Tom.G
  • #32
Always remember the print statement is your friend. It can always help you to find most of your bugs unless you introduce one in it too.
 
  • Like
Likes yungman
  • #33
jedishrfu said:
Always remember the print statement is your friend. It can always help you to find most of your bugs unless you introduce one in it too.
If I can give you a double like, I would! I did NOT know I can print the .cpp! I always had to copy onto word.

Yes, it's much easier to read on paper, so far I am stuck, hopefully reading from the paper can help. I still have not taken a peek at the the program in the book, I want to do it on my own first. But it's getting very short already. I must have put something in an infinite loop somewhere. But when I put in cout<<"..." to print out where I am in the program at different spot, it gave me correct answer.

Thanks

BTW, I only follow the uchar discussion on and off, too busy. So should I put in my notes to use it if it only works in VS? But in reality, even if I use short int that is 2bytes, it's not a big deal as memory is cheap now a days. At least I don't need it now, but spending a day looking into this sure learn a lot.
 
  • #34
I got it. With the print out, it's easier, I spotted one error from the print, but the most important and stupid one is I put a ';' at the end of the function definition. It skip the function all together!
C++:
// 8.4 Alan bubble sort
#include <iostream>
#include <vector>
using namespace std;
void sortAr(vector <int>&, int&);//sorting function with reference parammeters of vector SA and size of the vector
void InputAr(vector <int>&, int&);// to get numbers from user.
int main()
{
    int sz;
    vector <int> SA;// vector to store the numbers from user for sorting
    InputAr(SA, sz);// For user to input numbers for sorting
    cout << " The size of vector SA is " << SA.size();
    cout << "     SA = {";
    for (int i = 0; i < sz; i++)
        cout << SA[i] << " ";
    cout << "} \n\n";

    sortAr(SA, sz);
    cout << " The result after sorting = {";
    for (int i = 0; i < sz; i++)
        cout << SA[i] << " ";
    cout << "} \n\n";
    return 0;
}
void InputAr(vector<int>&Av, int &size)// to get numbers from user.
{
    int num;
    do
    {
        cout << " Enter any +ve integer to be sorted, enter -1 to quit "; cin >> num;
        if (num >= 0)
            Av.push_back(num);// Put new number into the last element starting with Av[0].
    } while (num >= 0);// only take numbers >=0, -ve number to terminate.
    cout << "\n\n";
    size = Av.size();
}

void sortAr(vector <int>& AR, int &size)
{       
    bool nSwap;
    int h = 1, temp;
    do
    {
       
        nSwap = true;// start the do-while with nSwap = true, let the inner while loop to change to false.
        h = 1; //Reset h = 1 and start over again.
        while (h < size)
        {
            if (AR[h-1] > AR[h])
            {
                nSwap = false;// If there is a swap, it is change to false
                temp = AR[h-1];
                AR[h-1] = AR[h];
                AR[h] = temp;//swap AR[h-1] with AR[h]
            }
            h = h + 1;
        }
    } while (nSwap == false);// repeat as long as one pair of elements need to be swap.
}

The ';' I put was at the end of line 38! That screwed up everything.

I looked at the program in the book, the sorting is very similar, but I made it fancier by letting user to input any number and any amount of numbers to sort. The book only use a fixed 6 elements array to sort. That's too easy. I am stoked.BUT, I still have an issue. I am supposed to put -1 to signal I want to quit after entering the numbers. BUT if I hit other key like 'q', it will run non stop and I can see the cmd screen keep rolling and rolling until I close the cmd window. Why?

Thanks
 
  • #35
I got burned by the semicolon a few times when writing code in a hurry:
C:
while(x<3);
{
  ...do something...
}

vs

C:
while(x<3) { ;
   ...do something...
}

The semicolon error of the first one didn't execute the { } block repeatedly while x<3 so I changed my programming style to use the { on the same line where now any errant semicolon is inside the block and so becomes a null statement.

I think modern IDE tools may have options to spot the "mistake" and flag it.
 
  • Like
Likes yungman
  • #36
yungman said:
BUT, I still have an issue. I am supposed to put -1 to signal I want to quit after entering the numbers. BUT if I hit other key like 'q', it will run non stop and I can see the cmd screen keep rolling and rolling until I close the cmd window. Why?
If the << operator can't parse the input as a number, it won't consume the input.
You need to test cin.fail() to see if reading a number worked, and if it didn't work, either stop reading more numbers, or use cin.ignore() to consume the wrong input until you can succesfully read a number again.
 
  • Like
Likes yungman
  • #37
yungman said:
BTW, I only follow the uchar discussion on and off, too busy. So should I put in my notes to use it if it only works in VS?
Instead, you can always use 'unsigned char' which is in standard C++. 'uchar' is simply a shortened name that Microsoft defines in Visual Studio for convenience.
 
  • #38
Regarding the original question, here is what Microsoft Visual C++ does with it using the default optimization settings:

Code:
  bool A[10] = {1, 1, 0, 1, 1, 1, 1, 1, 1, 1};
00141056  mov         dword ptr [ebp-10h],1010101h
0014105D  mov         dword ptr [ebp-0Ch],1010101h
00141064  mov         word ptr [ebp-8],101h

  bool B0 = true, B1 = true, B2 = true, B3 = true, B4 = true, B5 = true, B6 = true, B7 = true, B8 = true, B9 = true;
<optimized out>

  // I declared these volatile to prevent their assignments from being optimized out.
  volatile bool An, Bn; // result of AND

  An = A[0] && A[1] && A[2] && A[3] && A[4] && A[5] && A[6] && A[7] && A[8] && A[9];
0014106A  mov         byte ptr [ebp-1],1

  Bn = B0 && B1 && B2 && B3 && B4 && B5 && B6 && B7 && B8 && B9;
0014106E  mov         byte ptr [ebp-2],1

Also, I moved this into a separate function to make it easier to identify the assembler code. That didn't work. It moved it back inline.

Those 8-hexadigit numbers to the left of the assembler are the actual memory addresses used during program execution.

As you can see, both the An assignment and the Bn assignment were reduced to "Xn=1;".
The only difference was that the default optimization did not get rid of the array - in insisted on creating the array even though it was never used.

The bottom line: Using the array took 9.5 times as much memory [38 bytes (28 code bytes + 10 data bytes) vs. 4 code bytes] and roughly 4 or 5 times as much execution time. Execution time is harder to determine because it is dependent on the processor's particular caching features and the cache states when the code is executed.

This is is good at showing the difference between a MSVC "debug" build (no optimizations) and a "release" build (default optimizations). Using the release build, setting breakpoints becomes problematic. Since it moved my function inline, it was not possible to put a breakpoint anywhere in that source code. Instead, I needed to put the breakpoint on the call to that function.
 
Last edited:
  • #39
I am on fire! I did the Selection sort in one evening!
C++:
// 8.5 Selection sort
#include <iostream>
#include <vector>
using namespace std;
void sortAr(vector <int>&, int&);
void InputAr(vector <int>&, int&);
int main()
{
    int sz;
    vector <int> SA;
    InputAr(SA, sz);
    cout << " The size of vector SA = " << SA.size()<< "\n\n";
    cout << " SA = {";
    for (int i = 0; i < sz; i++)
        cout << SA[i] << " ";
    cout << "} \n\n";
    sortAr(SA, sz);
    cout << " The numbers after sorting of vector SA = ";
    cout << " {";
    for (int i = 0; i < sz; i++)
        cout << SA[i] << " ";
    cout << "} \n\n";
    return 0;
}
void InputAr(vector<int>&Av, int &size)
{
    int num;
    do
    {
        cout << " Enter any +ve integer to be sorted, enter -1 to quit "; cin >> num;
        if (num >= 0)
            Av.push_back(num);
    } while (num >= 0);
    cout << "\n\n";
    size = Av.size();
}
void sortAr(vector <int>& AR, int& size)
{
    int startScan = 0, index, temp;
    do
    {
        index = startScan + 1;;
        while (index < size)
        {
            if (AR[startScan] > AR[index])//comparing the lowest number element starting with AR[0] to the rest 
            {                    // one by oneswitch with them if it is higher than the other elements.
                temp = AR[startScan];
                AR[startScan] = AR[index];
                AR[index] = temp;
            }
            index = index + 1;// to the next higher element to compare,  AR[1]->AR[2]-> AR[3]...
        }
        startScan = startScan + 1;
    } while (startScan < (size - 1));
}
I am stoked, no question on this. Now I am going to work on why if I put a char instead of -1 to quit and causes the program into an infinite loop.
 
  • Like
Likes jedishrfu
  • #40
I cannot figure out why when I hit character instead of -1, it will not quit and run in loop. I simplified to just a few lines. Please help:
C++:
// infinite loop when enter character
#include <iostream>
#include <vector>
using namespace std;
void InputAr();
int main()
{
    int sz;
    InputAr();
    return 0;
}
void InputAr()
{
    int num;
    do
    {
        cout << " Enter any +ve integer to be sorted, enter -1 to quit "; cin >> num;
    } while (num >= 0);
}
Problem seems to be in line 18.
Thanks
 
  • #41
See post #36. If the input isn't a valid number, num won't change, and the non-numeric characters won't be removed from the input stream.
 
  • Like
Likes yungman
  • #42
Here's a example of how one might deal with this sort of input error. It takes advantage of the fact that when you use an input expression like cin << num in a Boolean expression, it evaluates as true or false depending on whether the input succeeded.

In addition to cin.ignore(), you also need to use cin.clear().

C:
#include <iostream>

using namespace std; // for conciseness because this is only a toy program

int main ()
{
    int num;
    cout << "Please enter an int: ";
    while (!(cin >> num))
    {
        cin.clear();  // reset the stream's failure flag
        // discard 100 chars, or until the next '\n', whichever comes first
        cin.ignore (100, '\n');
        cout << "That's not an int. Please try again: ";
    }
    cout << "OK, you entered " << num << endl;
    return 0;
}
Code:
% g++ inputerror.cpp -o inputerror
% ./inputerror
Please enter an int: 23
OK, you entered 23
% ./inputerror
Please enter an int: fooey
That's not an int. Please try again: 42
OK, you entered 42
% ./inputerror
Please enter an int: eeny
That's not an int. Please try again: meeny
That's not an int. Please try again: 42
OK, you entered 42
Alternative version using cin.fail(). Note cin >> num appears twice.
C:
#include <iostream>

using namespace std; // for conciseness because this is only a toy program

int main ()
{
    int num;
    cout << "Please enter an int: ";
    cin >> num;
    while (cin.fail())
    {
        cin.clear();  // reset the stream's failure flag
        // discard 100 chars, or until the next '\n', whichever comes first
        cin.ignore (100, '\n');
        cout << "That's not an int. Please try again: ";
        cin >> num;
    }
    cout << "OK, you entered " << num << endl;
    return 0;
}
 
Last edited:
  • Like
Likes yungman
  • #43
jtbell said:
Here's a example of how one might deal with this sort of input error. It takes advantage of the fact that when you use an input expression like cin << num in a Boolean expression, it evaluates as true or false depending on whether the input succeeded.

In addition to cin.ignore(), you also need to use cin.clear().

C:
#include <iostream>

using namespace std; // for conciseness because this is only a toy program

int main ()
{
    int num;
    cout << "Please enter an int: ";
    while (!(cin >> num))
    {
        cin.clear();  // reset the stream's failure flag
        // discard 100 chars, or until the next '\n', whichever comes first
        cin.ignore (100, '\n');
        cout << "That's not an int. Please try again: ";
    }
    cout << "OK, you entered " << num << endl;
    return 0;
}
Code:
% g++ inputerror.cpp -o inputerror
% ./inputerror
Please enter an int: 23
OK, you entered 23
% ./inputerror
Please enter an int: fooey
That's not an int. Please try again: 42
OK, you entered 42
% ./inputerror
Please enter an int: eeny
That's not an int. Please try again: meeny
That's not an int. Please try again: 42
OK, you entered 42
Alternative version using cin.fail(). Note cin >> num appears twice.
C:
#include <iostream>

using namespace std; // for conciseness because this is only a toy program

int main ()
{
    int num;
    cout << "Please enter an int: ";
    cin >> num;
    while (cin.fail())
    {
        cin.clear();  // reset the stream's failure flag
        // discard 100 chars, or until the next '\n', whichever comes first
        cin.ignore (100, '\n');
        cout << "That's not an int. Please try again: ";
        cin >> num;
    }
    cout << "OK, you entered " << num << endl;
    return 0;
}
Thanks so much, that works.

I have 3 books on C++, I can't find either
while (!(cin >> num)) OR if (!(cin >> num))
I did not know (cin >> num) can be a boolean to tell whether the input is NOT a number.

Thank you so much. Looks like I am going to finish chapter 8 sooner than I expected...knock on wood.
 
  • #44
I must be asking for it, I want to make the exercise more challenging, I am stuck on trying to do either a vector of strings or a 2D vector of char. This is the array I want to make into vector:
C++:
const int Row = 9, ProdCol = 31;
char Prod[Row][ProdCol] = { {"Six Steps to Leadership"}, {"Six Steps to Leadership"}, {"Road to Exellence"},
                {"Seven Lessons of Quality"},{"Seven Lessons of Quality"},{"Seven Lessons of Quality"},
                {"Teams Are Made, Not Born"}, {"Leadership for the Future"}, {"Leadership for the Future"} };

I went on line to try to look up 2D vector. It's easy to create 2D vector of numbers:

C++:
    vector<vector<int> > vect{ { 1, 2, 3 },
                               { 4, 5, 6 },
                               { 7, 8, 9 } };

BUT, it doesn't work for characters like this:

C++:
        vector<vector<char> > vect{ { "this is a test" },
                                    { "Second test"},
                                    { "Third test"} };

I looked up using vector of strings, it's over my head, I don't understand this:

C++:
    std::string s = "Hello World!";

    std::vector<char> v(s.begin(), s.end());

    for (const char& c : v)
        std::cout << c;

Is there any way to use vector that is within my knowledge level? If it is too advance for me, let me know.

Thanks
 
Last edited:
  • #45
If your compiler supports the C++ 2011 standard, you should be able to compile this.

C:
#include <iostream>
#include <string>
#include <vector>

using namespace std; // for brevity since this is just a toy program

int main ()
{
    vector<string> titles = { "Six Steps to Leadership",
                              "Six Steps to Leadership",
                              "Seven Lessons of Quality",
                              "Seven Lessons of Quality",
                              "Seven Lessons of Quality",
                              "Teams Are Made, Not Born",
                              "Leadership for the Future" };

    for (int k = 0; k < titles.size(); ++k)
    {
        cout << titles[k] << endl;
    }

    return 0;
}
With my compiler, I have to specify c++11 explicitly, otherwise it uses an earlier standard.
Code:
% g++ -std=c++11 vecstrings.cpp -o vecstrings
% ./vecstrings
Six Steps to Leadership
Six Steps to Leadership
Seven Lessons of Quality
Seven Lessons of Quality
Seven Lessons of Quality
Teams Are Made, Not Born
Leadership for the Future
%
You're using Visual Studio, right? Then see this Microsoft support page if necessary:

/std (Specify Langauge Standard Version)

According to that page, VS 2017 or later defaults to C++ 2014 (which of course includes all the features of C++ 2011), so you should be OK unless you're using an older version of VS.
 
Last edited:
  • Like
Likes yungman
  • #46
yungman said:
I have 3 books on C++, I can't find either
while (!(cin >> num)) OR if (!(cin >> num))
I did not know (cin >> num) can be a boolean to tell whether the input is NOT a number.
I don't remember whether I learned that technique in the textbook I was teaching from, or some other book, or online. It was 15-20 years ago.

A similar technique is commonly used when reading files, for detecting the end of file. (One way the input can fail is to reach the end of file.) Your book might discuss examples like this:

C:
#include <iostream>
#include <fstream>
#include <string>
#include <vector>

using namespace std; // for brevity since this is just a toy program

int main ()
{
    ifstream inputFile ("titles.txt");
    if (inputFile.fail())
    {
        cout << "Sorry, can't open titles.txt!" << endl;
        return 0;
    }

    vector<string> titles;
    string eachTitle;
    while (getline (inputFile, eachTitle))
    {
        titles.push_back (eachTitle);
    } 
    
    inputFile.close();

    for (int k = 0; k < titles.size(); ++k)
    {
        cout << titles[k] << endl;
    }

    return 0;
}
The file titles.txt:
Code:
Six Steps to Leadership
Six Steps to Leadership
Seven Lessons of Quality
Seven Lessons of Quality
Seven Lessons of Quality
Teams Are Made, Not Born
Leadership for the Future
And the output:
Code:
% g++ vecstringsfile.cpp -o vecstringsfile
% ./vecstringsfile
Six Steps to Leadership
Six Steps to Leadership
Seven Lessons of Quality
Seven Lessons of Quality
Seven Lessons of Quality
Teams Are Made, Not Born
Leadership for the Future
I'm pretty sure I remember teaching this method. It also works with the >> operator. Your book might prefer to use the eof() member function instead:
C:
#include <iostream>
#include <fstream>
#include <string>
#include <vector>

using namespace std; // for brevity since this is just a toy program

int main ()
{
    ifstream inputFile ("titles.txt");
    if (inputFile.fail())
    {
        cout << "Sorry, can't open titles.txt!" << endl;
        return 0;
    }

    vector<string> titles;
    string eachTitle;
    while (true)
    {
        getline (inputFile, eachTitle);
        if (inputFile.eof()) break;  // without this we would have an infinite loop
        titles.push_back (eachTitle);
    } 
    
    inputFile.close();

    for (int k = 0; k < titles.size(); ++k)
    {
        cout << titles[k] << endl;
    }

    return 0;
}
 
  • Like
Likes yungman
  • #47
jtbell said:
I don't remember whether I learned that technique in the textbook I was teaching from, or some other book, or online. It was 15-20 years ago.

A similar technique is commonly used when reading files, for detecting the end of file. (One way the input can fail is to reach the end of file.) Your book might discuss examples like this:

C:
#include <iostream>
#include <fstream>
#include <string>
#include <vector>

using namespace std; // for brevity since this is just a toy program

int main ()
{
    ifstream inputFile ("titles.txt");
    if (inputFile.fail())
    {
        cout << "Sorry, can't open titles.txt!" << endl;
        return 0;
    }

    vector<string> titles;
    string eachTitle;
    while (getline (inputFile, eachTitle))
    {
        titles.push_back (eachTitle);
    }
   
    inputFile.close();

    for (int k = 0; k < titles.size(); ++k)
    {
        cout << titles[k] << endl;
    }

    return 0;
}
The file titles.txt:
Code:
Six Steps to Leadership
Six Steps to Leadership
Seven Lessons of Quality
Seven Lessons of Quality
Seven Lessons of Quality
Teams Are Made, Not Born
Leadership for the Future
And the output:
Code:
% g++ vecstringsfile.cpp -o vecstringsfile
% ./vecstringsfile
Six Steps to Leadership
Six Steps to Leadership
Seven Lessons of Quality
Seven Lessons of Quality
Seven Lessons of Quality
Teams Are Made, Not Born
Leadership for the Future
I'm pretty sure I remember teaching this method. It also works with the >> operator. Your book might prefer to use the eof() member function instead:
C:
#include <iostream>
#include <fstream>
#include <string>
#include <vector>

using namespace std; // for brevity since this is just a toy program

int main ()
{
    ifstream inputFile ("titles.txt");
    if (inputFile.fail())
    {
        cout << "Sorry, can't open titles.txt!" << endl;
        return 0;
    }

    vector<string> titles;
    string eachTitle;
    while (true)
    {
        getline (inputFile, eachTitle);
        if (inputFile.eof()) break;  // without this we would have an infinite loop
        titles.push_back (eachTitle);
    }
   
    inputFile.close();

    for (int k = 0; k < titles.size(); ++k)
    {
        cout << titles[k] << endl;
    }

    return 0;
}
Thanks for all the help, Your first example works like a champ. I already put it in my notes and moved on.
 
  • #48
I am stuck on a new problem. This is on passing vector to function.
C++:
//
//
//
#include <iostream>
#include <iomanip>
#include <vector>
using namespace std;
void getnumSold(vector<int>&);
vector<int>DefaultNSold = { 842, 416, 127, 514, 437, 269, 97, 492, 212 };
int main()
{
    vector<int>Sold(9);
    getnumSold(Sold);// copy vector DefaultNSold into Sold
    cout << "In main return from getnumSold Sold = {";
    for (int i = 0; i < 9; i++)
        cout << Sold[i] << " ";
    cout << "} \n\n";// To show it got copied over
    return 0;
}
void getnumSold(vector<int>& numSold)// reference to return the values to Sold in main
{
        int row;
        vector<int>numSold(DefaultNSold);//copy the content of DefaultNSold into numSold
        cout << " In getnumSold, You chose to use default = {";
        for (row = 1; row < DefaultNSold.size(); row++)
        {
            cout << numSold[row - 1] << " ";
        }
}
I don't know why I get an error. I checked through the syntax and I cannot find any problem.

It is a very simple program, just calling a function that copy the vector DefaultNSold into numSold and display numSold to show it copy back to vector SOLD in main().

Please help.

Thanks
Compile error Listing 7.2.jpg
 
  • #49
You need to get better at reading error messages. The message says "redefininition of formal parameter 'numSold' on line 23" which clearly tells you all you need to know: on line 23 you redefine numsold which was already defined as a parameter to the function.

Also the code for iterating rows has a number of problems:

C:
       for (row = 1; row < DefaultNSold.size(); row++)
        {
            cout << numSold[row - 1] << " ";
        }

This will miss the last row (think about what happens if size() returns 1). C++ indices start at zero, starting at 1 and then subtracting 1 makes no sense at all - remember what a mess you got into before doing this? It is also not a good idea to use a different array (DefaultNSold) for the limit than the one you are iterating over (numSold) - this makes it difficult to debug (and also makes it almost impossible for the compiler to optimize).

The standard way to write this sort of loop is like this:

C:
    for (int row = 0; row < numSold.size(); row++) {
        cout << numSold[row] << " ";
    }

Oh and for the umpteenth time stop mixing capital letters at the beginning of variable names - (DefaultNSold and numSold). A good convention is to use camelCase for variable names, this means you can save PascalCase for names of classes and structs.
 
  • #50
jedishrfu said:
I think modern IDE tools may have options to spot the "mistake" and flag it.
I know for sure that Visual Studio will flag it, the community edition is free and pretty easy to use. I go back and forth between command line and IDE.
 
  • Like
Likes jedishrfu

Similar threads

Replies
7
Views
2K
Replies
6
Views
2K
Replies
5
Views
2K
Replies
75
Views
6K
Replies
9
Views
2K
Replies
6
Views
4K
Back
Top