C/C++ C++ Simple File I/O: Tips & Solutions

  • Thread starter Thread starter DivGradCurl
  • Start date Start date
  • Tags Tags
    C++ File
AI Thread Summary
The discussion focuses on challenges faced while implementing file I/O in C++, particularly reading strings with spaces and handling character data types. Users suggest using the "getline" function to read entire lines from a file, which simplifies processing by allowing conversion of strings to other data types afterward. Issues with reading empty lines leading to unexpected outputs, such as a "0" in the final output, are addressed, with recommendations to check for empty lines before processing. Additionally, the conversation touches on dynamically creating instances of classes using linked lists to maintain access to all created objects. Overall, participants share tips and code snippets to improve file reading and data handling in C++.
DivGradCurl
Messages
364
Reaction score
0
I'm trying to come up with a C++ program that reads input from a text file. Each line of this text file has a different variable. I have different data types (int, string, char). I'm having difficulty to read strings with spaces and read char's. The rest seems to work fine. If possible, I'd like to hear some tips on how to improve my work. I've already searched the web several times, but I haven't been able to find a solution. The programs (one that creates 20 blocks of inputs and the other which reads each block) are attached.

Any help is highly appreciated.
 

Attachments

Technology news on Phys.org
Do you have to use ifstream? Could you use fscanf?

The syntax would be something like this:

FILE *fp ;

fscanf(fp "%d %s %s %f %s %s", &id, name, description, &cost, department, color);

This is the way I like to do it. It is a much cleaner approach.
 
Last edited:
yah fscanf/fprintf are so much better. but can you have those spaces in theredduardo? %d %s or is it %d%s?
 
You can have whatever you want. Tabs, newlines, spaces, characters, etc.
 
It seems that the approach suggested is from C. I don't know whether or not that can be used as if it were C++ code. There are no compilation errors, but I don't get output from the program. I've uploaded a text file with what I have now. I'm a bit lost.

Thanks for your help, folks.
 

Attachments

You have to use C style strings, which means:

char mystring[n] ; //Use this if you know the size of the field

or

char **mystring ; //Use this if you don't know the size of the field
 
Last edited:
Processing user input in both C and C++ can give you a headache because of little details. Reading a string with "scanf" or "cin <<" will only read one word at a time, stopping at any whitespace. C function "gets" reads a whole line but does not check for overflow so you get subtle errors that mysteriously happen once in a while, not always. Function "fgets" does not remove the trailing '\n' from the input buffer so you have to remember to do it manually. Reading pretty much anything with "cin <<" in C++ can cause the same problem: the '\n' remains in the buffer so when you read a test line with "getline" after an integer then all you get is an empty one (from the newline chatracter); then the next call to read an integer causes an input error. All sort of annoying little details like this.

Here's my approach to resolve these annoyances. Whenever you have separate data items on separate lines, read each line as plain text first. In C++ you can use the "getline" function for this:

string str;
while (getline(cin, str)) {
// Do something with str.
}

You can replace "cin" with any other stream if you're reading from a file instead of the console. Once you have a line of data into a string, if you know what is in it then use an appropriate conversion function to convert it. It's not a sin to use some of the C functions for this (with str.c_str() to get a C char*), so use "atoi" to convert alpha to integer, use "atof" to convert alpha to float, leave the string as is if a string is what you need, use str[0] if all you want is the first character. It's simple and it works consistently.
 
Sorry for the delay. I've been trying to figure out the code...

Thank you so much, my program is beginning to function!

I am just having a problem reading the char datatype. I cannot pass it to a c++ char variable without using a conversion trick. Is there a way to accomplish this?
 
I've just found a way to incorporate Orefa's suggestion to the char problem. It does work! Now I just get a strange "0" in my last line of the final output file. Maybe it's just simpler to picture this by looking at the files attached. The first c++ code (see GenerateInputFile.txt) generates the input txt file whereas the other c++ code (see InOut.txt) reads it and writes an output txt of what has been read. That's where the '0' appears. :confused:
 

Attachments

  • #10
If your data file ends with a redundant newline character then the loop will repeat one time too many and your first IF clause will convert an empty line (caused by this lone '\n' character) into an integer. This will generate the 0 you're seeing.

What you should do is check for an empty line at the top of the loop. If the line length is zero then break out of the loop.

By the way, you know that you can simplify your code a great deal. Now that you've done all the work... :smile: No need for an array of strings, you can reuse only one. You can also eliminate a lot of repetitious code. Consider this simplified version (which I didn't try to compile and run, I hope it isn't too buggy):
Code:
int main() {
    int      count = 0;
    string   line;
    ifstream in("myProducts.txt");
    ofstream out("OUTPUT.txt");

    while (getline(in, line) && line.length() > 0) {
        switch (count % 5) {
            case 0: out << atoi(line.c_str());  break;  // ID
            case 1: out << line;                break;  // Name
            case 2: out << atof(line.c_str());  break;  // Cost
            case 3: out << line[0];             break;  // Department
            case 4: out << line;                break;  // Color
        }
        cout << endl;
        ++count;
    }
    out << "# LINES READ = " << count << endl;
    in.close();
    out.close();
    system("pause");
    return 0;
}

Edit: I realize that the above code does away with many variables you may need to keep. It is just to illustrate possible simplification methods.
 
Last edited:
  • #11
Thanks, Orefa!

Indeed, your approach greatly simplifies the problem. I managed to get something working the way it was supposed to! The purpose of these programs is to simply ensure that the inputs I read from a text file are accurate. Now I can play with the data, and hopefully have some fun. :smile:

I have a lot to learn. Thanks for your support, guys.
 
  • #12
dynamic objects

I'm wondering if any of you know how to dynamically create instances of a class. I've been trying, but all that I can do is read one single block of input from a text file. I've attached my work.

Any help is highly appreciated.

Thanks!
 

Attachments

Last edited:
  • #13
You can dynamically create instances of a class using the new operator.

However, i guess you would also like to keep access to all the objects that you have created, which is not that simple unfortunately, but its not very hard either.

Since we need to keep reference to all the objects created, we will maintain them in a linked list. The nodes of the linked list will have the following members,

1. A pointer of type <class>
2. Next node pointer

Basic node step creation would be as follows,
1. Create an instance of linked list node
newnode = new LinkedListNode()

2. Connect the newly created node to previously maintained Linked List,
tail->nextnode = newnode
tail = newnode
**tail is a pointer which is maintained so as to always point at the tail of the linked list. Correspondingly, we need also to maintain a head pointer which points to start of the linked list.

3. Assign memory to the <class> pointer inside the new instance just created.
tail->classptr = new <class>()

Thus, you have dynamically created a new instance of class and at the same time you have maintained all the objects you have created so far. You can access each of these objects by traversing the list from head to tail.

-- AI
P.S -> Linked List is a form of data structure that helps you maintain "things" (in your case "things" were class objects) in the form of a list. This is not the only data structure that you can use. You can use anything from stack, queues, hashtables etc etc. to meet your needs and is most efficient as per your requirements.
 

Similar threads

Back
Top