Extra garbage values outside dimensions char array - c++

I have a 2 dimensional char array char** field. I have a method get_field() which makes a copy of this char array and returns this copy.
char** Game::get_field() {
char** copy = new char*[this->width_field];
for (unsigned int i = 0; i < this->width_field; i++)
copy[i] = new char[this->length_field];
for (unsigned int i = 0; i < this->width_field; i++) {
for (unsigned int j = 0; j < this->length_field; j++)
copy[i][j] = this->field[i][j];
}
return copy;
}
When I output the values of the copy to the console I get some garbage values after each row. However each row of the char array does contain the '\0' character to mark the end of the string. After some investigation with the debugger I found out that in the get_field() method extra garbage values are added outside the dimensions specified when declaring the array.
When length_field equals 52 I got 51 dashes plus the '\0' character like in the image and after that some extra garbage values. Where do these garbage values come from and how do I get rid of them?
[EDIT:]
This is the code that does the output to the console:
char** field = game->get_field();
for (unsigned int i = 0; i < 13; i++) {
cout << field[i] << endl;
}
This is the code how the initial field is setup:
this->field = new char*[this->width_field];
for (unsigned int i = 0; i < this->width_field; i++)
this->field[i] = new char[this->length_field];
this->setup_field();
void Game::setup_field(){
this->field[0] = "---------------------------------------------------\n\0";
this->field[1] = "| | |\n\0";
this->field[2] = "| | |\n\0";
this->field[3] = "| | |\n\0";
this->field[4] = "|---- | ----|\n\0";
this->field[5] = "| | -|- | |\n\0";
this->field[6] = "| | | | | | |\n\0";
this->field[7] = "| | -|- | |\n\0";
this->field[8] = "|---- | ----|\n\0";
this->field[9] = "| | |\n\0";
this->field[10] = "| | |\n\0";
this->field[11] = "| | |\n\0";
this->field[12] = "---------------------------------------------------\n\0";
}

Neither the C++ standard nor the Microsoft implementation gives any guarantees about memory which does not belong to you.
Accessing it for any reason is undefined behavior => anything may happen.
If you hand a char* which does not point to a 0-terminated string to a function expecting one, it will access out-of-bounds memory until it finds a 0 or it crashs in some manner.
That should sufficiently explain your "added garbage".
Sidenote: Is there any reason you cannot allocate all needed memory in one chunk?
As you later added after prompting, your copied lines are not 0-terminated.
Full size of any line: length + 1: 51 printable + 1 newline + 1 terminator
Tip: If you cannot use strdup and / or memdup, define them for yourself.

When length_field equals 52 I got 51 dashes plus the '\0' character
You actually have 54 characters in your Game::setup_field() strings:
51 dashes
One \n
One \0
One implicit \0 to end the string
Thus in your Game::get_field() method when you copy only 52 characters (stopping at the \n) you don't copy the \0 character resulting in an unterminated string.
Better to use a vector<string> or be more careful/explicit of array lengths when you initialize or copy things.

You really don't want to do it that way. Try this:
#include <vector>
#include <string>
std::vector<std::string> Game::get_field() {
std::vector<std::string> copy(this->width_field);
for (unsigned int i = 0; i < this->width_field; i++) {
for (unsigned int j = 0; j < this->length_field; j++) {
copy[i].push_back(this->field[i][j]);
}
}
return copy;
}

Related

Create and print 2D board functions, using specific seed value with no repetitions

Before you read ahead or try to help, this question is regarding my homework so the requirements to this question will be very specific.
I am writing a code that has 2 functions. The first function creates or initializes a 5*5 matrix for an array with numbers from 1 - 25 in random positions.
The second function prints it. However, I am required to use a seed value of 233 in the srand() function which I am unsure of how to use, despite constantly searching for it online. Anyway, the printout should look something like this:
--------------------------
| 4 | 5 | 10 | 21 | 22 |
--------------------------
| 1| 11 | 3 | 19 | 20 |
--------------------------
| 24 | 18 | 16 | 14 | 9|
--------------------------
| 17 | 7 | 23 | 15 | 6|
--------------------------
| 2 | 12 | 13 | 25 | 8 |
--------------------------
The first and most easily explainable issue that I have is that all my display function is doing is printing all the values in a straight line and not in the format that I want it to be.
The other part is that when I use into srand(time(233)), it gives me an error and I'm not sure why even though it is required for my assignment.
The second issue is that some of the numbers start reoccurring in the matrix and they are not supposed to, is there a way to make sure there are no duplicates in the matrix?
Although this is in the C++ language, what I have learned is the C style syntax (no std:: kinds of code or stuff like that). So far I have learned basic arrays, loops, and functions.
#include <iostream>
#include <ctime>
using namespace std;
const int ROW_SIZE = 5;
const int COLUMN_SIZE = 5;
void createBoard(int matrix[][5]);
void display(int matrix[][5]);
int main()
{
srand(time(233)); //the seed value error
int matrix[5][5];
createBoard(matrix);
display(matrix);
}
void createBoard(int matrix[][5])
{
for (int i = 0; i < ROW_SIZE; i++)
{
for (int j = 0; j < COLUMN_SIZE; j++)
{
matrix[i][j] = 1 + rand() % 25;
}
}
}
void display(int matrix[][5])
{
cout << "--------------------------" << endl;
for (int i = 0; i < ROW_SIZE; i++)
{
for (int j = 0; j < COLUMN_SIZE; j++)
{
cout << "| " << matrix[i][j];
}
}
cout << "--------------------------" << endl;
}
Assuming the function time is a requirement, it receives the address of a time_t variable so you need something like:
time_t t = 233;
srand(time(&t));
Though the function will just replace the value of t, so, there is that.
If not, as suggested by molbdnilo, you can use srand(233)(which is probably what is being requested), but know that this will generate the same repeated sequence.
As for the repeated values in the array, a possible strategy is to go back in the array from the generated index and as soon as you find a repetition, stop, and generate a new one, repeat until no equal number is found, though you have better methods and algorithms.
Since you are not to use std:: kinds of code or stuff , as you so eloquently put it, here is a C post that may help:
Unique random number generation in an integer array
The array print formatting issue is just a matter of adjusting and printing the lines in the correct position, to keep a consistent spacing you should use <iomanip> library, setw():
#include <iomanip>
void display(int matrix[][5])
{
cout << " +------------------------+" << endl;
for (int i = 0; i < ROW_SIZE; i++)
{
for (int j = 0; j < COLUMN_SIZE; j++)
{
cout << " | " << setw(2) << matrix[i][j]; // set spacing
}
puts(" |\n +------------------------+");
}
}
Output:
+------------------------+
| 16 | 25 | 23 | 1 | 24 |
+------------------------+
| 11 | 4 | 23 | 7 | 22 |
+------------------------+
| 21 | 23 | 12 | 6 | 15 |
+------------------------+
| 18 | 10 | 8 | 22 | 11 |
+------------------------+
| 23 | 18 | 22 | 18 | 16 |
+------------------------+
Footnote:
There are much better ways to do this, not using rand, if not for your homework, you should take a look for future memory:
https://en.cppreference.com/w/cpp/numeric/random
You can use a Int Array with 26 element(cause its final index is 25)
then set all of the element to 0
use a while loop to try to generate a X number,if it hasnt been used(Check[X] =0), let matrix[i][j] = X and let Check[X] = 1, if it has been used (Check[X]=1) then break the while loop)
And with the seed 233, I dont know why its not run but when i replace it with 'NULL', its run pretty good :D
#include <iostream>
#include <ctime>
using namespace std;
const int ROW_SIZE = 5;
const int COLUMN_SIZE = 5;
int check[26]={0};
void createBoard(int matrix[][5]);
void display(int matrix[][5]);
int main(){
srand(time(NULL)); //the seed value error
int matrix [5][5];
createBoard(matrix);
display(matrix);
}
void createBoard(int matrix[][5])
{
for (int i = 0; i < ROW_SIZE; i++)
{
for(int j = 0; j < COLUMN_SIZE; j++)
{
while (true)
{
//random number X;
int x = 1 + rand() % 25;
if(!check[x]) // If X not used;
{
matrix[i][j] = x;//add to table;
check[x]=1; //Mark that X used;
break;
}
}
}
}
}
void display(int matrix[][5]){
cout<<"--------------------------"<< endl;
for(int i = 0; i < ROW_SIZE; i++){
for(int j = 0; j < COLUMN_SIZE; j++){
cout<<"| "<< matrix[i][j];
}
}
cout<<"--------------------------"<< endl;
}
For your display function, you just have to add line endings (std::endl) at the right place:
void display(int matrix[][5]){
cout<<"--------------------------"<< endl;
for(int i = 0; i < ROW_SIZE; i++){
for(int j = 0; j < COLUMN_SIZE; j++){
cout<<"| "<< matrix[i][j] << " ";
}
cout <<"|" << endl;
}
cout<<"--------------------------"<< endl;
}
For the creation, if you use C++, you can use shuffle: http://www.cplusplus.com/reference/algorithm/shuffle/
void createBoard(int matrix[][5]){
// Create an array { 1, 2 ... 25}
std::array<int,ROW_SIZE * COLUMN_SIZE> tmp;
for (int i = 0; i < ROW_SIZE * COLUMN_SIZE; i++)
{
tmp[i] = i + 1;
}
// define your seed
unsigned seed = 233;
// shuffle your array using that seed
shuffle (tmp.begin(), tmp.end(), std::default_random_engine(seed));
// store the elements in your matrix
for (int i = 0; i < ROW_SIZE; i++){
for(int j = 0; j < COLUMN_SIZE; j++){
matrix[i][j] = tmp[i * COLUMN_SIZE + j];
}
}
}
Note that if you're using C++, you can use STL containers to store your 5x5 board (like array, vector etc...). They come with very handy features (like shuffle).
Note also that the seed is just a number to initialize your random generator. Setting it to 233, makes sure that two different executions of your program will always generate the same sequence of number (that's how you understand that in computer world, it is not really random, but pseudo-random).

C++: Reading from a file with get(); not working as intended

Let's say I have a file that looks like the following:
|----------------------------------------------|
| |
| |---------| |--------------| |
| |.........| |..............| |
| |.........| |..............| |
| |----+----| |----+---------| |
| # # |
| ################### |
| |
|----------------------------------------------|
(it will be a map file for a game)
In this case, MAX_WIDTH is 48 and MAX_HEIGHT is 10.
I made it so that it does not skip whitespace when reading with
infile.unsetf(ios_base::skipws);
Then I used get() in a loop like following:
char tile[MAX_HEIGHT][MAX_WIDTH];
char c;
for(int i=0; i<MAX_HEIGHT; i++) {
for(int j=0; j<MAX_WIDTH + 1; j++) {
infile.get(c);
if(c == '\n') {
continue;
}
tile[i][j] = c;
}
}
But then after each line, it looked like lines were being pushed when I printed the array.
|--------------------------------------------|
|
|| |--------| |-------------|
|| |........| |.............|
|| |........| |.............|
|| |----+---| |----+--------|
Not exact but something like this.
What could've gone wrong and what can I do about it?
(+) Printing the array goes like the following:
for(int i=0; y<MAX_HEIGHT; y++) {
for(int j=0; x<MAX_WIDTH; x++) {
cout << tile[y][x];
}
cout << endl;
}
If you have windows style linebreaks in your input file you need to read two characters for each linebreak. \r\n. That would explain your corrupted output.
A fix would be to use std::getline style functions instead of get. Or explicitly check for the \r\n combination.
I guess it should be that j < MAX_WIDTH + 1
since your first line is good, probelm start happen in your second row
try remove that + 1
Edit:
remove that +1
you may try to is to add a check on both \r \n when reading

Searching a string of ints for a repeating pattern [duplicate]

My problem is to find the repeating sequence of characters in the given array. simply, to identify the pattern in which the characters are appearing.
.---.---.---.---.---.---.---.---.---.---.---.---.---.---.
1: | J | A | M | E | S | O | N | J | A | M | E | S | O | N |
'---'---'---'---'---'---'---'---'---'---'---'---'---'---'
.---.---.---.---.---.---.---.---.---.---.---.---.---.---.---.
2: | R | O | N | R | O | N | R | O | N | R | O | N | R | O | N |
'---'---'---'---'---'---'---'---'---'---'---'---'---'---'---'
.---.---.---.---.---.---.---.---.---.---.---.---.
3: | S | H | A | M | I | L | S | H | A | M | I | L |
'---'---'---'---'---'---'---'---'---'---'---'---'
.---.---.---.---.---.---.---.---.---.---.---.---.---.---.---.---.---.---.
4: | C | A | R | P | E | N | T | E | R | C | A | R | P | E | N | T | E | R |
'---'---'---'---'---'---'---'---'---'---'---'---'---'---'---'---'---'---'
Example
Given the previous data, the result should be:
"JAMESON"
"RON"
"SHAMIL"
"CARPENTER"
Question
How to deal with this problem efficiently?
Tongue-in-cheek O(NlogN) solution
Perform an FFT on your string (treating characters as numeric values). Every peak in the resulting graph corresponds to a substring periodicity.
For your examples, my first approach would be to
get the first character of the array (for your last example, that would be C)
get the index of the next appearance of that character in the array (e.g. 9)
if it is found, search for the next appearance of the substring between the two appearances of the character (in this case CARPENTER)
if it is found, you're done (and the result is this substring).
Of course, this works only for a very limited subset of possible arrays, where the same word is repeated over and over again, starting from the beginning, without stray characters in between, and its first character is not repeated within the word. But all your examples fall into this category - and I prefer the simplest solution which could possibly work :-)
If the repeated word contains the first character multiple times (e.g. CACTUS), the algorithm can be extended to look for subsequent occurrences of that character too, not only the first one (so that it finds the whole repeated word, not only a substring of it).
Note that this extended algorithm would give a different result for your second example, namely RONRON instead of RON.
In Python, you can leverage regexes thus:
def recurrence(text):
import re
for i in range(1, len(text)/2 + 1):
m = re.match(r'^(.{%d})\1+$'%i, text)
if m: return m.group(1)
recurrence('abcabc') # Returns 'abc'
I'm not sure how this would translate to Java or C. (That's one of the reasons I like Python, I guess. :-)
First write a method that find repeating substring sub in the container string as below.
boolean findSubRepeating(String sub, String container);
Now keep calling this method with increasing substring in the container, first try 1 character substring, then 2 characters, etc going upto container.length/2.
Pseudocode
len = str.length
for (i in 1..len) {
if (len%i==0) {
if (str==str.substr(0,i).repeat(len/i)) {
return str.substr(0,i)
}
}
}
Note: For brevity, I'm inventing a "repeat" method for strings, which isn't actually part of Java's string; "abc".repeat(2)="abcabc"
Using C++:
//Splits the string into the fragments of given size
//Returns the set of of splitted strings avaialble
set<string> split(string s, int frag)
{
set<string> uni;
int len = s.length();
for(int i = 0; i < len; i+= frag)
{
uni.insert(s.substr(i, frag));
}
return uni;
}
int main()
{
string out;
string s = "carpentercarpenter";
int len = s.length();
//Optimistic approach..hope there are only 2 repeated strings
//If that fails, then try to break the strings with lesser number of
//characters
for(int i = len/2; i>1;--i)
{
set<string> uni = split(s,i);
if(uni.size() == 1)
{
out = *uni.begin();
break;
}
}
cout<<out;
return 0;
}
The first idea that comes to my mind is trying all repeating sequences of lengths that divide length(S) = N. There is a maximum of N/2 such lengths, so this results in a O(N^2) algorithm.
But i'm sure it can be improved...
Here is a more general solution to the problem, that will find repeating subsequences within an sequence (of anything), where the subsequences do not have to start at the beginning, nor immediately follow each other.
given an sequence b[0..n], containing the data in question, and a threshold t being the minimum subsequence length to find,
l_max = 0, i_max = 0, j_max = 0;
for (i=0; i<n-(t*2);i++) {
for (j=i+t;j<n-t; j++) {
l=0;
while (i+l<j && j+l<n && b[i+l] == b[j+l])
l++;
if (l>t) {
print "Sequence of length " + l + " found at " + i + " and " + j);
if (l>l_max) {
l_max = l;
i_max = i;
j_max = j;
}
}
}
}
if (l_max>t) {
print "longest common subsequence found at " + i_max + " and " + j_max + " (" + l_max + " long)";
}
Basically:
Start at the beginning of the data, iterate until within 2*t of the end (no possible way to have two distinct subsequences of length t in less than 2*t of space!)
For the second subsequence, start at least t bytes beyond where the first sequence begins.
Then, reset the length of the discovered subsequence to 0, and check to see if you have a common character at i+l and j+l. As long as you do, increment l.
When you no longer have a common character, you have reached the end of your common subsequence.
If the subsequence is longer than your threshold, print the result.
Just figured this out myself and wrote some code for this (written in C#) with a lot of comments. Hope this helps someone:
// Check whether the string contains a repeating sequence.
public static bool ContainsRepeatingSequence(string str)
{
if (string.IsNullOrEmpty(str)) return false;
for (int i=0; i<str.Length; i++)
{
// Every iteration, cut down the string from i to the end.
string toCheck = str.Substring(i);
// Set N equal to half the length of the substring. At most, we have to compare half the string to half the string. If the string length is odd, the last character will not be checked against, but it will be checked in the next iteration.
int N = toCheck.Length / 2;
// Check strings of all lengths from 1 to N against the subsequent string of length 1 to N.
for (int j=1; j<=N; j++)
{
// Check from beginning to j-1, compare against j to j+j.
if (toCheck.Substring(0, j) == toCheck.Substring(j, j)) return true;
}
}
return false;
}
Feel free to ask any questions if it's unclear why it works.
and here is a concrete working example:
/* find greatest repeated substring */
char *fgrs(const char *s,size_t *l)
{
char *r=0,*a=s;
*l=0;
while( *a )
{
char *e=strrchr(a+1,*a);
if( !e )
break;
do {
size_t t=1;
for(;&a[t]!=e && a[t]==e[t];++t);
if( t>*l )
*l=t,r=a;
while( --e!=a && *e!=*a );
} while( e!=a && *e==*a );
++a;
}
return r;
}
size_t t;
const char *p;
p=fgrs("BARBARABARBARABARBARA",&t);
while( t-- ) putchar(*p++);
p=fgrs("0123456789",&t);
while( t-- ) putchar(*p++);
p=fgrs("1111",&t);
while( t-- ) putchar(*p++);
p=fgrs("11111",&t);
while( t-- ) putchar(*p++);
Not sure how you define "efficiently". For easy/fast implementation you could do this in Java:
private static String findSequence(String text) {
Pattern pattern = Pattern.compile("(.+?)\\1+");
Matcher matcher = pattern.matcher(text);
return matcher.matches() ? matcher.group(1) : null;
}
it tries to find the shortest string (.+?) that must be repeated at least once (\1+) to match the entire input text.
This is a solution I came up with using the queue, it passed all the test cases of a similar problem in codeforces. Problem No is 745A.
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(NULL);
string s, s1, s2; cin >> s; queue<char> qu; qu.push(s[0]); bool flag = true; int ind = -1;
s1 = s.substr(0, s.size() / 2);
s2 = s.substr(s.size() / 2);
if(s1 == s2)
{
for(int i=0; i<s1.size(); i++)
{
s += s1[i];
}
}
//cout << s1 << " " << s2 << " " << s << "\n";
for(int i=1; i<s.size(); i++)
{
if(qu.front() == s[i]) {qu.pop();}
qu.push(s[i]);
}
int cycle = qu.size();
/*queue<char> qu2 = qu; string str = "";
while(!qu2.empty())
{
cout << qu2.front() << " ";
str += qu2.front();
qu2.pop();
}*/
while(!qu.empty())
{
if(s[++ind] != qu.front()) {flag = false; break;}
qu.pop();
}
flag == true ? cout << cycle : cout << s.size();
return 0;
}
I'd convert the array to a String object and use regex
Put all your character in an array e.x. a[]
i=0; j=0;
for( 0 < i < count )
{
if (a[i] == a[i+j+1])
{++i;}
else
{++j;i=0;}
}
Then the ratio of (i/j) = repeat count in your array.
You must pay attention to limits of i and j, but it is the simple solution.

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';

Strange output after reading from a file

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.