Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Global variables such as <code>pay</code> — clearly defined as <code>FILE *pay;</code> — are a bad idea, and completely unnecessary in the example code. Always test the return value from <code>fscanf()</code> and its relatives to ensure that you got all the data you expected.</p> <p>However, your trouble is that <code>%s</code> stops at the first space, so you have immense problems reading the address field. Your inputs are unconstrained too. You also try to get multiple words of the street address using <code>e-&gt;street</code> multiple times; that won't work since the third word will overwrite the first.</p> <p>You need something like:</p> <pre><code>int inputLine(FILE *fp, Employee* e) { if (fscanf(fp, "%7s %c %9s %16c %11c %2s %d %d %c %d %f", e-&gt;first, &amp;e-&gt;initial, e-&gt;last, e-&gt;street, e-&gt;city, e-&gt;state, &amp;e-&gt;zip, &amp;e-&gt;age, &amp;e-&gt;sex, &amp;e-&gt;tenure, &amp;e-&gt;salary) != 11) return -1; e-&gt;street[16] = '\0'; e-&gt;city[11] = '\0'; return 0; } </code></pre> <p>This uses <code>%c</code> to read single characters; it uses <code>%16c</code> to read the multi-word street address and <code>%11c</code> to read the (possibly multi-word) city. It uses <code>%7s</code>, <code>%9s</code>, and <code>%2s</code> to prevent overflows of other strings. The assignments after the <code>fscanf()</code> call ensure that the counted <code>%c</code> strings are null terminated; by itself, <code>%16c</code> does not add a null terminator.</p> <p>The <code>inputLine()</code> function now returns an error indication (<code>-1</code> chosen) when there's a problem, and <code>0</code> to indicate success. This is a common pattern with the Unix system calls, but different from the behaviour of the underlying <code>scanf()</code>-family of functions, as noted in a <a href="https://stackoverflow.com/questions/18036686/c-read-space-separated-values-from-file/18037018#comment26386874_18037018">comment</a> by <a href="https://stackoverflow.com/users/2410359/chux">chux</a>.</p> <h3>Working code 1</h3> <p>This code reads standard input, using <code>fscanf()</code> as in the question. It ensures that there's no overflow of the <code>emp</code> array, too.</p> <pre><code>#include &lt;stdio.h&gt; typedef struct { char first[8], initial, last[10], street[17], city[12], state[3]; int age, tenure, zip; float salary; char sex; } Employee; void dump_employee(FILE *fp, const char *tag, const Employee *e); int inputLine(FILE *fp, Employee *e); enum { MAXEMP = 10 }; int main(void) { char line[4096]; Employee emp[MAXEMP]; if (fgets(line, sizeof(line), stdin) == 0 || fgets(line, sizeof(line), stdin) == 0) return 1; for (int i = 0; i &lt; MAXEMP &amp;&amp; inputLine(stdin, &amp;emp[i]) != 0; i++) dump_employee(stdout, "Employee", &amp;emp[i]); return 0; } int inputLine(FILE *fp, Employee *e) { if (fscanf(fp, "%7s %c %9s %16c %11c %2s %d %d %c %d %f", e-&gt;first, &amp;e-&gt;initial, e-&gt;last, e-&gt;street, e-&gt;city, e-&gt;state, &amp;e-&gt;zip, &amp;e-&gt;age, &amp;e-&gt;sex, &amp;e-&gt;tenure, &amp;e-&gt;salary) != 11) return -1; e-&gt;street[16] = '\0'; e-&gt;city[11] = '\0'; return 0; } void dump_employee(FILE *fp, const char *tag, const Employee *e) { fprintf(fp, "%s: %-7s %c %-9s %-16s %-11s %-2s %.5d %3d %c %d %6.2f\n", tag, e-&gt;first, e-&gt;initial, e-&gt;last, e-&gt;street, e-&gt;city, e-&gt;state, e-&gt;zip, e-&gt;age, e-&gt;sex, e-&gt;tenure, e-&gt;salary); } </code></pre> <h3>Sample output</h3> <pre><code>Employee: ADA A AGUSTA 33 BABBAGE ROAD LOVELACE GB 19569 28 F 2 350.50 Employee: ISSAC A ASIMOV 99 FICTION WAY AMHERST MA 63948 58 M 6 423.88 Employee: HUMPHRY R BOGART 71 SAM STREET HOLLYWOOD CA 48482 56 M 5 366.00 </code></pre> <h3>Working code 2</h3> <p>This code uses <code>fgets()</code> to read lines and <code>sscanf()</code> to convert the data. It would be much easier to report errors sanely with this version of the code.</p> <pre><code>#include &lt;stdio.h&gt; typedef struct { char first[8], initial, last[10], street[17], city[12], state[3]; int age, tenure, zip; float salary; char sex; } Employee; void dump_employee(FILE *fp, const char *tag, const Employee *e); int scan_employee(Employee *e, const char *line); enum { MAXEMP = 10 }; int main(void) { char line[4096]; Employee emp[MAXEMP]; if (fgets(line, sizeof(line), stdin) == 0 || fgets(line, sizeof(line), stdin) == 0) return 1; for (int i = 0; i &lt; MAXEMP &amp;&amp; fgets(line, sizeof(line), stdin) != 0; i++) { if (scan_employee(&amp;emp[i], line) == 0) dump_employee(stdout, "Employee", &amp;emp[i]); } return 0; } int scan_employee(Employee *e, const char *line) { if (sscanf(line, "%7s %c %9s %16c %11c %2s %d %d %c %d %f", e-&gt;first, &amp;e-&gt;initial, e-&gt;last, e-&gt;street, e-&gt;city, e-&gt;state, &amp;e-&gt;zip, &amp;e-&gt;age, &amp;e-&gt;sex, &amp;e-&gt;tenure, &amp;e-&gt;salary) != 11) return -1; e-&gt;street[16] = '\0'; e-&gt;city[11] = '\0'; return 0; } void dump_employee(FILE *fp, const char *tag, const Employee *e) { fprintf(fp, "%s: %-7s %c %-9s %-16s %-11s %-2s %.5d %3d %c %d %6.2f\n", tag, e-&gt;first, e-&gt;initial, e-&gt;last, e-&gt;street, e-&gt;city, e-&gt;state, e-&gt;zip, e-&gt;age, e-&gt;sex, e-&gt;tenure, e-&gt;salary); } </code></pre> <p>The output from this is identical to the output from the other for the sample data in the question.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload