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

#define MAX_SIZE 100  // Maximum size of the arrays

int main() {
    FILE *file;
    int array1[MAX_SIZE], array2[MAX_SIZE];
    int i = 0, j = 0;
    
    // Open the file for reading
    file = fopen("numbers.txt", "r");
    if (file == NULL) {
        printf("Error opening file\n");
        return 1;
    }

    // Read the first line of numbers into array1
    while (fscanf(file, "%d", &array1[i]) == 1) {
        i++;
        if (fgetc(file) == '\n') break;  // Stop reading when a newline is encountered
    }

    // Read the second line of numbers into array2
    while (fscanf(file, "%d", &array2[j]) == 1) {
        j++;
        if (fgetc(file) == '\n') break;  // Stop reading when a newline is encountered
    }

    // Print the arrays to verify
    printf("Array 1: ");
    for (int k = 0; k < i; k++) {
        printf("%d ", array1[k]);
    }
    printf("\n");

    printf("Array 2: ");
    for (int k = 0; k < j; k++) {
        printf("%d ", array2[k]);
    }
    printf("\n");

    // Close the file
    fclose(file);

    return 0;
}

The above program is not reading second line of numbers from the file. Can you please tell me what is wrong with this program?

Following is the content from the file:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
3
  • 3
    Can you ensure that there is no whitespace after the last number of each line? Otherwise your check for \n might find that whitespace instead and not detect the end of the line properly. Commented Mar 3 at 12:04
  • 4
    The scanf functions aren't very line-oriented, and are useful for strictly formatted input. You know the max size of each line, so you can use fgets and then process the line with sscanf or with strtok. Commented Mar 3 at 12:25
  • Questions seeking debugging help must generally provide a minimal reproducible example of the problem, which includes the exact input required to reproduce the problem. Your posted input does not reproduce the problem, probably because your actual input has an additional space or something like that at the end of the line, which your posted input does not have. Please post the actual input, otherwise your question will probably be closed. Commented Mar 3 at 15:37

3 Answers 3

1

The scanset "%*[ \f\r\t\v]" will scan and discard whitespace that is not a newline.
"%1[\n]" will scan one character that must be a newline.
This may resolve the problem.

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

#define MAX_SIZE 100  // Maximum size of the arrays

void showarray ( int *arr, size_t used) {
    size_t each = 0;

    while ( each < used) {
        printf ( "%d ", arr[each]);
        ++each;
    }
    printf ( "\n");
}

int scanintarray ( int *arr, size_t size, size_t *used, FILE *pf) {
    char nl[2] = "";
    int result = 0;
    size_t each = 0;

    while ( each < size && 1 == ( result = fscanf ( pf, "%d", &arr[each]))) {
        ++each;
        fscanf ( pf, "%*[ \f\r\t\v]"); // scan and discard whitespace not a newline
        if ( 1 == fscanf ( pf, "%1[\n]", nl)) { // scan one character that must be a newline
            *used = each;
            return 1;
        }
    }
    *used = each;
    return result;
}

int main ( void) {
    char *filename = "numbers.txt";
    int array1[MAX_SIZE] = { 0};
    int array2[MAX_SIZE] = { 0};
    size_t used1 = 0;
    size_t used2 = 0;
    FILE *file = NULL;

    // Open the file for reading
    if ( NULL == ( file = fopen ( filename, "r"))) {
        perror ( filename);
        return 1;
    }

    // Read the first line of numbers into array1
    if ( 1 != scanintarray ( array1, MAX_SIZE, &used1, file)) {
        fprintf ( stderr, "problem scanning array\n");
        fclose(file);
        return 1;
    }

    // Read the second line of numbers into array2
    if ( 1 != scanintarray ( array2, MAX_SIZE, &used2, file)) {
        fprintf ( stderr, "problem scanning array\n");
        fclose(file);
        return 1;
    }

    // Print the arrays to verify
    printf("Array 1: ");
    showarray ( array1, used1);
    printf("Array 2: ");
    showarray ( array2, used2);

    // Close the file
    fclose(file);

    return 0;
}
Sign up to request clarification or add additional context in comments.

1 Comment

Why test each + 1 < size? reading a full array should be OK
0

Modify how you read into array1 by changing lines 18-21:

while (i < MAX_SIZE && fscanf(file, "%d", &array1[i]) == 1) {
    i++;
    char next = fgetc(file);
    if (next == '\n' || next == EOF) break;
    ungetc(next, file);newline
}

And modify how you read into array2 by changing lines 24-27:

while (j < MAX_SIZE && fscanf(file, "%d", &array2[j]) == 1) {
    j++;
    char next = fgetc(file);
    if (next == '\n' || next == EOF) break;
    ungetc(next, file);
}

3 Comments

Your else branch is useless as it reads another character just to put it back again. You need to store result of the first fgetc and only call that function once. Also that loop afterwards won't do what you think. As the \n was already consumed by the fgetc in the if condition, this loop will skip the whole second line.
WIth your update, you have incorrect type for next. fgetc returns an int. With char you may not be able to correctly identify EOF depending on signedness of char. You must use int next;
The way I see it is that if you are having to kludge the newlines, then fscanf isn't the best way to go about it.
0

you can do this with this sequence (it will ensure that you have 30 numbers on each line, which seems to be a requirement):

    char line[256];
    int array1[MAX_SIZE], array2[MAX_SIZE]; /* I'm assuming MAX_SIZE is 30 */
    if (!fgets(line, sizeof line, stdin)) { /* EOF */
        fprintf(stderr, "Unable to read first line\n");
        /* hmmm... something to do here */
    }
    int n1 = sscanf(line,
         "%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d"
         "%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d", /* MAX_SIZE format specifiers */
         &array1[0],  &array1[1],  &array1[2],  &array1[3], /* MAX_SIZE elements */
         &array1[4],  &array1[5],  &array1[6],  &array1[7],
         &array1[8],  &array1[9],  &array1[10], &array1[11],
         &array1[12], &array1[13], &array1[14], &array1[15],
         &array1[16], &array1[17], &array1[18], &array1[19],
         &array1[20], &array1[21], &array1[22], &array1[23],
         &array1[24], &array1[25], &array1[26], &array1[27],
         &array1[28], &array1[29]);
    if (!fgets(line, sizeof line, stdin)) { /* EOF */
        fprintf(stderr, "Unable to read second line\n");
        /* hmmm... something to do here */
    }
    int n2 = sscanf(line,
         "%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d"
         "%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d",
         &array2[0],  &array2[1],  &array2[2],  &array2[3],
         &array2[4],  &array2[5],  &array2[6],  &array2[7],
         &array2[8],  &array2[9],  &array2[10], &array2[11],
         &array2[12], &array2[13], &array2[14], &array2[15],
         &array2[16], &array2[17], &array2[18], &array2[19],
         &array2[20], &array2[21], &array2[22], &array2[23],
         &array2[24], &array2[25], &array2[26], &array2[27],
         &array2[28], &array2[29]);

so n1 will hold the number of elements read in the array in first line, while n2 will hold the number read in line 2. IMHO this is the easiest, and most portable way of doing what you want.

scanf has been evolved to incorporate almost regexp functionality (but not complete to allow you to do depending what things) on its format string, but not all stdio libraries do support it. The approach above will be supported by all, although.

3 Comments

If either line is longer than 510 bytes, the values read my be invalid.
@chqrlie, the sample code was for illustrative purposes... anyway to fill 512 bytes with a maximum of 30 integers would require an average of 16 characters per integer. Probably a flex solution and a proper scanner should be better, for a general parser.... which context should I select? One easy to understand, or one complex that only an expert can decipher?
You could also notice that using the stack for a buffer allow you to incurr in stack overflow, which is not desirable, but doing the opposite (making the buffers static) would make the code non-reentrant, which is also undesirable. I don't see your solution anywhere... can you illustrate us?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.