Question:
Using scanf to input a text file of integers into an array, C?
2015-09-02 11:45:26 UTC
I have a programming assignment where i'm given a .txt file with a sudoku solution and i have to check to see if it is correct. My problem is that I MUST use scanf to input this file. I also don't know how large the array must be until I scanf since the input file will have multiple solutions and the first line of the file will have an integer telling how many solutions there would be.
Four answers:
cja
2015-09-04 11:51:48 UTC
Diabolical, your professor is, because this is a lot easier if the input does not come from stdin. Not impossible, though, as shown in my example below. Don't assume the input file is correctly formatted. Read what you're given, build the 2D array as you go, and make sure it's valid. All the rows must be the same length, which you check as each row comes in. When you encounter EOF, if each entered row is valid, the final check is to make sure the array is square: rows = cols.



/*

. * Populate an N x N matrix of integer from stdin. If input is not a

. * valid square matrix, display an error message and quit.

. *

. */

#include

#include

#include



#define MAX_LINE_LEN 1024

#define WHITESPACE " ,\t"

#define MAX(a,b) ((a) > (b) ? (a) : (b))



typedef struct {

. . unsigned size; /* size of array */

. . int *a; /* pointer to start of array */

} IntArray, *IntArray_p;



typedef IntArray_p *Int2dArray;

typedef enum { false = 0, true } bool;



IntArray_p newIntArray(unsigned size);

void print(Int2dArray, size_t);

void deleteIntArray2d(Int2dArray, size_t);

void deleteIntArray(IntArray_p);



char line[MAX_LINE_LEN];

char temp[MAX_LINE_LEN];



int main(int argc, char *argv[]) {

. . Int2dArray A;

. . size_t rows, cols, i = 0, j, prevRowLen;

. . int n;

. . char *s;

. . bool inputValid = true;



. . /* Start with 1 row, and grow if necessary */

. . A = (Int2dArray)malloc((rows = 1) * sizeof(IntArray_p));



. . /*

. . . * Read integers from each line, and fill in the rows of the Int2dArray.

. . . */

. . while ((inputValid == true) && (fgets(line, MAX_LINE_LEN, stdin) != NULL)) {

. . . . /*

. . . . . * See how many numbers we can find in this line.

. . . . . */

. . . . s = strcpy(temp, line);

. . . . cols = 0;

. . . . while (s != (char *)NULL) {

. . . . . . if (sscanf(s, "%d", &n) == 1) {

. . . . . . . . ++cols;

. . . . . . }

. . . . . . if ((s = strpbrk(s,WHITESPACE)) != (char *)NULL) {

. . . . . . . . s = &s[strspn(s,WHITESPACE)];

. . . . . . }

. . . . }



. . . . /*

. . . . . * Allocate an IntArray for this row, sized to the number of integers

. . . . . * found in this line.

. . . . . */

. . . . A[i] = newIntArray(cols);



. . . . /*

. . . . . * Scan the line again, and store the numbers.

. . . . . */

. . . . j = 0; s = line;

. . . . while (s != (char *)NULL) {

. . . . . . if (sscanf(s, "%d", &n) == 1) {

. . . . . . . . A[i]->a[j++] = n;

. . . . . . }

. . . . . . if ((s = strpbrk(s,WHITESPACE)) != (char *)NULL) {

. . . . . . . . s = &s[strspn(s,WHITESPACE)];

. . . . . . }

. . . . }

. . . . if ((rows > 1) && (cols != prevRowLen)) {

. . . . . . fprintf(stderr, "invalid row length\n");

. . . . . . inputValid = false;

. . . . }

. . . . ++i;

. . . . A = realloc(A, (rows += 1) * sizeof(IntArray_p));

. . . . A[i] = NULL;

. . . . prevRowLen = cols;

. . }



. . if ((inputValid == true) && ((rows - 1) == cols)) {

. . . . /* Display */

. . . . print(A, rows - 1);

. . } else {

. . . . fprintf(stderr, "rows != cols\n");

. . }



. . /* Clean up */

. . deleteIntArray2d(A, rows);



. . return 0;

}



IntArray_p newIntArray(unsigned size) {

. . IntArray_p a = calloc(1,sizeof(IntArray));

. . a->size = size;

. . a->a = calloc(MAX(1, size), sizeof(int));

. . return a;

}



void print(Int2dArray a, size_t len) {

. . size_t i,j;



. . for (i = 0; i < len; i++) {

. . . . if (a[i]->size > 0) {

. . . . . . for (j = 0; j < a[i]->size; j++) {

. . . . . . . . printf("%4d ",a[i]->a[j]);

. . . . . . }

. . . . . . puts("");

. . . . }

. . }

}



void deleteIntArray2d(Int2dArray a, size_t len) {

. . size_t i;



. . for (i = 0; i < len; i++) {

. . . . deleteIntArray(a[i]);

. . }

. . free(a);

}



void deleteIntArray(IntArray_p this) {

. . if (this != NULL) {

. . . . free(this->a);

. . . . free(this);

. . }

}



#if 0



Sample run:



$ ./matNxN < mat3.txt

1 2 3

4 5 6

7 8 9





Where:



$ cat mat3.txt

1 2 3

4 5 6

7 8 9



#endif
?
2015-09-02 15:21:13 UTC
A Soduku has 9 x 9 fields, so an integer array of [81] or [9][9] will do



This is the text file:

1 2 3 4 5 6 7 8 9

2 3 4 5 6 7 8 9 1

3 4 5 6 7 8 9 1 2

4 5 6 7 8 9 1 2 3

5 6 7 8 9 1 2 3 4

6 7 8 9 1 2 3 4 5

7 8 9 1 2 3 4 5 6

8 9 1 2 3 4 5 6 7

9 1 2 3 4 5 6 7 8



This is the code:

#include



void read_file(int ar[9][9])

{

for (int i = 0; i < 9; i++) {

fscanf(stdin, "%d %d %d %d %d %d %d %d %d ", &ar[i][0], &ar[i][1], &ar[i][2], &ar[i][3], &ar[i][4], &ar[i][5], &ar[i][6], &ar[i][7], &ar[i][8], &ar[i][9]);

}

}



void display(int ar[9][9])

{

for(int i = 0; i < 9; i++) {

puts("");

for (int j = 0; j < 9; j++) {

fprintf(stdout, "%d ", ar[i][j]);

}

}

}

int main()

{

int ar[9][9];

read_file(ar);

display(ar);

return 0;

}



This is how you can use the file:

a < ar.txt

This is in case you compile the code to produce the executable a.exe on windows, or a on linux.

Have fun with your logic.
jplatt39
2015-09-02 12:13:57 UTC
Look, you've told us enough so yes you should be able to handle this yourself. The format is scanf("%d", &variable); So the first number should be used to allocate space for the array with malloc (array=malloc(number*sizeof(int));).



Then use a counter to fill up the array. Scanf() throws out whitespace characters like space carriage return and so on. So just go ahead do it and test it.
?
2015-09-02 15:58:36 UTC
actually you have to use fscanf().


This content was originally posted on Y! Answers, a Q&A website that shut down in 2021.
Loading...