Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

corywoolf

macrumors 65816
Original poster
Jun 28, 2004
1,352
4
Hello MR members,

I have spent three hours trying to figure out how to read in the data of a group of people and store the information into an array of structures (struct Node) and then print out the array. I was given the following structure definition to work with:

Code:
struct Node { char name[20];
int ID; int distance;
};

I understand the concept of arrays and structures (a group of arrays), but I can't find a good example that is similar enough to my problem to study.

I am trying to read the following text from file "a6.txt" into an array of structures:

April,Joe
3120
12

Matthews,Jocob
4592
39

Garfield,Kitty
8917
33

Lake,Bill
2233
21

Jones,Betty
8912
18

Goodman,Betty
4598
19

Lands,Norman
7812
36

Johnson,Carl
8917
29

Here is the C++ I have so far:

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

using namespace std;

int READ(char txtfile[10]; int numarray[10]; int counter;)
{
    ifstream filename;
    filename.open (txtfile);
    while (!filename.eof())
    {
        filename >> numarray [counter];
        cout << numarray [counter] << endl;
        counter++;
    };
};
        

int main()
{
    char txtfile[]="a6.txt";
    int size=10;
    int numarray [size];
    int r;
    r= READ();
    cout<< r;
    
    system("PAUSE");
    return EXIT_SUCCESS;
}

Any tips or guidance is appreciated.

Thanks in advance,

- Cory
 
Ok, bare with me here, I'm winging this. :D

Code:
struct Node { char name[20];
int ID; int distance;
};

int main(int argc, char *argv[])
{
    FILE *Input_File;
    Node Names[100];
    int Count = 0;

    Input_File = fopen("a6.txt", "r");
    if (Input_File != null)
        Count = fread(&Names[0], sizeof(Node), 100, Input_File);
    fclose(Input_File);

    // Count = Number of items read, up to 100.
}

NOTE: This example will not work right for your data file, this would require a record data file. To handle the a6.txt file as you wrote it try the following :
Code:
struct Node {
char last_name[20]; 
char first_name[20];
int ID; 
int distance;
};

int main(int argc, char *argv[])
{
    FILE *Input_File;
    Node Names[100];
    int Count = 0;

    Input_File = fopen("a6.txt", "r");
    if (Input_File != null)
        while (!feof(Input_File) && (Count < 100))
        {
            scanf(Input_File, "%s,%s", &Names[Count].last_name, &Names[Count].first_name);
            scanf(Input_File, "%u", &Names[Count].ID);
            scanf(Input_File, "%u", &Names[Count++].distance);
        }
    fclose(Input_File);
    // Count = Number of items read, up to 100.
}

This second one isn't perfectly coded, but it is the general gist. It doesn't have any error checking or recovery if things happen that are unexpected. but should get you rolling on the right path.

Good Luck . . . and if this doesn't work perfect, again, I'm winging it. :D
 
First a few questions.

Is this homework for a class?
If so what is the name of the course?
What book?
What have you covered so far?

I'm assuming from the definition of 'Node' that C++ string objects haven't been covered in whatever has been presented (or study material your working from) yet.

What I/O routines have have you been made aware of?

And it looks like you're working in C++. Is that correct?
 
First a few questions.

Is this homework for a class?
If so what is the name of the course?
What book?
What have you covered so far?

I'm assuming from the definition of 'Node' that C++ string objects haven't been covered in whatever has been presented (or study material your working from) yet.

What I/O routines have have you been made aware of?

And it looks like you're working in C++. Is that correct?

It is an assignment for a class. Computer Methods I. Programming and Problem Solving with C++. We have just started to get into arrays and structures. The professor just reads off a powerpoint and doesn't provide enough examples to study from. I have had trouble finding a similar example to this assignment. I don't recall hearing much about nodes yet.
 
Ok, bare with me here, I'm winging this. :D

Code:
struct Node { char name[20];
int ID; int distance;
};

int main(int argc, char *argv[])
{
    FILE *Input_File;
    Node Names[100];
    int Count = 0;

    Input_File = fopen("a6.txt", "r");
    if (Input_File != null)
        Count = fread(&Names[0], sizeof(Node), 100, Input_File);
    fclose(Input_File);

    // Count = Number of items read, up to 100.
}

NOTE: This example will not work right for your data file, this would require a record data file. To handle the a6.txt file as you wrote it try the following :
Code:
struct Node {
char last_name[20]; 
char first_name[20];
int ID; 
int distance;
};

int main(int argc, char *argv[])
{
    FILE *Input_File;
    Node Names[100];
    int Count = 0;

    Input_File = fopen("a6.txt", "r");
    if (Input_File != null)
        while (!feof(Input_File) && (Count < 100))
        {
            scanf(Input_File, "%s,%s", &Names[Count].last_name, &Names[Count].first_name);
            scanf(Input_File, "%u", &Names[Count].ID);
            scanf(Input_File, "%u", &Names[Count++].distance);
        }
    fclose(Input_File);
    // Count = Number of items read, up to 100.
}

This second one isn't perfectly coded, but it is the general gist. It doesn't have any error checking or recovery if things happen that are unexpected. but should get you rolling on the right path.

Good Luck . . . and if this doesn't work perfect, again, I'm winging it. :D

Thanks for your effort, it didn't work though. Isn't "scanf" used in C and not C++?
 

Attachments

  • Screen shot 2010-03-30 at 12.20.46 AM.png
    Screen shot 2010-03-30 at 12.20.46 AM.png
    41 KB · Views: 1,384
THe problem shown is that it should be NULL, note the case.
As I said.... don't expect it to work correctly, I was making it up as I go along. I'm more of an embedded C programmer, but have moved on to other languages, thus C++ isn't my native language. :D
 
THe problem shown is that it should be NULL, note the case.

That's not the only problem. It shouldn't be calling scanf(), since scanf() reads stdin. I suspect fscanf() is more plausible. Some limits on string-length would also be wise, lest buffers be overflowed.


To the OP, I'm not seeing how this could work as the declaration for READ():
int READ(char txtfile[10]; int numarray[10]; int counter;)

And that's my tip for the OP: When you have errors, always post the exact text of the errors. And if you don't have errors, then you haven't tried compiling. And if you haven't tried compiling, you haven't really tried.

I also suggest providing an explanation of what this is intended to do:
Code:
    system("PAUSE");
 
That's not the only problem. It shouldn't be calling scanf(), since scanf() reads stdin. I suspect fscanf() is more plausible. Some limits on string-length would also be wise, lest buffers be overflowed.

Doh, yeah, fscanf. That's a big snafu. :D I guess I should have run it through a compiler; lol. It was last night, I was tired and rushing. :D
 
That's not the only problem. It shouldn't be calling scanf(), since scanf() reads stdin. I suspect fscanf() is more plausible. Some limits on string-length would also be wise, lest buffers be overflowed.

Yes, I'm well aware of that.

Not wanting to get side tracked to much I wanted to know what the exact wording of the assignment was so as offer helpful advice. He seems to have been given a starting point with a definition for 'Node'.

Also his homework seems to be very close, if not the same, as this one. So much so that I wanted to know if he was given the the declarations of other functions he was to use.
 
To the OP, I'm not seeing how this could work as the declaration for READ():

Indeed, that's either a notation I've never seen before or there is definitely something wrong here.

My suggestion is to always start small and work your way to bigger things. That way you can build on smaller successes rather than try to write out something bigger and have it fail and not know where to begin.

If I was doing this assignment, I might start by doing the following:

- Write a simple program that just reads the text file and prints out everything it reads. You can hard-code the filename to start.

- Write a program that creates a single Node object and fills it with data about a person. You can hard-code the variable assignments for this first round.

- Now change the program to create an array of these Nodes, fill them with data (you can hard code this), and prints out the array. Now is the time to practice looping through arrays and stuff like that.

- Now put it all the pieces together so that you read your list of names from the file and populate the node objects, as the assignment requires.

Are you required to use separate functions (e.g. your READ() function) or are you allowed to accomplish it all in the main() function? If you are using a separate READ() function to read values into the array, you're either going to need to declare the array as a global variable or pass a pointer to the function, neither of which you've mentioned if you know how to do or not.
 
The following is meant to give you an idea of how to continue your homework assignment.

It also points out a few potential gotcha's.

Code:
#include <cstdlib>

#include <iostream>
#include <fstream>

struct Node
{
    char    name[20];
    int     ID;
    int     dist;
};

int main (int argc, char* const argv[])
{
    const size_t    MAX_NODE_ENTRIES            = 4;
    Node            nodes_array[MAX_NODE_ENTRIES];

    std::ifstream   ifs("A6.txt");
    if ( ifs.is_open() )
    {
        // read records from 'ifs'
        size_t  nodes_index = -1;
        do
        {
            if ( ++nodes_index >= MAX_NODE_ENTRIES )
            {
                std::cout   << "Not enough entries in 'nodes_array' to read next record!\n"
                            << "Adjust value of 'MAX_NODE_ENTRIES'";
                return EXIT_FAILURE;
            }

            // WARNING!!!  unknown length read into 'name' field which is of fixed length
            if ( ifs )  ifs >> nodes_array[nodes_index].name;
            if ( ifs )  ifs >> nodes_array[nodes_index].ID;
            if ( ifs )  ifs >> nodes_array[nodes_index].dist;
        } while ( ifs );
        
        // --- display all entries in array 'nodes_array'
        for ( size_t i = 0; i < nodes_index; i++ )
        {
            Node    node = nodes_array[i];
            std::cout << node.name << "\n" << node.ID << "\n" << node.dist << "\n\n";
        }

        return EXIT_SUCCESS;
    }
    
    return EXIT_FAILURE;
}
 
The following is meant to give you an idea of how to continue your homework assignmen

Hi lloyddean.

Thanks for posting an example. I do not have a homework assignment to do, however I would really like to be able to read in some parameters from a file (any file will do) to a c++ file. I have a one question:

1) Is the example you posted above supposed to work? (I have pasted it into Xcode and tried it with the A6.txt included in the project folder and included in the project explicitly.

According to my console it seems that it cannot open the file. I added an output of BLANKET and PANCAKE to indicate if the file is notopen/open. I also tried it with ifs.open("A6.txt"); and without.

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

struct Node
{
    char    name[20];
    int     ID;
    int     dist;
};

int main (int argc, char* const argv[])
{
	
	std::cout << "BLANKET" << std::endl;
    const size_t    MAX_NODE_ENTRIES            = 4;
    Node            nodes_array[MAX_NODE_ENTRIES];
	
    std::ifstream   ifs("A6.txt");
	
	ifs.open("A6.txt");
	
    if ( ifs.is_open() )
    {
		
		std::cout << "PANCAKE" << std::endl;
        // read records from 'ifs'
        size_t  nodes_index = -1;
        do
        {
            if ( ++nodes_index >= MAX_NODE_ENTRIES )
            {
                std::cout   << "Not enough entries in 'nodes_array' to read next record!\n"
				<< "Adjust value of 'MAX_NODE_ENTRIES'";
                return EXIT_FAILURE;
            }
			
            // WARNING!!!  unknown length read into 'name' field which is of fixed length
            if ( ifs )  ifs >> nodes_array[nodes_index].name;
            if ( ifs )  ifs >> nodes_array[nodes_index].ID;
            if ( ifs )  ifs >> nodes_array[nodes_index].dist;
        } while ( ifs );
        
        // --- display all entries in array 'nodes_array'
        for ( size_t i = 0; i < nodes_index; i++ )
        {
            Node    node = nodes_array[i];
            std::cout << node.name << "\n" << node.ID << "\n" << node.dist << "\n\n";
        }
		ifs.close();
        return EXIT_SUCCESS;
    }
    
    return EXIT_FAILURE;
}
///////////////////////////////////////////////////////////////////////////////////

And here is the output:

///////////////////////////////////////////////////////////////////////////////////

[Session started at 2010-04-06 14:30:03 +0100.]
GNU gdb 6.3.50-20050815 (Apple version gdb-1346) (Fri Sep 18 20:40:51 UTC 2009)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "x86_64-apple-darwin".tty /dev/ttys000
Loading program into debugger…
Program loaded.
run
[Switching to process 70711]
Running…
BLANKET

Debugger stopped.
Program exited with status value:1.kill
(gdb)
/////////////////////////////////////////////////////////////////////////////////////

I just want to read in some parameters. Any help would be much appreciated even if it is a reference to a book. I have already spent a day and a half searching the web and testing examples.

Thanks very much!
:eek:
 
The example code worked for me, compiled under g++ and run from a Linux command line, however I had to explicitly include <cstring> to get size_t and define my own EXIT_SUCCESS and EXIT_FAILURE as my compiler declared them undefined.

TREERAT, are you running this from a command line? If so, is the A6.txt file in the same directory as your program binary?
 
Thanks notjustjay

Well originally I was running the file in Xcode (the software developer). So taking your advice I tried running from the command line like so:

/////////////////////////////////////////////////////////////////////////
mwoods-macbook:Reading Data From File maewoods$ ls
A6.txt MForums.cpp
mwoods-macbook:Reading Data From File maewoods$ g++ MForums.cpp -o MForums
mwoods-macbook:Reading Data From File maewoods$$
/////////////////////////////////////////////////////////////////////////

and got the same output again.

/////////////////////////////////////////////////////////////////////////
Last login: Tue Apr 6 16:41:18 on ttys003
mwoods-macbook:~ maewoods$ /Users/maewoods/Desktop/Reading\ Data\ From\ File/MForums ; exit;
BLANKET
logout

[Process completed]
/////////////////////////////////////////////////////////////////////////

The A6.txt is in the same folder as the cpp file.

Thanks :) :confused:
 
Code:
mwoods-macbook:Reading Data From File maewoods$ ls
A6.txt	 MForums.cpp
mwoods-macbook:Reading Data From File maewoods$ g++ MForums.cpp -o MForums 
mwoods-macbook:Reading Data From File maewoods$$
After the g++ command has completed, enter exactly this command:
./MForums
Do not quit Terminal. Do not close the window. Do not use another window. Do not 'cd' to another directory. Simply copy and paste the exact command-line directly into Terminal after your compiling command has completed.

The problem is that the file "A6.txt" is opened using a relative pathname (read the source, note the pathname). Relative pathnames are always interpreted relative to the working directory. If the file isn't located in the working directory, then it won't work.

http://en.wikipedia.org/wiki/Working_directory
http://en.wikipedia.org/wiki/Path_(computing)

The concept of a pathname, either relative or absolute, is fundamental to understanding file-systems.


Code:
mwoods-macbook:[U]~[/U] maewoods$ /Users/maewoods/Desktop/Reading\ Data\ From\ File/MForums ; exit;
In this trial run, the working directory is your home folder, represented by "~". I've underlined it above in your shell prompt.

I underlined it in your compiling command-line, too:
Code:
mwoods-macbook: [U]Reading Data From File[/U] maewoods$ g++ MForums.cpp -o MForums

There is a C function to get the working directory's pathname as a C string: getcwd(). You might want to change your program to print that string, then use it as a diagnostic aid to help you figure out what's happening. Online man page:
http://developer.apple.com/Mac/library/documentation/Darwin/Reference/ManPages/man3/getcwd.3.html
 
Hi lloyddean.

Thanks for posting an example. I do not have a homework assignment to do, however I would really like to be able to read in some parameters from a file (any file will do) to a c++ file. I have a one question:

1) Is the example you posted above supposed to work? (I have pasted it into Xcode and tried it with the A6.txt included in the project folder and included in the project explicitly.

According to my console it seems that it cannot open the file. I added an output of BLANKET and PANCAKE to indicate if the file is notopen/open. I also tried it with ifs.open("A6.txt"); and without.

/< CODE SNIPPED OUT *>/

I just want to read in some parameters. Any help would be much appreciated even if it is a reference to a book. I have already spent a day and a half searching the web and testing examples.

Thanks very much!
:eek:

Yes it compiles and works on this end. Although it was missing the inclusion of 'cstdio" from what I posted here. I must've missed in when copying into the code tags.

As to not finding the file "A6.txt" go to your "Project" menu select "Edit Active Execuatable <your executable name>". A setting dialog to set up the runtime executable environement will appear.

Make sure the "General" viw-tab is selected.

In the lower left quadrant locate the radio-botton labeled "Set the working directory to:" to what ever is appropriate for your use. If the "A6.txt" is sitting next to your Xcode project file select "Project Directory".

Close the Dialog.

Run.
 
Thank you for some answers. The file is now being read, although I have no display of the entries in nodes_array. If I change the value of nodes_index I get a display of either zero or another integer. No values from A6.txt are displayed.

chown33: It makes perfect sense but I did not know that about the relative pathnames so thanks.
 
If you're using the code "as is" against the "A6.txt" as you posted above you should see this output:

Not enough entries in 'nodes_array' to read next record!
Adjust value of 'MAX_NODE_ENTRIES'

It seems to me you've made little attempt to understand the example.

A simple modification at the very first line of 'main' will be required in order for the code to 'read' the complete file before it can display what was read. This was done on purpose on my part as one of the things that you'll need to understand to keep you from over running the end of your arrays.
 
Well thanks lloyddean but you are gravely wrong. I do not know about nodes and I have made an effort to understand the example, around about 17 hours is a lot of time to invest. I have not had any training in computer science and I would like to learn.

Every so often someone gives you correct information "as is" with the hope that the information will be understood properly and will not be used to for a selfish purpose. Those are the people who will never be famous but will help us cure diseases and increase our quality of life.

Note: I do not get the error:

Not enough entries in 'nodes_array' to read next record!
Adjust value of 'MAX_NODE_ENTRIES'
 
OK, let's back things up a bit. To make things easier, instead of a set of Node structures, let's just work with numbers: let's assume we have a file, full of numbers, one number per line, like so:

Code:
2
6
112
-135
45465
12

So your array to store these numbers in memory might look like this:

Code:
const size_t    MAX_ARRAY_SIZE = 10;
int array_of_numbers[MAX_ARRAY_SIZE];

This defines an array with 10 elements, so you can have up to 10 numbers stored in the file. If you try to read a file with more than 10 numbers, you'll have to increase the value of MAX_ARRAY_SIZE to suit.

And your code, based on the above example, would be simplified a bit and look like this:

Code:
#include <cstdlib>

#include <iostream>
#include <fstream>

int main (int argc, char* const argv[])
{
    const size_t    MAX_ARRAY_SIZE  =  10;
    int array_of_numbers[MAX_ARRAY_SIZE];

    std::ifstream   ifs("numbers.txt");
    if ( ifs.is_open() )
    {
        // begin reading numbers from 'ifs' file stream
        size_t  index = -1;
        do
        {
            if ( ++index >= MAX_ARRAY_SIZE )
            {
                // ran out of space in the array!
                std::cout   << "Not enough entries in 'array_of_numbers' to read next record! Adjust value of 'MAX_ARRAY_SIZE'" << std::endl;
                return EXIT_FAILURE;
            }
            // read the number into the next available index in the array
            if ( ifs )  ifs >> array_of_numbers[index];
        } while ( ifs );
        

        // now loop through the array so we can print each value
        for ( size_t i = 0; i < index; i++ )
        {
            std::cout << array_of_numbers[i] << std::endl;
        }

        return EXIT_SUCCESS;
    }
    
    return EXIT_FAILURE;
}

Hopefully this simplifies things enough to help you understand what's going on.
 
OK for any people who are having similar problems with reading in data I now have the answer to my problem. I was trying to use a "file.txt" that I had copied from a different project.

Maybe,

This resulted in a newline character error.

I attempted to resolve this issue by creating a file in terminal using the pico command.

Then I had to rename the file using the mv command.

Now I can read in the correct values from my file. I have not tested it with the example above, but I hope this will resolve the problem with that also.

Again thanks for your help guys! :)
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.