2

The question is attached and so I've tried to solve this but the output I'm getting is large numbers which is probably garbage data and therefore is definitely not correct.

enter image description here

Here is my code

#include <iostream>
#include <fstream>
using namespace std;
const int size=8;
 void readData(char filename[], int list[], int size)
 {

     ifstream fin;
     fin.open("HW4_Q1data.txt");
int value=0;
     for(int i=0;i<30;i++)
     {
         fin>>filename[i];
         value=filename[i];
     if (value >= 0 && value <= 24)
       list[0]++;

       else if (value >= 25 && value <= 49)
       list[1]++;

       else if (value >= 50 && value <= 74)
       list[2]++;

       else if (value >= 75 && value <= 99)
       list[3]++;

       else if (value >= 100 && value <= 124)
       list[4]++;

       else if (value >= 125 && value <= 149)
       list[5]++;

       else if (value >= 150 && value <= 174)
       list[6]++;

       else if (value >= 175 && value <= 200)
       list[7]++;
     }

       fin.close();
 }
 void print(int list[], int size)
 {
     cout << "   Range"<<'\t'<<"# of students"<<endl;
cout << "0-24:    " <<'\t'<<list[0] << endl;
cout << "25-49:   " << '\t'<<list[1] << endl;
cout << "50-74:   " <<'\t'<< list[2] << endl;
cout << "75-99:   "   <<'\t'<< list[3] << endl;
cout << "100-124: " <<'\t'<< list[4] << endl;
cout << "125-149: " <<'\t'<<list[5] << endl;
cout << "150-174: " <<'\t'<< list[6] << endl;
cout << "175-200: " <<'\t'<< list[7] << endl;

 }
int main()
{

    char filename[70];
    int list[size];

    readData(filename,list,size);
    print(list,size);

    return 0;
}
Suraj Rao
  • 29,388
  • 11
  • 94
  • 103
Tala Salim
  • 23
  • 4
  • 1
    Why are you using `filename` to store the content of the file? – Federico klez Culloca May 18 '17 at 10:59
  • 1
    You never initialize `list` values. – user7860670 May 18 '17 at 10:59
  • @FedericoklezCulloca isn't that what the question wants us to do? What else is the use of the char array then? – Tala Salim May 18 '17 at 11:07
  • @VTT so I need to set all the values of list to 0 before the if statements? – Tala Salim May 18 '17 at 11:08
  • @TalaSalim to pass the name of the file that the method should read, instead of hardcoding it inside the function. Also, variable have names for a reason. If they wanted you to use it to hold the file content, they would wave called it `filecontent`, not `filename` – Federico klez Culloca May 18 '17 at 11:09
  • @FedericoklezCulloca I don't quite get it, what do we need to store in the filename array? I'm sorry I'm just confused – Tala Salim May 18 '17 at 11:15
  • you should use `filename` to pass the name of the file to that function (instead of hardcoding it). If you want to use the same function to read from a different file it should not be necesarry to change anything on the function – 463035818_is_not_an_ai May 18 '17 at 11:16
  • btw `list` is a bad name for an array, because there is a `list` in `namespace std`. You dont include it, but once you did you would get a wall of confusing errors. (And it can be confusing for anybody that expects a `list` to be a `std::list`, especially in the presence of `using namespace std;`) – 463035818_is_not_an_ai May 18 '17 at 11:17
  • @tobi303 so why is filename declared as a character array? Where am I going wrong? – Tala Salim May 18 '17 at 11:20
  • @tobi303 oh, I just named it list because thats what the question asked us to do, didn't know that – Tala Salim May 18 '17 at 11:20
  • @TalaSalim oh didnt see that. Then still give it a better name and teach your teacher :P – 463035818_is_not_an_ai May 18 '17 at 11:21
  • sorry I dont really understand your confusion about the filename, simply when you call the function, do it like this: `readData("HW4_Q1data.txt",list,size);` – 463035818_is_not_an_ai May 18 '17 at 11:23
  • @tobi303 after I do that, whats the point of a character array thats what I don't understand. Or do I leave my code the way it is and just add what you said? – Tala Salim May 18 '17 at 11:26
  • "HW4_Q1data.txt" is the character array that you pass to the function where you should do `fin.open(filename);` and otherwise not use the `filename` – 463035818_is_not_an_ai May 18 '17 at 14:21

2 Answers2

2

As VTT said, you do not initialize list values, therefore it has garbage values there. You should initialize them with 0.

int main() {
    // filename stuff
    int list[size];
    for(int i = 0 ; i < size; i++) {
        list[i] = 0;
    }
    // read and write functions
}

Also, as I far I can read from the question char filename[] should be used as the name of the file: fin.open(filename);

EDIT

Most of the program, to fix your problems:

void readData(char filename[], int list[], int size)
{
    ifstream fin;
    fin.open(filename);
    int value;
    for(inti= 0; i<30; i++) {
        fin>>value;
        if (value >= 0 && value <= 24)
           list[0]++;
        // ... other if else stuff
    }

    fin.close()
}

// print stuff
int main() {
   int list[size] = {0}; // initialize the list with 0.
   readData(*filename*, list, size);  // replace *filename* with the real file name
   print(list,size);

   return 0;

}

Ðаn
  • 10,934
  • 11
  • 59
  • 95
Cristian Ionescu
  • 181
  • 3
  • 10
  • I've done what you said but the output is still wrong, not garbage anymore though, mostly zeroes. And what do you mean? They're asking us to read from the file called H4_q1. – Tala Salim May 18 '17 at 11:12
  • then use it this way: in main: `char *filename = "H4_q1.txt" // whatever the name of the file read(filename, ... );` – Cristian Ionescu May 18 '17 at 11:16
  • 3
    You can also do this in one liner int list[size] = {0}; – PapaDiHatti May 18 '17 at 11:23
  • @CristianIonescu so I use the character array to open the file not store the values? when do I read the values in the file to compare, can you point out which part of my program is wrong because I'm super confused right now – Tala Salim May 18 '17 at 11:55
  • @TalaSalim I edited my answer. Take a look there, the code isn't the proper way to write C++, I reckon this is for homework/class assignment therefore, should be enough. – Cristian Ionescu May 18 '17 at 12:06
  • @CristianIonescu I cannot thank you enough, it worked. Although it says warning: deprecated conversion from string constant to 'char. But it shows the correct output so all is good, thanks again! – Tala Salim May 18 '17 at 12:12
  • The "deprecated conversion" is because your tutor has *very* foolishly specified the function as taking `char filename[]`. This is appalling awful! It should be `const char filename []` (well, actually, it should be `const char* filename`, but that's slightly less heinious). Try not to learn too many bad habits from this course. – Martin Bonner supports Monica May 18 '17 at 12:36
  • @MartinBonner oh, makes sense. Will do, thanks! – Tala Salim May 18 '17 at 14:42
0

Your assumption is correct, you are getting random (undefined behavior as standard says) data as the array values are uninitialised. There are several ways to initialise static arrays:

You can initialise static array with curly braces

int list[10] = {1,2,3,4,5,6,7,8,9,10} // will put 1,2...10 to your array

If you specify less elements in the brackets the compiler will put 0 in there, therefore initialising your array to zeroes (which you might often do) can be achieved easily:

int list[10] = {}

If you want to use any number, you can easily use the fill function:

fill(std::begin(arr), std::end(arr), 25); //will fill all elements to 25

using std::end for static array is convenient, because sometimes you cannot exactly say how many elements are there. You can define array with 10 elements as before, or you can have a curly brackets at the definition and then let the compiler to count the elements for you

int list[] = {32,5,0,10};

In C (and so in C++ using C style code) you can get this information in a bit hacky way:

int arraySize = sizeof(list)/sizeof(list[0]);

In your case it might be even more convenient to use C++ std::array rather than plain old static array. It is a simple wrapper around static array with few good methods and overloaded operators.

Regarding your assignment I believe when programming in C++ you should not pass char pointers, rather references to string, since C++ provides these higher level classes that are generally safer and more convenient to use. I have written my solution using some C++ features.

#include <iostream>
#include <fstream>
#include <array>

constexpr int arraySize = 8;
constexpr int maxNumber = 200;
using arrayType = std::array<int, arraySize>;

bool readData(const std::string &fileName, arrayType &results, count int numCount){
    results.fill(0);

    std::ifstream inFile(fileName, std::ifstream::in);
    if (!inFile.is_open())
        return false;

    for(int i = 0; i < numCount; i++){
        int val;
        if(!(inFile >> val) || val < 0 || val > maxNumber)
            return false;
        results[std::min(maxNumber-1,val)/25]++; //Since 200 is included and the range contains 201 numbers
    }

    return true;
}

void print(const arrayType &count){
    std::cout << "Range" << '\t' << "# of Students" << std::endl;

    const auto printLine = [](const int minVal, const int maxVal, const int count){
      std::cout << minVal << "-" << maxVal << '\t' << count << std::endl;  
    };

    const int segmentSize = maxNumber/arraySize;
    for(int i = 0; i < arraySize-1; i++){
        printLine(i*segmentSize, (i+1)*segmentSize-1, count[i]);
    }
    printLine((arraySize-1)*segmentSize, maxNumber, count[arraySize-1]);
}

int main()
{
    constexpr int numberCount = 30;
    std::string fileName = R"(/mnt/d/Prog/C++/in2.txt)";
    std::array<int,arraySize> frequences;

    readData(fileName, frequences, numberCount);
    print(frequences);

    return 0;
}

Beside different language features used I also tried to remove the part with long list of if statements as it can be written with one line and such way follow the DRY principle, which is a good things to follow (less bugs, shorter code, lower chance of bugs in future as someone changes the code not at all places).

Community
  • 1
  • 1
Šimon Hrabec
  • 626
  • 1
  • 7
  • 10