C Segmentation fault with fscanf - c

Trying to read an input .txt file with using fscanf, and store the line content to the int variable, array, and 2D array, so I can use the value to do computation later. I think the problem over here is because I did not handle the "EOF" with using fscanf?
Here is my code:
int main(){
FILE *fp;
int n; // # resources
int m; // # processes
int avail[n];
int max[m][n], allo[m][n];
char temp1[10];
fp = fopen("test.txt", "r");
if (fp == NULL){
exit(EXIT_FAILURE);
}
fscanf(fp, "%d %d", &n, &m);
printf("%d %d", n, m);
printf("\n");
// Store the second line content to allo[]
for(int i = 0; i < n; i++){
fscanf(fp, "%s", temp1);
avail[i] = atoi(temp1);
printf("%d ", avail[i]);
}
printf("\n");
// Store the line3-7 content to 2D max[][]
for(int i = 0; i < m; i++){
for(int j = 0; j < n; j++){
fscanf(fp, "%s", temp1);
max[i][j] = atoi(temp1);
printf("%d ", max[i][j]);
}
printf("\n");
}
// Store the line8-12 content to 2D allo
for(int i = 0; i < m; i++){
for(int j = 0; i < n; j++){
fscanf(fp, "%s", temp1);
allo[i][j] = atoi(temp1);
printf("%d ", allo[i][j]);
}
printf("\n");
}
fclose(fp);
return 0;
}
Here is the .txt input file:
3 5
9 6 3
5 5 2
4 1 3
8 3 4
5 4 2
4 4 3
0 1 0
1 1 0
1 0 2
0 0 1
1 2 2
And here is the output:
3 5
9 6 3
5 5 2
4 1 3
8 3 4
5 4 2
4 4 3
Segmentation fault: 11

The problem is here:
int n; // # resources
int m; // # processes
int avail[n];
int max[m][n], allo[m][n], need[n][m];
n and m are not initialized when you declare the 2D array max. Try printing n and m before int max[m][n];, etc. and you will see that they contain garbage values.
As a result, Undefined Behavior is what you are experiencing, since you can't really tell what the size of your array is.
Change it to this:
int n; // # resources
int m; // # processes
fscanf(fp, "%d %d", &n, &m);
printf("%d %d", n, m);
int avail[n];
int max[m][n], allo[m][n], need[n][m];
Now when you create your arrays, n and m will be initialized with the values read from the file.
If you want to declare your arrays before reading n and m, then you should use pointers, read n and m and then dynamically allocate the arrays.

You declare int max[m][n], allo[m][n], need[n][m] while m and n are not set yet, so they are of unknown size. They will not resize themselves after the sizes are set. So writing to these will give you "undefined behaviour"

Since m,n is not initialized when you declared your arrays at the top of your file:
int avail[n];
int max[m][n], allo[m][n], need[n][m];
as #WeatherVane stated in the comments, you will get undefined behavior. Maybe you are overwriting some other part of the programs memory (who knows it is undefined!).
If you need dynamic array creation you should do something like the following:
int* avail;
...
fscanf(fp, "%d %d", &n, &m);
avail = (int*)malloc(n*sizeof(int));

When you initialize max,allo and need. the value of n and m is not defined.
You can define max, allo and need as int**.
After you have scanned the value of n and m, you can invoke the below function to allocate memory for above 2D arrays.
int ** get2DintArray(int r, int c){
int **arr = (int **)malloc(r * sizeof(int *));
for (i=0; i<r; i++)
arr[i] = (int *)malloc(c * sizeof(int));
return arr;
}
For. e.g:-
allo = get2DintArray(m,n);
need = get2DintArray(n,m);
This approach will be handy for higher values of n and m, where the stack memory may not be sufficient, because you are using heap memory in this case.

Related

Variables in C unexpectedly change

I'm writing a code to split an array into 2 different ones, one with even numbers and one with odd numbers. I read the numbers from a file, put it all into an array, and get the split right. Here's the code where everything works:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char** argv){
FILE* fpointer;
if (argc >= 2){
fpointer = fopen(argv[1], "r");
}else{
printf("No filename or multiple file names given");
return 0;
}
int numElem;
fscanf (fpointer, "%d\n", &numElem);
printf("Number of elements is %d\n", numElem);
int* arr;
int numEvens;
int numOdds;
arr = (int*) malloc(numElem*sizeof(int));
for (int i = 0; i < numElem; i++){
int temp;
fscanf(fpointer, "%d", &temp);
if(temp%2 == 0){
numEvens++;
}else{
numOdds++;
}
arr[i] = temp;
}
fclose(fpointer);
printf("number of evens: %d \n number of odds: %d\n", numEvens, numOdds);
//The array is now in "arr"
int* evens;
int* odds;
evens = (int*) malloc(numEvens*sizeof(int));
odds = (int*) malloc(numOdds*sizeof(int));
int a = 0;
int b = 0;
for (int i=0; i < numElem; i++){
printf("%d\n", arr[i]);
if (arr[i]%2 == 0){
evens[a] = arr[i];
a++;
}else{
odds[b] = arr[i];
b++;
}
}
printf("EVENS: %d\n", numEvens);
for (int i=0; i < numEvens; i++){
printf("%d\n", evens[i]);
}
printf("ODDS: %d\n", numOdds);
for (int i=0; i < numOdds; i++){
printf("%d\n", odds[i]);
}
Now I have a neat array with even numbers, and one with odd numbers. It outputs numEvens and numOdds correctly. Then I attempt to sort it:
int temp;
int x;
int y;
for (x = 0; x < numEvens-1; x++){
for (y=x+1; y < numEvens; y++){
if (evens[y] < evens[x]){
temp = evens[y];
evens[y] = evens[x];
evens[x] = temp;
}
}
}
return 0;
}
The output before I add in the sort method is:
Number of elements is 8
number of evens: 5
number of odds: 3
25
10
1
99
4
2
8
10
EVENS: 5
10
4
2
8
10
ODDS: 3
25
1
7
And the new output becomes:
Number of elements is 8
number of evens: 32772
number of odds: 1764530596
25
10
1
99
4
2
8
10
EVENS: 32772
10
4
2
8
10
0
0
0
0
....
The 0's go on presumably for another 32,000 times until I abort. I'm trying my hand at C after coming from java so memory allocation is a new subject for me, but I'm assuming it has something to do with that. I just don't understand how variables can be changed by lines of code added in after they are declared and printed. I don't really need help with new sorting methods, I just want some pointers on what's happening here so I can fix the errors. Thanks in advance!
int numEvens;
int numOdds;
Initialize your variables:
int numEvens = 0;
int numOdds = 0;
... and don't cast the result of malloc()!

2D array program shows garbage value in output

I am writing this simple code for dynamically allocated 2D array and displaying it. When I execute this program, it gives garbage value in the first row. How is that? Any errors in my program?
#include <stdio.h>
#include <stdlib.h>
int main()
{
int **ptr, limit, i, j;
printf("Enter the limit: ");
scanf("%d", &limit);
ptr = (int **) malloc(limit * (sizeof(int)));
for(i=0; i<limit; i++)
{
*(ptr+i) = (int *) malloc((i+1) * sizeof(int));
for(j=0; j<=i; j++)
{
ptr[i][j] = i;
}
}
for(i=0; i<limit; i++)
{
for(j=0; j<=i; j++)
{
printf("%d ", ptr[i][j]);
}
printf("\n");
}
return 0;
}
Output:
Enter the limit: 4
0
1 1
2 2 2
3 3 3 3
Enter the limit: 5
9478320
1 1
2 2 2
3 3 3 3
4 4 4 4 4
If I try to print the 2D array with the limit is less than or equal to 4, it works fine. What am I missing here..
Thanks
Maybe there are other issues as well; but one thing is for sure - you are allocating the wrong size for the pointer elements:
ptr = (int **) malloc(limit * (sizeof(int)));
though there should be limit objects of pointers to int, you are allocating ints. So it needs to be...
ptr = malloc(limit * (sizeof(int*)));
BTW: In C, avoid casting the result of malloc.

Why did my array get transposed?

I want declare a 2D array of doubles (double** data). I want to pass this by address to a helper function; so I pass &data and the helper function has argument double*** d.
Passed this way, the indexing that I used for the 2D array in the main function is no longer working.
Test code:
#include <stdio.h>
#include <stdlib.h>
void helperfunction(double*** data, int n, int c) {
printf("\nIn helper function\n");
for (int i = 0; i < n; i++) {
for (int j = 0; j < c; j++) {
printf("(%i %i %lf) ", i, j, *data[i][j]);
}
printf("\n");
}
}
int main(int argc, char **argv) {
int n = 4; //number of rows
int c = 4; //number of columns
double count = 0.0;
double** data = malloc(n * sizeof(double*));
for (int i = 0; i < n; i++) {
double* row = malloc(c * sizeof(double));
for (int j = 0; j < c; j++) {
row[j] = count;
count += 1.2;
}
data[i] = row;
}
printf("In main function\n");
for (int i = 0; i < n; i++) {
for (int j = 0; j < c; j++) {
printf("(%i %i %lf) ", i, j, data[i][j]);
}
printf("\n");
}
helperfunction(&data, n, c);
return 0;
}
Output:
In main function
(0 0 0.000000) (0 1 1.200000) (0 2 2.400000) (0 3 3.600000)
(1 0 4.800000) (1 1 6.000000) (1 2 7.200000) (1 3 8.400000)
(2 0 9.600000) (2 1 10.800000) (2 2 12.000000) (2 3 13.200000)
(3 0 14.400000) (3 1 15.600000) (3 2 16.800000) (3 3 18.000000)
In helper function
(0 0 0.000000) (0 1 4.800000) (0 2 9.600000) (0 3 14.400000)
Segmentation fault (core dumped)
Obviously, something is wrong with the indexing when I deference the address (*data[i][j]) in the helper function. What is causing this?
*data[i][j] does not do what you think. It is equivalent to *(data[i][j]). Your options are:
Use (*data)[i][j] instead, or
Pass data (instead of &data) and use data[i][j] since passing a triple pointer isn't necessary here.
Sorry, just figured this out. The dereferencing using [] occurs before the deferencing using *. Therefore a call to *data[i][j] will cause the segmentation fault when i != 0, since the highest level pointer is only pointing to one thing, while the two lover levels of pointers point to arrays.
A solution is to use data[0][i][j] instead.

Functions for dynamically allocating an array in C -- Any difference between the two?

Suppose you have a function in C that accepts the dimensions for a 2d array (for simplicity's sake, say for a square nxn array), dynamically allocates the array, then returns it.
I'm aware allocating memory here might be considered somewhat bad practice to begin with, since it will need to be freed elsewhere, but suppose that's not a huge issue. I'm wondering if there's any advantages/disadvantages associated with these two variations of said function:
Variation 1 - Locally define int** variable in function, allocate/return array:
int **create_array(int n) {
// define array pointer, allocate array...
int **a_ = (int**)calloc(n,sizeof(int*));
for (int i = 0; i < n; i++)
a_[i] = (int*)calloc(n,sizeof(int));
return a_;
}
int main() {
int n = 3;
int **array2d = create_array(n)
printf("First element: %d%c",array2d[0][0],'\n');
// do stuff... etc...
}
Variation 2 - Add in-out int** parameter to function, allocate/return array:
int **create_array_2(int **a_, int n) {
// allocate array...
a_ = (int**)calloc(n,sizeof(int*));
for (int i = 0; i < n; i++)
a_[i] = (int*)calloc(n,sizeof(int));
return a_;
}
int main() {
int n = 3;
int **array2d;
array2d = create_array_2(array2d,n);
printf("First element: %d%c",array2d[0][0],'\n');
// do other stuff... etc...
}
Obviously they return the same result and achieve the same task, but is one considered to be safer/more efficient/better practice than the other? In my opinion the 2nd variation just makes things look a bit redundant, but I'm curious if there's any real differences between the two and what happens on the stack/heap when they're called. Hopefully this isn't a dumb question; it's just something I've been curious about. If anyone has insight to share, I'd appreciate it.
I'll probably try to avoid calling malloc and free to many times so this kind of approach is what I'll do:
Example 1:
#include <stdio.h>
#include <stdlib.h>
int *foo(size_t row, size_t col);
int main(void){
int *arr;
unsigned int row, col, k;
printf("Give the ROW: ");
if ( scanf("%u",&row) != 1){
printf("Error, scanf ROW\n");
exit(1);
}
printf("Give the COL: ");
if ( scanf("%u",&col) != 1){
printf("Error, scanf COL\n");
exit(2);
}
arr = foo(row, col);
for (k = 0 ; k < (row * col) ; k++){
printf("%d ",arr[k]);
}
free(arr);
}
int *foo(size_t row, size_t col){
unsigned int i, j;
int *arr = malloc(sizeof *arr * row * col);
int l = 0;
if(arr == NULL){
printf("Error, malloc\n");
exit(3);
}
for ( i = 0; i < row ; i++){
for ( j = 0 ; j < col ; j++){
arr[i * col + j] = l;
l++;
}
}
return arr;
}
Output:
Give the ROW: 6
Give the COL: 3
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
Example 2 (if you are working with the standard C):
#include <stdio.h>
#include <stdlib.h>
int (*foo(size_t row, size_t col))[];
int main(void){
size_t row, col;
printf("Give the ROW: ");
if ( scanf("%zu",&row) != 1){
printf("Error, scanf ROW\n");
exit(1);
}
printf("Give the COL: ");
if ( scanf("%zu",&col) != 1){
printf("Error, scanf COL\n");
exit(2);
}
int (*arr)[col] = foo(row, col);
for ( size_t i = 0; i < row; i++){
for( size_t j = 0; j < col; j++){
printf("%d ",*(*(arr+i)+j));
}
}
free(arr);
}
int (*foo(size_t row, size_t col))[]{
int (*arr)[col] = malloc(row * col * sizeof(int));
int l=0;
if (arr == NULL){
printf("Error, malloc\n");
exit(3);
}
for ( size_t i = 0; i < row; i++){
for( size_t j = 0; j < col; j++){
*(*(arr+i)+j) = l;
l++;
}
}
return arr;
}
Output:
Give the ROW: 6
Give the COL: 3
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
The whole point here is that the call of malloc and free in both examples takes place only one time
IMO, of the two you are better off simply returning the value. This way there's a pure and solid wall between you and the caller.
"Give me some stuff!"
"Okay, here's some stuff."
On the other hand, for actually allocating an array of fixed size, why bother with pointers? Why not declare your return type so as to be castable to a sized array?
int (*p2a)[15] = (int(*)[15])create_array_2(15, 15);
Then you would calloc(15*15,sizeof(int)) and be done.

matrix using pointers

i have problem with the third function (GetMatrix) the others are works.
i want to catch data from user into the matrix by poiters only
the lines:
typedef int pArr[COLS];
void GetMatrix(pArr* ,int , int );
M[ROWS][COLS];
are constraints
how i need to do the scan, i try to use scanf("%d",*(M+cols*i+j))
but i get error..its probably wrong
what is need to do to make it right
thx all
the code :
#pragma warning ( disable: 4996 )
#include <stdio.h>
#include <string.h>
#define ROWS 2
#define COLS 3
typedef int pArr[COLS];
void MergeStrings(char* str1,char* str2,char* strRes);
void StrReverse(char* strRes,char* strRev);
void GetMatrix(pArr* M ,int rows , int cols);
void main()
{
char str1[256],str2[256],strRes[256],strRev[256];
int M[ROWS][COLS];
printf("Please enter first string:\n");
flushall();
gets(str1);
printf("\nPlease enter second string:\n");
flushall();
gets(str2);
printf("\nMerge of: %s\n",str1);
printf("with: %s\n",str2);
MergeStrings(str1,str2,strRes);
StrReverse(strRes,strRev);
printf("is:\n");
printf("==> %s\n",strRes);
printf("\nthe reversed merged string is:\n");
printf("==> %s\n\n",strRev);
GetMatrix(M,ROWS,COLS);
}
void MergeStrings(char* str1,char* str2,char* strRes)
{
int i=0,j=0,a=0,flag=0,flag2=0;
do
{
while( *(str1+i)==' ')
i++;
while( *(str2+j)==' ')
j++;
while( *(str1+i)!=' ' && *(str1+i)!='\0')
{
*(strRes+a)=*(str1+i);
i++;
a++;
}
if(flag!=1)
{
*(strRes+a)=' ';
a++;
}
if(*(str1+i)=='\0')
flag=1;
while( *(str2+j)!=' ' && *(str2+j)!='\0')
{
*(strRes+a)=*(str2+j);
j++;
a++;
}
if(flag2!=1)
{
*(strRes+a)=' ';
a++;
}
if(*(str2+j)=='\0')
flag2=1;
}while( (*(str1+i)!='\0') || (*(str2+j)!='\0') );
*(strRes+a)='\0';
}
void StrReverse(char* strRes,char* strRev)
{
int size,i=0,j=0;
size=strlen(strRes);
for(i=size-2 ; i>=0 ;i--)
{
*(strRev+j)=*(strRes+i);
j++;
}
*(strRev+size-1)='\0';
}
void GetMatrix(pArr* M ,int rows , int cols )
{
}
do you mean?
int GetMatrix( pArr* M ,int rows , int cols )
{
return 1==scanf("%d",&M[rows][cols]);
}
#define ROWS 2
#define COLS 3
typedef int pArr[COLS];
void GetMatrix(pArr* M ,int rows , int cols )
{
for(int i = 0; i < rows; i++)
for(int j = 0; j < cols; j++)
scanf("%d", &(M[i][j]));
}
int main()
{
int M[ROWS][COLS] = {{100, 101, 102},{103, 104, 105}};
printf("before\n");
for(int i = 0; i < ROWS; i++){
for(int j = 0; j < COLS; j++)
printf("%d ", M[i][j]);
printf("\n");
}
printf("enter values\n");
GetMatrix(M, ROWS, COLS);
printf("after\n");
for(int i = 0; i < ROWS; i++){
for(int j = 0; j < COLS; j++)
printf("%d ", M[i][j]);
printf("\n");
}
}
Output:
before
100 101 102
103 104 105
enter values
0 1 2 3 4 5
after
0 1 2
3 4 5
Inside the function, M is a pointer to an array of three integers. M[i] is the i-th array, and M[i][j] is the j-th element in the i-th array. & operator gives its address to the scanf, which happily stores the read number in there.
Here is what happens when you replace scanf("%d", &(M[i][j])); with scanf("%d",*(M+cols*i+j)):
for(int i = 0; i < rows; i++)
for(int j = 0; j < cols; j++)
scanf("%d", *(M + cols * i + j));
snip..
before
100 101 102
103 104 105
enter values
0 1 2 3 4 5
after
0 101 102
1 104 105
In the first iteration of the inner loop, i and j are zero, and *(M+cols*i+j) becomes *M. Since M is a pointer to an array, dereferencing it gives you an array of integers which decays into pointer to an integer. Thus the first number get stored at the correct place.
In the second iteration of the inner loop, j is 1. Thus, it is *(M + 1). Pointer arithmetic comes into picture here. Since M is a pointer to an array of three integers, (M + 1) is a pointer to an array of three integers that points to the second array; dereferencing it gives the array, which decays into pointer and scanf writes the second number there.
In the third iteration, j is 2 and (M + 2) points to the third (non existent) array and scanf writes the entered number into that memory location in the stack, thus corrupting the stack.
So on and so forth. It attempts to write into every third integer location, leaving our preinitialized values (101, 102, 104, 105) untouched.
If you want to it with pointers, you can cast M as a pointer to int as in:
scanf("%d", (int*)M + cols * i + j);
Once you cast M as int*, pointer arithmetic adds 1 * sizeof(int) to the starting position instead of 1 * sizeof(array of three ints), thus giving the desired results.
Update - answer to the comment I received in Facebook.
Consider the snippet:
int a = 10;
scanf("%d", &a);
printf("%d", a);
Scanf stores the entered value at the specified address - hence we pass a pointer to int as its argument. printf prints the passed value - hence we pass an int as the argument. The same difference applies here. ((int*)M + cols * i + j) is of type int*, pointer to an integer. To print the integer at that location we should dereference it using * operator. Thus it becomes:
printf("%d\t",*((int*)M + cols * i + j));
Oh, and by the way, you'd have received a faster reply if you had posted your doubts here itself instead of my FB. There are lots of good people ready to help hanging out in SO - and I check FB only on weekends.

Resources