Scan set of integers into 2-D array - arrays

Consider the following set of numbers:
10 20 30
11 31 45
...
I want to define a 2-D array int_array[][3] such that int[0] contains {10, 20, 30}, then int[1] contains {11, 31, 45} and so on.
Assume that these values are in a file. The code I would use is therefore:
int int_array[NUM_ROWS][3], i;
for (i=0; i<NUM_ROWS;i++)
fscanf(filePointer, "%d", int_array[i]);
However, this produces ridiculous results. What am I doing wrong?

produces ridiculous results. What am I doing wrong?
int_array[i] points to only 1 int, not the 3 needed.
Code lacks error checking.
Create a helper function to read 1 line of data, saving the data when d != NULL.
int read3int(FILE *inf, int d[3]) {
char buf[100];
if (fgets(buf, sizeof buf, inf) == NULL) {
return EOF;
}
int n = 0;
int i[3];
sscanf(buf, "%d%d%d %n", &i[0], &i[1], &i[2], &n);
// Was scan incomplete or with extra junk?
if (n == 0 || buf[n] != 0) {
return 0;
}
if (d) {
d[0] = i[0];
d[1] = i[1];
d[2] = i[2];
}
return 1;
}
To form the array, first find how many rows.
size_t rows = 0;
while (read3int(filePointer, NULL) > 0) {
rows++;
}
// Form the array
int data[rows][3]; // VLA or use malloc
// Rewind !!
rewind(filePointer);
for (size_t r = 0; r < rows; r++) {
if (read3int(filePointer, data[r]) < = 0) {
// Unexpected 2nd pass inconsistency
break;
}
}

You said in the comments: "my real set of numbers does not have 3 columns but instead multiple"
I am posting a general method to read lines of integers from a file, storing them in a 2D array. It works regardless of the number of integers in each line.
But I haven't run this piece of code and I never used strtol, so chances are it doesn't work. I am giving you the idea, you can implement it properly.
char line[N], *ptr;
for(i = 0; fgets(line, N, filePointer) != NULL; i++) {
int_array[i][0] = (int) strtol(line, &ptr, 10);
for(j = 1; *ptr != '\n'; j++) {
int_array[i][j] = (int) strtol(ptr, &ptr, 10);
}
}
The logic is to read an entire line as a string and then convert the numbers from char to int.

Related

random numbers being read into array instead of the text file values

I am trying to make a function that reads all the numbers from a text file into an array, where each line of the file has a number, ex:
57346
40963
24580
98307
98312
32777
10
16392
16396
...
My function does allocate the necessary size to store the values, but the values being stored are random ones and 0's that aren't in my text file. Output ex:
0
0
296386
0
-485579776
-653048057
584
0
2095946880
...
This is my code:
typedef struct set{
void** values;
int size;
}Set;
int checkSize(FILE* file) {
int counter = 0;
char chr;
chr = getc(file);
while (chr != EOF) {
if (chr == '\n') {
counter = counter + 1;
}
chr = getc(file);
}
return counter;
}
Set* readSet(FILE* file){
Set* new = malloc(sizeof(Set));
new->size = checkSize(file);
new->values = malloc(sizeof(void*)*new->size);
int arrayAux[new->size];
int i = 0, n;
while(i < new->size) {
fscanf(file, "%ld", &arrayAux[i]);
new->values[i] = arrayAux[i];
i++;
}
//loop to remove the first three lines of the file, which are the number of values in the file,
//the biggest value of the file and the division between the number of values and the biggest value
for(i = 0; i < 3; i++) {
new->values[i] = new->values[i + 1];
new->size--;
}
for (i = 0; i <= new->size; i++) {
printf("%d\n", new->values[i]);
}
return new;
}
How can I fix this? Thanks in advance for any help.
Why void and not long?
You cannot do int arrayAux[new->size]; as size is a variable and thus cannot be used at compile time !!! 100% guarantee of reading out of bounds.
Read the value from file into a long and assign it to the proper space in your list.
Why have the size in every row? Use a global int
why loop to step over the first three in the list?
size -=3
i+=3
Works just as well

Not able to print this 2D array (weird output) in C

I am trying to read a text file with 100 numbers like 1 2 45 55 100 text file here (all on a single line) and then put them in a 10x10 array (2D array).
736.2 731.6 829.8 875.8 568.3 292.2 231.1 868.9 66.7 811.9 292.0 967.6 419.3 578.1 322.5 471.7 980.0 378.8 784.1 116.8 900.4 355.3 645.7 603.6 409.1 652.1 144.1 590.6 953.1 954.0 502.0 689.3 685.6 331.9 565.1 253.9 624.1 796.2 122.8 690.7 608.0 414.8 658.3 27.3 992.9 980.8 499.0 972.8 359.7 283.1 89.7 260.1 638.4 735.4 863.6 47.5 387.5 7.7 638.1 340.6 961.7 140.1 29.8 647.3 471.9 594.9 901.2 96.0 391.1 24.0 786.7 999.1 438.7 445.0 26.4 431.6 425.9 525.4 404.4 785.6 808.5 494.1 45.7 447.0 229.5 909.3 494.4 617.0 917.0 132.5 957.5 878.8 272.6 987.4 526.1 744.5 582.3 427.3 840.5 973.3
Here is my code:
#include <stdio.h>
#define NR 10
#define NC 10
int main(void) {
int numbers[9][9];
int i = 0;
int count;
int j = 0;
FILE *file;
file = fopen("numbers.txt", "r");
for (count = 1; count < 101; count++) {
fscanf(file, "%d", &numbers[i][j]);
j++;
if ((count != 1) && (count % 10 == 0)) {
i++;
j = 0;
}
}
fclose(file);
int p = 0;
int q = 0;
for (p = 0; p < NR; p++) {
for (q = 0; q < NC; q++) {
printf("%d", numbers[p][q]);
}
printf("\n");
}
return 0;
}
As SparKot noted in a comment, to read a 10x10 matrix, you need to define the matrix with 10x10 elements:
int numbers[10][10];
That has to be one of the weirder ways of reading a 10x10 matrix that I've ever seen. Why not go for a simple approach of nested loops. Since the data contains floating-point numbers, you need to read them as double (or perhaps float) values.
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 10; j++)
{
double double_val;
if (fscanf(file, "%lf", &double_val) != 1)
{
fprintf(stderr, "failed to read matrix[i][j]\n", i, j);
exit(EXIT_FAILURE);
}
numbers[i][j] = double_val;
}
}
The mess with double_val works around the data containing floating point numbers and your original code trying to read integers. You'll get one valid value; thereafter, fscanf() will return 0 because the . is not a part of a valid integer. This highlights the importance of checking the return value from fscanf() and its relatives.
Frankly, you should be using double numbers[10][10]; for the data from the file. Then you could read directly into the array:
if (fscanf("%lf", &numbers[i][j]) != 1)
But you'd need to check (and probably change) all the rest of the code too.
There are multiple issues in your code:
the matrix is too small, make it numbers[NR][NC].
you do not check for fopen failure: you will have undefined behavior if the file numbers.txt is not in the current directory or cannot be open for reading.
you read the file contents as integers, but the file contains floating point numbers with a . decimal separator: the second and subsequent fscanf() will get stuck on the . and keep returning 0 without modifying the destination number, leaving the matrix mostly uninitialized. Make the matrix double numbers[NR][NC], read the numbers with %lf and test for conversion failure.
the counting method in the reading loop is weird. Just use 2 nested for loops with proper counter and tests.
printing the matrix contents, you should output at least a space between numbers so the output is readable.
Here is a modified version:
#include <errno.h>
#include <stdio.h>
#include <string.h>
#define NR 10
#define NC 10
int main() {
double numbers[NR][NC];
FILE *file;
file = fopen("numbers.txt", "r");
if (file == NULL) {
fprintf(stderr, "cannot open numbers.txt: %s\n", strerror(errno));
return 1;
}
for (int i = 0; i < NR; i++) {
for (int j = 0; j < NC; j++) {
if (fscanf(file, "%lf", &numbers[i][j]) != 1) {
fprintf(stderr, "error reading number at row %d, col %d\n",
i + 1, j + 1);
fclose(file);
return 1;
}
}
}
fclose(file);
for (int p = 0; p < NR; p++) {
for (int q = 0; q < NC; q++) {
printf(" %5g", numbers[p][q]);
}
printf("\n");
}
return 0;
}
Clear all a common condition that causes programs to crash; they are often associated with a file named core.
code is showing segmentation fault.

N permutations of string (with repetitions)

I have to print first n permutations with repetitions of a string.
String is formed with characters 'a','b','c','d','e','f'.
For example, first 10 permutations would be: aaaaaa,aaaaab,aaaaac,aaaaad,aaaaae,aaaaaf,aaaaba,aaaabb,aaaabc,aaaabd.
This is my failed attempt:
int main()
{
FILE *c;
c = fopen("C:\\Users\\Korisnik\\Desktop\\tekst\\permutacija.txt", "w");
char s[6] = "abcdef";
char t[6] = "aaaaaa";
s[6] = '\0';
t[6] = '\0';
int k = strlen(t);
int m = k;
int n;
scanf("%d", &n);
int br = 0;
int i = 0;
while (br < n) {
i = 0;
while (i < 6) {
t[k-1] = s[i];
fprintf(c, "%s ", t);
fprintf(c, "\n");
i++;
br++;
if (br == n) {
exit(1);
}
}
t[k-1] = 'a';
k--;
if (k < 0) {
k = m;
}
}
return 0;
}
And my output for first 10 permutations is:
aaaaa
aaaaab
aaaaac
aaaaad
aaaaae
aaaaaf
aaaa
aaaaba
aaaaca
aaaada
Any suggestions?
(Showing a different idea)If you look carefully you will see that all the permutations are the numbers in base-7. Consider a as 0, b as 1 and so on. So for every number 1..n you will convert it into base 7 and write it (By write it I mean, in place of 0 you put a,1 - b etc). That will give you the required result. (Ofcourse in conversion you will have to append 0 to the left of the number as per number of digits you want to show). There are problems in your code:
char s[6]="abcdef";
is legal in C.
s[6]=0;
This is not as you are accessing array index out of bound which is Undefined behavior. strlen(t) is undefined behavior as t is not NUL terminated.
Also you have fprintf(c,"%s ",t); in your code - this also leads to undefined behavior, it also expects a char* which points to a nul terminated char array. This will make your realize that how irrelevant it is to have something like this
char s[6]="abcdef";
Long story short, use char s[7]="abcdef"; (same applies to t also).

Input in specific format (matrix)

I have an issue with input in my homework. On stdin, I will get a specifically formatted input.
In first line, there will be 2 integers, that determine the size of a matrix (rows and cols). All the lines after represent rows of the matrix.
I essentially want to do something like getline(), but I don't want to use getline(). In fact I can't, its forbidden in the homework. Therefore I have to scan int by int (or char by char I guess). The issue here is I need it to be bulletproof (almost). Dummy-proof at least.
I'm imagining a big while loop that keeps going until EOF and inside that another loop (perhaps?) which always reads a line, saves it to my allocated matrix and carries on to the next. I'm aware that I'm supposed to be checking for '\n', but I kind of lack the ability to think of a solution today.
Here's what I'm working with: My matrices are a structure.
struct Matrix{
int nrows;
int ncols;
int** matrix;
};
I then have multiple functions.
A function to dynamically allocate space for the matrix of specific size:
struct Matrix init_matrix(int r, int c)
{
struct Matrix mat;
mat.nrows = r;
mat.ncols = c;
mat.matrix = calloc(r, sizeof(int *));
for(int i = 0; i < r; ++i)
{
*(mat.matrix+i) = calloc(c, sizeof(int));
}
return mat;
}
A function to free the previously allocated space:
void free_matrix(struct Matrix mat)
{
int top = mat.nrows;
for(int i = 0; i < top; ++i)
{
free(mat.matrix[i]);
}
free(mat.matrix);
}
Those 2 functions work perfectly fine.
Now I'm trying to make a function create_matrix(void) (at least I think it shouldn't take any args), that will read the input I'm supposed to receive, for example:
3 3
1 2 3
4 5 6
7 8 9
when the function reads the input, it could tell if the input is incorrect or is in incorrect format and exit the program with corresponding exit value (like 100 f.e.) If the input is correct and in correct format, it calls init_matrix() and then saves input to the matrix.
For your deeper understanding: the whole input I'm supposed to receive is:
matrix A (like above, size in first line, values in lines after)
an operation (+,-,*)
matrix B
Then execute the operation (A*B, A+B etc.). I'm trying to make most things into functions, so the main would be very simple, f.e.
int main(int argc, char *argv[])
{
struct Matrix mat1 = create_matrix();
char operation = get_operation();
struct Matrix mat2 = create_matrix();
struct Matrix result = compute(mat1,mat2, operation);
return 0;
}
Something in those lines, if you get me. The thing is I want to make the program complex enough so that I could later edit it to handle a bigger sequence (up to 100) of matrices than just two. Right now I could do it the dirty way, make it work for two matrices with one operation, but that's not what I really want.
Well, here's how I solved it. It works. It's not anywhere close to perfect, but it works, upload system took it and gave it full amount of points, so I'm satisfied.
struct Matrix read_matrix(FILE *fp)
{
struct Matrix mat;
//FIRST LINE
int ch;
int i = 0;
int n = 20;
char* line = calloc(n,sizeof(char));
while((ch = fgetc(fp)) != EOF && ch != '\n')
{
*(line + i++) = ch;
}
*(line + n-1) = '\0';
int r,c;
int k = sscanf(line,"%d %d", &r, &c);
if(k != 2)
{
fprintf(stderr, "Error: Chybny vstup!\n");
exit(100);
}
free(line);
//MATRIX
line = calloc(c, sizeof(int));
mat = init_matrix(r, c);
i = 0;
r = 0;
while(r < mat.nrows && (ch = fgetc(fp)))
{
if(ch == '\n' || ch == EOF)
{
*(line + i) = '\0';
int offset;
char *data = line;
for(int j = 0; j < mat.ncols; ++j)
{
int d = sscanf(data, " %d%n", &mat.matrix[r][j], &offset);
if(d != 1){
fprintf(stderr, "Error: Chybny vstup!\n");
exit(100);
}
data += offset;
}
i = 0;
++r;
if(ch == EOF){
break;
}
} else
{
*(line + i++) = ch;
}
}
free(line);
return mat;
}

fread fails to read an unsigned int? [C]

I have a Person Struct as the following:
typedef struct Person {
char name[NUM_CHARS];
unsigned int age;
} Person;
where #define NUM_CHARS 20.
I want to write this structure to a binary file, so I wrote two function to handle that:
int writePerson(Person* person, FILE* _fp) {
int i = 0;
int count = 0;
int len = strlen(person->name);
// Write name
for(i = 0; i < len+1; i++) {
count += fwrite(&(person->name[i]), sizeof(char), 1, _fp);
// fseek(_fp, 1, SEEK_CUR);
}
// Continue
// Write age
count += fwrite(&(person->age), sizeof(unsigned int), 1, _fp);
return count;
}
int readPerson(Person* person, FILE* _fp) {
int i = 0;
int count = 0;
// Write name
for(i = 0;person->name[i] != NULL;i++) {
count += fread(&(person->name[i]), sizeof(char), 1, _fp);
}
// Continue
// Write age
count += fread(&(person->age), sizeof(unsigned int), 1, _fp);
return count;
}
So I wrote a Person to a blank file Px.bin that I've created well in advance:
int main() {
FILE* fp = fopen("Px.bin", "r+b");
Person person = {"Billie", 40};
// Person y ;
int x = writePerson(&person, fp);
printf("%d", x);
// printPerson(&y);
getchar();
fcloseall();
return 0;
}
Seems to work well, prints 8.
but when I try to read this file:
int main() {
FILE* fp = fopen("Px.bin", "r+b");
// Person person = {"Billie", 40};
Person y ;
int x = readPerson(&y, fp);
printf("%d\n", x);
printPerson(&y);
getchar();
fcloseall();
return 0;
}
I'm getting this result:
11
Billie
-858993460
Where printPerson is:
void printPerson(Person* p) {
printf("%s\n%d\n", p->name, p->age);
}
What is the problem?
This bit
for(i = 0;person->name[i] != NULL;i++) {
count += fread(&(person->name[i]), sizeof(char), 1, _fp);
}
is going to use uninitialized (IOW, containing garbage) person->name[] as the condition for reading. And it may so happen that the wrong number of bytes will get read here.
After that the following
count += fread(&(person->age), sizeof(unsigned int), 1, _fp);
can read the integer from an incorrect location within the file, not where said integer has been stored.
The fix would be to first read a character and then see if it's '\0' or not. If it is, the string's been fully read. If it's not, keep reading characters.
Your code that reads name does check for likely non-initialized (or zeroed out) person->name[i] elements. As result the loop end at some non-predictable time (i.e. if it is zeroed out loop will not fread even single character).
for(i = 0;person->name[i] != NULL;i++) {
count += fread(&(person->name[i]), sizeof(char), 1, _fp);
}
You want to change it to do/while loop or instead of reading till 0 prefix data in the file string with length and read that many characters.

Resources