Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

small bug reading input with C program

Tags:

c

scanf

I thought I had this program up and running, but upon a second look at the output file, I noticed a few 'seemingly random' misprints in the calculations. After tracking down all the erroneous numbers, I found a weird pattern to the errors that I can't explain or figure out, although I have a feeling it has to do with the binary code being stored in memory.

The program is supposed to take a text file consisting of line after line of data, each line follows the format of having three letters, (either 'pre' or 'pos') then two more letters which represent a school ID, two numbers that represent the class (there are 4 possibilities for this combination, 51, 52, 61 or 62), and a final two digit number to represent the student's ID. This first bit makes up the ID tag of the data entry. The tag is followed by a line of 18 single-digit integers ranging from 0 to 2. These are the scores the student received for each of the 18 problems on a test. Here's an example of a single data entry, The text files being processed each have 100 lines like this. preIS6114 0 0 0 1 1 2 1 1 1 0 0 0 1 1 0 0 0 0

The issue I'm having is that when the program reads a line of data, MOST of the time it reads it just fine, does what it's supposed to do, and moves on. However! If the final two digits of the ID tag are either 08 or 09, the program thinks that the student's ID number is 0, and that the first SCORE of the test was an 8 or 9 respectively, which of course is impossible since 2 is the maximum score that a student could have received on a problem. I looked, and sure enough, in every instance of the student ID being 08 or 09, this error occurred. Lower ID's (01 through 07) work just fine, as do IDs higher than 09.... so why just these two numbers? I just find that to be unusual..

This is the second time I've come to SO with this program, the first time, user input was causing problems all over the place, so someone suggested using fgets first and then scanf to parse the data, which I did and got the program working (or so I thought.. i didn't notice this issue until a second look at the output data)

I'm working with C, and I'm not a programmer, I'm an English professor, so I clearly don't know everything there is to know about C. Given that, please don't worry about the other issues with my program (as I'm aware that there are many) unless you think it will cause other errors. The code is quite lengthy, so I'm going to cut out all the simple int variable declarations just to save space here and focus on the problematic part.

int main()
{
char pp[4];
char school[3];
int class;
int student;
int a;
int b;
int c;
int d;
int e;
int f;
int g;
int h;
int i;
int j;
int k;
int l;
int m;
int n;
int o;
int p;
int q;
int r;

//several lines skipped here...//


while (fgets(buf, sizeof buf, stdin) != NULL) {
  int count = sscanf(buf, "%3s%2s%2i%2i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i", 
    pp, school, &class, &student, &a, &b, &c, &d, &e, &f, &g, &h, &i, &j, &k, &l, &m, &n, &o, &p, &q, &r);
  if (count != 22) {
    printf("Error %d (TBD relevant text)\n", count);
    break;
  }
    runtotal = (a+b+c+d+e+f+g+h+i+j+k+l+m+n+o+p+q+r);
    average = (float)runtotal / 18;
    grouptotal = grouptotal + runtotal;
    xscore = (float)runtotal - trueavg;
    xscoresqr = (float)xscore * xscore;
    runxscore = (float)runxscore + xscoresqr;

//more happens inside this while loop here... I edited it out for this post//



counter++;
    printf ("%i.\n", counter);
    printf ("%s%s-%i-%i -- %1i %1i %1i %1i %1i %1i %1i %1i %1i %1i %1i %1i %1i %1i %1i %1i %1i %1i\n", pp, school, class, student, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r);
    printf ("Total score: %i\n", runtotal);
    printf ("Average: %f\n", average);
    printf ("Running Total: %i\n\n", grouptotal);
}
//the while loop ends here//

So I think the problem lies in the reading and storing of the data in the buffer.... maybe...

Just to give you a good example of what the input and output are doing, here's a bit of both.. INPUT ...

preHI5214 1 0 0 1 0 2 2 2 1 0 0 0 2 2 2 1 2 2
preKO5211 0 0 0 1 1 0 1 1 1 0 0 0 1 1 0 0 0 0
preIS5109 0 0 0 1 0 1 1 0 0 0 0 0 0 1 1 0 1 0
preSA6211 0 1 0 1 1 0 1 0 0 0 0 0 1 1 1 1 2 1
preSA6209 0 0 0 1 0 0 1 1 2 0 0 0 1 1 0 0 0 0
preHI6205 0 0 0 1 1 0 1 1 1 0 0 0 0 1 1 0 2 1
preKO5212 0 0 0 1 1 0 1 0 0 0 0 0 0 1 1 0 0 0
preSA6210 0 0 0 1 1 0 1 0 0 0 0 0 0 1 1 0 0 0
preHI6208 0 1 0 1 1 0 1 0 0 0 0 0 0 0 1 0 0 1
preKO5209 0 0 0 1 1 0 1 1 0 0 0 0 1 1 0 0 0 0
preHI5211 0 0 0 1 1 0 1 2 1 0 0 1 1 1 1 1 0 0
preKO6217 0 0 0 1 0 0 1 0 0 0 0 0 1 1 1 0 0 0
preIS5108 0 0 0 1 1 0 1 1 0 0 0 0 1 1 1 0 1 1

and the output... ...

88.
preHI-52-14 -- 1 0 0 1 0 2 2 2 1 0 0 0 2 2 2 1 2 2
Total score: 20
Average: 1.111111
Running Total: 932

89.
preKO-52-11 -- 0 0 0 1 1 0 1 1 1 0 0 0 1 1 0 0 0 0
Total score: 7
Average: 0.388889
Running Total: 939

90.
preIS-51-0 -- 9 0 0 0 1 0 1 1 0 0 0 0 0 0 1 1 0 1
Total score: 15
Average: 0.833333
Running Total: 954

91.
preSA-62-11 -- 0 1 0 1 1 0 1 0 0 0 0 0 1 1 1 1 2 1
Total score: 11
Average: 0.611111
Running Total: 965

92.
preSA-62-0 -- 9 0 0 0 1 0 0 1 1 2 0 0 0 1 1 0 0 0
Total score: 16
Average: 0.888889
Running Total: 981

93.
preHI-62-5 -- 0 0 0 1 1 0 1 1 1 0 0 0 0 1 1 0 2 1
Total score: 10
Average: 0.555556
Running Total: 991

94.
preKO-52-12 -- 0 0 0 1 1 0 1 0 0 0 0 0 0 1 1 0 0 0
Total score: 5
Average: 0.277778
Running Total: 996

95.
preSA-62-10 -- 0 0 0 1 1 0 1 0 0 0 0 0 0 1 1 0 0 0
Total score: 5
Average: 0.277778
Running Total: 1001

96.
preHI-62-0 -- 8 0 1 0 1 1 0 1 0 0 0 0 0 0 0 1 0 0
Total score: 13
Average: 0.722222
Running Total: 1014

97.
preKO-52-0 -- 9 0 0 0 1 1 0 1 1 0 0 0 0 1 1 0 0 0
Total score: 15
Average: 0.833333
Running Total: 1029

98.
preHI-52-11 -- 0 0 0 1 1 0 1 2 1 0 0 1 1 1 1 1 0 0
Total score: 11
Average: 0.611111
Running Total: 1040

99.
preKO-62-17 -- 0 0 0 1 0 0 1 0 0 0 0 0 1 1 1 0 0 0
Total score: 5
Average: 0.277778
Running Total: 1045

100.
preIS-51-0 -- 8 0 0 0 1 1 0 1 1 0 0 0 0 1 1 1 0 1
Total score: 16
Average: 0.888889
Running Total: 1061

If you'll look at the input and output data for the following five entries, you'll see what I mean quite clearly... preIS5109, preSA6209, preHI6208, preKO5209 and preIS5108

So how can I correct this?

like image 791
Jason Sturgeon Avatar asked Feb 23 '14 08:02

Jason Sturgeon


1 Answers

Use %2d instead of %2i.

When matching with the %i format specifier, any number that starts with 0 is interpreted as an octal. This doesn't matter for numbers containing only digits from 0 to 7, but numbers containing an 8 or 9 are not valid octal, causing the %2i input matching to fail.

like image 193
Buddy Gorven Avatar answered Oct 03 '22 19:10

Buddy Gorven