C++: Pass Numbers Into x & y Arrays from txt File

  • Context: C/C++ 
  • Thread starter Thread starter ChrisVer
  • Start date Start date
  • Tags Tags
    File Input Text
Click For Summary

Discussion Overview

The discussion revolves around reading numerical data from a text file into arrays in C++ and handling file paths for input. Participants explore issues related to file reading, memory allocation, and command-line arguments.

Discussion Character

  • Technical explanation
  • Debate/contested
  • Homework-related

Main Points Raised

  • One participant presents a C++ code snippet for reading data from a text file into arrays but encounters issues with uninitialized memory.
  • Another participant suggests that the file needs to be rewound between reading loops, indicating that the end-of-file status prevents further reading.
  • A different participant proposes using vectors instead of arrays to avoid the need for pre-defining sizes and to simplify the reading process.
  • Concerns are raised about the presence of a header line in the file, which could cause the input stream to fail when trying to read doubles.
  • Further inquiries are made about how to specify file paths via command-line arguments, with suggestions to use either relative or absolute paths.
  • Participants discuss the concept of command-line arguments and the need to process them correctly to allow dynamic file path input.
  • Some participants express confusion about the difference between relative and absolute paths, seeking clarification on how to implement this in their code.

Areas of Agreement / Disagreement

Participants generally agree on the need to handle file reading correctly, but there are multiple competing views on the best approach to manage file paths and data input. The discussion remains unresolved regarding the optimal method for processing command-line arguments.

Contextual Notes

Limitations include potential misunderstandings about file handling in C++, the need for proper error checking when reading files, and the complexity of managing command-line arguments. Some participants express uncertainty about specific implementations.

Who May Find This Useful

This discussion may be useful for C++ programmers, particularly those dealing with file I/O, data processing, and command-line argument handling.

ChrisVer
Science Advisor
Messages
3,372
Reaction score
465
I know this is pretty basic question, but something doesn't seem to work right for me...
Suppose I have a txt file, with the following input:
Code:
x    y
0.0    0.5
1.0    1.5
2.0    4.8
3.0    4.9
How can I pass those numbers into x and y arrays using a C++ code?
My code so far is like this:

C:
#include<iostream>
#include<fstream>
using namespace std;

int main(){
//read file
ifstream finput;
finput.open("data.txt");

// part to calculate the dimensionality
int N=0;
double temp;
while(! finput.eof() ){
    finput >>tempp;
    N++;
}
N=N/2;//part to fill the arrays
double x[N];
double y[N];
int m=0;
while(! finput.eof() ){
    finput >>x[m]>> y[m];
    m++;
}

system("pause");
return 0;
}

But it seems that the 2nd loop doesn't put my values for x,y's into the corresponding arrays. The filled elements are extremely small numbers which I didn't even input.
Any feedback?
 
Technology news on Phys.org
Don't you need to rewind the file between loops? Close and reopen for example. I suspect what you've got in the array is just nonsense that happens to be in the (uninitialised) memory that you allocated.

Easy check - debugger, or add a printf inside the second loop and see if it's being executed at all.

Edit: I think >> will automatically convert the string read from the file to a double - but it may be worth checking that parsing is happening if the above doesn't fix it.
 
Ibix said:
Don't you need to rewind the file between loops? Close and reopen for example. I suspect what you've got in the array is just nonsense that happens to be in the (uninitialised) memory that you allocated.

Easy check - debugger, or add a printf inside the second loop and see if it's being executed at all

I tried to close/open the file inbetween the loops... it worked after doing it... :confused:confused!
 
Is that an "I was confused" or an "I am confused"?

In case of the latter, your first loop exits when finput.eof() is true. You didn't tell finput to return to the start of the file or anything, so it simply carried on reporting that it was at the end of the file (i.e. finput.eof() remained true) and the second loop exited immediately. Closing and reopening the file moves you back to the beginning. If ifstream has a rewind() method (or something similar) you could use that to achieve the same result.
 
  • Like
Likes   Reactions: ChrisVer
Try using vectors instead of arrays. You can add data to them so that they automatically grow to the size you need, instead of having the declare the size in advance. You don't have to read the file twice, first to find out how big to make the array, then to read the data. Here's a simple example that reads ints from a file into a vector and then displays the vector's contents:

Code:
#include <iostream>
#include <fstream>
#include <vector>

using namespace std;

int main ()
{
  vector<int> numbers;  // has length zero, initially

  ifstream inputfile ("data.txt");
  if (!inputfile)
  {
    count << "Couldn't open data.txt!" << endl;
    return 0;
  }

  int n;
  while (inputfile >> n)  // loop terminates at end of file
  {
    numbers.push_back(n);  // append n to the vector and expand
                           // the vector as necessary
  }

  // the size() member function tells you how big the vector is

  count << "The numbers are:" << endl;
  for (int k = 0; k < numbers.size(); ++k)
  {
    count << numbers[k] << endl;
  }

  return 0;
}
 
  • Like
Likes   Reactions: Ibix
Here's another problem with your code. Your file begins with a header line containing text ("x y"). When your program tries to read a double from that line, the input stream goes into "fail" status, and you can't read anything further until you reset the stream status. To skip past that header line, read some text instead.

Code:
#include <string>

// ...

string head1, head2;
cin >> head1 >> head2;   // each '>>' reads one "word" at a time
                         // (sequence of characters delimited by whitespace)

// Now start reading the doubles
 
Last edited:
  • Like
Likes   Reactions: ChrisVer
Hey, thanks for the replies, they were understandable.
I would also like to ask a further question:
How can I feed in the txt file path in the terminal window??
suppose that I have the following paths:
[my code's path]/data.txt (I call it default)
[my code's path]/folder/data.txt (or any other path)

How can I use a non-default path for this code to run?
What I've been thinking is for a source code of the form:

C:
#include<string>

int main( int argc, char ** argstr){
    string fpath;
    if (argc==0)  fpath = "data.txt"; // have no command line arguments get the default
    else{
        fpath="";
        for(int i=0; i< argstr.size(); i++){
            fpath += argstr[i];
        }
    }
}

//REST OF CODE
 
ChrisVer said:
How can I use a non-default path for this code to run?
In the 'open' statement or the fstream constructor (as I did), specify either a relative path starting from your current location (in your example that would be folder/data.txt, with no slash at the beginning), or an absolute path starting from your file system root (which depends on your operating system).
 
jtbell said:
In the 'open' statement or the fstream constructor (as I did), specify either a relative path starting from your current location (in your example that would be folder/data.txt, with no slash at the beginning),.

Well yes, that would be the manual thing to do, which would require every time I wanted to change the path to enter my source code and change the filename in the fstream's constructor.
My point however is when I type this in the command line of the terminal:
./main
the code to run with the default path, and process the : "data.txt".
But when I type:
./main /folder1/xydata.txt
it would run on the txt file in the given path.
 
  • #10
jtbell said:
r an absolute path starting from your file system root (which depends on your operating system).
I don't really understand what this means... sorry if the answer to my question lies on this part of your post.
 
  • #11
Under Mac OS, I have a Documents folder, the default location for new files, which has the absolute path /Users/jtbell/Documents. If I have a program in that folder, and a data file data.txt which is also in that folder, I can open the file using either 'data.txt' or '/Users/jtbell/Documents/data.txt'. If the file is actually in a sub-folder named 'folder', I can use either 'folder/data.txt' or '/Users/jtbell/Documents/folder/data.txt'. In both examples, the first path is "relative" and the second path is "absolute."

But now I see that what you want is to specify the file name when you execute (run) the program, not as part of the source code. To do it like you said in post #9, you need to know how to process command-line arguments in C++. I haven't done this in a long time, so I'm not a good person to ask. I would have to re-learn it. Maybe someone else can contribute an example. Or if you Google for something like "c++ command line arguments" you'll probably find something.
 
  • Like
Likes   Reactions: ChrisVer
  • #12
jtbell said:
But now I see that what you want is to specify the file name when you execute (run) the program, not as part of the source code. To do it like you said in post #9, you need to know how to process command-line arguments in C++. I haven't done this in a long time, so I'm not a good person to ask.
@ChrisVer, what OS are you using? Are you running your code from the command line or from inside a debugger?

As an alternative to passing the path as a command-line argument, you could prompt the user to enter the path to the data file, and then to enter the name of the data file.
 
  • #13
Mark44 said:
prompt the user to enter the path to the data file, and then to enter the name of the data file.
...and then the program reads the name into a string, and you use the string as the argument to finput.open() or the constructor for finput.

A potential complication here is that finput.open() and the constructor both expect to receive C-style char* "strings" as arguments. If you read the filename into a C++ string, you have to do a conversion.

Code:
string filename;
count << "File name? ";
cin >> filename;
ifstream finput;
finput.open(filename.c_str());

Or you can combine the last two statements into

Code:
ifstream finput (filename.c_str());
 
  • #14
Regarding the code in post #7 to get a file name from the command line:

The command line inputs can be received as an array of strings, argv[0], argv[1], argv[2], ... in the standard way with

int main(int argc, char*argv[]){

argv[0] is the path to the program you are running.
argv[1] will be a file name that you put on the command line and argc will = 2. You can strcpy argv[1] to a string with a better name, like filename.

PS. If the path to your text file has a space in it, be sure to put quotes around it. Otherwise, it will be split at the spaces into argv[1], argv[2], etc.

PPS. The path to the file name will either be relative to where your command terminal is open or absolute. It is NOT relative to the location of the program unless you open the command terminal in the same folder as the program.
 
Last edited:
  • Like
Likes   Reactions: ChrisVer

Similar threads

  • · Replies 25 ·
Replies
25
Views
3K
  • · Replies 6 ·
Replies
6
Views
12K
Replies
20
Views
2K
Replies
12
Views
2K
  • · Replies 33 ·
2
Replies
33
Views
3K
  • · Replies 5 ·
Replies
5
Views
3K
  • · Replies 22 ·
Replies
22
Views
4K
Replies
1
Views
2K
  • · Replies 6 ·
Replies
6
Views
2K
  • · Replies 23 ·
Replies
23
Views
2K