edit: fixed thanks
Printable View
edit: fixed thanks
This line will overflow your buffer if the user types more than 39 characters:
You can use this to be safer:Code:scanf("%s", fname);
Are you asking what's wrong with the code you have now or what else you need to write to make it work?Code:fgets( fname, sizeof( fname ), stdin );
You're printing parts of the elements array even though you haven't written anything to the elements array...
Thanks for the tip on the buffer. I'd read a tutorial on it and had tried to implement it in this assignment however I think I got some parameters muddled up!
Anyway...
I assumed I had put things into the elements array and now I look back over it I realise that you are of course, correct.
I had tried to put things into the array by using
but I don't think this would workCode:puts(elements[lcount]);
so could I assign the data to an array by stating
Code:int abundance_sorter()
{
FILE *infile;
char fname[40];
char line[100];
char elements[20][50];
int lcount = 1;
/* Read in the filename */
printf("\nEnter the name the file you wish to open: ");
fgets( fname, sizeof( fname ), stdin );
/* Open the file. If NULL is returned there was an error */
if((infile = fopen(fname, "r")) == NULL) {
printf("Error Opening File.\n");
exit(1);
}
while(fgets(line, sizeof(line), infile) != NULL ) {
/* Get each line from the infile */
printf("Line %d: %s", lcount, line);
scanf("%c", &elements[lcount]);
lcount++;
//puts(elements[lcount]);
/* print the line number and data */
}
printf("\nFile reading finished");
printf("\n%d this is it", elements[2][5]);
//printf("\n the value is %s", elements[2][1]);
fclose(infile); /* Close the file */
}
Edit: I've just inserted the
and it misses out the step where I should type in the filename and instead jumps to this output. :/Code:fgets( fname, sizeof( fname ), stdin );
Enter the name the file you wish to open: Error Opening File.
I wouldn't mix numbers with letters. You can do it, by changing the numbers to their char designations and such but it just muddies the waters of the logic, a great deal.
Basically, I know of two ways to do what you want to do:
1) use a struct - it groups letters and numbers into one "thing". For handling multiple fields (3 or more), in a record, (the one "thing"), it's the only way to fly.
2) if you have just two parts (fields) to each record, you can use parallel arrays. One for the element names, and one for their abundance number.
This is a simple assignment. Beware of making a "piano" (aka Rube Goldberg), out of it. Three functions should be fine: one for input, one for sorting, and one for output.
I think I would prefer to do no. 2 as we've not been taught structs just yet. I know about arrays but am unsure as to how I could implement a parallel array. If I start from where the file is read line by line to the program... where could I go from here as surely sorting it into an array will affect both the name and the abundance. ie, it will all get mixed up.
If you have a link to an example piece of code I would be most grateful, or if you can explain it in slightly greater depth I would also be most grateful.
Thank you
unfortunately not :/
Edit: Just got it working... at least I think so
does this look correct?
Code:char line[100];
char elements[20][50];
int lcount = 1;
char fname[0];
/* Read in the filename */
printf("\nEnter the name the file you wish to open: ");
scanf("%s", fname);
fgets( fname, sizeof( fname ), stdin );
Ok. Let me bang out some code, for an example of parallel arrays, and I'll include fgets(), so you can see a good example (although there should be examples in the forum FAQ and on the board.
Back after bit.
You know to really debug what you have I'd probably need to see your whole program so I could run it and check for compiler warnings, etc.
Code:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <ctype.h>
#include "abundance_sorter.h"
#include "element_info.h"
int decision;
int main(){
while(1)
{
printf("This program has the ability to do four tasks. "
"\n\nPlease pick the corresponding number related"
" to the task you wish to be done.\n\n"
"1. Sort elements stored on file by either name or abundance.\n"
"2. Find maxima from data on wavelengths and absorbances.\n"
"3. Root Finding\n"
"4. Element Database\n");
scanf("%i", &decision);
if (decision == 1)
{
printf("You have selected option 1");
abundance_sorter();
break;
}
if (decision == 2)
{
printf("You have selected option 2");
break;
}
if (decision == 3)
{
printf("You have selected option 3");
break;
}
if (decision == 4)
{
printf("You have selected option 4");
element_info();
break;
}
else
{
printf("Invalid Number\n");
continue;
}
return 0;
}
}
That is the main file and this is abundance_sorter.h
The code in comments is what has been tried yet proved detrimental to the program... ie, only outputting one line from the entire file etc.
Code:
int abundance_sorter()
{
FILE *infile;
char line[100];
char elements[20][50];
int lcount = 1;
char fname[0];
/* Read in the filename */
printf("\nEnter the name the file you wish to open: ");
scanf("%s", fname);
fgets( fname, sizeof( fname ), stdin );
/* Open the file. If NULL is returned there was an error */
if((infile = fopen(fname, "r")) == NULL) {
printf("Error Opening File.\n");
exit(1);
}
{
while(fgets(line, sizeof(line), infile) != NULL ) {
/* Get each line from the infile */
printf("Line %d: %s", lcount, line);
//scanf("%s", &elements[lcount]);
lcount++;
//puts(elements[lcount]);
/* print the line number and data */
}
}
printf("\nFile reading finished");
printf("\n%c this is it", elements[2][1]);
//printf("\n the value is %s", elements[2][1]);
fclose(infile); /* Close the file */
}
this is part 4, or element_info.h
And think... I have to fill in parts 2 and 3 :OCode:
int element_info()
{
FILE *fp;
char infofilename[127], repeat[9], element[127], symbol[127];
int melt, answer;
printf("\n\n[Please enter the filename:]\n\n");
scanf("%s", infofilename);
/* Try opening the file.*/
fp = fopen(infofilename, "a"); /* If file exists, append data to end of file, else create new file...*/
printf("Your file %s was created\n\n"
"Now please enter the data you want stored"
"\nElement: ", infofilename);
scanf("%s", &element);
fprintf(fp, "%s ", &element);
printf("Symbol: ");
scanf("%s", &symbol);
fprintf(fp, "%s ", &symbol);
printf("Melting Point: ");
scanf("%d", &melt);
fprintf(fp, "%d\n\n", melt);
while(1)
{
printf("Would you like to enter more data?\n1. Yes\n2. No\n\n");
scanf("%i", &answer);
if(answer == 1)
{
printf("Please enter the data you want stored"
"\nElement: ");
scanf("%s", &element);
fprintf(fp, "%s ", &element);
printf("Symbol: ");
scanf("%s", &symbol);
fprintf(fp, "%s ", &symbol);
printf("Melting Point: ");
scanf("%d", &melt);
fprintf(fp, "%d\n\n", melt);
continue;
}
if(answer == 2)
{
printf("Thank you for exploiting me today");
break;
}
else
{
printf("Invalid Number");
continue;
}
}
fclose(fp);
return 0;
}
and my elements.txt file is
Code:Carbon 18
Calcium 1.5
Phosphorus 1.2
Hydrogen 10
Nitrogen 3
Chlorine 0.3
Sodium 0.1
Potassium 0.5
Sulfur 0.4
Oxygen 65
Magnesium 0.05
If you have to manage this much data for each element, then we need to upgrade you to structs, right away.
Forget parallel arrays for more than 2 fields in a record. :)
I thought I'd code up a little sample, but I believe I'll just tweak a bit of what you have.
choose one thing - do not use bothCode:scanf("%s", fname);
fgets( fname, sizeof( fname ), stdin );
also note that fgets leaves the \n char in the buffer - youneed to remove it for example
Code:char* p = strchr(fname, '\n');
if(p) *p = '\0';
Yeah, fname[0] was the problem. Also, I'd drop "abundance_sorter.h", and "element_info.h".
They're not needed, and don't add to the clarity of the program.
It now compiles, but is flawed in logic. I haven't run it yet, however.Code:#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <ctype.h>
//#include "abundance_sorter.h"
//#include "element_info.h"
#define MAX 30
//int decision;
struct element {
char name[40];
int abun;
//you can add wavelength or other data members here, easily.
};
int main(void) {
int i, decision;
struct element ele[MAX];
while(1)
{
printf("This program has the ability to do four tasks. "
"\n\nPlease pick the corresponding number related"
" to the task you wish to be done.\n\n"
"1. Sort elements stored on file by either name or abundance.\n"
"2. Find maxima from data on wavelengths and absorbances.\n"
"3. Root Finding\n"
"4. Element Database\n");
scanf("%i", &decision);
if (decision == 1)
{
printf("You have selected option 1");
abundance_sorter();
break;
}
if (decision == 2)
{
printf("You have selected option 2");
break;
}
if (decision == 3)
{
printf("You have selected option 3");
break;
}
if (decision == 4)
{
printf("You have selected option 4");
element_info();
break;
}
else
{
printf("Invalid Number\n");
continue;
}
}
return 0;
}
/*
That is the main file and this is abundance_sorter.h
The code in comments is what has been tried yet proved detrimental to the program... ie,
only outputting one line from the entire file etc.
Code:
*/
int abundance_sorter()
{
FILE *infile;
char line[100];
char elements[20][50];
int lcount = 1;
char fname[30];
/* Read in the filename */
printf("\nEnter the name the file you wish to open: ");
scanf("%s", fname);
fgets( fname, sizeof( fname ), stdin );
len = strlen(fname); //removes the filename newline char
fname[--len] = '\0';
/* Open the file. If NULL is returned there was an error */
if((infile = fopen(fname, "r")) == NULL) {
printf("Error Opening File.\n");
exit(1);
}
{
while(fgets(line, sizeof(line), infile) != NULL ) {
/* Get each line from the infile */
printf("Line %d: %s", lcount, line);
//scanf("%s", &elements[lcount]);
lcount++;
//puts(elements[lcount]);
/* print the line number and data */
}
}
printf("\nFile reading finished");
printf("\n%c this is it", elements[2][1]);
//printf("\n the value is %s", elements[2][1]);
fclose(infile); /* Close the file */
return 0; //
}
//this is part 4, or element_info.h
//Code:
int element_info()
{
FILE *fp;
char infofilename[127], repeat[9], element[127], symbol[127];
int melt, answer;
printf("\n\n[Please enter the filename:]\n\n");
scanf("%s", infofilename);
/* Try opening the file.*/
fp = fopen(infofilename, "a"); /* If file exists, append data to end of file, else create new file...*/
printf("Your file %s was created\n\n"
"Now please enter the data you want stored"
"\nElement: ", infofilename);
scanf("%s", &element);
fprintf(fp, "%s ", &element);
printf("Symbol: ");
scanf("%s", &symbol);
fprintf(fp, "%s ", &symbol);
printf("Melting Point: ");
scanf("%d", &melt);
fprintf(fp, "%d\n\n", melt);
while(1)
{
printf("Would you like to enter more data?\n1. Yes\n2. No\n\n");
scanf("%i", &answer);
if(answer == 1)
{
printf("Please enter the data you want stored"
"\nElement: ");
scanf("%s", &element);
fprintf(fp, "%s ", &element);
printf("Symbol: ");
scanf("%s", &symbol);
fprintf(fp, "%s ", &symbol);
printf("Melting Point: ");
scanf("%d", &melt);
fprintf(fp, "%d\n\n", melt);
continue;
}
if(answer == 2)
{
printf("Thank you for exploiting me today");
break;
}
else
{
printf("Invalid Number");
continue;
}
}
fclose(fp);
return 0;
}
your action selector could be improved
could be written asCode:if (decision == 1)
{
...
}
if (decision == 2)
{
...
}
if (decision == 3)
{
...
}
if (decision == 4)
{
...
}
to avoid checking conditions father after the correct match was foundCode:if (decision == 1)
{
...
}
else if (decision == 2)
{
...
}
else if (decision == 3)
{
...
}
else if (decision == 4)
{
...
}
or using switch statement