0

My data is on a text file that contains two columns, x-values, and y-values. The number of data points on this file can be different but never exceeds 1000. So I have declared two arrays x[1000] and y[1000]. I have to read the data file and assign each number a specific variable so that I can use it later to do some calculation. Let's say, I have 319 data points in my text file:

x          y
1          2.3
1.5        2.2
2.0        2.5
...        ...
160.0      35.5

Using my code below, I store the data in the following way:

x[0]=1,   x[1]=1.5, x[2]=2.0, ............., x[318]=160.0
y[0]=2.3, y[1]=2.2, y[2]=2.5, ............., y[318]=35.5

Now I would like to count the number of elements that x is holding. In other words, I would like to know the size of my array x and/or y.

#include <iostream>
#include <fstream>

using namespace std;

int main(){
int i=0;
ifstream fin;
fin.open("mydata.txt");
if (fin.fail()){
    std::cerr << "Error opening file!" << endl;
    exit(1);
}
double x[1000], y[1000];
fin.ignore(1000,'\n');
while(!fin.eof()){
    mufile >> x[i];
    mufile >> y[i];
    i++;
}

I tried:

int N=sizeof(x)/sizeof(*x);

This gives me 1000, the size of the array that I declared in the beginning, (not 319 the size of the updated x).

John Kugelman
  • 307,513
  • 65
  • 473
  • 519
  • `codeblocks` tag is irrevelant... – HolyBlackCat Feb 26 '17 at 21:05
  • 2
    An array always has the same number of elements. You need to keep track of how many you consider valid yourself. – molbdnilo Feb 26 '17 at 21:05
  • 3
    The size of both x and y is 1000. You only assign 319 items. You can know this by examining your counter i. – Anon Mail Feb 26 '17 at 21:05
  • 3
    You should read [Why is iostream::eof inside a loop condition considered wrong?](http://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-considered-wrong) – molbdnilo Feb 26 '17 at 21:06
  • 2
    or use `std::vector` – tnt Feb 26 '17 at 21:06
  • In addition to what molbdnilo suggested, you should also read this: http://stackoverflow.com/questions/4533063/how-does-ifstreams-eof-work – HolyBlackCat Feb 26 '17 at 21:07
  • The number of elements has to be known at some point. You can't count it, unless you define something like "the last element will be a 0, if I find a 0 I know it's the end, but then my array can't hold a 0 anywhere else". In this case `sizeof()` (that is a macro, not a function) tells you the total size of the array you allocated, not the size of the data you read into it. – Havenard Feb 26 '17 at 21:07
  • @Havenard One can just read until EOF, without any special markers like 0. – HolyBlackCat Feb 26 '17 at 21:08
  • @HolyBlackCat Yes, but that's a file, it has EOF. An array doesn't. He can learn the number of elements from the file, but not from the array. The array alone doesn't hold that information in any form. – Havenard Feb 26 '17 at 21:09
  • @Havenard But why do you need a special marker in an array? You can just count elements as you read them. Also, `sizeof` is an operator, not a macro. – HolyBlackCat Feb 26 '17 at 21:10
  • @HolyBlackCat I'm just saying that's the only way an array would hold information about it's own used size, like it's done with null-terminated strings in C. – Havenard Feb 26 '17 at 21:11
  • @Havenard Oh, then ok. I was confused by *"You can't count it, unless you define something ..."*. – HolyBlackCat Feb 26 '17 at 21:12
  • I don't know why you are using arrays in C++ anyway, could use `std::vector`, that has a handy `.size()` method that tells you the size. – Havenard Feb 26 '17 at 21:16

3 Answers3

3

How to count the number of elements in an array in c++?

You cannot "count" the number of elements in an array.

So I have declared two arrays x[1000] and y[1000]

OK, therefore each array contains exactly 1000 elements each. No more, no less.

What you want is to find out how many times you extracted a pair of numbers from the stream. You'll find that in the variable i, which you have cleverly used to count what you need. You'll want to deduct 1 from that since the last pair of numbers are the ones that reached EOF.


Note that the program will have undefined behaviour if:

  • There are more than 999 pairs of numbers in the file (the array will overflow).
  • The file ends in anything other than a number (the loop condition will never trigger -> the array will overflow).

The off-by-one of i and the problem with the end condition can both be fixed by correct checking of successful extraction before using the extracted value. See: Why is iostream::eof inside a loop condition considered wrong?

Community
  • 1
  • 1
eerorika
  • 181,943
  • 10
  • 144
  • 256
  • You should also mention that OP checks for EOF incorrectly. – HolyBlackCat Feb 26 '17 at 22:07
  • @HolyBlackCat that should be inferable from the problems that I've highlighted, but you're right it should be stated explicitly. I added a paragraph about that. – eerorika Feb 26 '17 at 22:54
0

Arrays are basic structures and they don't hold information about how many elements you actually filled with data, you can only tell it's total size in memory with sizeof(x) and the size of one of it's elements with sizeof(*x).

However, we are in C++, not C, and there's really no reason you should be using arrays here. Use std::vector instead.

std::vector<double> x;
std::vector<double> y;

x.reserve(1000);  // reserve 1000 elements, optional,
y.reserve(1000);  // it will resize automatically if needed

while (true)
{
    double d;

    fin >> d;
    if (fin.eof()) break; // end found
    x.push_back(d);

    fin >> d;
    y.push_back(d);
}

Now you can tell the number of elements from x.size(), you don't have to worry about buffer overflow because it will resize automatically if there are more than 1000 elements, also don't have to worry about counting how many times you looped, etc.

Someone put a lot of work on making those standard C++ templates so that you don't have to waste time reinventing the wheel every time, use them.

Havenard
  • 23,249
  • 4
  • 31
  • 59
-1

As a rule, every time you define an array, you must initialize your array values first. After then non-empty array values can be separated as it is done in the following code.

//define a negative large number for empty array values.
#define EMPTY -1.0E30 

#include <iostream>
#include <fstream>

using namespace std;

int main(){

   int i=0;
   ifstream fin;
   fin.open("mydata.txt");
   if (fin.fail()){
       std::cerr << "Error opening file!" << endl;
       exit(1);
   }
   double x[1000], y[1000];

   //fin.ignore(1000,'\n'); You don't need this line.

   //Initialize all your array values first.
   for (int i = 0; i < 1000; i++) {
       x[i]= EMPTY;
       y[i]= EMPTY;
   }

   while(!fin.eof()){
       fin >> x[i];
       fin >> y[i];
       i++;  //non-empty array values have already been counted on this line. 
   }

   int size=i; 

   /*
   // You may also count non-empty array values again by using
   // the following code. 

   int size=0;
   for (int i = 0; i < 1000; i++) {
      if (x[i] > EMPTY && y[i] > EMPTY) size++;

   }
   */

   cout<<"Size of array : "<<size<<endl;
}

The most advisable solution would be to use a vector, instead. Here is the sample code for that.

#include<iostream>
#include <fstream>
#include<vector>

using namespace std;

int main(){
   int i=0;
   ifstream fin;
   fin.open("mydata.txt");
   if (fin.fail()){
       std::cerr << "Error opening file!" << endl;
       exit(1);
   }
   vector<double> x, y;

   //fin.ignore(1000,'\n'); You don't need this line.

   double xval, yval;

   while(!fin.eof()){
       fin >> xval;
       fin >> yval;
       x.push_back(xval);
       y.push_back(yval);
   }

   // x.size() give you the number of array values stored in vector x.
   cout<<"Size of array : "<< x.size() <<endl;
}
  • Yes to vector, but I don't think that applies here. Question is about determining the level of fill in an array, and the only sane way to do that is with the counter already in OP'as possession. Downvoted because the answer repeats too many of OP's incidental mistakes. – user4581301 Feb 26 '17 at 22:31