Hi!

I am supposed to only use the "procedural fragment of C++", i.e. no object-oriented programming (like cin, cout etc). Vectors are not allowed either.

So, one of my goals is to count the number of lines in a text file (let's call it train1.in) which contains data like:

engine 15
engine 40
coach 30
boxcar 52

Now, I am supposed to count the number of cars (i.e. the number of lines in the file), which in this particular case is clearly 4 (two engines, a coach, a boxcar).

Please tell me a simple way to do this. I have one idea in mind- count the number of newlines but I am not sure how exactly to implement this. I am not sure but I think getline() is perhaps not a part of procedural C++. The bottomline is that the code should look like C code.

I have another question. I am just interested in knowing how to read the "spur file_name n" and "shunt file_name n" from user and interpret them as commands.

Write pseudocode and procedural C++ routine for a main routine that accepts a sequence of

train construction commands from standard input (i.e. just use read).
• spur fname n – accept a filename and a number of cars (locomotives) to remove
• shunt fname n – accept a filename and a number of cars (locomotives) to remove (before the reversal)
and then print out the train that results from concatenating each of the trains that the commands generate,
including its length.
For example, if train1.in contains
engine 15
engine 40
coach 30
boxcar 52
and train2.in contains
engine 25
engine 35
lowboy 45
hopper 50

then the commands

spur train1.in 1
shunt train2.in 2

yield

The train contains 5 cars
engine, 40 m.
coach, 30 m.
boxcar, 52 m.
hopper, 50 m.
lowboy, 45 m.
totalling 217 m.

So, if I get to know how to read the commands from user and also interpret them then I will put the necessary code in braces to perform the requisite task. I need help on this as soon as possible. I would greatly appreciate your help.
Thanks a lot!!:)

I have written a few pseudocode algorithms (may have a lot of errors)
http://pastebin.com/HFkrHuGR

Recommended Answers

All 14 Replies

In C, you read a text file line by line, using

fgets(charArrayName, sizeof(charArrayName), filePointerName);

Which will automatically insert the whole line of text, into your char array, including the newline (and the end of string char: '\0', after that. (If room allows).

while((fgets(charArrayName, sizeof(charArrayName), filePointerName)) != NULL) {
  //your code here

}

Is a standard idiom in C to read every row of text in the file.

Railroad theme, I see. ;)

commented: very helpful +2

If you can't use c++ objects then use FILE* and call fgets() in a loop until end-of-file is reached, counting the number of iterations of the loop. When done, you will have the number of lines in the file.

commented: thanks. +2

Thank you so much, Adak! All I had to do to count lines was putting count=count+1 inside while loop.

Any way, I still need to figure out the second question I asked, i.e. how to take commands from user and also interpret them as two different commands.
For example, if the user inputs: spur train1.in 1 then the program runs a certain set of functions that spur the given train
and if the user inputs shunt train2.in 2 then the program runs a certain set of functions that shunt the given train

Thanks again.:)
Hopefully, this will solve all my major difficulties because I think I have got the pseudocode algorithms more or less in good shape. All I had trouble with was with reading strings etc.

PS: train1.in and train2.in are filenames for text files containing stuff like:
engine 45
coach 36
boxcar 26

First you have to write a function for each command you want to support

Next, read a line, split the line into its individual words, then call the appropriate function for the verb in the first part of the string. Something like this:

string verb;
string line;
size_t pos = line.find(' '); // find first word
verb = line.substr(0,pos);
if( verb == "spur")
   spur(line);
else if(verb == "shunt")
   shunt(line);

I wish to add that:

From the user input command, I also want to retrieve the filename (e.g. train1.in) and the following number (e.g. 1) and store them as separate variables.

Thanks

The easiest way to do that would be to use stringstream class

#include <sstirng>
#include <string>
#include <fstream>
// other includes too

int main()
{
   std::string line = "shunt train2.in 2";
   std::string verb, filename;
   int num;
   strgingstream s(line);
   // now splie the line into its individual parts
   s >> verb >> filename >> num;
}

Hi, Ancient Dragon!

Thanks for your input but I am afraid I am not allowed to use any object-oriented programming and can only use the "procedural fragment of C++". In other words, anything that works in C is allowed.

From your code, it appears to me that I may be violating the rules. Please correct me if I am mistaken here because I do not know as much about C and C++ as you do. The << reminds me of OOP because cin and cout are not allowed in procedural C++.

Sounds like you have to write a C program, not a C++ program. In that case I would use strtok() to split the line.

#include <stdio.h>
#include <string.h>

int main()
{
   char line[] = "shunt train2.in 2";
   char *verb, *filename, *ptr;
   int num;
   verb = strtok(line," ");
   filename = strtok(NULL," ");
   ptr = strtok(NULL," ");
   printf("%s %s %s\n", verb,filename,ptr);
}

Thanks a lot, Ancient Dragon! Your program worked like a charm and is very helpful.:icon_biggrin:

It looks to me like everyone miss this line in your instructions:

train construction commands from standard input (i.e. just use read).

Your instructor told you what command to use for input, didn't he?
I agree fgets() is better. Then again, maybe he meant it only as an example.

I have a problem with adding of two trains. Consider the scenario when I do not know how many trains the user is going to perform operations on. The user will input a set of commands on a certain number of trains. At the end of all operations, I need to join one train after the other (like linked lists) in the order in which the commands concerning those trains were input.

So, how can I add two trains one after the other?
Furthermore, since I do not know the number of trains the user will be operating on, I intend to prompt the user to enter the number of trains. Then using a loop, I will prompt the user to enter commands for each train individually and respectively. While taking each command, I will be executing the commands immediately and when all the commands for a single train (starting with the first train) have been executed, I add them to an empty queue (or stack). For the next train, all the commands will be executed and the resulting train will be added just behind the previous one in the queue (or stack).

So, I do not know the exact C way to add the trains, one behind each other. All I can think of is linking the tail of the first to the head of the latter but I don't know how exactly it will be implemented.
Some files are available for me to use with a note saying (You will need to (only) change the typedef lines inside Stack.h and Queue.h in order to use our code. You still do not need to hand in the Stack.h and Queue.h files however.) :
Queues (i.e. Queue.h, QueueInterface.h, and Queue.cc) and Stacks (i.e.
Stack.h, StackInterface.h, and Stack.cc)

struct Car {
  char *kind;
  int length;
};

struct Train {
  int nCars;
  Car *cars;
};


Write C routine for a main routine() that accepts a sequence of

train construction commands from standard input (i.e. just use read).
• spur fname n – accept a filename and a number of cars (locomotives) to remove
• shunt fname n – accept a filename and a number of cars (locomotives) to remove (before the reversal)
and then print out the train that results from concatenating each of the trains that the commands generate, including its length.
For example, if train1.in contains

engine 15
engine 40
coach 30
boxcar 52

and train2.in contains
engine 25
engine 35
lowboy 45
hopper 50

then the commands

spur train1.in 1
shunt train2.in 2

yield

The train contains 5 cars
engine, 40 m.
coach, 30 m.
boxcar, 52 m.
hopper, 50 m.
lowboy, 45 m.
totalling 217 m.

It looks to me like everyone miss this line in your instructions:

Your instructor told you what command to use for input, didn't he?
I agree fgets() is better. Then again, maybe he meant it only as an example.

Sorry for the confusion WaltP. First we have to write main() in pseudocode (and that is why "read" was used) and then the pseudocode should be translated to procedural C++ code (which is just like writing C code in C++).

Please help me with my current problem. I do not fully understand how the Train structure could be manipulated with these given routines.

Instructor:
you can include train.h, and use the train functions with the typedef Car Element; statement (and there will be a typedef added to the file by the TA's, making Elements equivalent to the Car struct)

or, you can use the element structure defined in one of these threads, and include element.h.

the two are incompatible. there is one other complication: the typedefs existing on the stack and queue.h files need to be removed for either of these methods to work. this will be done come grading of the assignments, but you need to do it yourself to test your program.

Instructor gives some more details:

We will be using our own

    * List.cc,
    * List.h,
    * ListInterface.h,

rrom tutorial 5: where Element.h actually be train.h since we (obviously) use a Car structure as the element (as in Assignment 3).

We will be using

    * Stack.cc,
    * Stack.h,
    * StackInterface.h,

from tutorial 6 (again our element will be generalized to a Car structure).

We will be using

    * Queue.cc,
    * Queue.h,
    * QueueInterface.h,

from tutorial 7 (again our element will be generalized to a Car structure), and

    * train.cc
    * train.h (which will contain the Car structure)

from assignment 3.

As long as your code only calls ADT routines as documented in ListInterface.h, StackInterface.h, QueueInterface.h for the various tutorials, and train.cc as in Assignment 3, it will work with our code.

Note that this means you cannot rely on a particular List implementation, (i.e. no accessing an array element of a List, or using a next pointer).  You can only insertHead, insertTail, deleteHead, deleteTail, head, tail, destroyList, createList, etc.  You also cannot rely on a particular Stack or Queue implementation, but you must use push, pop, enQueue, deQueue, empty, ...
 
More details again:
 
Recalling assignment 3,

struct Car {
    char *kind;
    int length;
}

struct Train {
    int nCars;
    Car *cars;
}

After getting Element.h and Element.cc from Tutorial 5 to understand that elements will be cars, we can try something:

#include <cstdlib>
#include <cassert>
#include <cstdio>

#include "train.h"           // from Assignment 3
typedef Car Element;

#include "List.h"            // from Tutorial 5
#include "ListInterface.h";  // from Tutorial 5

// accept a train and return it as a List of Cars
// using only the operations in the List ADT
List train2List(Train t) {
    List trainAsList = createList();
    for (int i=0; i<t.nCars; i+=1) {
        assert(insertTail(trainAsList, t.cars[i]));
    }
    return trainAsList;
}

// accept a List of Cars and convert it to a train
// using only the operations in the List ADT
Train list2Train(List l) {
    Train t = *(makeTrain(lengthList(l)));
    for (int i=0; !emptyList(l); i+=1) {
        assert(head(l, t.cars[i]));
        assert(deleteHead(l));
    }
    return t;
}

// simple activity
int main() {
    while (!feof(stdin)) {
        int nCars;
        char tFile[BUFSIZ];

scanf(" %d %s", &nCars, tFile);
if (0 == nCars) { // stop when the count is 0
     break;
        }
        Train t = *(makeTrain(nCars));
if (!readTrain(t, tFile)) {
            fprintf(stderr, "Read failed\n");
            continue;
        }
char ignored[BUFSIZ];
fgets(ignored, BUFSIZ, stdin);

printTrain(t);
        List l = train2List(t);
        Train t2 = list2Train(l);
        printf("\n This should be the same:\n");
        printTrain(t2);
    }

    return EXIT_SUCCESS;
}

This will do a simple activity, of reading a train and operating it on as a List.

I am attaching the lab5 files on Element and List.

commented: Endless repitition of the same text and attaching the same files to every post is a waste or your time and our bandwidth. Think before you post! -3

The first comment "you can include traing.h ... " was given by a student and not an instructor.

Unfortunately, your post above, is all about your assignment - and not about using C style C++. This is the part of the assignment that you need to work through. It has so many parts to it, with so many constraints, that it's very unlikely anyone will be willing to donate the time necessary to fully understand it. I've read your description of the problem through twice, and have an insufficient grasp of the total problem yet.

And you can't even start to put up pseudo code, until you really understand the problem fully. :(

Use your class notes, your memory from the lectures, and if you're stuck, ask your teacher a class mate, or assistant, to explain some details for you.

My advice is to work it through until and unless, you have a specific problem that is C related, and not assignment related - then we can help you. If you can't describe the C problem in a paragraph or two, you need to get to the point that you can do that.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.