Trouble with sort function replacing values - c++

I'm just learning c++, and I've come to my first problem. I'm using visual studio and c++11. this is the code:
cout << "Enter 5 numbers to add." << endl;
for (int i(0); i < 5; ++i) {
int x;
cin >> x;
intList.push_back(x);
}
for (int item:intList) {
sort(begin(intList), end(intList));
cout << item << " ";
total += item;
}
cout << endl;
cout << "Your total is " << total << endl;
As you can tell, it ask you to input 5 number and it adds them up. When I use cout, it output the contents of the vector correctly. As soon as I added the sort line, I had problems. It sorts the vector correctly, except it replaces the lowest value with the first value, even though it places it in the correct order. Example:
Enter 5 numbers to add.
87 95 61 43 2
87 43 61 87 95
Your total is 373
Also an additional question, is using item::intList the best/efficient way to iterate a vector.
I'm sure this is an obvious solution. Thanks.

You need to reposition the call to sort so that it's outside the for loop.
Currently your sort is invalidating the iterator (on its first call as thereafter it's a no-op) which is causing the effect you observe.
(I'm sure you know that you don't need to sort the vector in order to compute the total.)

Related

Output is letter by letter after converting to uppercase to negate case sensitivity

I am trying to figure out what is causing my function to output letter by letter on separate lines after converting from a lowercase string to all uppercase, in an effort. My assignment is asking us to write a program that asks the user for a state's capital and then reports if the user was correct. It keeps a tally of the number of correct answers and gives it at the end.
It specifically states that the user's answers are not case sensitive, which is giving me the most trouble.
So far, I have tried using a character array and then converting that, but that became very confusing to try and convert/compare the multidimensional string array of states and capitals with the user's potential guesses.
Now, however, it has started saying that any input is incorrect unless it is in all caps. It has also started printing letter by letter, all caps, on different lines, so at least we know the loop is working.
My intention was to take input that was not in caps, convert it, and compare that converted string to the correct answer, so that both strings being compared were in all caps.
To spare y'all, I've cut it down to four states, and made sure to include a state with a space in the string answer.
1 #include <iostream>
2 #include <string>
3 using namespace std;
4 string convertCase(string entryToConvert){
5 string convertedString;
6 int i=0;
7 while (i <= size(entryToConvert)){
8 convertedString = toupper(entryToConvert[i]);
9 i++;
10 cout << convertedString << endl;
11 }
12 return convertedString;
13 }
14
15 int main() {
16 string statesAndCaps[4][2] = {
17 {"Alabama", "MONTGOMERY"}, {"Alaska", "JUNEAU"},
18 {"Arizona", "PHOENIX"}, {"Arkansas", "LITTLE ROCK"},
19 };
20 int correctCounter = 0, statesLoop = 0;
21 string guess, convertedString;
22 while (statesLoop != 4) {
23 cout << "Enter the capital of " << statesAndCaps[statesLoop][0] << " and press ENTER: ";
24 getline(cin, guess);
25 convertedString = convertCase(guess);
26 cout << convertedString;
27 if (convertedString == statesAndCaps[statesLoop][1]){
28 cout << "Correct. Total correct guesses: " << correctCounter << endl;
29 correctCounter++;
30 } else {
31 cout << "Incorrect. Total correct guesses: " << correctCounter << endl;
32 }
33 statesLoop++;
34 }
35 cout <<"You got " << correctCounter << " correct!" << endl;
36 return 0;
37 }
I have specifically coded in some outputs to try and check on what exactly was going awry. These are cout << convertedString << endl; and cout << convertedString; in lines 10 and 26. It produced:
Enter the capital of Alabama and press ENTER: Montgomery
M
O
N
T
G
O
M
E
R
Y
Incorrect. Total correct guesses: 0
Enter the capital of Alaska and press ENTER: JUNEAU
J
U
N
E
A
U
Incorrect. Total correct guesses: 0
Enter the capital of Arizona and press ENTER:
I believe it is the convertCase() function causing this, but can't quite figure out what is setting it off to (seemingly) not compare the converted string as a whole.
Guidance appreciated! Please make it simple, I am still trying to figure this all out, it is rather confusing and there's a lot of jargon I am still puzzling through.
Line 10 looks to have a spurious print statement - probably useful for debugging at some point:
cout << convertedString << endl;
Just remove that line and your code is partially fixed.
Also, this looks suspicious:
while (i <= size(entryToConvert)){
You probably meant:
while (i < size(entryToConvert)){
But that's not the only bug in that function.
This line:
convertedString = toupper(entryToConvert[i]);
Assigns a single string to convertedString and overrites whatever was there before. Hence, your convert function will just return the last char of entryToConvert as a string.
You really want:
convertedString += toupper(entryToConvert[i]);
This is closer to what you want:
string convertCase(const string& entryToConvert){
string convertedString;
for (char c : entryToConvert) {
convertedString += toupper(c);
}
return convertedString;
}

Local Variable being changed without manipulation

I'm creating a simple quick sort program that initializes an empty array and asks the users for inputs to determine how many elements are going to be sorted and what elements are going to be sorted.
The problem I am encountering is a local variable is being changed despite being only being referenced to once assigned. Attached below is the code.
int main()
{
int amount;
int numbersarray[] = {};
std::cout << "How many numbers do you want to sort? " << std::endl;
std::cin >> amount;
for(int i = 0; i <= amount; i++){
std::cout << "Enter number to be sorted: " << std::endl;
std::cin >> numbersarray[i];
}
std::cout <<"Amount to be sorted: " << amount << std::endl;
for(int i = 0; i <= amount; i++){
std::cout << numbersarray[i] << std::endl;
}
}
What I expect to be occurring, when I input the amount as 5, I should be able to input 5 elements into the array, instead however the Amount printed is 2 and the maximum elements I can put into the array is 3.
Below is the execution output.
How many numbers do you want to sort?
5
Enter number to be sorted:
5
Enter number to be sorted:
2
Enter number to be sorted:
5
Amount to be sorted: 2
5
2
5
I've tried messing around with the for statement but I don't think I'm doing it right as it hasn't fixed the problem, The manipulation of the for statement I'm doing is changing the condition (i.e !=, <, <=)
You have undefined behavior. Anything can happen. Local variable can change without reason, the program can crash and your computer can format itself with linux 6.9
There are many problem. The first is that your program is invalid according to the standard:
int numbersarray[] = {};
This is not valid. Array need a size:
constexpr int max_amount = 32;
int numbersarray[max_amount] = {};
If you need it to be dynamic, use vector:
std::vector<int> numbersarray;
numbersarray.resize(amount);
Second, you have another source of undefined behavior:
// Iterates too much, numbersarray[amount] is past the end
// ~~~v~~~~~~~
for(int i = 0; i <= amount; i++){
std::cout << "Enter number to be sorted: " << std::endl;
std::cin >> numbersarray[i];
}
It should be:
for(int i = 0; i < amount; i++){
std::cout << "Enter number to be sorted: " << std::endl;
std::cin >> numbersarray[i];
}
To avoid invalid code and undefined behavior, you should enable warnings.
numbersarray is a C-style array with a size of zero and doesn't adjust its size dynamically (most compilers might even fail to compile int numbersarray[] = {}; since an empty initializer isn't allowed for an array with unspecified size).
Writing or reading its elements causes undefined behaviour (which can be access violations, changing unrelated variables, and much more). This is the reason why you might see the values of local variables changing. Someone else that uses the same code could get completely different behaviour, since it is undefined.

Unexpected array behavior in basic averaging program

It seems like I always come here to ask silly questions, but here it goes. As of right now I am in my first compsci course and we are learning c++. I've had an extremely basic introduction to c before, so I had thought I'd go above and beyond my current assignment. Now I was doing this just to showboat, I felt like if I didn't practice my previous concepts they would eventually fade. Anyways, on to the problem! I was supposed to write some code that allowed the user to input their initials, and a series of exams. Now this was supposed to accomplish three things: average the exams, print out the entered exams, and print out their initials. Well, what was a simple assignment, got turned into a huge mess by yours truly.
#include <iostream>
#include <string>
#include <iomanip>
using namespace std;
int main()
{
string uInitials;
float avgExam = 0, tExam = 0;
int aExams[10] = {'0'};
int i, nExam = 0, cExam;
cout << "Enter your three initials!";
cin >> uInitials;
do
{
cout << "Enter your exam(s) to be averaged. Enter 0 when complete!\n";
cin >> cExam;
aExams[nExam] = cExam; //I used this before nExam was incremented, in order to get nExam while it was '0' That way the first exam score would be properly saved in the first space
nExam++;
tExam += cExam; //This is just to add all the exams up to later calculate the average
}
while(cExam != 0);
avgExam = tExam/(nExam - 1); //subtracted '1' from nExams to remove the sentinel value from calculations.
cout << "The average for initials: " << uInitials << " is: " << avgExam << endl;
cout << "This average was obtained using the following scores that were entered: \n";
for(i = 0; i < (nExam+1); i++)
{
cout << aExams[i] << endl; //Used a for loop to prevent redundancy
}
return 0;
}
The previous is my code, and the problem is that I'm getting output errors where it adds two '0's when I print out the list of entered exams. Also I feel like I made the whole do{}while() loop one huge clunky mess, so I'd like to refine that as well. If anyone could assist this poor, ignorant, beginner I would greatly appreciate it. Thank you for your time!
Some advice that i can give is for example in the 5th line there is no need
to put the 0 between ' ' and not even need to use the assign = operator.
You can initialize the array like this:
int aExams[10]{0};
Which will initialize all elements to 0,but can't be used for other value.
For example you won't have all the elements with value 1 if you write
int aExams[10]{1};
If your intention to initialize all elements in an array is with value other than 0 you can use fill_n(); function.
fill_n(aExams, 10, 1);
The first argument is the name of the array, the second is up-to which element you want to be initialized with the third argument, and the third is the value you want all elements to have.
Do not leave uninitialized variables like in line 6 with cExam and i variables. Initialize it like cExam=0; (copy-assign initialization) or cExam(0); (direct initialization). The latter calls the constructor for int built-in type.
A negative i see in your do-while loop is that you do not make sure that the user will enter under 10 exams,bad things will happen if the user tries to input 15 exams in an array that can hold only 10.
Just change the while to something more like this:
while( cExam != 0 && (nExam<10) );
You can also write the first two lines of the do-while loop outside the loop.
It is needed only once to tell the user that to stop the loop he/she needs to enter 0. There is no need to tell them this on every iteration plus that you will have a good performance benefit if you put those two lines outside the loop.
Look here how i would write the code and ask if you have any questions.
http://pastebin.com/3BFzrk5C
The problem where it prints out two 0's at the end of your code is a result of the way you wrote your for loop.
Instead of:
for(i = 0; i < (nExam+1); i++)
{
cout << aExams[i] << endl; //Used a for loop to prevent redundancy
}
Use:
for (i = 1; i < (nExam); i++)
{
cout << aExams[i - 1] << endl; //Used a for loop to prevent redundancy
}

stl::sort() is changing the attributes of the objects it is sorting

I've been coding a solution for the Graph Coloring Problem using Brown's algorithm. The algorithm is working just fine but, to add a little efficiency I'm trying to sort the nodes by their degree. To do so I'm using stl::sort(). Nonetheless, after sort has ordered the elements, the adyacency list of each element has been modified. I've got 4 files:
nodo.h:
class Nodo{
private:
int id;
int color;
vector<Nodo*> adyacentes;
public:
int grado;
vector<Nodo*> getAdyacentes();
int getId();
int getColor();
}
nodo.cpp -> Includes the basic implementation of the getters.
grafo.h:
class Grafo{
private:
Nodo *nodos;
int tam;
public:
void colorearBrown();
void imprimir();
}
grafo.cpp:
void Grafo::imprimir(){
cout << setw(6) << "Numero" << setw(5) << " Color" << " Nodos adyacentes" << endl;
for(int i = 0; i < tam; ++ i){
cout << setw(6) << nodos[i].getId() << setw(5) << nodos[i].getColor() << " ";
vector<Nodo*> ady = nodos[i].getAdyacentes();
for(vector<Nodo*>::iterator it = ady.begin(); it != ady.end(); ++ it){
if (it != ady.begin()){
cout << ",";
}
cout << (*it)->getId();
}
cout << endl;
}
}
bool operator<(const Nodo& a, const Nodo& b){
return (a.grado >= b.grado);
}
void Grafo::colorearBrown(){
imprimir();
sort(&nodos[0], &nodos[tam]);
cout << endl << endl;
imprimir();
}
And that's it. Assuming I've a correctly loaded graph in a 'Grafo' object, I run the method colorearBrown() and get the following output (part):
.
.
.
16 -1 1,22,36,43,47,48
17 -1 10,13,20,22,44,47
18 -1 27,32,48
19 -1 4,32,36
20 -1 6,8,10,12,17,33,36,38,43,45,48
21 -1 4,6,45
22 -1 6,16,17,26,30,31
23 -1 3,8,10,14,24,26,32,36
.
.
.
Numero Color Nodos adyacentes
20 -1 4,42,22,32,10,3,34,50,18,19,25
7 -1 20,32,6,13,3,50,2,18,31,19
36 -1 7,14,16,44,12,38,30,1,50,37
14 -1 22,30,49,24,2,11,40,5
.
.
.
See how the list of adyacent nodes changes on node 20(here), but this is repeated for all nodes.
The program perfectly compiles and, if not sorted, the nodes stay the same way throughout the hole execution.
Any ideas on why the sorting algorithm is messing with my structure would be helpful.
std::sort copies (or moves, in C++11) the objects. However you have pointers in your objects, which point at the place where the object is. After the sort, there's another object at that place.
Think of it as people sitting on chairs. You give each person a list of chairs where the "adjacent" people sit. And then you ask the people to change places. People changing places does not change what is written on the paper.
The people are the node objects, the places are the positions in he array, and the pieces of paper with the lists are your vectors of pointers to adjacent nodes.
A simple solution to that problem would be using a std::list and sorting with its sort member function. That member function doesn't move objects around, but just relinks the internal nodes, therefore your pointers will continue to point to the correct object. One disadvantage of that solution (which may or may not matter in your case) is that the list doesn't offer random access.

(C++) Specific values in an array

I'm not sure how to title my question, but here goes. I am testing some features, and I have hit a snag.
What I want to know is how can I set up a "for" or "if" statement to only put values in an array that meet a criteria? For example, find every divisor for a number, but only put factors in an array.
Any help would be loved, source code can be provided if needed :). Yes, I am new, so be gentle!
#include <iostream>
using namespace std;
int main(){
int n;
int counter = 1;
cout << "What number would you like to use? ";
cin >> n;
int DiviArray[n];
for (int k=0,j=1;k<n;k++,j++)
{
DiviArray[k] = n-k;
}
int k = 3;
int factn[n];
cout << "Factors of " << n << ": " << endl;
for (int i=0, j=1;i<n;i++,j++)
{
factn[i] = n/DiviArray[i];
if(factn[i]*DiviArray[i]==n)
{
cout << counter << ". " << factn[i] << " x " << DiviArray[i] << endl;
counter++;
}
}
return 0;
}
EDIT: Decided to go with vectors, not sure if I can get it to work, but thanks for the feedback guys :)
Since you don't know in advance how many values will meet the condition, you should use a std::vector.
As a benefit, it keeps track of how many elements you've already added, so push_back will always use the next available index.
This also fixes
cin >> n;
int DiviArray[n];
which isn't legal C++.
If you only want to put the values into the array that match the condition, then you should only put a number into the array when the condition is matched. To do that, the statement that puts a number into the array has to be inside the if-block for the condition. I hope I don't need to explain why :)
This is the only time in your program where you actually do want two indices: one that is incremented every time through the loop (to count how many times to run the process), and one that is incremented only when you put a number in the array (to figure out where the next number goes). Everywhere else, you've created a completely useless j variable (the uselessness should be apparent from the fact that there is no code that actually uses the value, only code to set it).