I have a program (who's code is available at the bottom) which generates a list of numbers the way that I want it to. The program works fine as is and does exactly what I want. I'm just not a fan of the way I wrote it. It returns "Segmentation fault" if I change one thing, which I'll say at the bottom as well. Here's the code:
#include "stdio.h"
#include "stdlib.h"
#define NCH 81
// Generate swap-mode data for bonds for input.conf file
int main()
{
int i,j,k;
int **dat2, *dat;
//double *dat;
int ns = 500;
int nrow = NCH*(ns-1);
dat = (int*) calloc(nrow, sizeof(int));
dat2 = (int**) calloc(nrow,sizeof(int*));
for (i=0; i<nrow; i++) {
dat2[i] = (int*) calloc(2, sizeof(int));
for (j=0; j<2; j++)
dat2[i][j] = 0;
}
// Generates the bonds
k=2;
for (i=0; i<nrow; i++) {
k--;
for (j=0; j<2; j++) {
dat2[i][j] = k++;
if ( ((k%501) == 0) ) {
k--;
dat2[i][j] = k++;
k++;
}
}
}
FILE *inp2;
inp2 = fopen("bonds.out", "w");
for (i=1; i<=nrow; i++)
fprintf(inp2, "%d %d\n", dat2[i-1][0], dat2[i-1][1]);
fclose(inp2);
// Generates the bond ID in the pattern 1 2 3 3 2 1 ... (appropriate for Bond swap!)
k=1;
while ( k < nrow ) {
for (j=0; j<250; j++) {
dat[k] = (j+1);
k++;
}
for (j=250; j>0; j--) {
dat[k] = j;
k++;
}
}
// Scans bonds.out (because just reporting dat2[][] returns segmentation error, not sure why.
// scans the bonds.out file and stores both values into dm1 and dm2, then reports into 'results.out' file
int dm1, dm2;
FILE *inp;
inp = fopen("input.out", "w");
inp2 = fopen("bonds.out", "r");
for (i=1; i<=nrow; i++) {
fscanf(inp2, "%d %d", &dm1, &dm2);
fprintf(inp, "%d %d %d %d\n", i, dat[i], dm1, dm2);
}
printf("\nDone. All data has been written to \"input.out\"\n");
fclose(inp2);
fclose(inp);
return 0;
}
Now, I don't like the fact that it's first writing dat2[][] to a file and then scanning that file for the values. Why, instead, can't I incorporate dat2[][] in the main loop that writes the "results.out" file? If I do so, I get Segmentation fault. For clarification, I mean changing these lines in the code:
for (i=1; i<=nrow; i++) {
fscanf(inp2, "%d %d", &dm1, &dm2);
fprintf(inp, "%d %d %d %d\n", i, dat[i], dm1, dm2);
}
To these:
for (i=1; i<=nrow; i++) {
fprintf(inp, "%d %d %d %d\n", i, dat[i], dat2[i-1][0], dat2[i-1][1]);
}
I'd love an explanation as I'm still very new to C.
Thanks a lot!
Amit
I think you forgot to subtract 1 from the array index of dat, like this:
for (i=1; i<=nrow; i++) {
fscanf(inp2, "%d %d", &dm1, &dm2);
fprintf(inp, "%d %d %d %d\n", i, dat[i-1], dm1, dm2);
}
The reason why this causes a segfault is because you're looping until i <= nrow, which will go out of the bounds of dat on the final loop iteration.
I think there is something else on your code too besides what Relkin (correctly) pointed out.
int nrow = NCH*(ns-1);
dat = (int*) calloc(nrow, sizeof(int));
If my calculations are right, nrow == 81*(500-1) (== 40419) so it is dat[40419]
On the following explosive algorithm :
k=1;
while ( k < nrow ) {
for (j=0; j<250; j++) {
dat[k] = (j+1);
k++;
}
for (j=250; j>0; j--) {
dat[k] = j;
k++;
}
}
Every internal for loop increases k by 250 (so both increase it by 500 for every while loop), while k < 40419. This means there is a point where k reaches 40001, the condition is satisfied and the loop goes one more. At this moment, on the second for loop you exceed 40419 and write in memory you shouldn't. Take a look at that and check my maths again plz.
Once you are inside the while loop, and the condition falsifies, this does not mean the loop will automatically exit.
Related
So, I'll preface this by saying I'm fairly new to pointers and dynamic allocation. Currently I am trying to store a file that contains a 3x3 matrix of ints into a 2d array. I've tried debugging my code and what I notice is that it reads my first 2 values, but than begins to generate random garbage into my 2d array. I assume that I am storing my ints incorrectly and there is a flaw in my logic, but as I keep trying to think about it, I can't seem to find where it could be incorrect as they are moving from [0][0], [0][1], etc.
Here is my code for reference. Thanks, I'd appreciate just some guidance on how I can troubleshoot this problem for this specific case and future issues.
#include <stdio.h>
#include <stdlib.h>
int main() {
FILE* fpM1;
fpM1 = fopen("m1.txt", "r");
int i, j, row1 = 2, col1 = 2;
int* ptrM1 = (int* )malloc(9 * sizeof(int));
if (fpM1 != NULL) {
for (i = 0; i < row1; i++) {
for (j = 0; j < col1; j++) {
fscanf(fpM1, "%d", ((ptrM1 + i) + j));
}
}
for (i = 0; i < row1; i++)
for (j = 0; j < col1; j++) {
{
printf(" %d", *((ptrM1 + i) + j));
}
}
}
free(ptrM1);
fclose(fpM1);
return 0;
}
Your for loops end too fast. You should use <= instead of <. After that, everything seems to work perfectly.
Maybe you should consider adding new line in outer for loop during printing array. It will help with clarity:
for (i = 0; i < row1; i++) {
for (j = 0; j < col1; j++) {
printf(" %d", *(ptrM1 + i));
}
printf("\n");
}
Also you don't need those double brackets before first printf statement. In C you can put many scopes without context, but you shouldn't do that without reason.
EDIT: It actually doesn't work. Reading from file should be done this way:
fscanf(fpM1, "%d", ptrM1 + (i * (col1 + 1) + j));
and printing:
printf(" %d", ptrM1[i * (col1 + 1) + j]);
I was reading the book "Computer Organization and Design" by Patterson and Hennesy (5th Edition) and found this bubble sort code:
void sort (int v[], int n)
{
int i,j;
for (i=0; i<n; i+=1) {
for (j = i-1; j>=0 && v[j] > v[j+1]; j+=1) {
swap(v,j);
}
}
}
void swap (int v[], int k) {
int temp;
temp = v[k];
v[k] = v[k+1];
v[k+1] = temp;
}
I don't understand how this function would sort an array. Especially if the first element of the array is also the largest, it seems to me that the index j would go out of bounds. Running the code and printing the indices confirmed this.
This is the code I used:
#include <stdio.h>
void swap (int v[], int k) {
int temp;
temp = v[k];
v[k] = v[k+1];
v[k+1] = temp;
}
void sort (int v[], int n)
{
int i,j;
for (i=0; i<n; i+=1) {
printf("%d \n", i);
for (j = i-1; j>=0 && v[j] > v[j+1]; j+=1) {
printf("%d, %d \n", i, j);
swap(v,j);
}
}
}
int main() {
int x[3] = {5,1,2};
int N = 3;
sort(x, N);
for(int i = 0; i < 3; i++) {
printf("%d ", x[i]);
}
return 0;
}
This was the result:
/Users/mauritsdescamps/Desktop/test/cmake-build-debug/test
0
1
1, 0
1, 1
1, 2
1, 3
1, 4
2
2, 1
2, 2
2, 3
Process finished with exit code 6
Is there something I am forgetting? If not, I think there must be a mistake in the second loop condition. I have seen other implementations of the algorithm but I want to know how to get this approach to work.
I've tried this code, too. I have compiled it with GCC and somehow it worked for me (the exit status of the program was 0 and the array was sorted correctly). But I also think that their is a problem with the second loop. I would change the j+= 1 instruction into j-=1. Otherwise the second loop could end in an infinite loop. Additionally I would change the i=0 instruction in the first loop into a i=1 instruction, because it would end in an unnecessary iteration.
I am writing a program that opens numerous text files and reads from them parameters for planetary bodies. I have a problem when reading the text files.
sample text file
2
1, 1, 2
3.5, 3, 4
The first number (2) refers to the number of bodies found in the file. The next 2 lines correspond to the planet's parameters (x and y coordinates and mass respectively). I have 4 text files containing different amounts of bodies and need to store all the data in a variable.
my code
struct body {
float x;
float y;
float mass;
};
int main()
{
struct body b[8];
FILE *fp;
int i, j, k;
int num, count = 0;
char fName[10];
for (i = 1; i < 5; i++)
{
sprintf(fName,"bodies%d.txt",i);
fp = fopen(fName, "r");
if (fp == NULL)
{
printf("Can't open %s \n",fName);
exit(-1);
}
fscanf(fp, "%d", &num);
for (j = count; j < num; j++)
{
fscanf(fp, "%f%*c %f%*c %f%*c", &b[j].x, &b[j].y, &b[j].mass);
printf("%f %f %f\n", b[j].x, b[j].y, b[j].mass);
count = j;
}
}
It is reading the numbers from the text files, but it is stopping after 6 readings and there are 8 in total.
What could be the problem?
Your code has some problems:
fName is declared as
char fName[10];
and you use
sprintf(fName,"bodies%d.txt",i);
which writes 12 characters into fName(including the NUL-terminator) which can atmost hold 9 characters(+1 for the NUL-terminator).
The for loop:
for (j = count; j < num; j++)
{
fscanf(fp, "%f%*c %f%*c %f%*c", &b[j].x, &b[j].y, &b[j].mass);
printf("%f %f %f\n", b[j].x, b[j].y, b[j].mass);
count = j;
}
has many problems and is confusing too. When you do j = count, you check j < num. This makes no sense as count is not related to num.
Fixes:
For the first problem, allocate enough space for fName:
char fName[12];
instead of
char fName[10];
As for the second problem, use
for (j = 0; j < num; j++) //j should be initialized to 0
{
fscanf(fp, "%f%*c %f%*c %f%*c", &b[count].x, &b[count].y, &b[count].mass);
printf("%f %f %f\n", b[count].x, b[count].y, b[count].mass); //Use b[count] instead of b[j]
//count = j; Works, but the below is better
count++;
}
Try replacing j = count with j = 0 in the second for loop.
Ok, so I'm writing a program to make a 10 x 10 array filled with random numbers between 0 & 9, and (with each step organized into a function):
(a) sum the first row and print it out
(b)print out average of main diagonal (top to bottom, left to right)
(c)print out how many 0's are in the first column
(d)make more 10 x 10 arrays with random numbers between 0 & 9 and if all the values in the main
diagonal (top to bottom, left to right) are 7 or greater, print out the array, and the
amount of tries it took. If it can't do it in 1,000,000 attempts, print that it could not
be done.
(e)make a 1D dynamically allocated array containing 10 numbers between -10 & +10, multiply by
the first array made and display the resulting vector
Can't figure out what's not making it work, getting the wrong values for all the steps when they're printed out :'( and some errors
void simple_array(int ten_by_ten[10][10])
{
int i, j;
printf("\n");
for (i=0; i<10; ++i)
{
for (j=0; j<10; ++j)
{
ten_by_ten[i][j] = rand() % 10;
printf("%d ", ten_by_ten[i][j]);
}
printf("\n");
}
}
void sum_first_row(int y[10][10])
{
int i = 0, j, sum_row = 0;
for (j=0; j<10; ++j)
{
sum_row += y[i][j];
}
printf("\nThe sum of the first row is: %d\n", sum_row);
}
void average_main_diagonal(int z[10][10])
{
int i, j = 0, average_diagonal = 0;
for (i=0; i<10; ++i)
{
++j;
average_diagonal += z[i][j];
}
printf("\nThe average of the diagonal is: %lf\n", (average_diagonal / 10.0));
}
void zeros(int a[10][10])
{
int i, j = 0, zeroz = 0;
for (i=0; i<10; ++i)
{
if (a[i][j] == 0)
++zeroz;
}
printf("\nThere are %d zero's in the first column\n", zeroz);
}
void multiple_arrays()
{
int sum_diagonal = 0,array[10][10], i, j, k, l, c;
while ((sum_diagonal < 70) && (c <= 1000000))
{
j = 0;
k = 0;
l = 0;
i = 0;
for (i=0; i<10; ++i)
{
for (j=0; j<10; ++j)
{
array[i][j] = rand() % 10;
}
}
for (k=0; k<10; ++k)
{
++l;
sum_diagonal += array[k][l];
}
++c;
}
if (c = 1000000)
printf("\nCould not get a diagonal with numbers >= 7\n");
else
{
j = 0;
i = 0;
for (i=0; i<10; ++i);
{
printf("\n");
for (j=0; j<10; ++j)
printf("%d ", array[i][j]);
}
printf("It took %d many tries to get a diagonal with all numbers >= 7", c);
}
}
void array_multiplication(int b)
{
int **arrays, i, j, k, l, m, prod[10];
arrays = (int **) calloc (10, sizeof(int *));
for (i=0; i<10; ++i)
arrays[i] = (int *) calloc (1, sizeof(int));
for (i=0; i<10; i=i+1)
{
arrays[i] = (rand() % 21) -10;
}
for (k=0; k<10; ++k)
{
prod[k] = 0;
for (l=0; l<10; ++l)
prod[k] = prod[k] + b[k][l] * arrays[l];
}
printf ("The product is: <");
for (m=0; m<10; ++m)
printf ("%d, ", prod[m]);
printf (">\n");
}
int main()
{
int x[10][10];
simple_array(x);
sum_first_row(x)
average_main_diagonal(x);
zeros(x);
multiple_arrays();
array_multiplication(x);
return (0);
}
Getting the following errors:
When I comment out the "array multiplication" function (because it's getting the following errors: (a) assignment makes pointer from integer without cast "arrays[i] = (rand() % 21) -10;" (b) value is neither array nor pointer "prod[k] = prod[k] + b[k][l] * arrays[l];" (c) passing arg1 of "array_multiplication" makes integer from pointer without cast "array_multiplication(x);"
and it prints out an incorrect average of the diagonal
Help is Extremely appreciated!!!
Thanks,
--Rob
arrays[i] = (rand() % 21) -10; : arrays[i] is a pointer. You can't assign an integer to a pointer. Actually you just assigned some allocated memory to arrays[i] on the previous line, so even if this worked you would leak that memory.
Maybe you meant to have two nested loops, if you want to put a value in every row and every column?
Also you never free the memory you calloc'd. And don't cast the value returned by calloc either.
The other errors, you meant to declare your function as
void array_multiplication(int b[10][10])
instead of (int b). It is complaining that you are doing array operations on an int.
Your code that looks at the diagonals is incorrect (which you knew). You are incrementing "j" before using it...and so "i" is 0 and "j" is 1...which is not the diagonal. You either need to do your "++j" AFTER using it to look up the value....but would be better suited to just use z[i][i] (use "i" for BOTH indices).
This problem happens in both average_main_diagonal and multiple_arrays.
I am trying to create a matrix in C in order to solve the LaPlacian
However, this is going wrong. I have located the problem at the initialisation stage of the matrix. Every time the program is run, it places a seemingly random value in one element. This number changes each time suggesting an instability in the code, and happens if the matrix is made to be greater than 9x9.
Why could this be happening?
Thanks
The code I am using to show the matrix is:
// create matrix
double mat[meshno][meshno] = { {0} }; // x direction defined by i, y by j
//variables
int i, j, k;
//print initial matrix
for (i=0;i<=meshno;i++)
{
for(j=0;j<= meshno;j++)
{
printf("%f ", mat[i][j]);
}
printf("\n");
}
You are looking at an element past the end of each array.
Your for loops should use < and not <=:
for (i = 0; i < meshno; ++i)
{
for(j = 0; j < meshno; ++j)
{
Change to
for (i=0; i< meshno;i++)
{
for(j=0; j< meshno;j++)
{