0

I have been given the following function;

double* insert(char *file_Name, int Rows, int Columns)
{
 double* input = new double[Rows*Columns];
 //insert function code
}

In order to get this to work correctly, I need to know both the number of rows and columns in my file in order to pass them to this function. I have already worked out the number of rows using;

int RowCount = 0;
string rows;

while (getline(myfile, rows)) {
    RowCount++;
}

However, I am having a lot of trouble trying to figure out how many columns there are in my file.

One approach I have tried is attempting to find all instances of '\n' and incrementing a counter on each instance;

int ColumnCount = 0;
while (!myfile.eof()){
    if(myfile.peek()=='\n'){
        countC++;
    }
}

The while loop itself is never triggered so 'ColumnCount' remains as 0

The file itself is a large collection of numbers, each separated by whitespace.

Lightness Races in Orbit
  • 358,771
  • 68
  • 593
  • 989
  • do you know what separates the columns? – zdan Nov 01 '18 at 17:03
  • 1
    What do you mean by "I am having a lot of trouble" exactly – Lightness Races in Orbit Nov 01 '18 at 17:04
  • @zdan The file itself is a large collection of number separated by whitespace –  Nov 01 '18 at 17:05
  • @LightnessRacesinOrbit The approaches I have tried, such as searching the file for instances of '\n' have not worked –  Nov 01 '18 at 17:07
  • 2
    Then you should document those approaches for us and explain in detail in what way they have "not worked" – Lightness Races in Orbit Nov 01 '18 at 17:07
  • 2
    I am curious though why you were searching each line for `\n` when (a) by definition they won't contain any, and (b) the delimiter is whitespace. – Lightness Races in Orbit Nov 01 '18 at 17:08
  • 3
    The number of columns is equal to the number of contiguous whitespace blocks in a line + 1. Intuitively, 1 space separates 2 columns, 2 spaces separate 3 columns and so on. – lakshayg Nov 01 '18 at 17:11
  • 2
    Possible duplicate of [C++ function to count all the words in a string](https://stackoverflow.com/questions/3672234/c-function-to-count-all-the-words-in-a-string) – lakshayg Nov 01 '18 at 17:13
  • 1
    You really want to steer towards using `std::vector` or `std::array` instead of a `new[]` style array. – tadman Nov 01 '18 at 17:24
  • Your case is a bit weird, but [`while (!myfile.eof())` is almost always a bad idea.](https://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-considered-wrong) – user4581301 Nov 01 '18 at 17:25
  • _"The while loop itself is never triggered"_ That doesn't sound right. Did you just plonk this after another loop that consumed all the data already? – Lightness Races in Orbit Nov 01 '18 at 17:30
  • Your requirements are lacking. Part of software engineering is fighting tooth and nail to get clear, specific, concrete, requirements. What is the definition of "column?" Are we talking about the maximum number of characters found in any line? In that case, just read line by line and get the size of each string, no? – Christopher Pisz Nov 01 '18 at 18:38

2 Answers2

1

Since I'm bored…

This certainly has bugs in the edge cases (particularly relating to delimiters found at the end of the line; meh), but works for the example input, and shows (generally) one possible approach.

#include <iostream>
#include <sstream>
#include <cstring>

bool CharIsIn(const char c, const char* str, const size_t strLen)
{
    for (size_t i = 0; i < strLen; i++)
        if (str[i] == c)
            return true;
    return false;
}

// Detects the number of subsequences of "delimiters" in the line.
// 
// By default a valid delimiter is either whitespace or a tab character,
// and "empty" columns are collapsed.
size_t DetectNumColumns(
    const std::string& line,
    const char* delimiters = " \t",
    const bool collapseEmpty = true
)
{
    if (line.empty())
        return 0;

    const size_t delimsLen = std::strlen(delimiters);

    size_t result = 1;

    bool lastWasDelim = true;

    for (size_t pos = 0; pos < line.size(); ++pos)
    {
        if (CharIsIn(line[pos], delimiters, delimsLen))
        {
            if (!lastWasDelim || !collapseEmpty)
                result++;
            else if (pos == line.size()-1 && lastWasDelim && !collapseEmpty)
                result++;
            lastWasDelim = true;
        }
        else
        {
            lastWasDelim = false;
        }
    }

    return result;
}

int main()
{
    // Simulating your input file
    std::stringstream ss;
    ss << "1.5 7.6\n";
    ss << "2.3 4.5\n";
    ss << "9.9 7.5\n";

    bool GotColumnCount = false;
    int RowCount = 0, ColumnCount = 0;
    std::string line;
    while (std::getline(ss, line))
    {
        // On the first iteration (only!) count columns.
        const int columns = DetectNumColumns(line);

        if (!GotColumnCount)
        {
            // On the first iteration, store this.
            ColumnCount = columns;
            GotColumnCount = true;
        }
        else
        {
            // On subsequent iterations, just ensure the column
            // count is consistent.
            if (columns != ColumnCount)
                throw std::out_of_range("Inconsistent column count in input");
        }

        // Always increment the row count (this bit's easy)
        RowCount++;
    }

    std::cout << "The input consists of " << RowCount << " rows of " << ColumnCount << " columns\n";
}

(live demo)

The salient point is that you need to parse at least one row of text to find out how many times your delimiter(s) appears (or how many times a sequence of your delimiter(s) appears, depending on your exact requirements). You may want to parse every row of text to validate for a consistent number of columns throughout the file.

I'm deliberately not fixing the bugs, not only because I can't be arsed (though that is certainly true) but also to discourage you from simply copy/pasting this example as your solution! Please do use it for inspiration and come up with something better.

Hint: if your delimiter is always just a single character (e.g. a single whitespace), and you don't need to leniently handle things like added leading or trailing whitespace, DetectNumColumns becomes substantially simpler than my attempt above; it's literally just counting (but be sure to count your fence's panels, rather than its posts!).

Lightness Races in Orbit
  • 358,771
  • 68
  • 593
  • 989
0

You could use stringstream and assuming the lines have different columns.

Edit: For you case you may not need maxColumnCount. Just do the column count and break.

int maxColumnCount = 0;
string row;

while (getline(myfile, row)) {
    RowCount++;
    std::istringstream iss(row);
    int columnCount = 0;
    for(string columnValue; iss >> columnValue; )
        columnCount++;
    if(columnCount > maxColumnCount)
        maxColumnCount = columnCount ;

}
HariUserX
  • 1,263
  • 1
  • 7
  • 16