Read numbers from text file to 2D array - c

Despite the numerous examples on here I can't seem to get this working...
I have a text file, containing many rows, each row has three (int) values separated by a single space. For example:
1 0 0
0 0 0
1 0 1
0 0 2
1 0 2
I am trying to read this into a 2d array.
My code so far:
int main(void)
{
char c;
int i = 0;
int maxLines = 18;
char lines[maxLines][BUFSIZ];
FILE *fp = fopen("inputs/control.txt", "r");
if (fp == 0)
{
fprintf(stderr, "failed to open inputs/control.txt\n");
exit(1);
}
char buffer[maxLines];
while (i < maxLines && fgets(buffer[i], sizeof(buffer[0]), fp))
{
sscanf (buffer, "%d %d %d", &lines[i][0], &lines[i][1], &lines[i][2]);
i++;
}
fclose(fp);
return 0;
}
Can someone provide advice how I can develop this further so that each value in the row is stored in a separate array index? In my example above, we would store something like:
lines[0][0] = 1
lines[0][1] = 0
lines[0][2] = 0
and so on.....
Currently it stores the entire row in a single array pos.
As you can probably tell I'm a C noob, any help would be fantastic!

You were well on your way, you just had problems thinking you were reading a character array instead of an array of signed characters (which could be changed to int, etc) Here is your example:
#include <stdio.h>
#define MAXB 32
#define MAXL 18
#define MAXD 3
int main(void)
{
int i = 0;
int numlines = 0;
char buf[MAXB] = {0};
char lines[MAXL][MAXD];
FILE *fp = fopen("inputs/control.txt", "r");
if (fp == 0)
{
fprintf(stderr, "failed to open inputs/control.txt\n");
return 1;
}
while (i < MAXL && fgets (buf, MAXB - 1, fp))
{
if (sscanf (buf, "%hhd %hhd %hhd", &lines[i][0], &lines[i][1], &lines[i][2]) == 3)
i++;
}
fclose(fp);
numlines = i;
int j = 0;
for (i = 0; i < numlines; i++)
for (j = 0; j < MAXD; j++)
printf (" line[%2d][%2d] : %hhd\n", i, j, lines[i][j]);
printf ("\n");
return 0;
}
Output
$ ./bin/read_array_a3
line[ 0][ 0] : 1
line[ 0][ 1] : 0
line[ 0][ 2] : 0
line[ 1][ 0] : 0
line[ 1][ 1] : 0
line[ 1][ 2] : 0
line[ 2][ 0] : 1
line[ 2][ 1] : 0
line[ 2][ 2] : 1
line[ 3][ 0] : 0
line[ 3][ 1] : 0
line[ 3][ 2] : 2
line[ 4][ 0] : 1
line[ 4][ 1] : 0
line[ 4][ 2] : 2
Note: char lines[MAXL][MAXD]; is fine, you just must understand that each element is restricted to an 8-bit signed value, meaning values between -128 < val < 127. You can make them int if you need to store larger values.

Use scanf. Example:
#include <stdio.h>
int main(int argc, char *argv[]) {
int i, j;
int lines[18][3];
i = 0;
while (
i != sizeof(lines) / sizeof(lines[0])
&& 3 == scanf("%i %i %i", lines[i] + 0, lines[i] + 1, lines[i] + 2)
) {
i++;
}
for (j = 0; j !=i; j++) {
printf("%i %i %i\n", lines[j][0], lines[j][1], lines[j][2]);
}
return 0;
}
Note that the input is read from stdin (use fscanf for more flexibility), meaning that the snippet above must be called as ./a.out < data.txt.

Using fgets you are reading the whole line from the file. You will need to then parse this line to extract individual numbers and store them into the array. In the while loop you can read the line in a buffer and then use something like strtok/sscanf to parse each number.

Related

C Programming Occurrences of an Integers in an Text File

Problem: Write a program that reads all integers that are in the range
of 0 to 100, inclusive from an input file named: a.txt and counts how
many occurrences of each are in the file. After all input has been
processed, display all the values with the number of occurrences that
were in are in the input file.
Note: The program ignores any number less than 0 or greater than 100.
Note: Do not display zero if a number is not in the file. Hints: An
array of size 101 is good enough. A number in the file plays the role
of an index.
For example: Suppose the content of the file: a.txt is as follows:
99 2 99
3
-12 80 12 33
3 99 100 1234 84
The display output is:
2 has occurred: 1 times,
3 has occurred: 2 times,
12 has occurred: 1 times,
33 has occurred: 1 times,
80 has occurred: 1 times,
84 has occurred: 1 times,
99 has occurred: 3 times,
100 has occurred: 1 times
Here is the code that I have right now:
#include <stdio.h>
#include <stdlib.h>
int main(){
FILE *inFile;
int count = 1, num[101];
inFile = fopen("a.txt", "r");
for(int i = 1; i <= 100; i++) {
fscanf(inFile, "%d", &num[i]);
}
for(int i = 1; i <= 100; i++){
if(num[i] == i) {
printf("%i has occurred: %d times\n", i, count);
count++;
}
}
fclose(inFile);
}
Output:
2 has occured: 1 times
Hello, I'm trying to do this assignment for my C Programming class due Sunday at midnight, but I'm having trouble trying to print all of the numbers from the array with their occurrences. In my code, I first declared int count to increase the number of occurrences if the number is found more than once in the text file and created an array size of 101. Then, I used a for loop to read the text file and store all the numbers from 1-100 into the array. The second for loop, followed by an if statement is to compare the numbers from the array. Even though this is a test program, we are supposed to be able to do this with all data values. Hope this is a good enough explanation, thank you.
You are close.
Instead of reading each value into num, You want to use your num array to keep the count of each number seen in the file.
int main() {
FILE* inFile;
int value = 0;
int result = 0;
int num[101] = { 0 }; // zero-init this array
inFile = fopen("a.txt", "r");
if (inFile == NULL) {
printf("unable to open file\n");
return -1;
}
result = fscanf(inFile, "%d", &value);
while (result == 1) {
printf("Just read: %d\n", value);
if ((value >= 0) && (value <= 100)) {
num[value] = num[value] + 1; // num[value]++
}
result = fscanf(inFile, "%d", &value);
}
for (int i = 0; i <= 100; i++) {
if (num[i] > 0) {
printf("%i has occurred: %d times\n", i, num[i]);
}
}
fclose(inFile);
}
In addition to the good answer by #selbie, from my answer to your earlier question How do I get the counter to work..., you can apply the same principals to filling a Frequency Array here. In this case you simply use n as an index instead of a counter.
For example with your index n and your array num declared (and initialized all zero), you would simply read all integers in the file and check if the value n was between 0 <= n <= 100 and if so , update the value at the index n in your num array by one, e.g. num[n]++;. You could do it like:
int n = 0; /* index */
int num[NELEM] = {0}; /* array */
...
while (fscanf(myFile, "%d", &n) == 1) /* read each int */
if (0 <= n && n <= 100) /* if 0 <= n <= 100 */
num[n]++; /* increment value at index */
Then for your output, you just handle your special check on num[0] to determine whether to output that index, and then loop from 1-NELEM outputting the frequency of occurrence of each value, e.g.
if (num[0]) /* check if 0 found, output if so */
printf ("num[%3d] occurred %3d times\n", 0, num[0]);
for (int i = 1; i < NELEM; i++) /* output counts for 1-100 */
printf ("num[%3d] occurred %3d times\n", i, num[i]);
The complete example could be:
#include <stdio.h>
#define NELEM 101 /* if you need a constant, #define one (or more) */
int main(int argc, char **argv) {
int n = 0; /* index */
int num[NELEM] = {0}; /* array */
/* read filename from 1st argument (stdin by default) */
FILE *myFile = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!myFile) { /* validate myfile is open for reading */
perror ("fopen-myfile");
return 1;
}
while (fscanf(myFile, "%d", &n) == 1) /* read each int */
if (0 <= n && n <= 100) /* if 0 <= n <= 100 */
num[n]++; /* increment value at index */
if (myFile != stdin) /* close file if not stdin */
fclose (myFile);
if (num[0]) /* check if 0 found, output if so */
printf ("num[%3d] occurred %3d times\n", 0, num[0]);
for (int i = 1; i < NELEM; i++) /* output counts for 1-100 */
printf ("num[%3d] occurred %3d times\n", i, num[i]);
}
Example Use/Output
With 500 random integers in a file, you would get output similar to:
$ ./bin/fscanffreq dat/500_rand_0-100.txt
num[ 0] occurred 3 times
num[ 1] occurred 8 times
num[ 2] occurred 7 times
num[ 3] occurred 2 times
num[ 4] occurred 1 times
num[ 5] occurred 4 times
num[ 6] occurred 3 times
num[ 7] occurred 5 times
num[ 8] occurred 6 times
num[ 9] occurred 4 times
num[ 10] occurred 6 times
...
num[ 95] occurred 6 times
num[ 96] occurred 4 times
num[ 97] occurred 6 times
num[ 98] occurred 2 times
num[ 99] occurred 5 times
num[100] occurred 6 times
(note: if num[0] was 0, it would not be displayed)
Look things over and let me know if you have further questions.

How can I stop before reading the next line?

I have to read a file like this:
0 -> 1:50 2:30 3:10
1 ->
2 -> 0:10 3:20
3 -> 1:20 2:10 3:30
Here's my code:
graphs = fopen(argv[2],"r");
if(graphs==NULL){
printf("File hostgraphs not found\n");
exit(EXIT_FAILURE);
}
while((err=fscanf(graphs,"%d ->",&num))==1){
row=num;
while((err1=fscanf(graphs," %d:%d ",&column,&visits))==2){
hostgraphs[row*n+column]=visits;
}
if(err1!=2)
break;
if(err==0){
printf("Hostgraph out of bounds\n");
exit(EXIT_FAILURE);
}
}
for(i=0;i<n;i++){
for(j=0;j<n;j++){
printf("%d ", hostgraphs[i*n+j]);
}
printf("\n");
}
It gives me the following result:
0 50 30 10
0 0 0 0
0 0 0 0
0 0 0 0
The expected output must be:
0 50 30 10
0 0 0 0
10 0 0 20
0 20 10 30
Can anyone help me please?
You can do this by reading the file, one line at a time, using getline, and then applying the same logic, as you are doing, on each line separately.
In the following code, I first get a single line from the file in buffer using getline method. Then I process that line as a FILE pointer fbuffer using fmemopen method, which is used to read a string like a file:
graphs = fopen(argv[2],"r");
if(graphs==NULL)
{
printf("File hostgraphs not found\n");
exit(EXIT_FAILURE);
}
char *buffer = NULL;
size_t len = 0;
while(getline(&buffer, &len, graphs) != -1)
{
FILE * fbuffer = fmemopen(buffer, len, "r");
while((err=fscanf(fbuffer,"%d -> ",&num))==1)
{
row=num;
while((err1=fscanf(fbuffer," %d:%d ",&column,&visits))==2)
{
hostgraphs[row*n+column]=visits;
}
if(err1!=2)
{
break;
}
if(err==0)
{
printf("Hostgraph out of bounds\n");
exit(EXIT_FAILURE);
}
}
free(buffer);
buffer = NULL;
len = 0;
}
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
printf("%d ", hostgraphs[i*n+j]);
}
printf("\n");
}
Note: I have just added code to make your existing code work, without making any changes to your code.
The fix is simple: remove the trailing space in the fscanf format string in
fscanf(graphs," %d:%d ",&column,&visits)
It should be simplified as
fscanf(graphs,"%d:%d", &column, &visits)
fscanf ignores the newline then after read first row, it moves to next row and read 5 and results 1 in err1. That is the root-cause. You can add fseek to move back and start new sequence as bellow code-snip or simply change the algorithm to another effective one.
graphs = fopen(argv[2],"r");
if (!graphs) {
printf("File hostgraphs not found<%s>\n", argv[1]);
exit(EXIT_FAILURE);
}
while((err = fscanf(graphs, "%d ->", &num)) == 1) {
pos = ftell(graphs); // save position
while((err1 = fscanf(graphs, " %d:%d", &column, &visits)) == 2 ) {
hostgraphs[num * n + column] = visits;
pos = ftell(graphs); // save position
}
// seek back to previous one and start new sequence
fseek ( graphs , pos, SEEK_SET );
}
for(i = 0; i< n; i++){
for(j = 0; j < n; j++){
printf("%d ", hostgraphs[i * n + j]);
}
printf("\n");
}
You were close, but you needed a way of locating each '\n' without reading the next row value from the file. That is very difficult to do with fscanf where you have varying number of elements in each row in your input file.
Another approach is to use fgets to read the entire line, and then separate the initial "row -> " prefix from the data values. If you move the values into a separate values buffer (say vbuf), you can then repeatedly loop through the buffer by finding the space, advancing to the next digit and then using sscanf to split the column and visits.
(you actually don't even need to split the values in vbuf, you can simply use a pointer to advance past the "row -> " text working with the entire line.)
The following example puts those pieces together and parses the values into the correct positions in hostgraphs. Look it over and let me know if you have questions:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
enum { COLS = 4, MAXH = 16, MAXC = 64 };
int main (int argc, char **argv) {
char buf[MAXC] = "", vbuf[MAXC] = "";
char *p = NULL, *rfmt = "%d -> %[^\n]";
int row, column, visits, hostgraphs[MAXH] = {0};
size_t i, j, n = 0;
FILE *graphs = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!graphs) {
fprintf (stderr, "error: file open failed '%s'.\n", argv[1]);
return 1;
}
while (fgets (buf, MAXC, graphs))
{
*vbuf = 0; /* initialize vbuf, split %d:%d pars into vbuf */
if (sscanf (buf, rfmt, &row, vbuf) < 1)
break;
if (!*vbuf) { /* check vbuf contians values */
n++;
continue;
}
/* read 1st pair */
if (sscanf (vbuf, "%d:%d", &column, &visits) != 2) {
fprintf (stderr, "error: invalid line format\n");
exit (EXIT_FAILURE);
}
hostgraphs[row*COLS+column] = visits;
p = vbuf; /* assign p, parse remaining pairs */
while ((p = strchr (p, ' '))) /* find space */
{
while (*p < '0' || '9' < *p) /* find digit */
p++;
if (sscanf (p, "%d:%d", &column, &visits) == 2)
hostgraphs[row*COLS+column] = visits;
}
n++; /* advance row count */
}
for (i = 0; i < n; i++) { /* output values */
printf (" row[%2zu] : ", i);
for(j = 0; j < COLS; j++) {
printf (" %2d", hostgraphs[i * COLS + j]);
}
printf ("\n");
}
if (graphs != stdin)
fclose (graphs);
return 0;
}
Input File
$ cat ../dat/hostgraph.txt
0 -> 1:50 2:30 3:10
1 ->
2 -> 0:10 3:20
3 -> 1:20 2:10 3:30
Output
$ ./bin/hostgraph < ../dat/hostgraph.txt
row[ 0] : 0 50 30 10
row[ 1] : 0 0 0 0
row[ 2] : 10 0 0 20
row[ 3] : 0 20 10 30

How to accessing any variable name according to looping index in C [duplicate]

This question already has answers here:
How to access any variable name according to loop index
(5 answers)
Closed 7 years ago.
I have integer variables, I named them with n0 to n9, and i want to access them using loop, i try write this code to do that:
for(i = 0; i < 10; i++){
if(digit == 1){
n[i] = n[i] + 1;
}
}
I know it's not true, but I don't know how to do it right. please guys help me. thanks.
It is a bit difficult to understand what you are asking, but the answer is largely the same anyway. If you want to hold values for n[0] to n[9] in a data structure so you can loop though the values, then the immediate choice is an array (you can use a linked-list, tree, etc.., but I don't think you want those). The array provides the benefit of placing all values in a sequential block of memory. This allows you to iterate (loop) over the values in several ways. Example:
#include <stdio.h>
#define MAX 10
void prnarray (int *a, int n);
int main (void) {
int i = 0;
int n[] = {0,1,2,3,4,5,6,7,8,9};
printf ("array before loop:\n\n");
prnarray (n, MAX);
for (i = 0; i < MAX; i++)
if (n[i] == 1)
n[i] += 1;
printf ("\narray after loop:\n\n");
prnarray (n, MAX);
return 0;
}
void prnarray (int *a, int n)
{
int i;
for (i = 0; i < n; i++)
printf (" array[%2d] : %d\n", i, a[i]);
}
Output
$ ./bin/array09
array before loop:
array[ 0] : 0
array[ 1] : 1
array[ 2] : 2
array[ 3] : 3
array[ 4] : 4
array[ 5] : 5
array[ 6] : 6
array[ 7] : 7
array[ 8] : 8
array[ 9] : 9
array after loop:
array[ 0] : 0
array[ 1] : 2
array[ 2] : 2
array[ 3] : 3
array[ 4] : 4
array[ 5] : 5
array[ 6] : 6
array[ 7] : 7
array[ 8] : 8
array[ 9] : 9
On the other hand, if you have simply assigned your values to individual variables n0, n1, n2, ..., then your only option is to use some type of list or tree construct to provide an association between the individual variables (memory locations). Given your question, that seems well beyond the scope of what you are asking. Suffice it to say, if you have done this:
#include <stdio.h>
#define MAX 10
int main (void) {
int i = 0;
int n0 = 0;
int n1 = 1;
int n2 = 2;
int n3 = 3;
int n4 = 4;
int n5 = 5;
int n6 = 6;
int n7 = 7;
int n8 = 8;
int n9 = 9;
/* you are stuck - no way to loop,
no guarantee n0 - n9 are contiguous
in memory. (advanced datastruct needed)
*/
return 0;
}
start over...

Pass string to main and break up into array

I am passing arguments to main with this code:
#include <stdio.h>
int main(int argc, char ** argv)
{
int i = 1;
for(i = 1; i < argc; i++)
printf("%c", argv[i]);
return 0;
}
So I use ./test 218 abc 392990xFF[w2 dlx which works fine. However, the array is:
arr[1] = "218"
arr[2] = "abc"
arr[3] = "392990xFF[w2"
arr[4] = "dlx"
I want the array to be like this:
arr[0] = '2'
arr[1] = '1'
arr[2] = '8'
arr[3] = 'a'
etc...
How can I achieve this without putting a space after each digit or character?
The arguments passed by the run time environment to the program can be captured by main using int argc, char** argv only. If you have a need to combine them into one large array, you'll need to write the code for that, or print them one character at a time.
int main(int argc, char ** argv)
{
int i = 1;
int j;
int len;
for(i = 1; i < argc; i++)
{
len = strlen(argv[i]);
for ( j = 0; j < len; ++j )
{
printf("%c", argv[i][j]);
}
}
return 0;
}
First of all this is not what it will print -
arr[0] = "218"
arr[1] = "abc"
arr[2] = "392990xFF[w2"
arr[3] = "dlx"
argv[0] will store ./test. And "218" will be on index 1 thus others similarly .
And also printf("%c", argv[i]); .%c expects a char and you pass a string which is incorrect.
Solution could be -
#include <stdio.h>
int main(int argc, char ** argv)
{
int i = 1,j;
for(i = 1; i <argc; i++)
for(j=0;argv[i][j]!='\0';j++)
printf("%c\n", argv[i][j]);
return 0;
}
Rather than a for loop, you can also simply use pointers and while loops instead. There are generally many ways to solve problems in C:
#include <stdio.h>
int main (int argc, char **argv) {
int i = 1;
int j = 0;
while (i < argc) {
char *p = argv[i];
while (*p) {
printf (" arr[%2d] = \"%c\"\n", j++, *p);
p++;
}
i++;
}
return 0;
}
Output
$ ./bin/argvchars 218 abc 392990xFF[w2 dlx
arr[ 0] = "2"
arr[ 1] = "1"
arr[ 2] = "8"
arr[ 3] = "a"
arr[ 4] = "b"
arr[ 5] = "c"
arr[ 6] = "3"
arr[ 7] = "9"
arr[ 8] = "2"
arr[ 9] = "9"
arr[10] = "9"
arr[11] = "0"
arr[12] = "x"
arr[13] = "F"
arr[14] = "F"
arr[15] = "["
arr[16] = "w"
arr[17] = "2"
arr[18] = "d"
arr[19] = "l"
arr[20] = "x"
Determine the total number of characters in all of the strings, then allocate a new character array of that length, and then copy the input characters into the new array.
The last part could take advantage of the sizes you gather in the first part: have an outer loop over all the argument strings, with an inner loop over the characters in each string.
EDIT: Now that I'm not on a mobile device, here's the above in code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char ** argv)
{
//For storing sizes of each input string
int *arg_chars;
//Where the individual characters are stored
char *stored_chars;
/* Determine total number of characters, and store
characters in each word for later re-use */
arg_chars = malloc(argc * sizeof(int));
int total_chars = 0;
//Loop starts at 1 since we don't care about arg 0
for(int i=1; i<argc; i+=1)
{
arg_chars[i] = strlen(argv[i]);
total_chars += arg_chars[i];
printf("Word %d is %d long\n", i, arg_chars[i]);
}
/* Load argument characters into the stored_chars array */
stored_chars = malloc(total_chars * sizeof(char));
int current_char = 0;
//Loop starts at 1 to exclude the program name (arg 0)
for(int i = 1; i < argc; i+=1)
{
printf("Scanning word %d (%s):\n", i, argv[i]);
for(int j = 0; j < arg_chars[i]; j+=1)
{
stored_chars[current_char] = argv[i][j];
printf(" Stored letter %d `%c` (letter %d of word %d)\n", current_char, argv[i][j], j, i);
current_char += 1;
}
}
/* Demonstrate that it's all loaded and accessible in any order */
for(int i=total_chars-1; i >= 0; i-=1)
{
printf("stored_chars[%d] = `%c`\n", i, stored_chars[i]);
}
return 0;
}
Output:
Word 1 is 3 long
Word 2 is 3 long
Word 3 is 12 long
Word 4 is 3 long
Scanning word 1 (218):
Stored letter 0 `2` (letter 0 of word 1)
Stored letter 1 `1` (letter 1 of word 1)
Stored letter 2 `8` (letter 2 of word 1)
Scanning word 2 (abc):
Stored letter 3 `a` (letter 0 of word 2)
Stored letter 4 `b` (letter 1 of word 2)
Stored letter 5 `c` (letter 2 of word 2)
Scanning word 3 (392990xFF[w2):
Stored letter 6 `3` (letter 0 of word 3)
Stored letter 7 `9` (letter 1 of word 3)
Stored letter 8 `2` (letter 2 of word 3)
Stored letter 9 `9` (letter 3 of word 3)
Stored letter 10 `9` (letter 4 of word 3)
Stored letter 11 `0` (letter 5 of word 3)
Stored letter 12 `x` (letter 6 of word 3)
Stored letter 13 `F` (letter 7 of word 3)
Stored letter 14 `F` (letter 8 of word 3)
Stored letter 15 `[` (letter 9 of word 3)
Stored letter 16 `w` (letter 10 of word 3)
Stored letter 17 `2` (letter 11 of word 3)
Scanning word 4 (d1x):
Stored letter 18 `d` (letter 0 of word 4)
Stored letter 19 `1` (letter 1 of word 4)
Stored letter 20 `x` (letter 2 of word 4)
stored_chars[20] = `x`
stored_chars[19] = `1`
stored_chars[18] = `d`
stored_chars[17] = `2`
stored_chars[16] = `w`
stored_chars[15] = `[`
stored_chars[14] = `F`
stored_chars[13] = `F`
stored_chars[12] = `x`
stored_chars[11] = `0`
stored_chars[10] = `9`
stored_chars[9] = `9`
stored_chars[8] = `2`
stored_chars[7] = `9`
stored_chars[6] = `3`
stored_chars[5] = `c`
stored_chars[4] = `b`
stored_chars[3] = `a`
stored_chars[2] = `8`
stored_chars[1] = `1`
stored_chars[0] = `2`

Read integers from stdin and store in 2d array (C)

I'm trying to read a text file containing integers via stdin and store the values in a 9x9 array (please note that the file must be read via stdin and not as an arg)
This is what I have:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
int main()
{
int puzzle[9][9];
int i,j,count=0;
char value[81];
for( i = 0; i < 9; i++ ) {
for( j = 0; j < 9; j++ ) {
scanf("%c", &value[count]);
puzzle[i][j] = value[count] - '0';
count++;
}
}
}
But it doesn't seem to convert the ASCII characters from scanf to int, which is what I thought the value[count] - '0' was supposed to do, so I end up getting values like this:
-16-16-160-16-160-16-161
Basically i'm trying to do exactly whats described in this thread, but in C instead of C++:
How to convert a 2d char array to a 2d int array?
Edit -
The input file looks like this (contains both white space and new lines):
0 0 1 9 0 0 0 0 8
6 0 0 0 8 5 0 3 0
0 0 7 0 6 0 1 0 0
0 3 4 0 9 0 0 0 0
0 0 0 5 0 4 0 0 0
0 0 0 0 1 0 4 2 0
0 0 5 0 7 0 9 0 0
0 1 0 8 6 0 0 0 7
7 0 0 0 0 9 2 0 0
The problem is not with the conversion line puzzle[i][j] = value[count] - '0';. The problem lies with the following scanf() statement, scanf("%c", &value[count]);. The scanf is reading the first white space. Use scanf(" %c", &value[count]); to read the input.
%c does eactly what it should: it reads one character. D'oh, it's whitespace? That doesn't matter. This is why...
... you shouldn't use %c but %d for scanning integers;
...you shouldn't use scanf() at all for something simple like this.
What I'd do if I were you:
int matrix[9][9];
int i = 0;
char buf[0x100];
while (fgets(buf, sizeof(buf), stdin)) {
char *end;
char *p = strtok_r(buf, " ", &end);
while (p) {
matrix[i / 9][i % 9] = strtol(p, NULL, 10);
i++;
p = strtok_r(NULL, " ", &end);
}
}
Is there any reason this doesn't work? Scan them in as integers.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
int main()
{
int puzzle[9][9];
int i,j,count=0;
char value[81];
for( i = 0; i < 9; i++ ) {
for( j = 0; j < 9; j++ ) {
scanf("%d", &value[count]);
puzzle[i][j] = value[count];
printf("%d", puzzle[i][j]); //to verify it is stored correctly
count++;
}
}
}
EDIT: since you said it's coming from a file, i copy/pasted the sample file you gave into C:\file.txt, and the following code appears to work just dandy.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
int main()
{
FILE *fp;
int puzzle[9][9];
int i,j,count=0;
int value[81];
fp = fopen("C:\\file.txt", "r");
for( i = 0; i < 9; i++ ) {
for( j = 0; j < 9; j++ ) {
fscanf(fp, " %d", &value[count]);
puzzle[i][j] = value[count];
printf("element %d is %d\n",count, puzzle[i][j]);
count++;
}
}
}

Resources