C++ Array Processing - c++

I am having trouble debugging this code so it reads two columns from the file and when the first column (Department is the same it just adds the second column to the old dept already created)This code is having trouble with looping. Any walk through, help would be much appreciated ! Thanks.
#include <iostream>
#include <fstream>
using namespace std;
ifstream inputFile; //stream object
int main()
{
inputFile.open("text.txt");
const int SIZE = 15;
int candy[SIZE];
int dept[SIZE];
int valuecounter = 0;
int Candy;
int Department;
while (inputFile >> Department >> Candy)
{
// Exit loop if we have filled the entire array
if (valuecounter == SIZE)
break;
// Update previous values
for (int index = 0; index < valuecounter; index++)
{
if (dept[index] == Department)
{
candy[index] += Candy;
}
}
// Update current values and increment counter
dept[valuecounter] = Department;
candy[valuecounter] = Candy;
valuecounter++;
}
for (int i = 0; i < valuecounter ; i++)
cout << dept[i] << " " << candy[i] << endl;
inputFile.close();
return 0;
}
and the list of input being for ex:
910 8
450 9
750 10
150 35
750 19
150 18
910 19
390 19
520 6
110 78
300 23
110 1
110 5
120 6
150 16
300 23
110 1
110 5
120 6
150 16
the array should be partially filled. but it produces weird outcome! logic error?

You have initialized valuecounter, and all elements of array dept, to zero. For this reason, in every iteration of the while loop, condition dept[valuecounter] == NULL will always evaluate to true. This means that, in every iteration, only code in the first if statement will execute.
Note that this is not the only problem with this code. As user Crazy Eddie pointed out, using NULL as an integer is considered very bad practice.
EDIT:
Replace your while loop with the following:
while (inputFile >> Department >> Candy)
{
// If this Department already exists ...
for (int index = 0; index < valuecounter; index++)
{
if (dept[index] == Department)
{
// ... update the corresponding value in 'candy' and continue the loop
candy[index] += Candy;
continue;
}
}
// If this Department does not exist, and if there are are more
// available array elements, assign a new Department
if (valuecounter < SIZE)
{
dept[valuecounter] = Department;
candy[valuecounter] = Candy;
valuecounter++;
}
}

int main()
{
const int SIZE = 15;
int candy[SIZE];
int dept[SIZE];
int valuecounter = 0;
int Candy;
int Department;
inputFile.open("text.txt");
if (!inputFile)
{
cout << "\nError opening file" << endl
<< "Exiting\n" << endl;
exit(1);
}
while (valuecounter < SIZE && inputFile >> Department >> Candy)
{
//setting bool to false everytime loop starts over.
bool found = false;
for (int index = 0; index < valuecounter; index++)
{
if (dept[index] == Department)
{
candy[index] += Candy;
//setting bool to true if department found
found = true;
}
}
if (!found)
{
dept[valuecounter] = Department;
candy[valuecounter] = Candy;
valuecounter++;
}
}
inputFile.close();
if (valuecounter == 0)
{
cout << "\n\nEMPTY FILE\nExiting.\n\n" << endl;
exit(1);
}
here i had three different functions do different things with data
return 0;
}
basically what i was missing is to set bool back to false whenever while loop started over this is why data wasn't calculated properly. Anyways Thank you all for help and all the tips!

Related

Why is my linear search always returning false, even if the item is in the array?

I'm in an Intro to C++ class, and for one of our assignments we're making an online shop. One of our problems is to make a search function for the inventory, using a linear search, then display the corresponding price, stock, and shipability for that item.
For some reason, no matter how much I try and tweak it, it always returns false for the search, and that the store doesn't carry the item, even if I type in an item that I know is in the items array.
For example, if I type Moon Pie (which is in my array) in the getline, it'll still return as -1 like it isn't. Anything noticeably wrong with this code?
Here's my inputInventory.txt
Moon Pie 3.50 15 1
Cosmic Brownie 2.00 12 0
Moon Shine 7.00 7 1
Astronaut Icecream 4.00 11 1
Neptune Nuggets 2.50 30 1
Venus Vodka 6.50 10 1
Planet Pop 4.50 20 0
Starry Salad 3.00 15 0
Celeste Cakes 5.00 11 1
Plasma Potion 9.99 4 1
Star Fruit 2.50 10 1
Sun-dae 7.00 20 0
Moon Cheese 5.00 10 1
Milky Way Milkshake 6.50 5 0
Pluto Pie 7.00 9 10
#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
using namespace std;
const int MAX = 15;
void searchInventory(string itemNames[], double itemCost[], int itemNoShip[MAX][2]);
int linearSearch(string arr[], int size, string value);
int main() {
int input;
string items[MAX];
double priceItems[MAX];
int noItems[MAX][2];
cout << "\n1. Read in Inventory\n";
cout << "2. Display Inventory\n";
cin >> input;
while (input > 2 || input < 1) {
cout << "An error has occured. Please input a value 1 - 2. >> ";
cin >> input;
}
switch (input) {
case 1:
if (readInventory(items, priceItems, noItems) == true) {
cout << "\nReading the file...\n";
}
break;
case 2:
searchInventory(items, priceItems, noItems);
break;
}
}
bool readInventory(string itemNames[], double itemCost[], int itemNoShip[MAX][2]) {
bool fileRead = false;
ifstream inputFile; // Pointer
inputFile.open("inputInventory.txt");
if (inputFile) // Test if file opened
{
for (int row = 0; row < MAX; row++) {
getline(inputFile, itemNames[row], '\t');
inputFile >> itemCost[row];
inputFile >> itemNoShip[row][0];
inputFile >> itemNoShip[row][1];
}
fileRead = true;
inputFile.close();
}
return fileRead;
}
void searchInventory(string itemNames[], double itemCost[], int itemNoShip[MAX][2]) {
string search;
int result;
int position;
cout << "Please type the name of the item you are looking for. > ";
cin.ignore();
getline(cin,search);
result = linearSearch(itemNames, MAX, search);
cout << result;
if (result >= 0) {
cout << "\nYour item was found!\n";
cout << itemNames[result] << itemCost[result] << itemNoShip[result][0] << "Shippable:" << itemNoShip[result][1];
}
else {
cout << "\nThis item was not found in the list.";
}
}
int linearSearch(string arr[], int size, string value) {
int position;
int index;
for (index = 0; index < size; index++) {
if (arr[index] == value) {
position = index;
}
else {
position = -1;
}
}
return position;
}
for (index = 0; index < size; index++)
if (arr[index] == value) {
position = index;
}
else {
position = -1;
}
This loop continually overwrites position.
Unless your sought-after element is the last one in the array, immediately after it's been found the next element will cause position to be set to -1 again (unless that one matches too 😋).
You should stop looping (or, at least, stop updating position) as soon as a match is found.
Also, it would be advisable to wrap the entire loop body in {} braces, as that is conventional and what people will expect to see, making the code easier to read and to understand.
How about:
int linearSearch(string arr[], int size, string value)
{
for (int index = 0; index < size; index++)
{
if (arr[index] == value)
return index;
}
return -1;
}
You should break out of the for loop once you found the item, if not the loop will just continue and overwrite position. Edited: Based on PaulMcKenzie's comment, you should initialize position with a value so that it will not return garbage value.
int linearSearch(string arr[], int size, string value) {
int position = -1;
int index;
for (index = 0; index < size; index++) {
if (arr[index] == value) {
position = index;
break;
}
}
return position;
}
The problem is cin.ignore(), since the default value of the first parameter is one, the first letter will always be taken out. So if someone typed "Moon Pie", the value in search will be "oon Pie".

Sorting arrays and in output getting extra first line of random symbols

I wrote a program where program sorts people by the each person time, and if time is the same, program sorts by the name alphabetically. Everything works fine, just I am getting extra first line full of random symbols. I of course can write if function and say not to show that first line, but is it good thing to do?
#include <algorithm>
#include <iostream>
#include <stdlib.h>
#include <string>
using namespace std;
struct people {
string full_name;
int h;
int min;
int sec;
};
bool comp(const people &p1, const people &p2) {
return (p1.min < p2.min || p1.min == p2.min && p1.sec < p2.sec ||
p1.min == p2.min && p1.sec == p2.sec && p1.full_name < p2.full_name);
}
int main() {
int time;
string fullnamechange[30];
people peo[30];
cin >> time;
for (int i = 0; i < time; i++) {
getline(cin, peo[i].full_name); // taking everything into a string
fullnamechange[i] = peo[i].full_name;
fullnamechange[i].erase(fullnamechange[i].begin(),
fullnamechange[i].end() - 8);
peo[i].h = atoi(fullnamechange[i].c_str());
fullnamechange[i].erase(fullnamechange[i].begin(),
fullnamechange[i].end() -
5); // changing time in string to int
peo[i].min = atoi(fullnamechange[i].c_str());
fullnamechange[i].erase(fullnamechange[i].begin(),
fullnamechange[i].end() - 2);
peo[i].sec = atoi(fullnamechange[i].c_str());
}
for (int i = 0; i < time; i++) { // erasing time from string
peo[i].full_name.erase(peo[i].full_name.begin() + 20,
peo[i].full_name.end());
}
sort(peo, peo + time, comp);
cout << endl;
for (int i = 0; i < time; i++) {
cout << peo[i].full_name << " " << peo[i].min << " " << peo[i].sec << endl;
}
return 0;
}
/*
input for example:
6
Petras A. Petraitis 0 20 00
Jurgis Jurgutis 0 12 59
Romas Jonas 0 15 12
Zigmas Nosis 0 23 9
Rimas Senasis 0 15 12
output I get:
em3╣Mg n Ç 0 0 //random numbers I get
Jurgis Jurgutis 12 59
Rimas Senasis 15 12
Romas Jonas 15 12
Petras A. Petraitis 20 0
Zigmas Nosis 23 9 */

C++ Counting Specific Counters in Character Array from File

I'm trying to count the number of specific characters from a file. The problem I have run into is that the output is a huge number that does not match up with the amount of each letter in the file.
RainOrShine.txt
RRCSSSCSCRRRCSSSCSSRSCCRCRRCSS
SSSCCSSSCCSSSCCSSSCRCRCCSSSSSS
SSSSCSSSCSSSCRRCCCSSSSSCSSSSCS
#include <iostream>
#include <string>
#include <fstream>
#include <cstring>
using namespace std;
int main()
{
string filelocation = "C:/Users/erizj/OneDrive/Documents/RainOrShine.txt";
ifstream textfile;
textfile.open(filelocation.c_str());
char weather[3][30];
int countR,countC,countS = 0;
if (!textfile)
{
cout << "Error opening the file.";
return 0;
}
else
{ // Read weather data in from file
for (int row = 0; row < 3; row++)
{
for (int col = 0; col < 30; col++)
{
textfile >> weather[row][col];
if(weather[row][col]=='R'){
countR++;
}
if(weather[row][col]=='C'){
countC++;
}
if(weather[row][col]=='S'){
countS++;
}
}
}
}
cout<<"Rainy Days during 3-Month Period: "<<countR<<endl;
cout<<"Cloudy Days during 3-Month Period: "<<countC<<endl;
cout<<"Sunny Days during 3-Month Period: "<<countS<<endl;
//cout<<"Rainy Days in June: "<<
textfile.close();
return 0;
}
Output:
Rainy Days during 3-Month Period: 4201688
Cloudy Days during 3-Month Period: 6356911
Sunny Days during 3-Month Period: 50
Does it have something to do with the counter that I set up? Thank in advance.
int countR,countC,countS = 0;
initializes countS but leaves countR and countC uninitialized.
Your program is assuming that there are a fixed number of rows and columns in the data. This could be a problem.
I suggest a more flexible approach, no assumptions about how the data is organized or the quantity of data.
Let's define a structure for our database. The data can be stored sequentially, but we need the data structure to be dynamic: std::vector.
Now to read in the data before making any analysis:
std::vector<char> database;
std::string text_line; // Easier to read in a lot of data
while (getline(data_file, text_line))
{
std::string::size_type index;
const std::string::size_type length = text_line.length();
for (index = 0; index < length; ++index)
{
const char c = text_line[index];
if ((c == 'R') || (c == 'S') || (c == 'C'))
{
database.push_back(c);
}
}
}
Since the data is read into a database, you can analyze it:
unsigned int duration = 0;
unsigned int rain_quantity = 0;
unsigned int sunny_quantity = 0;
unsigned int cloudy_quantity = 0;
// Set up the duration for the first 30 days
duration = 30;
if (database.size() < 30)
{
duration = database.size();
}
for (unsigned int index = 0; index < duration; ++index)
{
const char c = database[index];
if (c == 'C')
{
++cloudy_quantity;
}
else
{
if (c == 'R')
{
++rain_quantity;
}
else
{
++sunny_quantity;
}
}
}
You can perform other analysis without reading the data from the file.
You need to initialize all of your integer variables separately.
int countR = 0, countS = 0, countT = 0;

How to avoid infinite loop in this program

I am trying to solve a 3n+1 problem in C++. I want to take the input in pairs and calculate its maximum cycle length then output it.
I/P: 1 10
100 200
201 210
900 1000
O/P: 1 10 25
100 200 125
201 210 89
900 1000 174
Code:
#include<iostream>
using namespace std;
int clen(int i)
{
int len=1;
while(i!=1)
{
len++;
if(i%2==0)
i/=2;
else
i=3*i+1;
}
return len;
}
int maxclen(int a, int b)
{
int i,len,maxlen=0;
for(i=a;i<=b;i++)
{
len=clen(i);
if(len>maxlen)
maxlen=len;
}
return maxlen;
}
main()
{
int b[10][2],l,i,len[10];
for(i=0;;i++)
{
cin>>b[i][0];
if(cin.fail())
{
cin.clear();
goto a;
}
cin>>b[i][1];
if(cin.fail())
goto a;
}
a:
l=i;
for(i=0;i<=l;i++)
{
if(b[i][1]>b[i][0])
len[i]=maxclen(b[i][0],b[i][1]);
else
len[i]=0;
}
for(i=0;i<l;i++)
cout<<b[i][0]<<" "<<b[i][1]<<" "<<len[i]<<endl;
}
I want to stop entering the input whenever cin.fail() returns true but its working for few first execution of the program but after that it is entering in an infinite loop to enter the numbers and it just cant get out. Can anyone help me on this cin issue, How can I avoid this infinite loop?
I found it died if you hit ctrl+d (eof) after only entering one number.
Maybe try adding another 'clear' the error state there:
main()
{
int b[10][2],l,i,len[10];
for(i=0;;i++)
{
cin>>b[i][0];
if(cin.fail())
{
cin.clear();
goto a;
}
cin>>b[i][1];
if(cin.fail())
{
cin.clear(); // ADDED LINE
goto a;
}
}
...
Though I wasn't able to reproduce the error 100% .. that seemed to help the behaviour with me.
Also your array is only 10 long .. maybe it's reading too much and going into some weird state ?
You have an off-by-one error over here:
for(i=0;i<=l;i++)
{
// ...
}
I modified your main like this to correct a couple of problems:
int main()
{
const size_t length = 10;
int b[length][2], len[length];
size_t i = 0;
while(i < length)
{
cin >> b[i][0];
if(!cin) break;
cin >> b[i][1];
if(!cin) break;
++i;
}
for(int j = 0; j < i; j++)
{
if(b[j][1] > b[j][0])
len[j] = maxclen(b[j][0], b[j][1]);
else
len[j] = 0;
}
for(int j = 0; j < i; j++)
cout << b[j][0] << " " << b[j][1] << " " << len[j] << endl;
}

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.