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!
Related
By using a function, the program should read the data from each line as information about a car’s name, cargo type, weight (full), length, required horsepower to pull that car type, and number of cars of that type. The data must be stored in an array of structures as it is being read from the file then displayed in console. The strsub() function must be used.
Unfortunately the data from the text file isn't printing to the console. I think the problem may lie in my use of pointers, but I've read the chapter on it more than five times now. And if it does print, only gibberish prints.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 100
FILE *fpIn;
void strsub(char buf[], char sub[], int start, int end);
void readFile();
typedef struct {
char name[10];
char type[1];
float weight;
int length;
int power;
int amount;
}data;
// Substring extractor function from book
void strsub(char buf[], char sub[], int start, int end){
int i, j;
for (j = 0, i = start; i <= end ; i++, j++){
sub[j] = buf[i];
}
sub[j] = '\0';
}
// Prints out file
void outFile(data* train) {
printf(" Name: %s ", train->name);
printf(" Type: %s ", train->type);
printf(" Weight: %.2f ", train->weight);
printf(" Length: %d ", train->length);
printf(" Horsepower: %d ", train->power);
printf(" Number in Train: %d ", train->amount);
}
// Reads file
void readFile(){
int count = 0;
data train[MAX];
// Opens file
if(!(fpIn = fopen("traindata.txt", "r"))){
printf("Error. File can not be opened. \n");
}
// Reads each line of text in file
while (!feof(fpIn)){
char buf[MAX+2];
char weightbuf[5];
char lengthbuf[3];
char powerbuf[2];
char amountbuf[3];
fgets(buf, MAX, fpIn);
strsub(buf, train[count].name, 0, 8);
strsub(buf, train[count].type, 10, 10);
strsub(buf, weightbuf, 12, 16);
strsub(buf, lengthbuf, 18, 20);
strsub(buf, powerbuf, 22, 23);
strsub(buf, amountbuf, 25, 27);
train[count].weight = atof(weightbuf);
train[count].length = atoi(lengthbuf);
train[count].amount = atoi(amountbuf);
train[count].power = atoi(powerbuf);
++count;
}
for (int i = 0; i < count; ++i){
data* train = &train[i];
outFile(train);
}
}
int main(int argc, char *argv[]) {
printf("This table shows the current Train Cars\n\n");
readFile();
return 0;
}
Expected results:
Boxcar D 44000 55 16 45
Hopper B 23000 62 18 33
Tanker G 15000 45 30 12
Autocar A 30000 37 23 6
Livestock L 56500 50 18 19
Coalcar C 49300 53 22 100
Flatcar F 18000 66 15 25
Current Display:
This table shows the current Train Cars
Name: ���� Type: Weight: 0.00 Length: 20 Horsepower: 1696 Number in Train: -2112880507
Error?:
data* train = &train[i];
- Local variable "train" might not have been initialized
Wrong array size.
char type[1];
printf(" Type: %s ", train->type);
Type cannot hold \0 character as you pass it to the printf or access out of bound, you have undefined behavior.
Solution:
char type;
train[count].type = buf[10]; //Do not call substr function.
printf(" Type: %c ", train->type);
Scope problem.
for (int i = 0; i < count; ++i){
data* train = &train[i];
outFile(train);
}
Here train as array has higher preference over train as pointer, thus you are unknowingly passing train as array to outFile function.
Solution:
for (int i = 0; i < count; ++i){
data* pTrain = &train[i];
outFile(pTrain );
}
Suggestion: use sscanf function.
I am trying to store data for Value, Weight and Cost from a file containing a table which contains three columns of numbers for Value, Weight and Cost. The table may vary in length (9 or 21 rows) depending on the file chosen by the user.
I am having trouble trying to store the data from this file to use in a brute force function to solve the problem.
This is what I have so far.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int nr_rows;
int i = 1;
int j = 2;
int k = 3;
int l,m,n = 0;
int budget_cost;
int weight_lim;
char file_name[50];
float c[nr_rows][3];
char stringA[20] = "objectsA.txt";
char stringB[20] = "objectsB.txt";
printf("Enter the filename containing item listing: ");
scanf("%s", &file_name);
if(strcmp(file_name,stringA)==0)
{
nr_rows = 9;
}
else if(strcmp(file_name,stringB)==0)
{
nr_rows = 21;
}
printf("The number of rows is %d", nr_rows);
float value[nr_rows], weight[nr_rows], price[nr_rows];
FILE *fpointer;
fpointer = fopen(file_name, "r");
if(!fpointer)
{
printf("The file %s could not be opened.", file_name);
return 1;
}
j=0;
while(j<nr_rows)
{
i=0; // Skip the first line
while(i<3)
{
fscanf(fpointer, "%f", &c[j][i]);
//printf("%.0f\n", c[j][i]);
if(i=1) /* Change this if statement so that 1 ,4 ,7 ,10
etc. activates*/
{
c[j][i] = v[l];
l++;
printf("%f", v[l]);
}
else if(i=2)/* Change this if statement so that 2,5,8 etc.
activates*/
{
c[j][i] = w[m];
m++;
}
else if(i=3)/* Change this if statement so that 3,6,9 etc.
activates*/
{
c[j][i] = p[n];
n++;
}
i++;
}
j++;
}
fclose(fpointer);
//1. Read carefully your file name by doing:
scanf("%s", file_name); // instead of scanf("%s", &file_name);
//2. Declare c[nr_rows][3] only after reading "nr_rows"
//3. The main "while" loop could look like this
while(j < nr_rows)
{
fscanf(fpointer, "%f %f %f", &c[j][0], &c[j][1], &c[j][2]);
}
// Then,
fclose(fpointer);
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.
This code for tolerance analysis compiles and runs, but the output is incorrect and I believe it to be the incorrect handling of the file and the data within the file.
The data in the file is:
PART,2.000,-1,0.050,V
PART,0.975,-1,0.025,V
PART,3.000,+1,0.010,F
GAP,0.000,0.080
The code:
#include <stdlib.h>
#include <string.h>
#include <math.h>
void parsePart(char input[], float*pnom, int*pinp, float*ptol, char*pFV);
void parseGap(char input[], float *pmin, float *pmax);
float meanGap(float nom[], float imp[], int size);
float tolGap(float tol[], int size);
int main()
{
FILE *ptable;
int i, num_of_parts;
int impact[10];
float nominal[10], tolerance[10];
char FV[10];
char input_str[30];
float max, min, gap, tol;
float curr_max, curr_min;
ptable=fopen("D:\\Input.txt", "r");
for(i=0; i<11; i++);
{
fgets(input_str, 30, ptable);
if(input_str[0] == 'P')
{
parsePart(input_str, &nominal[i], &impact[i], &tolerance[i], &FV[i]);
}
else
{
parseGap(input_str, &min, &max);
num_of_parts = i;
}
}
gap = meanGap(nominal, impact, num_of_parts);
tol = tolGap(tolerance, num_of_parts);
curr_max = gap+tol;
curr_min = gap-tol;
printf("Gap mean is: %f inches\n", gap);
printf("Gap tolerance is: %f inches\n", tol);
if(fabs(max-curr_max)< 0.0001 && curr_max > (gap*2)) //they are equal
{
printf("The maximum gap is %f which is greater than the allowed %f\n", curr_max, gap*2);
}
else
{
printf("The maximum gap is %f which is within the allowed %f\n", curr_max, gap*2);
}
if(fabs(min+curr_min)<0.0001 && curr_min < gap-gap)
{
printf("The minimum gap is %f which is less than the allowed %f\n", curr_min, gap-gap);
}
else
{
printf("The minimum gap is %f which is within the allowed %f\n", curr_min, gap-gap);
}
return 0;
}
void parsePart(char input[], float*pnom, int*pinp, float*ptol, char*pFV)
{
int i;
char * field[5];
field[0]=strtok(input, ",");
for(i=1; i<5; i++);
{
field[i] = strtok(NULL, ",");
}
*pnom = atof(field[1]);
*pinp = atoi(field[2]);
*ptol = atof(field[3]);
*pFV = *field[4];
}
void parseGap(char input[], float *pmin, float *pmax)
{
char *field[2];
field[0] = strtok(input, ",");
field[1] = strtok(NULL, ",");
field[2] = strtok(NULL, ",");
*pmin = atof(field[1]);
*pmax = atof(field[2]);
}
float meanGap(float nom[], float imp[], int size)
{
int i;
float sum=0;
for(i=0; i<size; i++);
{
sum += nom[i]*imp[i];
}
return sum;
}
float tolGap(float tol[], int size)
{
int i;
float sum=0;
for(i=0; i<size; i++);
{
sum += tol[i];
}
return sum;
}
The output should look something like:
Actual Gap Mean: 0.025”
Actual Gap Tolerance: 0.085”
The Maximum Gap (0.110”) is (Greater) than specified (0.080”)
The Minimum Gap (-0.060”) is (Less) than the specified (0.000”)
I get a 0 for gap mean and all the other values are incredibly large numbers.
Any and all hints as to where I could be going wrong or need improvement are great. Thank you.
In line 85, char *field[2]; should be char *field[3];.
Firstly arrays impact et al are sized at 10, so
for(i=0; i<11; i++);
Is wrong for 2 reasons:
1) loop should go from 0 to 9
2) a for statement shouldn't have a ; after it, that terminates the whole statement.
typedef struct{char c[6];} String;
String field1,field2,… …;
String *pf1,*pf2,… …;
pf1=field1;
pf2=field2;
…
…
pf1=strtok(input,…
Is the correct (outline) way to code parseGap assuming the longest data in the input file is 5 characters long,
So I have a function built already that calculated 25 random temperatures and outputted them and had a max, min, and average feature. I'm now trying to incorporate input files and output files via txt.
I tried to do some research and plug in what I could (even if I barely understood it), can someone lend some light on my code?
int get_value(void);
void calc_results(void);
void read_temps(void);
int sum = 0;
int min = 0;
int max = 0;
int temp[25];
int i = 0; //For array loop
int j = 0; //For printf loop
float avg = 0;
void read_temps() {
char fname[128];
printf("Enter .txt file name \n");
scanf("%123s", fname);
strcat(fname, ".txt");
FILE *inputf;
inputf=fopen(fname, "w");
for (i = 0; i < 25; i++){
temp[i] = fname;
sum += temp[i];
}
}
int main () {
calc_results();
return 0;
};
void calc_results(void) {
FILE * fp;
fp = fopen("Output_temps.txt", "w+");
avg = ((sum)/(25));
max = temp[0];
for(i=1;i<25;i++){
if(max<temp[i])
max=temp[i];
};
min =temp[0];
for(i=1;i<25;i++){
if(min>temp[i])
min=temp[i];
};
fprintf("Temperature Conditions on October 9, 2015 : \n");
fprintf("Time of day Temperature in degrees F \n");
for(j=0;j<25;j++){
fprintf(" %d %d\n",j,temp[j]);
}
fprintf("Maximum Temperature for the day: %d Degrees F\n", max);
fprintf("Minimum Temperature for the day: %d Degrees F\n", min);
fprintf("Average Temperature for the day: %.1f Degrees F\n", avg);
fclose(fp);
};
There were a few errors in your code, the most critical one being it doesn't compile. If you're having issues you'll want to follow the instructions for how to make a ssce. You will get a much better response this way. Then explain clearly the specific issue you are having and what it is that is happening or not happening as opposed to what you expect.
With your code you seem to be assigning to your temp array the fname variable instead of reading in the int data from the user file.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
// assuming you want a maximum of temperatures of 25
#define TEMP_NUMBER 25
// use a struct to maintain and the temparatur data in one place
// without resorting to using global variables or having functions
// that require numerous parameters.
struct temp_data {
char fname[128];
int max;
int min;
int sum;
int temps[TEMP_NUMBER];
float avg;
};
struct temp_data *temps_init(void)
{
// creates a pointer to struct temp_data to hold
// your various temparture related fields
struct temp_data *td = malloc(sizeof *td);
td->sum = 0;
td->avg = 0.0;
return td;
}
void read_temps(struct temp_data *td)
{
// in your sample code you have this set to "w", needs to be "r"
FILE *inputf = fopen(td->fname, "r");
// handle error
if (!inputf) {
perror("fopen");
exit(0);
}
for (int i = 0; i < TEMP_NUMBER; i++) {
// you were setting fname to the temparature array
// instead you need to scan the temp file
fscanf(inputf, "%d", &(td->temps[i]));
td->sum += td->temps[i];
}
}
void print_results(struct temp_data *td)
{
// a print function to separate logic
FILE *fp = fopen("Output_temps.txt", "w+");
if (!fp) {
perror("fopen");
exit(0);
}
fprintf(fp, "Temperature Conditions on October 9, 2015 : \n");
fprintf(fp, "Time of day Temperature in degrees F \n");
for(int i=0; i < TEMP_NUMBER; i++)
fprintf(fp, " %d %d\n", i, td->temps[i]);
fprintf(fp, "Maximum Temperature for the day: %d Degrees F\n", td->max);
fprintf(fp, "Minimum Temperature for the day: %d Degrees F\n", td->min);
fprintf(fp, "Average Temperature for the day: %.1f Degrees F\n", td->avg);
fclose(fp);
}
void calc_results(struct temp_data *td)
{
// do only calculations
td->avg = td->sum / TEMP_NUMBER;
td->min = td->temps[0];
td->max = td->temps[0];
for (int i=1; i < TEMP_NUMBER; i++) {
td->min = td->temps[i] < td->min ? td->temps[i] : td->min;
td->max = td->temps[i] > td->max ? td->temps[i] : td->max;
}
}
int main(int argc, char *argv[])
{
// Moved user input into the main() from read_temps()
// now read_temps() only needs to read and record the temp data
struct temp_data *td = temps_init();
printf("Enter .txt file name \n");
scanf("%123s", td->fname);
strcat(td->fname, ".txt");
read_temps(td);
calc_results(td);
print_results(td);
free(td);
return 0;
};
Using a file called sample.txt:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25