Creating a two dimensional array from a file input in C - c

TL;DR: Struggling with 2 dimensional arrays.
I'm trying to create two two dimensional array from a list of integers from a text file. This is programmed in C.
tester.txt contains:
2 1 2 3 4 5 6 7 8
The first number means that both arrays have 2 rows and 2 columns, if it were any other number the columns/rows would be represented as such.
tester.txt should ouput the following:
1 2 5 6
3 4 7 8
Here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int i,j,k;
FILE *filepointer;
int nrows;
int size;
fputs("Enter a filename: ", stdout);
fflush(stdout);
if ( fgets(filename, sizeof filename, stdin) != NULL )
{
char *newline = strchr(filename, '\n'); /* search for newline character */
if ( newline != NULL )
{
*newline = '\0'; /* overwrite trailing newline */
}
printf("filename = \"%s\"\n", filename);
}
filepointer=fopen(filename,"r");
fseek(filepointer, 0, SEEK_END); // seek to end of file
size = ftell(filepointer);
printf("Size=%d\n",size);
fseek(filepointer, 0, SEEK_SET);
int holderarray[size];
for(i=0; i<size; i++)
fscanf(filepointer, "%d", &holderarray[i]);
nrows=holderarray[0];
printf("Number of rows/columns=%d\n",nrows);
if (filepointer == NULL)
{
fprintf(stderr, "Can't open input file in.list!\n");
exit(1);
}
}
Everything works as expected up until this point. I can't visualize how to add the first half of the values to the new 2 dimensional arrays, hopefully you guys can help. Here's my brainstorming in codeblocks.
int matrix1[nrows][nrows];
int matrix2[nrows][nrows];
for (i=1; i<sizeof(holderarray);i++)
{
for (j=0;j<nrows;j++)
{
matrix[i][j]=holderarray[j];
}
for (i=0;i<sizeof(nrows);i++)
{
for (j=0;j<sizeof(nrows);j++)
{
printf("%d",matrix[i][j]);
}
}
return 0;

you can get them by looping using getc
1. you read the first char in line and define the array structure , cast to integer
2. initialize the arrays eg you read 2 so 2*2 is the size of the array, 3*3 is the size of the array and number of the elements to read in every array
3. continue reading in to reach the first array bound based 2*2 = 4 3*3= 9 based on the first line.
4. fill the other array since the first array is full,

You can't dynamically declare arrays in standard C like this based on variables that aren't known at compile time:
int matrix1[nrows][nrows];
int matrix2[nrows][nrows];
What you need to do, if you aren't using C99 or a later version, is use the malloc function that dynamically allocates memory for you:
int **matrix1, **matrix2;
int i;
matrix1 = malloc(nrows * sizeof(int*));
matrix2 = malloc(nrows * sizeof(int*));
for(i = 0; i < nrows; i++) {
matrix1[i] = malloc(nrows * sizeof(int));
matrix2[i] = malloc(nrows * sizeof(int));
}
Two-dimensional arrays in C are treated as pointers to pointers. Each pointer is a reference to a contiguous chunk of memory that contains integers (i.e. the rows of your matrix), and then we use a pointer to a pointer as a reference to another contiguous chunk of memory that contains references/pointers to the first element in all of these rows.
This image (not mine) may help: DYNAMIC 2D ARRAY
Note that this dynamically allocated memory should be freed when you are finished using it:
for(int i = 0; i < nrows; i++) {
free(matrix1[i]);
free(matrix2[i]);
}
free(matrix1);
free(matrix2);

Related

how to allocate arrays (in array of pointers) C -- can it be done in one line? with malloc

is there a simple one liner I can use in C to allocate arrays in (pointer of arrays)
This line creates 10 pointers of arrays
char *out[10];
I can't do this
char *out[100]=(char[10][100])malloc(sizeof(char)*10*100);
error: cast specifies array type
same error with
char *out[10]=(char*[10])malloc(sizeof(char)*10*100);
do I need to do it in loop like this
int main()
{
char *out[10];
int x=0;
while(x<10)
{
*(out+x)=malloc(sizeof(char)*100);// is this line correct?
x++;
}
*out[0]='x';
printf("%c\n",out[0][0]);
free(out);
return 0;
}
but this cause warning that
req.c:75:3: warning: attempt to free a non-heap object ‘out’ [-Wfree-nonheap-object]
75 | free(out);
so do I need to allocate and free each array in (array of pointers) in loop
Can't I do allocation and free arrays in array of pointer in one line instead of loop?
or is there anything thing in my loop wrong too
To allocate an array of pointers to strings, you need to do:
char** out = malloc(sizeof(char*[10]));
The whole point of using this form is that each pointer in that array of pointers can be allocated with individual size, as is common with strings. So it doesn't make sense to allocate such with a "one-liner", or you are using the wrong type for the task.
In case you don't need individual sizes but are rather looking for a char [10][100] 2D array with static size, then the correct way to allocate such is:
char (*out)[100] = malloc(sizeof(char[10][100]));
You can allocate the full array in one single step and have pointers inside that array:
char *out[10];
data = malloc(100); //sizeof(char) is 1 by definition
for (int x=0; x<10; x++) {
out[i] = data + x * 10;
}
*out[0] = 'x';
printf("%c\n",out[0][0]);
free(data); // you must free what has been allocated
int i;
char** out = (char**)malloc(sizeof(char*)*10);
for(i = 0; i<10;i++)
out[i] = (char*)malloc(sizeof(char)*100);
out[1][1] = 'a';
OR with same dimensions
#include <stdio.h>
#include <stdlib.h>
void main()
{
int r = 10, c = 100; //Taking number of Rows and Columns
char *ptr, count = 0, i;
ptr = (char*)malloc((r * c) * sizeof(char)); //Dynamically Allocating Memory
for (i = 0; i < r * c; i++)
{
ptr[i] = i + 1; //Giving value to the pointer and simultaneously printing it.
printf("%c ", ptr[i]);
if ((i + 1) % c == 0)
{
printf("\n");
}
}
free(ptr);
}

c - Which is the correct way to dynamically allocate multidimensional float arrays? Valgrind error

I'm implementing a K-means algorithm in C. It works well most of the time, but debugging it with Valgrind tell me that I'm doing an "Invalid read of size 8 - Invalid write of size 8 - Invalid read of size 8" using '''memcpy''' at the beginning. I think the problem isn't there, but where I assign a value to the multidimensional float array element, which memory is dynamically allocated with '''malloc''' with a for loop at some point. 'Cause Valgrind also tell "Address 0x572c380 is 0 bytes after a block of size 80 alloc'd".
I've tried to add 1 to the number of bytes that I allocate, cause I thought that maybe '''malloc''' "needed" more memory to do its job, but nothing changed. I know maybe it's a basic error, but I'm quite new to the language and at my course it wasn't explain anything so "technical". I've tried to search the answer and explanation of the error but I have only found problems with '''char''' arrays, and with those I'd understood the function '''strcpy''' can resolve the issue. What about float arrays? It's the first time a use '''memcpy'''.
Here are pieces of code that raise those Valgrind messages.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void main(){
FILE* fp; //used to open a .txt file to read
char buf[100];
float ** a;
char * s;
int i;
int j;
int rows = 10;
fp = fopen("data.txt", "r");
if(fp==NULL){
perror("Error at open file.");
exit(1);
}
a = (float**) malloc(rows*sizeof(float*));
for(i=0; i<rows; i++){
s = fgets(buf, 100, fp); //reading .txt file
if (s==NULL){
break;
}
a[i] = malloc(dim*sizeof(float));
a[i][0] = atof(strtok(s, ","));
for(j=1; j<dim; j++){
a[i][j] = atof(strtok(NULL,",")); //save as float value the token read from a line in file, for example, from line "1.0,2.0,3.0" as first line -> get a[0][1] = 2.0
}
}
fclose(fp);
m = (float**) malloc(rows*sizeof(float*));
for (i=0; i<rows; i++){
m[i]=malloc(dim*sizeof(float)); //not initialized
}
memcpy(m, a, rows*dim*sizeof(float));
}
Can someone also help me understand why it works but Valgrind raises these error messages?
You're first allocating an array of float*, then allocating several arrays of float so your last memcpy(m, a, rows*dim*sizeof(float)) copies an array of float* (pointers to float) to another one, but using rows * dim floats, which #SomeProgrammerDude rightfully noted. That would copy pointers, and not values.
Also, as pointed by #xing, you're allocating rows but using righe (which you didn't show). It might be a cause of problems.
I would suggest allocating the whole array at once on the first row, then having all other rows pointing to adequate rows:
a = malloc(rows * sizeof(float*));
a[0] = malloc(dim * rows * sizeof(float)); // Allocate the whole matrix on row #0
for (i = 1; i < rows; i++) {
a[i] = a[0] + i * dim; // sizeof(float) automatically taken into account as float* pointer arithmetics
}
...
m = malloc(rows * sizeof(float*));
m[0] = malloc(dim * rows * sizeof(float));
memcpy(m[0], a[0], dim * rows * sizeof(float));
(add NULL checks of course)

Error: subscripted value is not an array, pointer, or vector and idk what the issue is? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
The purpose of this exercise is to use the two-subscript method of dynamic memory allocation.
Input for this program is a two-dimensional array of floating point data located in a file named
testdata2. The input array will contain 3 rows of data with each row containing 5 columns of data.
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE *fp;
int temp;
int number;
int r = 3;
int c = 5;
fp = fopen("testdata2.txt", "r");
number = (int)malloc(r * c * sizeof(int));
while (fscanf(fp, "%d", &temp) != EOF){
for(int i = 0; i < 3;i++){
for(int j = 0; j < 5; j++){
temp = number[i][j];
}
}
}
return(0);
}
Among the plethora of things incorrect in your code (any one of which can result in undefined behavior):
The core data type is wrong. The question specifically calls for floating-point values, yet you're using integer types.
The receiver of any memory allocation in C should be a pointer; you're using a simple int.
You're hiding whatever warnings/errors you're receiving by hard-casting. Casting malloc in C isn't necessary, nor advised.
Even if everything else were fixed, your assignment statement for temp = ... is backward. You want to save the value just-read into your matrix, not throw it away and overwrite it with whatever undefined value resides in your memory-just-allocated.
All of that said, knowing the width of your array of arrays is five, the problem reduces to this. Note temp isn't needed at all
#include <stdio.h>
#include <stdlib.h>
int main()
{
static const size_t r = 3;
static const size_t c = 5;
FILE *fp = NULL;
double (*number)[c] = NULL; // pointer to array of dimension c.
fp = fopen("testdata2.txt", "r");
if (fp == NULL)
{
perror("Failed to open file: ");
return EXIT_FAILURE;
}
number = malloc(r * sizeof *number); // allocate r-rows of dimension c
if (number == NULL)
{
perror("Failed to allocate array of arrays: ");
return EXIT_FAILURE;
}
for (size_t i=0; i<r; ++i)
{
for (size_t j=0; j<c; ++j)
{
if (fscanf(fp, "%lf", number[i]+j) != 1)
{
fprintf(stderr, "Failed to parse int at %zu,%zu", i, j);
return EXIT_FAILURE;
}
}
}
for (size_t i=0; i<r; ++i)
{
for (size_t j=0; j<c; ++j)
printf("%lf ", number[i][j]);
fputc('\n', stdout);
}
free(number);
return(0);
}
You are declaring an integer:
int number;
and you are allocating memory with malloc assuming it is a multi-dimensional array, then trying to access its elements in the same way.
Change the declaration to:
int **number;
it is not
(int)malloc(rcsizeof(int))
It is
(int*) malloc(rcsizeof(int))
One more mistake is that you can't access the elements as
temp=number[i][j];
Replace it with
temp=number[i*r+j]
Hope this helps
number = (int)malloc(r * c * sizeof(int));
In C, never cast the result of a malloc. If you had left out the cast to int, you'd have a diagnostic here telling you that number is not a pointer type.
You can do this:
int* number = malloc(r * c * sizeof(int));
But that gives you one big single dimensional array. You would need to dereference it like this:
temp = number[i * c + j];
If you want two dimensional indices as if you had declared it like this:
int number[r][c];
you need to allocate it in two stages:
int** number = malloc(r * sizeof(int*));
number[0] = malloc(r * c * sizeof(int));
for (int i = 1 ; i < r ; i++)
{
number[i] = &number[0][i * c];
}
That sets up a big array of ints and an intermediate array of pointers to ints for each row. Now you can do
temp = number[i][j];
Edit
Or you can do what Dmitri says which is this:
int (*number)[c] = malloc(r * c * sizeof(number[0][0]));
That effectively mallocs an array of r blocks of c ints in one go.

Precise Syntax for Accessing Elements in a 2D Array - by Pointer?

I'm a CS student working on a homework assignment, and I need help with a C syntax issue. Yesterday in class, my professor said, "an int** pointer is a pointer to a 2D int array." This blew my mind.
Turns out, we have to write a C program which reads an int matrix from a file, then do operations on that matrix. For example, "matrix1.txt" might look like this:
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
...for a 5x3 matrix. I get the dimensions of the matrix from another file, which is a problem I've already solved. But the point is I have to dynamically allocate the matrix array using variables.
Here's my issue: Its easy enough to use an int** pointer to malloc() an Y-by-X array... but what's the syntax to access it? Here's my code:
#include<stdio.h>
#include<stdlib.h>
int main(int argc, char *argv[]){
char *myFile = argv[1];
FILE *targetFile;
targetFile = fopen(myFile, "r");
if (targetFile == NULL)
return -1;
else {
// Successfully opened "matrix1.txt" file
int x, y; // dimensions of the array, learned elsewhere...
int i, j;
char* data = NULL;
int** matrix = (int**)malloc((x*y)*sizeof(int)); // allocate memory for an Y-by-X array
for(i=0; i<y; i++){
for(j=0; j<x; j++){
fscanf(targetFile, "%c ", &data);
matrix[i][j] = atoi(data); // program seg faults here
}
}
}
fclose(targetFile);
return 1;
}
The issue is the "matrix[i][j] = atoi(data);" line; I'm either using the wrong syntax or I haven't initialized the array. I can't tell which - the program seg faults IMMEDIATELY once I hit this line in the GDB debugger.
I'm sure this is a C 101 kind of question... but I post this because I've been reading a lot of different posts on 2D arrays and pointers, yet I can't seem to find an example that fits my precise situation. Can anyone help me out with this?
Thanks,
-ROA
The syntax used in
matrix[i][j] = atoi(data);
is not incorrect. It's the logic used to allocate memory that is wrong.
One way to allocate memory for the 2D array is:
// Allocate memory for y number of int*s.
int** matrix = malloc(y*sizeof(int*));
for(i=0; i<y; i++)
{
// Allocate memory for x number of ints.
matrix[i] = malloc(x*sizeof(int));
for(j=0; j<x; j++)
{
// Assign to the ints
matrix[i][j] = <some value>;
}
}
For reading the data, use
int data;
and
fscanf(targetFile, "%d", &data);
Then, the inner loop above can be updated to:
for(j=0; j<x; j++)
{
// Assign to the ints
fscanf(targetFile, "%d", &data);
matrix[i][j] = data;
}
Make sure to add code to release the dynamically allocated memory.
// Free the memory allocated for the ints
for(i=0; i<y; i++)
{
free(matrix[i])
}
// Free the memory allocated for the int*s
free(matrix);

2 Dimensional array and Print out average of the Columns and Rows

Im still a beginner in C programming and I need a little help writing a code for my C programming class.
The prompt is: Input for this program is a two-dimensional array of floating point data located in a file named textfile94. The input array will contain 3 rows of data with each row containing 5 columns of data.
I want you to use the two-subscript method of dynamic memory
allocation.
Use malloc to create an array that holds pointers.
Each element of that array points at another array, which is the row of data.
Use malloc in a loop to create your rows.
Then you can use two subscript operators [r][c] to get at your data
to do the summing and averaging that the program calls for.
This program calls for hard-coded height and width of the 2D array,
known ahead of time (3x5, actually).
Instead of writing in the literal numbers in your code, I want you to
create a global constant variable to hold those dimensions, and use
those in your code.
Here is my code:
#include <stdio.h>
#include <stdlib.h>
#define int rows = 3;
#define int columns = 5;
float array[rows][columns];
int main(int argc, char* argv[]){
FILE* fin;
float x;
int i,j;
int* array;
fin = fopen("textfile94", "r");
fscanf(fin,"%f", &x);
array =(int*) malloc(rows* sizeof(int*));
for(i=0;i<rows;i++){
for(j=0;j<columns;j++)
array[i]=(int*)malloc(columns* sizeof(int));
}
printf("The Average values for the three rows are:[%f]",array[i]);
printf("The Average values for the five columns are:[%f]", array[j]);
return 0;
}
In text file: 4.33 5.33 1.11 99.00 100.00 1.0 33.3 12.5 1.1 -1000.00 22.1 11.9 2.4 8.3 8.9
The program should output:
The average values for the three rows are: 41.95 -190.42 10.32
The average values for the five columns are: 9.14 16.84 5.33 36.13 -297.7
Having Trouble getting it to do this correctly, any help would be appreciated. I don't want the answer I want to learn from this but just need some hints. Thank you.
Updated Code:
#include <stdio.h>
#include <stdlib.h>
#define ROWS 3
#define COLUMNS 5
float array[ROWS][COLUMNS];
int main(int argc, char* argv[]){
FILE* fin;
int i;
float x;
float** array;
fin = fopen("textfile94", "r");
array=(float**) malloc(ROWS*sizeof(float*));
for(i=0;i<ROWS;i++)
array[ROWS]=(float*)malloc(COLUMNS*sizeof(float));
for(j=0;j<COLUMNS;j++){
fscanf(fin,"%f",&x);
x = array[ROWS][COLUMNS];
}
printf("The Average values for the three rows are:%f", array[ROWS]);
printf("The Average values for the five columns are:%f", array[COLUMNS]);
return 0;
}
Ok, I'll see what I can add.
Defines are not written like that, and by convention should be all upper case
#define ROWS 3
#define COLUMNS 5
He wants you to dynamically allocate the array via malloc, you are now statically allocating a 2-dimensional array of floats and then you try to force arrays of ints into it. You should look up how to do multidimensional arrays with malloc.
Basically what you want is
float **array;
Now array is a pointer to pointer to float, then assign array rows number of pointers to float.
ROWS * sizeof(float*)
After that you can for each row assign array[row] with
COLUMNS * sizeof(float)
Now you have your array[ROWS][COLUMNS] structure
One approach to reading in the data in pythonesque pseudo code would be
for(row 1..3)
array[row] = malloc(...)
for(col 1..5)
fscanf(value)
array[row][col] = value
Tell me if I am being too vague, trying to give hints without giving the code.
This should get you started on how to allocate the array, assign and access values, and then free memory. Error checking is omitted for clarity. Most likely you will want verify that calloc actually returns a valid pointer.
To complete the program you will have to read the values into the array and then calculate the averages.
#include <stdlib.h>
#include <stdio.h>
const size_t rows = 3;
const size_t columns = 5;
int main(void)
{
size_t i, j;
/* allocate a two-dimensional array of zeroes */
double **array = calloc(1, rows * sizeof(double *));
for (i = 0; i < rows; ++i) {
array[i] = calloc(1, columns * sizeof(double));
}
/* print it out - replace this by reading in values */
for (i = 0; i < rows; ++i) {
for (j = 0; j < columns; ++j) {
fprintf(stdout, "%.2f", array[i][j]);
fputc(' ', stdout);
}
fprintf(stdout, "\n");
}
/* TODO loop through the array again and average the data */
/* free memory */
for (i = 0; i < rows; ++i) {
free(array[i]);
}
free(array);
return EXIT_SUCCESS;
}

Resources