value in loop doesnt return - c

i have this data in file
ATOM 1 N MET A 1 25.909 16.164 -8.037
ATOM 2 CA MET A 1 25.498 14.786 -8.206
ATOM 3 C MET A 1 26.612 13.934 -8.806
ATOM 4 O MET A 1 27.442 14.402 -9.588
this is my full code
#include<stdio.h>
#include<math.h>
typedef struct prot {
char atom[10];
int atomno;
char site[10];
char residue[10];
char chain;
int residueno;
float x, y, z;
} Td;
int main()
{
FILE*fd;
fd=fopen("2zoi.pdb","r+");
Td data[1300];
char buffer[1300];
int a=0;
while(fgets(buffer, 1300, fd))
{
sscanf(buffer, "%s %d %s %s %c %d %f %f %f",data[a].atom,&data[a].atomno,data[a].site,
data[a].residue,&data[a].chain,&data[a].residueno,&data[a].x, &data[a].y, &data[a].z);
printf("%s %d %s %s %c %d %6.3f %6.3f %6.3f \n",data[a].atom,data[a].atomno,data[a].site,
data[a].residue,data[a].chain,data[a].residueno,data[a].x, data[a].y, data[a].z);
a++;
}
//---user input
int fr,sr;
int fa,sa;
int i=0;
float x1,x2,y1,y2,z1,z2;
float distance=0;
printf("Enter first no of atom :");
scanf("%d",&fa);
printf("Enter second no of atom :");
scanf("%d",&sa);
while(data[i].atomno>=0)
{
if(fa==data[i].atomno)
{
x1=data[i].x;
y1=data[i].y;
z1=data[i].z;
}
else if(sa==data[i].atomno)
{
x2=data[i].x;
y2=data[i].y;
z2=data[i].z;
}
i++;
}
printf("%f %f %f",x1,y1,z1);
printf("%f %f %f",x2,y2,z2);
//distance= sqrt(pow((x2 - x1), 2) + pow((y2 - y1), 2) + pow((z2 - z1), 2));
//printf("%6.3f",distance);
return 0;
}
the problem is at this part
printf("%f %f %f",x1,y1,z1);
printf("%f %f %f",x2,y2,z2);
i try to return to values from above loop where the value for x1,y1,z1 is for the first atom and x2,y2,z2 for second atom.
when i input 3 and 4, it gives answer
26.612 13.934 -8.806
27.442 14.402 -9.588
which is correct. but when i input 1 and 2, it gives rubbish answer. it seems like i cant input number 2 also number 10.did i do any mistake?

You have a big problem with data array values: not all elements of the array are set to 0 then the final loop can be broken.
You can use memset to reset to 0 all bytes of data array.
#include<stdio.h>
#include<math.h>
#include <string.h>
typedef struct prot
{
char atom[10];
int atomno;
char site[10];
char residue[10];
char chain;
int residueno;
float x, y, z;
} Td;
int main()
{
FILE*fd;
Td data[1300];
char buffer[1300];
size_t a=0;
fd=fopen("2zoi.pdb","r+");
if (fd != NULL)
{
memset(data, 0x00, sizeof(data));
while ((fgets(buffer, 1300, fd)) && (a < sizeof(data)/sizeof(data[0])))
{
sscanf(buffer, "%s %d %s %s %c %d %f %f %f",data[a].atom,&data[a].atomno,data[a].site,
data[a].residue,&data[a].chain,&data[a].residueno,&data[a].x, &data[a].y, &data[a].z);
printf("%s %d %s %s %c %d %6.3f %6.3f %6.3f \n",data[a].atom,data[a].atomno,data[a].site,
data[a].residue,data[a].chain,data[a].residueno,data[a].x, data[a].y, data[a].z);
a++;
}
//---user input
int fr,sr;
int fa,sa;
size_t i=0;
float x1,x2,y1,y2,z1,z2;
float distance=0;
printf("Enter first no of atom :");
scanf("%d",&fa);
printf("Enter second no of atom :");
scanf("%d",&sa);
while ((data[i].atomno>=0) && (i < sizeof(data)/sizeof(data[0])))
{
if(fa==data[i].atomno)
{
x1=data[i].x;
y1=data[i].y;
z1=data[i].z;
}
else if(sa==data[i].atomno)
{
x2=data[i].x;
y2=data[i].y;
z2=data[i].z;
}
i++;
}
printf("%f %f %f\n",x1,y1,z1);
printf("%f %f %f\n",x2,y2,z2);
}
else
{
fprintf(stderr, "Error opening file\n");
exit(1);
}
return 0;
}
You should check the fopen return value (as you can see in code posted), but as a standard rule: you should always check functions return values.

Related

Struggling to search an array of structs in a file by integer

I'm in the middle of a major assignment and I'm really struggling to be able to pull a structure from an array in a file. I'm not sure where to go from here in my code as I don't have much experience working with C.
I am trying to search the file looking for "Robot_Number" (integer to far left) then print all of that specific robots information. My code compiles and runs but won't print anything from the while loop (Ln57-66). There are also no apparent problems with the .txt file.
My .txt file is laid out like this:
1 Bender 2054 30.500000 80 60 0.000000
2 Crusher 1979 15.000000 86 80 0.000000
3 Sprinter 2042 45.000000 41 30 0.000000
4 Vulc4n 2178 47.000000 90 50 0.000000
My code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define RobMax 10
typedef struct {
int Robot_Number;
char Robot_Name[20];
int Year_Manufactured;
float Top_Speed;
int Strength;
int Mass;
float Best_Score;
}robot_t;
int main(){
int targetNumber;
int RobCounter = 4;
//create an array of struct,
robot_t robot_info[RobCounter] =
{{1, "Bender", 2054, 30.5, 80, 60, 0},
{2, "Crusher", 1979, 15, 86, 80, 0},
{3, "Sprinter", 2042, 45, 41, 30, 0},
{4, "Vulc4n", 2178, 47, 90, 50, 0}};
//opening a file for reading and writing
FILE* file =fopen("Robot.txt", "r+w");
if(file ==NULL){
printf("ERROR: file failed to open!\n");
exit(-1);
}
/*//Initialising the .txt file, first time only
for (i=0; i<4; i++){
fprintf(file, "%d %s %d %f %d %d %f\n",
robot_info[i].Robot_Number,
robot_info[i].Robot_Name,
robot_info[i].Year_Manufactured,
robot_info[i].Top_Speed,
robot_info[i].Strength,
robot_info[i].Mass,
robot_info[i].Best_Score);
}*/
printf("you selected search a robot by number. (Type 0 to view all avalible robots)\n");
scanf("%d", &targetNumber);
int RNo, YM, S, M;
char RNa[20];
float TS, BS;
if (targetNumber != 0){
printf("Robot ID: %d's information:\n", targetNumber);
while( fscanf(file, "%d%19s%d%f%d%d%f", &RNo, RNa, &YM, &TS, &S, &M, &BS) ==2) {
robot_info[targetNumber].Robot_Number = RNo;
strcpy(robot_info[targetNumber].Robot_Name, RNa);
robot_info[targetNumber].Year_Manufactured = YM;
robot_info[targetNumber].Top_Speed = TS;
robot_info[targetNumber].Strength = S;
robot_info[targetNumber].Mass = M;
robot_info[targetNumber].Best_Score = BS;
printf("Num: %d, Name: %19s, Manufactured: %d, Top Speed: %f, Strength: %d, Mass: %d, Best Score: %f.", RNo, RNa, YM, TS, S, M, BS);
}
}
fclose(file);
return 0;
}
Some notes to consider, as stated in the comment section, too:
Why do you have an array of structs with robot info, when you intend to read them from a file?
Why open the file with r+w when you're really just reading from it?
So lets suppose, that you do not have those information about the robots and you only want to read the file. If this was the original intent, here is a snippet, that'll probably help you.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define RobMax 10
typedef struct {
int Robot_Number;
char Robot_Name[20];
int Year_Manufactured;
float Top_Speed;
int Strength;
int Mass;
float Best_Score;
}robot_t;
int scan_file(const char* fname, robot_t* robot_info, const int N)
{
int counter = 0;
// opening a file for reading
// Note the change in file open mode as you
// do not need to write it
FILE* file = fopen(fname, "r");
if(file == NULL)
{
printf("ERROR: file failed to open!\n");
return 0;
}
int RNo, YM, S, M;
char RNa[20];
float TS, BS;
// Note the change in scan format - you need to include the correct delimiters
// in your case the white spaces. Also changed 2 -> 7 as you'd expect 7 values
// to be read and not 2
int scanres;
while((scanres = fscanf(file, "%d %19s %d %f %d %d %f", &RNo, RNa, &YM, &TS, &S, &M, &BS)) == 7 && scanres != EOF)
{
// if we reached maximum capacity
if (counter >= N)
break;
robot_info[counter].Robot_Number = RNo;
strcpy(robot_info[counter].Robot_Name, RNa);
robot_info[counter].Year_Manufactured = YM;
robot_info[counter].Top_Speed = TS;
robot_info[counter].Strength = S;
robot_info[counter].Mass = M;
robot_info[counter].Best_Score = BS;
printf("SCANNED: Num: %d, Name: %19s, Manufactured: %d, Top Speed: %f, Strength: %d, Mass: %d, Best Score: %f.\n", RNo, RNa, YM, TS, S, M, BS);
++counter;
}
fclose(file);
return counter;
}
// gets the robot's index in the robots array by ID
int get_roboti_by_id(const int ID, const robot_t* robots, const int N)
{
for (int i = 0; i < N; ++i)
{
if (robots[i].Robot_Number == ID)
{
return i;
}
}
return -1;
}
void print_info(const robot_t* info)
{
printf("Num: %d, Name: %19s, Manufactured: %d, Top Speed: %f, Strength: %d, Mass: %d, Best Score: %f.",
info->Robot_Number, info->Robot_Name, info->Year_Manufactured, info->Top_Speed, info->Strength, info->Mass, info->Best_Score);
}
int main()
{
int targetNumber;
int RobCounter;
// create an array of struct,
robot_t robot_info[RobMax];
printf("you selected search a robot by number. (Type 0 to view all avalible robots)\n");
scanf("%d", &targetNumber);
// scans the whole file populated with robots
RobCounter = scan_file("robots.txt", robot_info, RobMax);
if (targetNumber != 0)
{
int robot_index = get_roboti_by_id(targetNumber, robot_info, RobCounter);
if (robot_index >= 0)
{
print_info(&robot_info[robot_index]);
printf("\n");
}
else
{
printf("There is no such robot with index: %d\n", targetNumber);
}
}
else
{
for (int i = 0; i < RobCounter; ++i)
{
print_info(&robot_info[i]);
printf("\n");
}
}
return 0;
}
If you spot any mistakes or this was not what you needed, please do not hesitate to correct me. Any suggestions are appreciated!

Getting Array Input From Command Line

I am using the command line to get input of 3 floats separated by spaces. e.g. "1.234 5.678 9.012".
I am currently using:
float xyz[3] = {0};
scanf("%f", xyz);
print(%f %f %f, xyz[0], xyz[1], xyz[2]);
However the output is "1.234000 0.000000 0.000000".
Expected output is "1.234000 5.678000 9.012000"
EDIT: I need to use floats instead of integers.
Maybe this
#include <stdio.h>
int main(int argc, char** argv)
{
float vals[3];
printf("input 3 float values: ");
int res = scanf("%f %f %f", &vals[0], &vals[1], &vals[2]);
if(res == 3)
{
printf("read 3 floats %f %f %f\n", vals[0], vals[1], vals[2]);
} else
{
printf("failed to read 3 float values\n");
}
return 0;
}
If you use command line arguments , simply try like
#include<stdio.h>
#include<stdlib.h>
main(int c, char **v)
{
float xyz[3]={0};
xyz[0]=atof(v[1]);
xyz[1]=atof(v[2]);
xyz[2]=atof(v[3]);
printf("%f %f %f\n",xyz[0],xyz[1],xyz[2]);
}

Reading from a File to an Array - C

int main()
{
FILE* infile1;
int stockCode[15];
char stockName[100];
int stockQuantity[15];
int stockReorder[15];
int unitPrice[15];
int i;
infile1 = fopen("NUSTOCK.TXT", "r");
while(fscanf(infile1, "%d %s %d %d %f",
&stockCode, stockName, &stockQuantity, &stockReorder, &unitPrice) != EOF)
{
printf(" %3d %-18s %3d %3d %6.2f \n",
stockCode, stockName, stockQuantity, stockReorder, unitPrice);
}
fclose(infile1);
}
What I'm trying to do is to take information from a file and store it into 5 separate arrays. However, when printing out, it only prints out the name correctly.
1394854864 Prune-Basket 1394854688 1394854624 0.00
1394854864 Pear-Basket 1394854688 1394854624 0.00
1394854864 Peach-Basket 1394854688 1394854624 0.00
1394854864 Deluxe-Tower 1394854688 1394854624 0.00
The original file looks like this. So all the numbers aren't being scanned in and I can't figure out why...
101 Prune-Basket 065 060 25.00
105 Pear-Basket 048 060 30.00
107 Peach-Basket 071 060 32.00
202 Deluxe-Tower 054 040 45.00
I think what you want to do is designing a structure for saving many personal records.
And each record contain:
code
name
quantity
reorder
unitPrice
You should know the meaning of each type in C language.
I suggest you rewrite your codes like these:
#include <stdio.h>
#include <stdlib.h>
struct OneRecord{
int code;
char name[100];
int quantity;
int recorder;
float unitPrice;
};
int main(){
struct OneRecord* records = (struct OneRecord*)calloc(15, sizeof(struct OneRecord));
int i = 0;
FILE* infile1 = fopen("NUSTOCK.TXT", "r");
int max=0;
//%99s is used for max string length, because of we can protect the out of string's memory length
while((max<15)&&(fscanf(infile1, "%d %99s %d %d %f",
&records[i].code, records[i].name, &records[i].quantity, &records[i].recorder, &records[i].unitPrice) == 5))
{
i++;
max++;
}
for(i=0;i<max;i++){
printf(" %3d %-18s %3d %3d %6.2f \n",
records[i].code,records[i].name,records[i].quantity,records[i].recorder,records[i].unitPrice);
}
fclose(infile1);
free(records);
}
And how to use the C Structure in functions or many other places?
In C programming language, there are different types such as int, char, struct and so on. You can use struct like many other types.
void printRecords(const struct OneRecord* records, int max)
{
int i;
for(i=0;i<max;i++){
printf(" %3d %-18s %3d %3d %6.2f \n",
records[i].code,records[i].name,records[i].quantity,records[i].recorder,records[i].unitPrice);
}
}
You are using those arrays incorrectly. Try this:
i = 0;
while(fscanf(infile1, "%d %s %d %d %f",
stockCode+i, stockName, stockQuantity+i, stockReorder+i, unitPrice+i) != EOF)
{
printf(" %3d %-18s %3d %3d %6.2f \n",
stockCode[i], stockName, stockQuantity[i], stockReorder[i], unitPrice[i]);
i++;
}
Also, the unitPrice should be a array of float, not of int.

exact multiple scanf input

I'm wondering on how to basically input exactly 5 numbers (integers specifically) in one line using simple commands such as while, if and arrays. For example:
if I input 5 numbers separated by spaces,
1 2 3 4 5
program would print
1 2 3 4 5
but, If I input less than 5 or more than 5,
1 2 3 4
program would print
invalid input.
So far I have
#include<stdio.h>
int main(int argc,char *argv[]){
int array[5], numbers;
numbers = 0;
while (numbers < 5) {
scanf("%d", &array[numbers]);
numbers = numbers + 1
}
printf("%d %d %d %d %d\n", array[0], array[1], array[2], array[3], array[4]);
return 0;
}
What about if we assign all the array cell with 9999 (a number not used by the program). And we make a loop to check that each array has been changed to a new value and if its still 9999 it would be invalid. But problem here still lies, how would we just grab one line of different number of input and move on. E.g input 2 3
Output 2 3 9999 9999 9999
Or input 2 3 4
Output 2 3 4 9999 9999
If you want to force the input to be on one line, first read the input and then parse it:
char line[100];
fgets(line, 100, stdin);
char x[100];
int n = sscanf(line, "%d %d %d %d %d %s", array, array+1, array+2, array+3, array+4, x)
if (n != 5)
printf("invalid input\n");
else
printf("read 5 numbers\n");
The x is added to detect if too much was read.
EDIT
To enter 5 numbers you may use
int a[5];
char x;
scanf("%d %d %d %d %d", &a[0], &a[1], &a[2], &a[3], &a[4]);
while(scanf("%*[^\n]%*c")) {
scanf("%c", &x); // after 5 ints were loaded, get rid of rest of the elements untill new line symbol
}
printf("%d %d %d %d %d\n\n", a[0], a[1], a[2], a[3], a[4]);
It will ignore everything after 5 numbers (in fact, it will write to x untill new line symbol appears), but there is no way to easily set number of numbers to read in this case.
You just have to note it will not work if you have less than 5 ints in line.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int intRead(int array[], int size){
char buff[128];
int status=!0;//status == 0, Something happened!
printf("\ninput %d integer:", size);
while(fgets(buff, sizeof(buff), stdin)){
int count=0;
char*p;
for(p=buff;NULL!=(p=strtok(p, " \t\n"));p=NULL){
char *ck;
int i;
i=(int)strtol(p, &ck, 0);
if(*ck){
fprintf(stderr, "invalid input:can't parse of int <<%s>>\n", p);
status=0;
continue;
}
if(count < size){
array[count++]=i;
continue;
}
count = size + 1;//more than
break;
}
if(count < size)
fprintf(stderr, "invalid input: less than %d\n", size);
else if(count == size) return status;
if(count > size)
fprintf(stderr, "invalid input: more than %d\n", size);
printf("\ninput %d integer:", size);
status = !0;
}
return 0;
}
int main(int argc,char *argv[]){
int array[5];
intRead(array, 5);//or: while(!intRead(array, 5));
printf("%d %d %d %d %d\n", array[0], array[1], array[2], array[3], array[4]);
return 0;
}

Parsing data from ASCII formatted file in C

I am trying to do what's been done here Read co-ordinates from a txt files using C Program . The data that I am trying to input is in this format:
f 10 20 21
f 8 15 11
. . . .
f 11 12 25
The only difference in my point structure is that I have a an extra char to store the letter in the first column (which may or may not be the letter f). I guess im either declaring my char wrong, or I'm calling it in printf incorrectly. Either way, I only get the first line read and then my program terminates. Any ideas ?
Here is my MWE below
#define FILEPATHtri "/pathto/grid1DT.txt"
#define FILEPATHorg "/pathto/grid1.txt"
#define MAX 4000
#include <stdio.h>
#include <stdlib.h>
#include "math.h"
typedef struct
{
float x;
float y;
float z;
char t[1];
}Point;
int main(void) {
Point *points = malloc( MAX * sizeof (Point) ) ;
FILE *fp ;
fp = fopen( FILEPATHtri,"r");
int i = 0;
while(fscanf(fp, "%s %f %f %f ", points[i].t, &points[i].x, &points[i].y, &points[i].z ) == 4 )
{
i++;
}
fclose(fp);
int n;
for (n=0; n<=i; n++){
printf("%c %2.5f %2.5f %2.5f \n", points[i].t, points[n].x, points[n].y, points[n].z ); }
printf("There are i = %i points in the file \n And I have read n = %i points ",i,n);
return 0;
}
Since there's only 1 char in there, not a string just use a single char in your code:
char t;
}Point;
Then when you read it in:
while(fscanf(fp, "%c %f %f %f ", &points[i].t, &points[i].x, &points[i].y, &points[i].z ) == 4 )
{
I'll note that having an array of 1 char, at the end of a structure, sets you up for the struct hack which might not have been your intentions... A good reason to use just char t instead of char t[1]
Also this line:
for (n=0; n<=i; n++){
Should be
for (n=0; n<i; n++){
One last note... if you wanted to print the character out that you read in the prints at the bottom, you should be using n:
// note your previous code was points[i].t
printf("%c %f %f %f \n", points[n].t, points[n].x, points[n].y, points[n].z ); }
Check this
while(fscanf(fp, "%c %f %f %f ", points[i].t, &points[i].x, &points[i].y, &points[i].z ) == 4 )
{
i++;
}
fclose(fp);
int n;
for (n=0; n<i; n++){
printf("%c %2.5f %2.5f %2.5f \n", points[n].t, points[n].x, points[n].y, points[n].z ); }
printf("There are i = %i points in the file \n And I have read n = %i points ",i,n);
getch();
return 0;
}
modification are since only a single character is read %s modified to %c also in printf its not points[i].t its points[n].t . Also the limit checking in for loop is also corrected to n<i

Resources