Converting and Passing Arrays - c++

I basically want to pass this array of data I'm reading to diffent functions and eventually plot it.
The array contains a 32 bit word of '1's and '0's, I then want to add these individual bits together to see where my data spikes. So in other words if I add "0100" to "0110" I get "0210" - which is probably easier done with separate bins and plotting.
At the moment I'm just getting garbage out.
void binary(int convert, int* dat) {
bitset<32> bits(convert);
//cout << bits.to_string() << endl;
char data[32];
for(unsigned i = 0; i < 32; ++i) {
data[i] = bits[i];
}
for(unsigned i = 32; i; --i) {
dat[i] = (int(data[i-1]))+dat[i];
}
}
void SerDi() {
int dat[32];
cout << " Reading data from memory..." << endl;
ValVector< uint32_t> data=hw.getNode("SerDi.RAM").readBlock(8);
hw.dispatch();
cout << data[0]<<endl;
cout << data[1]<<endl;
for (unsigned i = 2; i < 7; i++) {
binary(data[i], dat);
}
cout << dat[7] << endl;
graph(dat); //passes the array to a place where I can plot the graph
}

You have
int dat[32];
But in convert you have i = 32 and dat[i] That will access something outside of the array and bad things will happen.
Also that is not initialized. Add a memset/loop somewhere to make dat initially 0.

Related

Why String is returning Junk values

Here I am using Data Structure Queues to change cards places using strings. User picks the top card than put it at last of the deck. The problem is that I need to return updated string to main. What it is returning is junk Values. I also tried to copy the string array and than returning that arraybut didn't work. Can anyone help?
#include<iostream>
#include<string>
using namespace std;
string CommunityChest(string Cards[]){
struct Que{
string cards[6];
int front =0;
int back=-1;
}ComQ;
string temp;
for(int i=0; i<5;i++)
{//Enqueue(Cards)
ComQ.back++;
if(ComQ.back<=5)
{
ComQ.cards[ComQ.back]=Cards[i];
}
else{
cout<<"Overflow";
}
}
//Display
for(int i=ComQ.front; i<=ComQ.back; i++)
{
cout<<ComQ.cards[i]<<endl;
}
//Del()
if(ComQ.front>=0)
{
temp=ComQ.cards[ComQ.front];
ComQ.front++;
}
cout<<endl<<"Pick the top Card"<<endl;
cout<<temp<<endl;
//EnQ the picked card
ComQ.back++;
if(ComQ.back<=5)
{
ComQ.cards[ComQ.back]=temp;
}
else{
cout<<"Overflow";
}
cout<<endl<<"After Inserting top card:"<<endl;
//Display
string newQ1[5];
for (int i=ComQ.front; i<=ComQ.back; i++) //Making an alternate array to copy Comq.cards array data
{
newQ1[i]=ComQ.cards[i];
}
for(int i=0; i<5; i++)
{
return newQ1[i]; //trying to return string array
//cout<< newQ1<<endl;
}
}
int main(){
string cards[5]{ "1 Advance ........",
"2. It is your ...........",
"3. You have won .............",//Cards as strings
"4. From sale of..............",
"5. Pay Hospital............"};
string newQ1=CommunityChest(cards);
for(int i=0; i<5; i++)
cout << newQ1[i] << endl;
return 0;
}
There are some issues with this code as mentioned in the comments, you are trying to do a return in a loop, this may look okay but it's wrong since a return can get you out of the function. But it seems like you want to return an array of strings.
A fix for this function would be like this:
#include <iostream>
std::string* CommunityChest(std::string Cards[]) {
struct Que {
std::string cards[6];
int front = 0;
int back = -1;
} ComQ;
std::string temp;
for (int i = 0; i < 5; i++) { // Enqueue(Cards)
ComQ.back++;
if (ComQ.back <= 5) {
ComQ.cards[ComQ.back] = Cards[i];
}
else {
std::cout << "Overflow";
}
}
// Display
for (int i = ComQ.front; i <= ComQ.back; i++) {
std::cout << ComQ.cards[i] << std::endl;
}
// Del()
if (ComQ.front >= 0) {
temp = ComQ.cards[ComQ.front];
ComQ.front++;
}
std::cout << std::endl
<< "Pick the top Card" << std::endl;
std::cout << temp << std::endl;
// EnQ the picked card
ComQ.back++;
if (ComQ.back <= 5) {
ComQ.cards[ComQ.back] = temp;
}
else {
std::cout << "Overflow";
}
std::cout << std::endl
<< "After Inserting top card:" << std::endl;
// Display
// Creating a dynamic array to store the values
std::string* newQ1 = new std::string[5];
for (int i = ComQ.front, j = 0; i <= ComQ.back && j < 5; i++, j++) {// Making an alternate array to copy Comq.cards array data
newQ1[j] = ComQ.cards[i];
}
return newQ1; // Returning the dynamic array
}
int main()
{
std::string cards[5]{
"1 Advance ........",
"2. It is your ...........",
"3. You have won .............", // Cards as strings
"4. From sale of..............",
"5. Pay Hospital............"
};
std::string* newQ1 = CommunityChest(cards);
for(int i = 0; i < 5; i++) {
std::cout << newQ1[i] << std::endl;
}
delete[] newQ1; // Deleting the array
return 0;
}
The output will be:
1 Advance ........
2. It is your ...........
3. You have won .............
4. From sale of..............
5. Pay Hospital............
Pick the top Card
1 Advance ........
After Inserting top card:
2. It is your ...........
3. You have won .............
4. From sale of..............
5. Pay Hospital............
1 Advance ........
In this fix, I'm returning a dynamically allocated array of strings because a static array will be destroyed once the scope ends, it would be better sometimes to use other ways to allocate memory such as std::unique_ptr<> or std::shared_ptr<>, but I'd suggest you learn how to do it yourself first then use those when needed.
EDIT:
You can also return an std::array<>, I suggest you to read about it as C-Style arrays cannot be returned in you way that you tried and can't be returned without using dynamic allocation, so an std::array<> can be a good replacement over std::string* in this case

Writing a Hash Table to File and Restoring From File in C++

I am working on an assignment for school using hash tables in a structure program. Part of the assignment is writing a hash table composed of 20 primary buckets and 10 overflow buckets, each with 3 slots composed of a key and data field to disk and then restoring from it. Here is what I have so far:
#include <iostream>
#include <fstream>
#include <iomanip>
#include <stdio.h>
#include <string.h> // for strcpy()
using namespace std;
typedef char STR10[10+1];
typedef char STR20[20+1];
struct SLOT
{
STR10 key;
STR20 data;
};
struct BUCKET
{
SLOT entry[3];
int count;
BUCKET* overflow;
};
struct HASHTABLE
{
BUCKET pBkt[20];
BUCKET oBkt[10];
};
void WriteHTtoDisk (HASHTABLE ht, char *HashDisk);
void ReportHT (HASHTABLE ht, char * when);
int main()
{
int maxP = 20;
int maxO = 10;
int maxS = 3;
HASHTABLE ht;
STR10 mKey;
STR20 mData;
FILE * inFile;
inFile = fopen("DATAIN.dat","rb");
if (inFile == NULL)
{
cout << " DATAIN file access error ... \n";
cout << " Terminating application ... \n ";
cout << " Press any key ... \n ";
return -100;
}
char crLF;
while (!feof(inFile))
{
fscanf(inFile,"%10c%20c\n",mKey,mData);
mKey[10] = mData[20] = 0; // add string terminators
printf(" MyKey: %10s\n MyData: %20s\n",mKey,mData);
cin.ignore(80,'\n'), cin.get();
//InsertIntoHT (ht, mKey, mData);
}
fclose(inFile);
WriteHTtoDisk(ht, "hashTable.dat");
ReportHT (ht,"BEFORE");
return 0;
}
void WriteHTtoDisk (HASHTABLE ht, char *HashDisk)
{
FILE * HASHDISK = fopen(HashDisk, "rb");
int maxBkt = 30;
int maxSlot = 3;
for (int i = 0; i < maxBkt; i++)
{
for (int j = 0; j < maxSlot; j++)
{
fwrite(ht.pBkt[i].entry[j].key,11,sizeof(maxSlot),HASHDISK);
fwrite(ht.pBkt[i].entry[j].data,21,sizeof(maxSlot),HASHDISK);
}
}
}
void ReportHT (HASHTABLE ht, char * when)
{
int maxB = 30;
int maxS = 3;
cout << "Hash Table \n" << "Verification Report \n" << when << " Restoration" << endl;
for (int b = 0; b < maxB; b++)
{
cout << "Bucket " << (b+1) << endl;
if (b < 20)
{
for (int i = 0; i < maxS; i++)
{
cout << setw(3) << "Slot " << (i+1) << ": " << ht.pBkt[b].entry[i].key << setw(3) << ht.pBkt[b].entry[i].data << endl;
}
}
else
{
for (int i = 0; i < maxS; i++)
{
cout << setw(3) << "Slot " << (i+1) << ": " << ht.oBkt[b].entry[i].key << setw(3) << ht.oBkt[b].entry[i].data << endl;
}
}
}
}
The code compiles with no problems, but when I inspect the file, I find that it is all just gibberish and weird symbols. The data I am using was previously extracted from another file and I want to save it in the format in which it was inserted. I am sure the issue is with the lines with fwrite (I am not that experienced with C syntax as I am with C++).
The data was in the DATAIN.dat file like this:
TATUNG CO.EL PR. LONG BEACH CA
KAMERMAN LCIRRUS BEAVERTON, OR
QUADRAM COLOACH AV NORCROSS GE
AST RESEARALTON AV IRVINE CA
I am expecting the new file to look like this:
TATUNG CO.
EL PR. LONG BEACH CA
KAMERMAN L
CIRRUS BEAVERTON, OR
QUADRAM CO
LOACH AV NORCROSS GE
AST RESEAR
ALTON AV IRVINE CA
Any help would be greatly appreciated. Thank you.
It looks like your code doesn't initialize or even use the member count. When a hash bucket is empty, the count should indicate it. In C++ it's easy to implement: just add = 0 to its definition:
struct BUCKET
{
SLOT entry[3];
int count = 0;
BUCKET* overflow;
};
Also, when writing the bucket's data to a file, use the count and don't assume that all the entries in the bucket are filled.
for (int j = 0; j < ht.pBkt[i].count; j++)
...
Also, write only the required number of bytes. fwrite accepts two parameters: the size of the data elements to write and their number. Here, the size is 11 or 21, and the number is 1, because each fwrite call can only write one string to your file.
fwrite(ht.pBkt[i].entry[j].key,11,1,HASHDISK);
fwrite(ht.pBkt[i].entry[j].data,21,1,HASHDISK);
By the way, since you have a STR10 type, you can avoid magic numbers and write sizeof(STR10) instead of 11. This way, when you change the length of your string, your code will still work.

C++ Skipping elements in a one d array

I have an assignment with several ways to manipulate an array, but I'm having trouble with one of the parts.
I am reading about 50 numbers into the array from a .txt file
And for every odd location in the array (1,3,5,…), I have to subtract it from the previous even location (0,2,4,…) and store results in the odd location. Then I print out all values in the array.
Here is what I have so far:
void oddMinusEven(int ary[],int num)
{
for(int idx = ary[0]; idx<num; ary[idx+2])
{
ary[idx] = ary[idx+2]-ary[idx];
cout<<ary[idx]<<endl;
}
}
How do I do this? If you could provide some examples, that would be great.
This should do:
void oddMinusEven(int ary[], int num) {
for(int i = 1; i < num; i += 2) {
ary[i] = ary[i-1] - ary[i];
std::cout << "a[" << i << "] = " << ary[i] << std::endl;
}
}

Issue in reading repeated fields from protocol buffers in C++

org.proto
message Optimize {
required int element_size = 1;
required string element_name = 2;
}
message nodes {
repeated Optimize = 1;
}
Have this decoding function:
DecodeNodeMsg(char *msg, int size)
{
Org::nodes node;
int element_size;
string element_name;
int NumofElem = 0;
node.ParseFromArray((void *)msg, size);
for (int i = 0; i < nodes.Optimize().size(); i++)
{
element_size = nodes.Optimize(i).element_size();
element_name = nodes.Optimize(i).element_name();
cout << "size" << element_size << endl;
cout << "name" << element_name << endl;
NumofElem++;
}
cout << "number of" << NumofElem << endl;
}
I am encoding a nodes message with three Optimize messages in it. and calling this decode function. Encoding part is an old code which is working fine from long time. So i dont suspect the encoding function.
In the decode function, I see that the NumofElem is correctly printed as three. However, i see that both element_size & element_name are just garbage. Integer has some junk value and string has a binary data.
I am having this issue only if this repeated fields. If fields are required/optional fields, then i dont have this issue.
Could some one has similar issue... ? if so any clues on how to fix this ?
Thanks,
Kiran
I don't see where you are actually decoding a message. I see you creating a new node object, but then calling Org::nodes() which looks wrong. I think you need to access the Optimize elements like this:
for (int i = 0; i < node->optimize_size(); i++)
{
element_size = node->optimize(i).element_size();
element_name = node->optimize(i).element_name();
cout << "size" << element_size << endl;
cout << "name" << element_name << endl;
NumofElem++;
}
But again I think your nodes object needs to be decoded from something. The mutable methods allow you to set data. There's also the ParseFrom methods. Also in my proto files I number the elements in a message. See https://developers.google.com/protocol-buffers/docs/overview
message nodes {
repeated Optimize = 1;
}
The function deserializes the buffer into the local variable node, but the loop references nodes. I'd also validate the return value from ParseFromArray.

C, Large pointer array allocation (linux 64 bit)

Im allocating 25,000,000,000 units of these :
struct test
{
public:
test();
void insert(unsigned int var1, unsigned int var2, unsigned long var3);
bool isEmpty() const;
unsigned char * data;
};
test::test()
{
data = NULL;
}
bool test::isEmpty() const
{
return (data == NULL);
}
unsigned long index = 25000000000;
like this :
test *something = new (nothrow) test[index];
if (!something)
{
cout << "Error allocating memory for [something]" << endl;
return ;
}
cout << "DONE !" << endl;
then i even made sure its data initialized to NULL.
unsigned long j=0;
while (j<index)
{
something[j].data = NULL;
j++;
}
And its all good, except when i iterate through the something[], like this :
test *chk;
unsigned long empty = 0;
unsigned long not_empty = 0;
unsigned long i=0;
for (i=0; i< index; i++ )
{
chk = &something[i];
if (!chk->isEmpty())
{
not_empty++;
} else
empty++;
}
cout << "Empty [" << empty << "]" << endl;
cout << "Not Empty [" << not_empty << "]" << endl;
cout << "Total [" << empty + not_empty << "]" << endl;
(LAST UPDATE)
It turned out to be hardware problem - memory. Some of sticks were not working properly together with others. Thanks everyone for suggestions and too bad hardware path isnt in answers o/
(UPDATE)
I get constant number of initialized elements that are not NULL (not_empty). Still have no idea why.
Of course, empty + not_empty = index.
If i comment out data = NULL; in constructor function, i get proper empty/not_empty numbers if i loop through array right after allocating it. but still, after forcing pointers to NULL, i get same constant not_empty value, after looping through array again.
I also had this reworked to plain pointers, using malloc(), and it made no difference, except that it was first the time i noticed pointers to be correct (empty) until i set them.
I did some tests with smaller [index] value (5,500,000,000), and i could not replicate the behavior.
Im using google`s ltcmalloc and allocated memory size suggests, it is using correct [index] size;
Rather than 25000000000, write 25000000000ul. I have suspect your number becomes a 32-bit integer, thus the j < 25000000000 is always true as int(25000000000) = -769803776.