Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calculating using array of structs?

I have been pretty lost on this project that focuses on using array of structures. We just learned about them. I think I get the basics of it after going over some of our labs and looking at related questions:

StackOverflow
Trouble passing an array of structs
array of pointers to structures
How to initialize array of structures with?
Arrays in stuctures
Creating an array of structs in C++
How to initialize an array of struct in C++?

Cplusplus
Declaring an array of structures
Array of Structs C++ Program Help
Problem with a Dynamic Array of Structs

I'd REALLY appreciate any advice or help anyone can give. We are allowed to use this old lab (it was assigned right after we finished this lab and now we are 3 labs past it) as a starting point:

Dynamic Arrays

// Assignment : Lab 
// File : Lab.cpp

// Description : This program will take a text file called words.txt and then swap 
// its individual (word)strings. Finally, it will calculate the vowels, consonants,   
// digits, and special characters in each string.

#include <iostream>
#include <fstream>
#include <iomanip>
#include <cstdlib>

using namespace std;
bool isvowel (char aletter);
// const int MAXWORDS = 100;

struct worddata
{
  worddata (); 
  string word;
  int vowels;
  int consonants;
  int digits;
  int specialchars;
 };


 int ReadFile (ifstream & input, worddata * & Words);
 void WriteReport(ostream & output, worddata Words [], int count);
 void Swap (worddata & a, worddata & b);
 void WordSort (worddata W [], int N);

 int main (int argc, char * argv [])
 {
   // Check to see if the user entered a file name
   // Exit if no file name
   if (argc < 2)
   {
      cout << "Usage: " << argv[0] << " <filename>\n";
      exit (1);
    }
   // Open the input file
   ifstream input (argv[1]);
   if (input.fail())
   {
      cout << "File: " << argv[1] << " not found\n";
      exit (2);
   }
   // Declare a pointer to an array of worddata objects
   // to hold the words and their vowel, consonant, digit, and  
   // special character counts.
   // worddata WordArray [MAXWORDS];
   worddata * WordArray;

   // Call the ReadFile function to read the file, store the 
   // words in the array and return the number of words read
   // from the file.
   int count = ReadFile (input, WordArray);

   // Call the WordSort function to sort the words into
   // alphabetical order.
   WordSort (WordArray, count);

   // Call the WriteReport function to write the data
   // stored in the array in a formatted fashion.
   WriteReport (cout, WordArray, count);

   return 0;
   }

   worddata::worddata ()
   {
     vowels = 0;
     consonants = 0;
     digits = 0;
     specialchars = 0;
   }

int ReadFile (ifstream & input, worddata * & Words)
{

    int count = 0;
    string oneword;
    // Read and count the words in the file
    while (input >> oneword)
    count++;
    // Allocate space for the number of words counted by the
    // previous loop
    Words = new worddata [count];
    // Clear the fail flag
    input.clear();
    // Reposition the file pointer to the beginning of the file
    input.seekg (0, ios::beg);
    count = 0;

    // Read the words from the file into the array
    while (input >> Words[count].word)
    {
      // Count the number of vowels, consonants, digits
      // and special characters in the word and store them
      // in the object Words [count]

      string aword = Words[count].word;

      // Number of letters in word
      int l = 0;
      while (l < aword.length())
      {
         if (isvowel(aword[l]))
           Words[count].vowels++;
         else if (isalpha(aword[l]))
           Words[count].consonants++;
         else if (isdigit(aword[l]))
           Words[count].digits++;
         else
           Words[count].specialchars++;
      l++;
      }
      count++;
   }
  // Close the file
  input.close ();
  // Return the size of the Words array
  return count;
}

void WriteReport (ostream & output, worddata Words [], int count)
{
  worddata totals;
  totals.vowels, totals.consonants = 0;
  totals.digits, totals.specialchars = 0;

  output << setw (14) << left << "Word";
  output << setw (8) << right << "Vowels";
  output << setw (8) << "Const.";
  output << setw (8) << "Digits";

  output << setw (8) << "Special" << endl;;

 for(int i = 0; i < count; i++)
 {
      output << setw (14) << left << Words[i].word;
      output << setw (8) << right << Words[i].vowels;
      totals.vowels += Words[i].vowels;
      output << setw (8) << Words[i].consonants;
      totals.consonants += Words[i].consonants;
      output << setw (8) << Words[i].digits;
      totals.digits += Words[i].digits;
      output << setw (8) << Words[i].specialchars << endl;
      totals.specialchars += Words[i].specialchars;
  }
 {
    output << setw (14) << left << " ";
    output << setw (8) << right << "---";
    output << setw (8) << "---";
    output << setw (8) << "---";
    output << setw (8) << "---" << endl;
    output << setw (14) << left << "Totals";
    output << setw (8) << right << totals.vowels;
    output << setw (8) << totals.consonants;
    output << setw (8) << totals.digits;
    output << setw (8) << totals.specialchars << endl;
  }
}

void Swap (worddata & a, worddata & b)
{
  worddata t = a;
  a = b;
  b = t;
}

void WordSort (worddata W [], int N)
{
  int i = 1;
  while(i < N)
  {
      int j = i;
      while(j > 0 && W[j].word < W[j-1].word)
      {
          Swap(W[j], W[j-1]);
          j--;
      }
      i++;
  }
}

// Returns true/false depeninding if a letter in a word is a vowel or not
bool isvowel (char aletter)
{
  char upcase = toupper (aletter);
  if (upcase == 'A' || upcase == 'E' || upcase == 'I' || upcase == 'O' || upcase == 'U')
    return true;
  return false;
}

Project link

This is what I've managed to write so far without getting lost or it breaking into oblivion

#include <iostream>
#include <string>
#include <iomanip>
#include <fstream>
#include <vector>
#include <sstream>
#include <cstdlib>

using namespace std;
// const int ListSize = 50;

struct Assignment {
  char atype;
  string date;
  float received;
  int possible;
  string title;
};

// functions used by main
int ReadFile(ifstream& input, Assignmnent list[], int listSize);
void WriteReport(ostream & output, Assignment list [], int numRecords);
void Swap (Assignment & a, Assignment & b);
void CategorySort (Assignment C [], int N);

int main() {
  // Check to see if the user entered a file name
  // Exit if no file name
  if (argc < 2)
  {
    cout << "Usage: " << argv[0] << " <filename>\n";
    exit (1);
  }
  // Open the input file
  ifstream input (argv[1]);
  if (input.fail())
  {
    cout << "File: " << argv[1] << " not found\n";
    exit (2);
  }


  int numRecords = ReadFile(input, Assignmnent list[], int listSize);

  if(numRecords > ListSize+1)
  {
    cout << "Too Many Records for this program to read" << endl;
    system("read");
    return -1;
  }

  // no records?
  if(numRecords == 0)
  {
    cout << "Empty File" << endl;
    system("read");
    return -1;
   }
}

I also know that I'll probably be using getline. That's about it. I have a feeling once I have an outline for how I want to approach ReadFile and declare some of these scopes I'll be fine. I am just really cautious and unsure about starting that off. Also, if the prototypes seem strange I based it on a lab I looked at from another class at another school so I have no idea if they work in this context.

like image 994
Jars Avatar asked Nov 12 '22 10:11

Jars


1 Answers

Since this is an assignment I don't want to just give away any answers, but here is stuff that should help.

I read your assignment and I don't see the word dynamic used anywhere. This means you can just create the array of size 50 to start.

// non dynamic array allocation:
assignments assign[50];
// dynamic allocation containers
vector<assignments> assign;  // array list
list<assignments> assign;    // linked list
queue<assignments> assign;   // queue list, useful with insertion sort

To parse the input data I recommend getline with strtok to break the line into the proper data.

Example:

int linelength = 256; // don't forget the +1 for end of string terminator
char *whitespaces = " \t" // \n and \0 will never be part of the token based on getline
char line[256]; // or some other safe number length
char *token; // no need to define size

inputstream.getline(line, 256);
token = strtok(line, whitespaces);
// save token to correct location
token = strtok(NULL, whitespaces);
// save token to correct location
token = strtok(NULL, whitespaces);
// save token to correct location
// ...

Just don't expect to use line after strtoks.

As for your ReadFile function, I would give it the input stream and have it return one of the dynamic containers. I try to minimize how often I modify parameters.

vector<assignment> load(istream) {
    // stuff like the second block of code goes here
    return assign;
}

Hope this helps.

Thanks,

  • Will
like image 70
Will Avatar answered Nov 15 '22 06:11

Will