0

Hi I have a c program that calculates a score (per person) based on 14 different parameters:

$ ./ScorecommandLine 30 0 0 0 0 0 35 1 1 1 130 1 1 1
0.057748

however at the moment I can only calculate one score at a time. What I would like to do is load the parameters multiple times for lots of different people i.e instead of doing:

$ ./ScorecommandLine 150 0 0 0 0 0 35 1 1 1 130 1 1 1
    0.0577487
$ ./ScorecommandLine 30 1 0 10 4 0 31 1 15 1 90 1 4 1
    0.0897333
$ ./ScorecommandLine 50 0 0 9 0 0 25 1 3 1 123 1 0 0
    0.4567748
$ ./ScorecommandLine 30 0 1 0 0 8 35 1 1 1 130 1 1 1
    0.0838395
$ ./ScorecommandLine 30 1 1 0 1 0 65 4 4 1 32 1 3 1
    0.0495855

where i have to run the command 5 times and have to type the new data for each person every time, I would rather have the data in a csv file and load that into the command line so my program returns all the scores in one go.

tckmn
  • 57,719
  • 27
  • 114
  • 156
brucezepplin
  • 9,202
  • 26
  • 76
  • 129

5 Answers5

4

I suggest opening the file with fopen(), reading each line with fgets(), and then parsing out the numbers with sscanf().

2

Have your program read whole lines from stdin using fgets, say inside a while loop. Then use sscanf to parse the whole line into the variables your code needs. Still inside the while loop, run the bit that generates your score.

After you compile the program - pretend it is myprog:

myprog < myfile.csv
jim mcnamara
  • 16,005
  • 2
  • 34
  • 51
2

You have the right idea already! You're program is perfect, it only needs to be called N number of times to complete a job, and that can all be defined, as you say in a .csv file.

Now all you need is a program that reads a .csv file and calls your program N times to complete the job. A nice way to do this would be to use a separate c program and call your original program using popen. Even nicer still, as it's a small job, would be to write a shell script to do this for you.

Using something like popen is very simple, and exciting too; try The Art of Linux Programming to get an idea of how to start.

If you don't have time to learn popen, then you could always edit your original program. Just check if the first parameter is "-csv", for example, and if so call a separate function that loads a csv file nd enters a while loop as necessary.

deau
  • 1,193
  • 1
  • 9
  • 14
  • have not heard of popen, will give it a try. the approach you describe of just running the program n times works for me, it doesn't have to be the fastest so wil give this a try. – brucezepplin Feb 07 '13 at 22:02
1

I suggest you to write simple shell script to read file and pass parameters to your program in a while loop. Here for example described how to read csv file in bash. Check this also.

Community
  • 1
  • 1
pmod
  • 10,450
  • 1
  • 37
  • 50
  • Not a bash script, a *shell* script. Don't make assumptions. – Jens Feb 07 '13 at 21:49
  • @Jens you see, deau votes for bash also :), for many bash is de-facto == shell script – pmod Feb 07 '13 at 21:54
  • 1
    I question your statement. For many it is zsh. For many it is ksh93. For many it is busybox or ash. Anyone on Solaris or OpenIndiana must care for sh. Assumption is the mother of all screw-ups. It is easy to script portably for all shells. We should do just that and not assume everybody uses what we use. Don't suffer from All-the-world's-a-Linux-box syndrome. – Jens Feb 08 '13 at 10:22
  • @Jens good point, but you are little bit picky - I was giving just an example and not solution – pmod Feb 08 '13 at 21:53
  • I understand that and it really is fair enough. But as an engineer, my raison d'etre is pedantry :-) I seek the very best, not just the good. – Jens Feb 08 '13 at 22:32
1

A much simpler approach would be to do something like this:

#include <stdio.h>

void doYourCalculation(int *iArray) { 
   /*do whatever you do*/
}

int main(int argc, char *argv[])
{
  int iArray[14];
  int i = 0;
  while(1){
    if(scanf("%d",&iArray[i]) != 1){
      break;
    }
    i++;
    if(i == 14) {
      i = 0;
      doYourCalculation(iArray);
    }
  }
  return 0;
}

And since you are using unix/linux, take advantage of the shell:

issue this command in the terminal:

$ cat your_data_file.dat | ScorecommandLine

Where your_data_file.dat looks like :

150 0 0 0 0 0 35 1 1 1 130 1 1 1
130 0 0 0 0 0 25 1 1 1 150 2 4 3
50 0 0 9 0 0 25 1 3 1 123 1 0 0
-

The - at the end marks end-of-input.

The philosophy of programming is to keep it as simple and accurate as possible.

Aniket Inge
  • 25,375
  • 5
  • 50
  • 78
  • this approach is similar to what I had in mind, will give it a try and get back to this. thanks. – brucezepplin Feb 07 '13 at 22:02
  • just trying this out by simply returning iArray. I have replaced 'return 0' with 'printf("%d ", iArray[i]);' and the result i get is '432495072' and with each time a run the program I get a new number. why is this? – brucezepplin Feb 07 '13 at 22:37
  • @brucezepplin that seems to be because iArray[i] contains garbage - uninitiated memory. I suspect that happens when scanf reads space after the first number, and this is not as it expects - so returns 0, breaks the loop. You can check that by printing index (printf("%d %d", i, iArray[i])) or by printing the whole array: for (i=0;i<14;i++) printf("%d ", iArray[i]) – pmod Feb 08 '13 at 21:40
  • @Aniket: Arrghhh!  Don’t use `cat (file) | (command)` when you can say `(command) < (file)`.  (@bruce: But this is a matter of style and efficiency; the pipe syntax should not be causing incorrect results.) – Scott - Слава Україні Feb 08 '13 at 21:40
  • @Aniket, @bruce: `scanf` is OK to use if you are 100% sure that you will always have perfect input.  But, if the input file is corrupted, and a line has only 13 numbers on it, `scanf` will take the first number on the next line and treat it as the 14th number on the corrupted line –– and then propagate that error to every remaining line in the file.  The combination of `fgets` with `sscanf` gives you much more control, and ability to detect errors. – Scott - Слава Україні Feb 08 '13 at 21:42