1

I'm fairly new to C. This is the first program I've written involving reading and writing to files. So far, I was able to read the file, perform the operations I need but I am having trouble with 2 things.

  1. Whatever the file is, it omits the last line when reading. For example if the file has:

    3
    5
    6
    

    It will only read the 3 and 5. But if I leave an empty/blank line at the bottom it'll read all three. Any ideas as why that is?

 

  1. I now need to take what I did, essentially converting volts to milliVolts, microVolts, etc. and write it back to the file. What I have been doing up until now is reading it from the file and working through the console. So essentially, I want write the last two printf statements to the file. I had some attempts at this but it wasn't working and I couldn't seem to find decent support online for this. When I tried, it would completely erase what was in the file before.

 

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char** argv) {
    FILE * file = fopen ("bacon.txt", "r");
    float voltage = 0, voltageArray[100],  voltageToMilli = 0,voltageToMicro = 0, voltageToKilo = 0, voltageToMega = 0;
    int i = 1, j = 0;

    fscanf (file, "%f", &voltage);    
    while (!feof (file)) {
        printf("Line # %d\n", i);
        printf ("The voltage is: %f\n", voltage);
        voltageArray[j] = voltage;
        fscanf (file, "%f", &voltage); 

        printf("The voltage in Element %d is: %f Volts",j,voltageArray[j]);
        voltageToMilli = voltageArray[j] * 1000;
        voltageToMicro = voltageArray[j] * 1000000;
        voltageToKilo = voltageArray[j] * 0.001;
        voltageToMega = voltageArray[j] *0.000001;
        printf("\nThe voltage is %f Volts, which is: %f milliVolts, %f microVolts, %f kiloVolts, %f megaVolts",voltageArray[j],voltageToMilli,voltageToMicro,voltageToKilo,voltageToMega);


        printf("\n\n");
        i++;
        j++;



      }
    fclose (file);     

    return (0);
}

Please try to keep explanations clear and simple as I am a beginner in C. Thank you!

  • 2
    Please always check if your `scanf` calls are succesfull. – fuz Nov 22 '15 at 22:27
  • 1
    For the first issue, your loop logic is wrong. For the last input, the `fscanf` inside the loop will read the value correctly. But you don't store the result before checking `feof`. That check will then cause the loop to exit because there is no more data to read yet you have not stored the last read data. – kaylum Nov 22 '15 at 22:30
  • @FUZxxl Am I using it incorrectly somewhere? I've only used fscanf here. – Ibrahim M. Eshera Nov 22 '15 at 22:30
  • 1
    @IbrahimM.Eshera You should do error checking. `fscanf` (and `scanf`, too) can fail and probably do fail in your code. – fuz Nov 22 '15 at 22:31
  • @kaylum I'm sorry, I don't follow. I thought I was reading it from the file then immediately storing it in variable, voltage, then passing that to an element in the array. At what point will it find the end of the file before doing that? – Ibrahim M. Eshera Nov 22 '15 at 22:36
  • 1
    Trace your code. `voltageArray[j] = voltage;` that line is **above** the `fscanf` line. That is, you are storing the **previous** read value not the next value just about to be read. That value will only get stored on the next iteration of the loop and only if the `feof` check passes (which it doesn't after reading the last value). – kaylum Nov 22 '15 at 22:38
  • 1
    Check this page: http://stackoverflow.com/questions/5431941/why-is-while-feof-file-always-wrong – chqrlie Nov 22 '15 at 22:52
  • @kaylum I see what you are trying to say, but even if I switch those two lines so that I am first reading in then storing, I still have the same problem. I feel like I am not understanding something here. – Ibrahim M. Eshera Nov 22 '15 at 23:09
  • You can't just switch those two lines. That will cause other problems because you already have an `fscanf` outside the loop. I'll try to write an answer for that because it's too hard to put that code into these comments. – kaylum Nov 22 '15 at 23:15

2 Answers2

2

For the first issue, the problem is that the loop logic is incorrect. On each iteration is stores the previous read data, reads the next data and then goes back to the top of the loop. The problem with this is that the next data is not stored until the next iteration. But after reading the last data item (and before storing it into the array) the feof check is always false. Refer to this question for why checking feof as a loop condition is almost always wrong.

Here is an example of how you could restructure your code to read all the items as intended:

int rval;

while ((rval = fscanf(file, "%f", &voltage)) != EOF) {
    if (rval != 1) {
        printf("Unexpected input\n");
        exit(-1);
    }

    voltageArray[j] = voltage;

    /* Do the rest of your processing here. */    
}
Community
  • 1
  • 1
kaylum
  • 13,833
  • 2
  • 22
  • 31
  • For the second issue, please show your attempted code that you say is not working. Actually, it would be better if you posted that as a sepetate new question. – kaylum Nov 22 '15 at 23:51
  • Ok, will do that. Regarding this code, I got it to work but I want to make sure I'm understanding this correctly. rval is an int declared outside the loop and is the read value from the file and so as long as that is not the End of File (EOF) it'll keep reading. Is that reasoning correct? – Ibrahim M. Eshera Nov 23 '15 at 00:10
  • It's not the read value from the file. That is what is stored in `voltage`. It is the return value of `fscanf` which you can read about in the [man page](http://linux.die.net/man/3/fscanf). Specifically, it returns the number of matching items : `1` in your case if successful or `0` if no match (no match if the input contains a non-float). And it returns `EOF` when there is no more input available. – kaylum Nov 23 '15 at 00:20
  • I see. Thank you for your help, I really appreciate it. – Ibrahim M. Eshera Nov 23 '15 at 00:38
1

problem is in the file there is nothing after the last number, so, after reading the last number from the file, feof(file) is true. and the while exits.

simplest fix is change it to this

while(fscanf (file, "%f", &voltage) == 1) {

and remove the other fscanf calls.

this works because that fscanf() call will return 1 when it is able to read a number and either 0 or EOF (which is a negative number) otherwise.

Jasen
  • 11,837
  • 2
  • 30
  • 48
  • `fscanf` will return `EOF` when there is no more input. Not `0`. So the above code will produce an infinete loop. – kaylum Nov 22 '15 at 23:54