My C program is ending on it's own and I can't figure out the issue. I have added a comment above the loop where it is stopping.
I am creating a program to match dna samples in arrays with each other. The dna samples are floats and I am reading them from a file.
This is the file I am reading from:
2.3 3.3 4.5 6.7 7.8 2.1 3.2 4.3 5.2 6.5
5
2.3 3.3 4.5 6.7 7.8 2.1 3.2 4.3 5.2 6.5
1.3 0.3 9.5 8.7 5.8 4.1 3.2 2.3 6.2 6.9
6.3 9.3 4.3 6.4 7.5 2.9 3.0 4.1 5.3 6.5
6.1 9.4 4.5 6.6 7.4 2.8 3.2 4.4 5.0 6.0
2.3 3.3 4.5 6.6 7.8 2.2 3.2 4.3 5.2 6.5
The expected output is all the values will be printed (5 lines for the criminal samples) and the first line will be matched and the rest will not. However this is my output:
Reading chromosomes of the suspect.
2.3 3.3 4.5 6.7 7.8 2.1 3.2 4.3 5.2 6.5
Reading chromosomes of the criminals.
2.3 3.3 4.5 6.7 7.8 2.1 3.2 4.3 5.2 6.5
1.3 0.3 9.5 8.7 5.8 4.1 3.2 2.3 6.2
I have attempted debugging it and at one point it was randomly assigning my sizeR variable to like 10000 or something during the loop and I assumed that was the problem somewhere but now it's not I'm struggling to understand why it is still stopping for me.
Code:
#include <stdio.h>
#include <stdbool.h>
FILE *fp;
int main(){
fp = fopen("dna_input.txt", "r");
int sizeR = 0, sizeC = 10; // declare size variables
float suspect[sizeC]; // declaring suspect array
float criminal[sizeR][sizeC]; // declaring criminal array
// reads 10 input values from first line of the file
printf("Reading chromosomes of the suspect. \n");
for (int i = 0; i < sizeC; i++){
fscanf(fp, " %f", &suspect[i]);
printf("%.1f ", suspect[i]);
}
printf("\n");
// reads integer from 2nd line of file for the amount of lines to read for next loop
fscanf(fp, " %d", &sizeR);
printf("Reading chromosomes of the criminals. \n");
// read 10 input values into 5 criminal arrays
// THIS LOOP IS WHERE MY PROGRAM IS STOPPING <---------------------------------------------
for (int i = 0; i < sizeR; i++){
for (int j = 0; j < sizeC; j++){
fscanf(fp, " %f", &criminal[i][j]);
printf("%.1f ", criminal[i][j]);
}
printf("\n");
}
// check for match
bool match = true;
for (int i = 0; i < sizeR; i++){
for (int j = 0; j < sizeC; j++){
if (suspect[j] != criminal[i][j]){
match = false;
}
}
// display matching result
if (match)
printf("The two profiles match! \n");
else
printf("The two profiles don't match! \n");
}
fclose(fp);
return 0;
}
You need to dynamically allocate the criminals array.
//Here sizeR is 0 so you are declaring criminal[0][10]
float criminal[sizeR][sizeC]; // declaring criminal array
Typical buffer overflow problem.
Thank you for the comments, I missed that completely. I've moved my criminal array to be declared after the fscanf
// reads integer from file for the amount of lines to read
fscanf(fp, " %d", &sizeR);
// declare criminal aray
float criminal[sizeR][sizeC];
Related
For a terminal application written in C I need to plot (in the terminal) two tables as line plots. To do this I use (following e.g. gnu tutorial)
FILE *gnuplot = popen("gnuplot", "w");
...
fprintf(gnuplot, "plot '-' u 1:2 t 'data1' w lp lt 0\n");
for (int i = 0; i < lines; ++i) {
fprintf(gnuplot,"%f %f \n", x[i] - x[0], y[i]);
}
fprintf(gnuplot, "\n");
fprintf(gnuplot, "t 'data2' lt 2\n");
for (int i = 0; i < lines; ++i) {
fprintf(gnuplot,"%f %f \n", x[i] - x[0], 0.4*(x[i] - c0)/c1);
}
fprintf(gnuplot, "e\n");
fflush(gnuplot);
The problem is that the data is plotted as one data block instead of two different ones. I expected to have a separation by using the line
fprintf(gnuplot, "t 'data2' lt 2\n");
which seems not to be the case. What is wrong in this code?
You probably want to do the following. Each inline data has to be terminated by an e.
In gnuplot console it would be:
plot '-' u 1:2 t 'data1' w lp lt 0, '' u 1:2 t 'data2' lt 2
1 0.1
2 0.2
3 0.3
4 0.4
e
11 0.5
12 0.6
13 0.7
14 0.8
e
Check help inline data and help special-filenames.
Although, to my opinion it is a bit confusing and suitable examples are missing. Maybe you can find them elsewhere.
I've been working on an assignment for school, basically we're creating 2 arrays of random doubles, then sorting them using 3 different algorithms and printing the results. The output needs to be printed with 5 elements per line.
I've got this code:
//print sorted arrayB
for (i = 0; i < size; i++)
{
printf ("%.1lf ", arrayB[i]);
if (i % 5 == 0 && i > 0)
{
printf ("\n");
}
}
where all variables are defined before the sort, and my output looks like this every time:
1.0 2.0 3.0 4.0 5.0 6.0
7.0 8.0 9.0 10.0 11.0
12.0 13.0 14.0 15.0 16.0
17.0 18.0 19.0 20.0 21.0
etc...
I don't understand why it's printing 6 elements in the top row, and 5 in all the rest. Any help is greatly appreciated!
Just write the evaluation by hand for your conditional:
if (i % 5 == 0 && i > 0)
i result
0 false
1 false
2 false
3 false
4 false
5 true
6 false
Now we can see that it is false 5 times, then true, which makes it print a newline, but only after you printed the number!
So you need to rearrange your logic slightly, but the conditional is correct.
The point is in the && i > 0 part of the if statement. If you'd remove it, this would be the output:
1.0
2.0 3.0 4.0 5.0 6.0
7.0 8.0 9.0 10.0 11.0
12.0 13.0 14.0 15.0 16.0
17.0 18.0 19.0 20.0 21.0
etc...
By excluding zero, you have prevented printing the newline after the first number, see?
The solution is to move the i index by one, like this:
if ((i + 1) % 5 == 0)
{
printf ("\n");
}
Now you don't even need the && i > 0 part, because i + 1 will never be zero.
You need to update the \n condition as below -
if ((i+1) % 5 == 0)
{
printf ("\n");
}
i % 5 will cause newlines after indices 5,10,15... This is your case where you have 6 at index 5, 11 at index 10..
Rather you need to break at 4,9,14... which are all covered by (i+1).
Just add 1 to i(therefore the condition i > 0, becomes unnecessary), which will solve. This occurs because in the condition imposed by you, for the first line break (\ n) to occur, it will have to go from 0 to 5, and to do so you will have to repeat the loop 6 times, so on the first line it showed 6 numbers , instead of 5
Like this:
#include <stdio.h>
#define SIZE 25
int main() {
int i, arrayB[SIZE] = {0};
for (i = 0; i < SIZE; i++)
{
printf ("%.1lf ", arrayB[i]);
if ((i+1) % 5 == 0)
{
printf ("\n");
}
}
return 0;
}
The program I am making must store the values in the text file on their respective variables. The problem seems to arise in the inner loop. I have the respective structs already defined. The program runs properly for the outer loop but when it proceeds in the inner loop, the file pointer does not read the proper values from the text file and outputs "0.0" and does not proceed with the processes from the outer loop altogether.
my input file looks something like this:
GENERAL
1 4
PANELS
1 2.1 3.1 4.1 5.1 6.1 7.1 1
2 2.2 3.2 4.2 5.2 6.2 7.2 2
1 2.21 3.21 4.21 5.21
2 2.22 3.22 4.22 5.22
3 2.3 3.3 4.3 5.3 6.3 7.3 0
4 2.4 3.4 4.4 5.4 6.4 7.4 4
1 2.41 3.41 4.41 5.41
2 2.42 3.42 4.42 5.42
3 2.43 3.43 4.43 5.43
4 2.44 3.44 4.44 5.44
MATERIAL
1 1000.0 2000.0 3000.0 4000.0
2 1010.0 2020.0 3030.0
3 1010.1 2020.2
CHB
1 10 20 30 2
2 11 22 33 1
these are just placeholders to see if they are stored. single digits are integers while floats have decimal points.
here is the code
typedef struct _open
{
int id;
double length;
double height;
double origX;
double origY;
int frames;
double thickness;
double E;
double v;
}CHBOpening;
typedef struct _panels
{
int id;
double length;
double height;
double origX;
double origY;
double origZ;
double angle;
int nOpenings;
int nReinforcement;
double *xReinf;
double sx;
double xReinf0;
CHBUnit *chb;
CHBOpening *openings[];
}CHBPanel;
typedef struct _chb
{
int nStories;
int nModes;
int nIter;
int nPanels;
CHBPanel *panels[];
}CHBStructure;
int ReadPanelBlock (FILE *fp, CHBStructure *S)
{
int i,j;
S->panels = malloc(S->nPanels*sizeof(CHBStructure));
for (i=0; i< S->nPanels; i++)
{
fscanf(fp,"%d",&S->panels[i].id);
fscanf(fp,"%lf",&S->panels[i].length);
fscanf(fp,"%lf",&S->panels[i].height);
fscanf(fp,"%lf",&S->panels[i].angle);
fscanf(fp,"%lf",&S->panels[i].origX);
fscanf(fp,"%lf",&S->panels[i].origY);
fscanf(fp,"%lf",&S->panels[i].origZ);
fscanf(fp,"%d",&S->panels[i].nOpenings);
if (S->panels[i].nOpenings > 0)
{
S->panels[i].openings = malloc(sizeof(CHBOpening)*S->panels[i].nOpenings);
for (j=0; j<S->panels[i].nOpenings;j++)
{
fscanf(fp,"%d",&S->panels[i].openings[j].id);
fscanf(fp,"%lf",&S->panels[i].openings[j].length);
fscanf(fp,"%lf",&S->panels[i].openings[j].height);
fscanf(fp,"%lf",&S->panels[i].openings[j].origX);
fscanf(fp,"%lf",&S->panels[i].openings[j].origY);
}
}
}
return 1;
}
When you allocate pannels you do
S->panels = malloc(S->nPanels*sizeof(CHBStructure));
The problem here is that you use sizeof(CHBStructure) instead of sizeof(CHBPanel). The problem with this is that sizeof(CHBStructure) < sizeof(CHBPanel), so you don't allocate enough memory for the data you read.
That will lead to writing out of bounds, and undefined behavior.
This is in addition to the "typo" in the input file, which will lead you to enter the inner loop when there's nothing to read.
I am writing some code in C to read some file data in arrays and keep getting a segmentation fault compiling with gcc. It reads the file up to 11th line of data then gives the fault. Been through some other similar questions on here but can't find a solution.
Thanks
code:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
int ainb(char a[],char b[])//returns 0 if str b contains a returns 1 otherwise
{
int i=0,j0=-1,j1=0,count=0;
if(strlen(b)<strlen(a)) {return 1;}
for(i=0;i<strlen(b);i++) {
if((b[i]==a[j1])&&(j1==j0+1)){
j0=j1;j1++;
} else {
j0=-1;j1=0;
}
if((j1+1)==strlen(a)) {break;}
}
if((j1+1)==strlen(a)){
return 0;
} else {
return 1;
}
}
void read_pdb(FILE* fp,char **atm,int *atnum,char **name,char **res,char *chain,int *resnum,double *x,double *y,double *z,double *occ,double *bfac,char **elem,double ac[2][3]) //reads file lines and stores in arrays
{
printf("\nReading pdb data\n");
int i=0,j=0;
char buff[7];
fpos_t position;
while(!feof(fp))
{
fgetpos(fp,&position);fgets(buff,sizeof buff,fp);
if((ainb("ATOM",buff)==0)||(ainb("HETATM",buff)==0))
{
fsetpos(fp,&position);printf("\ngetting position %d\n",i+1);
fscanf(fp,"%6s%5d %4s %3s %1s%4d %8lf%8lf%8lf%6lf%6lf %2s \n",atm[i],&atnum[i],name[i],res[i],&chain[i],&resnum[i],&x[i],&y[i],&z[i],&occ[i],&bfac[i],elem[i]);
printf("\nnode %d data found\n",i+1);
printf("\n%6s%5d %4s %3s %1s%4d %8.3lf%8.3lf%8.3lf%6.2lf%6.2lf %2s \n",atm[i],atnum[i],name[i],res[i],&chain[i],resnum[i],x[i],y[i],z[i],occ[i],bfac[i],elem[i]);
if(ainb("HETATM",atm[i])==0){
ac[j][0]=x[i];ac[j][1]=y[i];ac[j][2]=z[i];j++;
}
i++;
}
}
printf("\n%d Atoms read\n",i);
}
void main()
{
double ac[2][3];
int N,k;
double *x,*y,*z,*occ,*bfac;
char **atm,**name,**res,**elem,*chain;
int *atnum,*resnum;
FILE *out;
out=fopen("OUT.pdb","r");//something to check for file
N=66;
//make dynamic arrays
x=(double*)malloc(N*sizeof(double));
y=(double*)malloc(N*sizeof(double));
z=(double*)malloc(N*sizeof(double));
occ=(double*)malloc(N*sizeof(double));
bfac=(double*)malloc(N*sizeof(double));
atnum=(int*)malloc(N*sizeof(int));
resnum=(int*)malloc(N*sizeof(int));
atm=(char**)malloc(N*sizeof(char));
name=(char**)malloc(N*sizeof(char));
res=(char**)malloc(N*sizeof(char));
elem=(char**)malloc(N*sizeof(char));
chain=(char*)malloc(N*sizeof(char));
for(k=0;k<N;k++)
{
atm[k]=(char*)malloc(7*sizeof(char));
name[k]=(char*)malloc(5*sizeof(char));
res[k]=(char*)malloc(4*sizeof(char));
elem[k]=(char*)malloc(3*sizeof(char));
}
//read in data
read_pdb(out,atm,atnum,name,res,chain,resnum,x,y,z,occ,bfac,elem,ac);
fclose(out);
printf("\n-------------------------------------------\nTest Complete\n");
free(x);
free(y);
free(z);
free(occ);
free(bfac);
free(elem);
free(name);
free(atm);
free(res);
free(resnum);
free(atnum);
free(chain);
}
The output is:
Reading pdb data
getting position 1
node 1 data found
ATOM 1 CA PRO A 1 4.612 0.903 5.089 1.00 24.97 C
getting position 2
node 2 data found
ATOM 2 CA SER A 2 3.526 0.341 3.809 1.00 59.99 C
getting position 3
node 3 data found
ATOM 3 CA ARG A 3 6.208 1.550 6.551 1.00 20.40 C
getting position 4
node 4 data found
ATOM 4 CA TRP A 4 5.912 2.348 4.388 1.00 50.28 C
getting position 5
node 5 data found
ATOM 5 CA GLE A 5 4.087 4.359 6.884 1.00 54.04 C
getting position 6
node 6 data found
ATOM 6 CA THR A 6 4.405 1.292 2.566 1.00 62.06 C
getting position 7
node 7 data found
ATOM 7 CA TYR A 7 3.327 3.041 5.205 1.00 50.46 C
getting position 8
node 8 data found
ATOM 8 CA VAL A 8 5.276 0.109 0.387 1.00 58.00 C
getting position 9
node 9 data found
ATOM 9 CA LEU A 9 2.992 3.190 3.084 1.00 41.48 C
getting position 10
node 10 data found
ATOM 10 CA CYS A 10 3.565 0.287 0.721 1.00 47.65 C
getting position 11
Segmentation fault (core dumped)
Lets consider this code:
name=(char**)malloc(N*sizeof(char));
for(k=0;k<N;k++)
{
name[k]=(char*)malloc(5*sizeof(char));
}
You allocate n*sizeof(char) array and try to store N pointers to char in it. But size of pointer to the char is greater than sizeof(char), so you get buffer overflow and undefined behavior even on the initialization stage. You are lucky and your program is not crashing at this stage, but it will fail on the array usage. To prevent this error you should use sizeof(char*) in your allocation code.
Rather than hard code the type, and get it wrong for name, let the compiler figure it out. Less code, easier to read and easier to code & maintain.
//bfac=(double*)malloc(N*sizeof(double));
//resnum=(int*)malloc(N*sizeof(int));
//name=(char**)malloc(N*sizeof(char)); OP was looking for `sizeof (char*)`
bfac = malloc(N * sizeof *bfac);
resnum = malloc(N * sizeof *resnum);
name = malloc(N * sizeof *name);
Also in C, no need to cast the result of malloc().
This is the output I expect
x |x|
1.2 1.2
-2.3 2.3
3.4 3.4
but I keep getting this:
x |x|
1.2 1.2
-2.3 2.3
3.4 3.4
Here is my part of code:
printf(" x |x|\n");
for (i = 1; i <= n; i++)
{
printf(" %.1f %.1f\n", array[i], array1[i]);
}
how do I change it?
You should specify a number before dot in %.1f that shows all the number including '-' for example:
printf("%3.1f",array[i]);
Will result in :
x |x|
1.2 1.2
-2.3 2.3
3.4 3.4
It means that a number should fill 3 places in screen.
Sorry for bad English.