Strange output after reading from a file - c++

Using this code, the following execution yields strange results:
C 100
R
W
The text file's first line defines the number of elements to read from it, and it contains a few values under 15, but every time I run this, the first value in my array is always printed out as 87 (the ASCII value for 'W'). If I change the 'W' functionality to 'X', then the first result in the array is 88.
#include <iostream>
#include <fstream>
using namespace std;
int arrayLength;
class ELEMENT
{
public:
int key;
};
class HEAP
{
public:
int capacity;
int size;
ELEMENT H [];
};
HEAP initialize(int n)
{
HEAP h;
h.capacity = n;
h.size = 0;
return h;
}
void buildHeap(HEAP &h, ELEMENT *a)
{
h.size = arrayLength;
for (int i = 1; i <= arrayLength; i++)
{
h.H[i] = a[i];
}
for (int i = h.size/2; i >= 1; i--)
{
// HEAPIFY HERE
}
}
void printHeap(HEAP &h)
{
cout << "Capacity:\t" << h.capacity << endl;
cout << "Size:\t\t" << h.size << endl;
cout << "|";
for (int i = 1; i <= h.size; i++)
{
cout << " ";
cout << h.H[i].key << " |";
}
cout << endl;
}
int main()
{
char c;
int val;
HEAP h;
while (c != 'S')
{
cin >> c;
switch (c)
{
case 'S':
break;
case 'C':
cin >> val;
h = initialize(val);
break;
case 'W':
printHeap(h);
break;
case 'R':
{
ifstream infile;
infile.open("HEAPinput.txt");
infile >> arrayLength;
ELEMENT* a = new ELEMENT[arrayLength];
for (int i = 1; i <= arrayLength; i++)
infile >> a[i].key;
infile.close();
buildHeap(h, a);
}
break;
}
}
return 0;
}
It is being compiled using g++ on a Unix server.
EDIT:
To clarify:
With a text file with the following contents (space = new line):
12 9 10 11 12 8 7 6 5 4 3 2 1
The output is:
Capacity: 100
Size: 12
| 87 | 10 | 11 | 12 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 |
So it's working except for that first element.

Whatever you think
ELEMENT H [];
is doing, it probably isn't. C++ does not support dynamic arrays - you need to use the std::vector class.
And BTW, C++ by convention uses UPPERCASE to name pre-processor macros and constants. You should use mixed case to name your classes.

In addition to the wrong use of arrays: it would not be a bad idea to make initialize(), buildHeap(), and printHeap() member functions of heap.

It might be because when you say
cout << h.H[i].key <<
H[] is an array of ELEMENTs and the key is an int. If key was a char or cast to char in the cout statement, you'll see the char representation of the int.

What Neil said. Also, arrays in C++ are zero-based. So for example your loop in main():
for (int i = 1; i <= arrayLength; i++)
Should probably be:
for (int i = 0; i < arrayLength; i++)
It could be that the algorithm for binary heap construction just happens to be simpler to implement if you use one-based arrays -- in that case, you'll need to allocate enough space:
ELEMENT* a = new ELEMENT[arrayLength + 1]; // Note the "+ 1"
Currently, the last loop iteration is writing past the end of the array.

Related

Converting an array of decimals to 8-bit binary form in c++

Okay so I'm tryna create a program that:
(1) swaps my array
(2) performs caesar cipher substitution on the swapped array
(3) convert the array from (2) that is in decimal form into 8-bit binary form
And so far I've successfully done the first 2 parts but I'm facing problem with converting the array from decimal to binary form.
And this is my coding of what I've tried
#include<iostream>
#include<bits/stdc++.h>
using namespace std;
void swapfrontback(int a[], int n);
int main()
{
int a[10], i, n;
cout << "enter size" << endl;
cin >> n;
if (n == 0)
{
cout << "Array is empty!\n";
}
else
{
cout << "p = " << endl;
for (i = 0; i < n; i++)
{
cin >> a[i];
}
}
swapfrontback(a,n);
//caesar cipher
int shift = 0;
cout << "input shift: ";
cin >> shift;
int modulus = 0;
cout << "input modulus: ";
cin >> modulus;
cout << "p''=" << endl;
for (i = 0; i < n; i++)
{
a[i] = (a[i] + shift) % modulus;
cout << a[i] << endl;
}
// Function that convert Decimal to binary
int b;
b = 8;
cout<< "p'''=" << endl;
for (i = 0; i < n; i++)
{
for(int i=b-1;i>=0;i--)
{
if( a[i] & ( 1 << i ) ) cout<<1;
else cout<<0;
}
}
return 0;
}
void swapfrontback(int a[], int n)
{
int i, temp;
for (i = 0; i < n / 2; i++)
{
temp = a[i];
a[i] = a[n - i-1];
a[n - i-1] = temp;
}
cout << "p' = '" << endl;
for (i = 0; i < n; i++)
{
cout << a[i] << endl;
}
}
the problem is that instead of converting the array of decimal from the 2nd part which is the caesar cipher into its binary form, I'm getting 000000010000000100000001 .
My initial array is
3
18
25
Shift 8 and modulo 26. If anyone knows how to fix this please do help me.
Well, there seems to be something that may be an issue in the future (like the n being larger than 10, but, regarding your question, this nested for sentence is wrong.
for (i = 0; i < n; i++)
{
for(int i=b-1;i>=0;i--) //here you are using the variable 'i' twice
{
if( a[i] & ( 1 << i ) ) cout<<1; //i starts at 7, which binary representation in 4 bits is 0111
else cout<<0;
}
}
When you're using nested for sentences, it is a good idea to not repeat their iterating variables' names since they can affect each other and create nasty things like infinite loops or something like that. Try to use a different variable name instead to avoid confusion and issues:
for(int j=b-1;j>=0;j--) //this is an example
Finally, the idea behind transforming a base 10 number to its binary representation (is to use the & operator with the number 1 to know if a given bit position is a 1 (true) or 0 (false)) for example, imagine that you want to convert 14 to its binary form (00001110), the idea is to start making the & operation with the number 1, an continue with powers of 2 (since them will always be a number with a single 1 and trailing 0s) 1-1 2-10 4-100 8-1000, etc.
So you start with j = 1 and you apply the & operation between it and your number (14 in this case) so: 00000001 & 00001110 is 0 because there is not a given index in which both numbers have a '1' bit in common, so the first bit of 14 is 0, then you either multiply j by two (j*=2), or shift their bits to the left once (j = 1<<j) to move your bit one position to the left, now j = 2 (00000010), and 2 & 14 is 2 because they both have the second bit at '1', so, since the result is not 0, we know that the second bit of 14 is '1', the algorithm is something like:
int j = 128; 128 because this is the number with a '1' in the 8th bit (your 8 bit limit)
int mynumber = 14;
while(j){ // when the j value is 0, it will be the same as false
if(mynumber & j) cout<<1;
else cout<<0;
j=j>>1;
}
Hope you understand, please ensure that your numbers fit in 8 bits (255 max).

i want the user to input a string in the format [1 2 3,4 5 6,7 8 9] and convert it to a 2d float array without knowing the number of rows and columns

i tried to use the strtok function but it requires me to provide the number of rows and columns
void getvalues(char* t,float** v, int n, int m)
{
char* c;
c = strtok(t, "[ ,");
while (c != NULL)
{
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
v[i][j] = atof(c);
c = strtok(0, "[ ,");
}
}
}
}
int main()
{
float** matrix1 = new float* [100];
for (int i = 0; i < 100; i++)
matrix1[i] = new float[100];
float** matrix2 = new float* [100];
for (int i = 0; i < 100; i++)
matrix2[i] = new float[100];
float** matrix3 = new float* [100];
for (int i = 0; i < 100; i++)
matrix3[i] = new float[100];
int n, m,r ,f;
char s[999];
char d[999];
char choice;
cin.getline(s, 999);
getvalues(s, matrix1, n, m);
To solve this issue in C++, the C library function strtok() as well as
character arrays char* shouldn't be used.
Better use the vector container from the C++ STL, which can hold dynamical data
and takes care about the memory allocation/deallocation, hence garbage collection.
The final matrix shall be stored in vector<vector<float>>. Please check also the
vector reference.
The input shall be saved in std::string, as it is very robust against input
error, e.g. characters instead of numbers, etc. Please have a look to the
string reference.
The idea of my code is to hold the [1 2 3,4 5 6,7 8 9] matrix input as string
and to submit it to some string manipulation using the methods
string::find and
string::substr to
cut the rows and subsequently the numbers out of the input string.
Every detected number is than converted from string to float using
std::stof, before
it is stored by push_back into the final matrix.
#include <iostream>
#include <string>
#include <vector>
using namespace std; // Should be avoided in real life C++ projects, but for samples ok
// Detect all numbers in one row and store it to a vector of floats (no error handling right now)
vector<float> getMatrixRowNum(const string& givenRow) // Hand row string over as const reference
{
vector<float> ret;
float myFloat;
int startColIndex = 0;
int endColIndex = 0;
while ((endColIndex = givenRow.find(' ', startColIndex)) != string::npos)
{
myFloat = stof(givenRow.substr(startColIndex, endColIndex - startColIndex));
ret.push_back(myFloat);
startColIndex = endColIndex + 1;
}
myFloat = stof(givenRow.substr(startColIndex, endColIndex - startColIndex));
ret.push_back(myFloat);
return ret;
}
int main()
{
string matrixInput;
vector<vector<float>> myMatrix; // STL container for parsed matrix (std::vector)
cout << "Give a matrix in format [1 2 3,4 5 6,7 8 9]:" << endl;
getline(cin, matrixInput);
if (!matrixInput.empty() && matrixInput[0] == '[' && matrixInput.back() == ']')
{
cout << "Given matrix to parse: " << matrixInput << endl;
string matrixTemp = matrixInput.substr(1, matrixInput.length() - 2);
// Start parsing the given matrix string
string matrixRow;
int startRowIndex = 0;
int endRowIndex = 0;
while ((endRowIndex = matrixTemp.find(',', startRowIndex)) != string::npos)
{
matrixRow = matrixTemp.substr(startRowIndex, endRowIndex - startRowIndex);
startRowIndex = endRowIndex + 1;
auto matrixRowNum = getMatrixRowNum(matrixRow);
myMatrix.push_back(matrixRowNum);
};
matrixRow = matrixTemp.substr(startRowIndex);
auto matrixRowNum = getMatrixRowNum(matrixRow);
myMatrix.push_back(matrixRowNum);
// Write the parsed matrix to console output
cout << "\nParsed numerical matrix:" << endl;
for (const auto& row : myMatrix)
{
for (const auto& ele : row)
{
cout << ele << ' ';
}
cout << endl;
}
}
else
{
cout << "Wrong matrix format given: " << matrixInput << " Please try again." << endl;
}
return 0;
}
The console output looks like this:
Give a matrix in format [1 2 3,4 5 6,7 8 9]:
[1 2 3,4 5 6,7 8 9]
Given matrix to parse: [1 2 3,4 5 6,7 8 9]
Parsed numerical matrix:
1 2 3
4 5 6
7 8 9
Some input error handling is added in the code, but it still could be improved, e.g. catching exceptions
for std::stof.

Prevent loop from echoing if another same-value array element has been already echoed in C++

First of all, sorry for the mis-worded title. I couldn't imagine a better way to put it.
The problem I'm facing is as follows: In a part of my program, the program counts occurences of different a-zA-Z letters and then tells how many of each letters can be found in an array. The problem, however, is this:
If I have an array that consists of A;A;F;A;D or anything similar, the output will be this:
A - 3
A - 3
F - 1
A - 3
D - 1
But I am required to make it like this:
A - 3
F - 1
D - 1
I could solve the problem easily, however I can't use an additional array to check what values have been already echoed. I know why it happens, but I don't know a way to solve it without using an additional array.
This is the code snippet (the array simply consists of characters, not worthy of adding it to the snippet):
n is the size of array the user is asked to choose at the start of the program (not included in the snippet).
initburts is the current array member ID that is being compared against all other values.
burts is the counter that is being reset after the loop is done checking a letter and moves onto the next one.
do {
for (i = 0; i < n; i++) {
if (array[initburts] == array[i]) {
burts++;
}
}
cout << "\n\n" << array[initburts] << " - " << burts;
initburts++;
burts = 0;
if (initburts == n) {
isDone = true;
}
}
while (isDone == false);
Do your counting first, then loop over your counts printing the results.
std::map<decltype(array[0]), std::size_t> counts;
std::for_each(std::begin(array), std::end(array), [&counts](auto& item){ ++counts[item]; });
std::for_each(std::begin(counts), std::end(counts), [](auto& pair) { std::cout << "\n\n" << pair.first << " - " pair.second; });
for (i = 0; i < n; i++)
{
// first check if we printed this character already;
// this is the case if the same character occurred
// before the current one:
bool isNew = true;
for (j = 0; j < i; j++)
{
// you find out yourself, do you?
// do not forget to break the loop
// in case of having detected an equal value!
}
if(isNew)
{
// well, now we can count...
unsigned int count = 1;
for(int j = i + 1; j < n; ++j)
count += array[j] == array[i];
// appropriate output...
}
}
That would do the trick and retains the array as is, however is an O(n²) algorithm. More efficient (O(n*log(n))) is sorting the array in advance, then you can just iterate over the array once. Of course, original array sequence gets lost then:
std::sort(array, array + arrayLength);
auto start = array;
for(auto current = array + 1; current != array + arrayLength; ++current)
{
if(*current != *start)
{
auto char = *start;
auto count = current - start;
// output char and count appropriately
}
}
// now we yet lack the final character:
auto char = *start;
auto count = array + arrayLength - start;
// output char and count appropriately
Pointer arithmetic... Quite likely that your teacher gets suspicious if you just copy this code, but it should give you the necessary hints to make up your own variant (use indices instead of pointers...).
I would do it this way.
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main()
{
string s;
vector<int> capCount(26, 0), smallCount(26, 0);
cout << "Enter the string\n";
cin >> s;
for(int i = 0; i < s.length(); ++i)
{
char c = s.at(i);
if(c >= 'A' && c <= 'Z')
++capCount[(int)c - 65];
if(c >= 'a' && c <= 'z')
++smallCount[(int)c - 97];
}
for(int i = 0; i < 26; ++i)
{
if(capCount[i] > 0)
cout << (char) (i + 65) << ": " << capCount[i] << endl;
if(smallCount[i] > 0)
cout << (char) (i + 97) << ": " << smallCount[i] << endl;
}
}
Note: I have differentiated lower and upper case characters.
Here's is the sample output:
output

Palindrome C++ (strcpy)

I tried to find a solution on internet but couldnt find anything similar to this. I am using strcpy and iteration to make a palindrome function in c++ everything is working fine but the strcpy section. I dont know how to solve it or what other alternative to use. Thank you.
#include <iostream>
#include <cstring>
using namespace std;
void palindrom(char[]);
int main()
{
char binput[100];
cout << "Hello please enter your word here: " << endl;
cin >> binput;
palindrom(binput);
system("pause");
return 1;
}
void palindrom(char binput[])
{
int max= strlen(binput);
char cinput[100];
char dinput[100];
for (int i=max, n=0; i>=0, n<=max; i--, n++)
strcpy(dinput[n],binput[i]);
cout << dinput << endl;
if (strcmp(binput,dinput)==true)
cout << "Is palindrome " << endl;
else
cout << "Is not " << endl;
}
Hope this solves.Basically first just check the first letter of the word and the last. If they are not equal then they are not palindrome. If they are equal then proceed on by comparing from the front end character with their respective back ends.
#include<iostream>
#include<cstring>
using namespace std;
int CheckPalindrome(char input[],int len);
int main()
{
char input[100];
int result,inpLen;
cout<<"Enter Word:"<<endl;
cin>>input;
cout<<"Entered Word:"<<input<<endl;
cout<<"Checking....."<<endl;
inpLen=strlen(input);
result=CheckPalindrome(input,inpLen);
if(result == 1)
{
cout<<"Entered Word:"<<input<<" is a palindrome!"<<endl;
}
else
{
cout<<"Entered Word:"<<input<<" is not a palindrome!"<<endl;
}
return 0;
}
int CheckPalindrome(char input[],int len)
{
int result;
if(input[0] != input[len-1])
{
result = 0;
}
else
{
for(int i=0 ; i<len ; i++)
{
if(input[i] == input[len-1-i])
{
result = 1;
}
else
{
result = 0;
break;
}
}
}
return result;
}
Looks like you are not clear one what strcpy does. It copies an entire string from a source to a destination. You don't need that here. You need to make simple assignments.
Let's say your input is "abc". I assume you want to create the string "abccba" from it.
Given the characters in the input:
+---+---+---+
| a | b | c |
+---+---+---+
you need to map them to the output array as:
binput[0]
| binput[len-1]
| | binput[len-1]
| .... | | binput[0]
| | | .... |
v v v v
+---+---+---+---+---+---+
| a | b | c | c | b | a |
+---+---+---+---+---+---+
Now, translate that logic into code:
int len= strlen(binput);
char dinput[100];
for (int i = 0; i < len; ++i )
{
dinput[i] = binput[i]; // Takes care of the left side of the palindrome.
dinput[2*len-i-1] = binput[i]; // Takes care of the right side of the palindrome
}
// Make sure to null terminate the output array.
dinput[2*len] = '\0';
Update, in response to OP's comment
You need:
for (int i = 0; i < len; ++i )
{
dinput[len-i-1] = binput[i];
}
dinput[len] = '\0';
if(strcmp(word,strrev(word)==0)
Pallindrome
You should initialize i to max-1 instead of max, the way you have it now it will copy the NULL terminator character '\0' to the first element of dinput which results in a 0 length string.
You will also need to make sure to NULL terminate dinput. Try:
for (int i=max-1, n=0; i>=0, n<=max; i--, n++)
dinput[n] = binput[i];
dinput[max] = '\0';

Calculating the points of a football team by knowing their wins/matches in C

Ok, I am doing a C++ online challenge where I have to calculate the points a team has by knowing their matches (win, lose, equal etc).
A program input is the following:
3
4 0 1
2 0 2
0 1 4
I have to output the points of the team with highest amount of points.
In this case 4x3=12 is the highest, so the output should be 12.
My code so far:
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
int n;
cin >> n;
int a[150],b[150],c[150];
for(int i=0;i<n;i++)
{
cin >> a[i] >> b[i] >> c[i];
}
sort(a,a+n);
sort(b,b+n);
sort(c,c+n);
int temp;
if(a[0]>b[0])
{
temp=a[0];
a[0]=b[0];
b[0]=temp;
}
if(b[0]>c[0])
{
temp=b[0];
b[0]=c[0];
c[0]=temp;
}
if(c[0]>a[0])
{
temp=c[0];
c[0]=a[0];
a[0]=temp;
}
cout << a[0] << endl;
cout << b[0] << endl;
cout << c[0] << endl;
cout << a[0]*3 << endl;
return 0;
}
I know it looks bad.. I'm not sure what to do next.
Why not create a struct that holds wins ties and losses.
This would allow you to define an operator<
Right now you are sorting the wins ties and losses individually which means the data is not staying together.
struct TeamInfo
{
int mWins;
int mTies;
int mLosses; //don't actually use this value but makes it easier to read
//declare the operator< between two TeamInfo structs
bool operator<(const TeamInfo & other);
};
//This function allows us to compare two TeamInfo structs.
bool TeamInfo::operator<(const TeamInfo & other)
{
int myValue = mWins * 3 + mTies * 1;
int otherValue = other.mWins * 2 + other.mTies * 1;
return myValue < otherValue;
}
//an example:
int main(int argc, char ** argv)
{
TeamInfo teamA;
TeamInfo teamB;
teamA.mWins = 3;
teamA.mTies = 2;
teamA.mLosses = 0;
teamB.mWins = 0;
teamB.mTies = 2;
teamB.mLosses = 3;
//the < here is the same as going teamA.operator<(teamB);
//which will return false because teamA is better than teamB
bool teamAIsBetter = teamA < teamB;
//sort uses operator< so you could put these structs into an array and call sort
return 0;
}
You can then call sort on these structs.
For every team, calculate match_wins * 3 + draw * 1, and find the highest one is fine. I think it is unnecessary to sort the array.
Part of the code may look like this:
int highest_score = -1;
for(int i = 0 ; i < n ; ++ i){
if( a[i] * 3 + c[i] > highest_score ){
highest_score = a[i] * 3 + c[i] ;
}
}
cout << highest_score << endl;
Also the output should just be the highest score right? while it seems that you output 4 values.