linear searches in 2d arrays - c

#define NUMLEG 7
int Search_type(char leg_type[6][10], int travel_int[6][15], int trip_num);
c = Search_type(type,leg_type, travel_int, trip_num);
if (c == -1)
printf("Destination not found.\n");
else
printf("Destination Found \nDestination Name:%s", travel_name[c]);
int Search_type( char type, char leg_type[6][10], int travel_int[6][15], int trip_num)
{
int i, n;
char target;
getchar();
printf("Please enter travel type you wish to search by:");
scanf("%c", &target);
for (i =0; i <trip_num; i++)
{
for ( n = 0; n < travel_int[i][NUMLEG]; n++)
{
if( leg_type[i][n] == target)
{
return i;
}
}
return -1;
}
}
This is a rip out of a function I'm currently working on from a project and for some strange reason I can't seem to get it to search properly, I know that its not the rest of the code but this area since all the other function works properly. So I decided to break this out of the code and test it.
I can't seem to get it to search after 1 row:
travel_int[i][NUMLEG] contains the number of legs
leg_type is where i store the char of each leg
I want it to search through the leg_type till it finds the specified character. Without pointers.
EDIT
For example
Trip#:1
Destination Name:Austin
Leg(#1):A
Leg(#2):T
Trip#:2
Destination Name:Florida
Leg(#1):S
Leg(#2):F
so
trip number = 2
travel_int stores 2 trips and each trip has 2 legs
leg type stores in the 2 leg types at the trip number
When I put in A or T it prints out Austin like it should but when I input S or F it return destination not found =/. Am I doing the search wrong, or is it the print statement that is wrong. Or is it where I'm place my return -1;.
(I would put up the code but its a bit long..)

In your nested loops you are returning -1 without doing complete search in the entire arrays.
Place return -1 outside all the for() loops.
for (i =0; i <trip_num; i++)
{
for ( n = 0; n < travel_int[i][NUMLEG]; n++)
{
if( leg_type[i][n] == target)
{
return i;
break;
}
}
} return -1
This would definitely make your program run correctly.And this is the only reason why you get the correct results when you search for trip #01.

Related

Pythagorean triplets program

I have written a program that should be rather simple but on execution, it is not giving the wanted results. Even when debugging the program, I guess I found the error (getting stuck in the first if condition) but I'm not able to solve it (my inexperience perhaps). Anyways, this program, which should have been frugal, took 3 days whereas I expected it to take mere hours. Please help me with guiding me where I'm going wrong and how to solve it.
Here is the code
/*WAP to read pre entered no. of ints. consider only +ve and print the pythagorean triplets in them.*/
#include <stdio.h>
int main(){
int c,p,pp,count=0,a;
printf("How many entries to accept?\n");
scanf("%d",&a);
printf("Enter the nos.\n");
for (int i = 0; i < a; i++)
{
scanf("%d",&c);
if (c<0) //skip -ve nos.
{
continue;
}
if (count==0)
{
pp=c;
count++;
}
else if (count==1)
{
p=c;
count++;
}
else if ((pp*pp)+(p*p)==(c*c)) //Tracking count not necesarry after first three
{
printf("Pythagorean triplet found\n");
printf("%d %d %d",pp,p,c);
pp=p;
p=c;
}
}
return 0;
}
The main objective is to first scan a no. to signify the inputs to be read. Then scan the inputs, separated by a space or enter, in a loop which will only accept the no. of inputs stated before. It should neglect any -ve entries. It should print out the Pythagorean triplet if it encounters one, in a consecutive manner i.e. the triplet should appear one after the other & not randomly. We have to do the task without using arrays.
sample input is (you can consider any)(all given through the terminal)
(no. of entries)
6
1 -1 3 4 -4 5
(Here it will ignore -1 & -4)
expected output will be
Pythagorean triplet found
3 4 5
I am still learning so sorry for the elaborate program.
Thank you in advance.
since I cant see the input file I dont know if the values are sorted, since we need to identify which is the hypotenuse, makes it a bit more fiddly.
Also not clear what 'skip negatives' means. Does it mean
that we might see 3 -6 4 5 and say 'yes 3,4,5' is a triple
that we might see 3 -4 5 and say yes 3 4 5
or that we might see 3 -4 5 and simply ignore the whole set
I have assumed the first one
#include <stdio.h>
int main() {
printf("How many entries to accept?\n");
int a;
if (scanf("%d", &a) != 1) {
printf("bad input\n");
return (-1);
}
printf("Enter the nos.\n");
for (int i = 0; i < a; i++)
{
int sides[3] = { 0 };
int max = 0; // longest side length -> hypot
for (int j = 0; j < 3; j++)
{
int c;
if (scanf("%d", &c) != 1) {
printf("bad input\n");
return (-1);
}
if (c < 0) //skip -ve nos.
j--; // try again
else {
if (c > max) {
max = c;
}
sides[j] = c;
}
}
int hyp = max * max; // hypotenuse squared
int adjTot = 0; // adj sides squared total
for (int j = 0; j < 3; j++)
{
if (sides[j] == max)
continue;
adjTot += sides[j] * sides[j];
}
if (adjTot == hyp)
printf("%d %d %d is py\n", sides[0], sides[1], sides[2]);
else
printf("%d %d %d isnt py\n", sides[0], sides[1], sides[2]);
}
return 0;
}
Since you say you are reading from a file it just exits if there is non numeric data

new to c problem with simple game problem with function

im new to c i try to make a little and very simple game of hangedman and i dont know why doesent work get error in gcc "expected declaration or statement at the end of input"
im new to c and ii try very hard to learn it.
im missing something? my function is not right? some advice to learn alghorytmically thinking?
thanx in advance for the hel you gonna give me
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//function to find letter in string
int findletter(char y)
{
char c;
int i;
char secret[] = "outcast";
i = 0;
scanf("%c", &c);
while (c != secret[i] && i < strlen(secret))
i++;
if(c == secret[i])
return (1);
else
return (0);
}
//confirmation letter
int guessed(char a)
{
int z;
char guess [6] = {0};
z = 0;
while(findletter(guess[z]) != 1 && findletter(guess[z]) < 6)
{
z++;
if(findletter(guess[z]) == 1)
return 1;
else
return 0;
//word guessed
int tryguess(char v)
{
int x;
x = 0;
while(findletter(guess[x]) == 0)
{
x++;
if(findletter(guess[x] == 1))
return 1;
else
return 0;
}
}
int main()
{
char secret[] = "outcast";
char letter;
int lives;
char guess [6] = {0};
int i;
lives = 10;
i = 0;
printf("welcome to the hanged man\n");
while(i < 6)
{
if((findletter(secret[i] == 1)))
printf("%c", secret[i]);
else
printf("*\n");
i++;
}
return 0;
}
Correction to your code...
int guessed(char a)
{
int z;
char guess [6] = {0};
z = 0;
while(findletter(guess[z]) != 1 && findletter(guess[z]) < 6)
{
z++;
if(findletter(guess[z]) == 1)
return 1;
else
return 0;
} // you forgot closing while loop here
} // function closing parenthesis
//word guessed
Advice:
I don't know how much you had practice and how much you had learned yet..but on observing your mistake above I would like to suggest that whenever you create function or loop always write its prototype first, let's say you want to create a function for adding two numbers..
STEP 1: write prototype
int add(int x, int y)
{
//then do your stuff here...
return 0;
}
This will eliminate you chances of making error of parentheses...
There are a lot of issues with this program, from both a syntax standpoint and a logical one.
General issues include:
Function guessed and its while loop are not closed (missing }).
There is a lot of unused code (functions and variables).
The line if((findletter(secret[i] == 1))) compares the character value of secret[i] with 1 and passes that result to findletter. This doesn't matter though since you don't use this argument, and take user input within the function.
You have hardcoded strings and lengths, which makes your program less dynamic and harder to change in the future.
Using while loops as guards (in the unused functions tryguess and guessed), that are always exited on the first iteration.
findletter simply checks if secret contains the character c, returning on the first occurrence.
It could be more clearly expressed as:
int findletter(char unused) {
char secret[] = "secret",
c;
scanf(" %c", &c);
for (size_t i = 0; i < strlen(secret); i++)
if (secret[i] == c)
return 1;
return 0;
}
With that said, findletter would be better if you passed both the secret and c as arguments, so that you can use it more generically, and decouple user input from the function itself.
(Or you could simply use the standard library function strchr which achieves a very similar goal.)
The pattern of
if (a == b)
return 1;
else
return 0;
can simply be reduced to
return a == b;
Aside from the issues above, the structure of your program doesn't make much sense. If our program worked, you'd basically be asking the player to guess a word of unknown length, one character of the word at a time. They can also simply guess any letter to display the current one. One could 'solve' the entire word "secret" by simply inputting 's' repeatedly.
The structure of a very basic hangman program is:
Select the word to be guessed. Select number of lives.
Create a blanked version of word to track progress. Display this blanked version, which indicates the length to the player.
Ask the player to guess a letter. Skip those already guessed.
Update all positions in the blanked version where letter appears in the word.
Decrement lives on miss, end game if out of lives.
Check if the amount of characters changed in the blank version matches the length of word.
Win condition, or return to step 3.
There are many different ways to achieve this, and there are likely thousands of examples online.
Here is a rough program that is about as simple as it gets. This showcases the usual structure and flow of a game of hangman.
#include <stdio.h>
#include <string.h>
size_t update_all(char *to, const char *from, size_t len, char g) {
size_t changed = 0;
for (size_t i = 0; i < len; i++)
if (from[i] == g) {
to[i] = g;
changed++;
}
return changed;
}
void play_hangman(const char *word, unsigned lives) {
size_t word_length = strlen(word),
blanked_length = 0;
char blanked[word_length + 1],
guess = '\0';
for (size_t i = 0; i < word_length; i++)
blanked[i] = '*';
blanked[word_length] = '\0';
while (lives) {
printf("The word: [%s]\n"
"(Lives = %u) Enter a guess: ",
blanked,
lives);
scanf(" %c", &guess);
if (strchr(blanked, guess)) {
printf("[%c]: Already guessed!\n", guess);
continue;
}
size_t found = update_all(blanked, word, word_length, guess);
blanked_length += found;
if (!found) {
printf("[%c]: NOT FOUND!\n", guess);
lives--;
} else
printf("[%c]: FOUND!\n", guess);
if (!lives)
puts("Out of lives! You lose!");
else if (blanked_length == word_length) {
printf("You win! Word is [%s].\n", word);
return;
}
}
}
int main(void) {
play_hangman("secret", 10);
}
Note that this program is far from perfect, as it doesn't fully keep track of guessed letters, so the player can guess the same wrong letter multiple times, and lose a life every time. To fix this, we would need even more state, collecting each guess the player makes, and use that data instead of the naive if (strchr(blanked, guess)).
It also makes use of the '*' character as a sentinel value, which would cause confusion if our word contained '*'. To fix this, we could use an array of boolean values indicating the correctly guessed letters in the word thus far, and use this to print our word character-by-character. Or we could restrict character inputs with functions like isalpha.
This program simply serves as an example that for a proper approximation of the typical "Hangman" you need to handle more game state than you have.
(Error handling omitted for brevity throughout this answer.)

Array pointer while loop input

I am trying to write a program to check for duplicate input from a programmable handheld barcode scanner, I am programming it to be able to scan 2000 barcodes.
I am new to c Programming, I am trying to take an input and put it into the array and increase the pointer to the next with every loop.
Example: int Array [10];
I want to scanf() into Array location 0 on the first loop then increment by 1 location to location 2 etc every time the while loops runs. Please help, your help is much appreciated.
#include <stdio.h>
int main ()
{
int i,j,k=1,arr[2000],ArrSize=2000;
//Welcome message
printf("Welcome to Yamato Transport (S) Pte. Ltd.\n");
printf("Barcode checker Ver 1.0\n");
while (k>=2000,k++)
{
//Scanner Input
for(i=0;i<ArrSize;i++)
{
scanf("%d",&arr[i]);
}
//Duplicate Logic
printf("Duplicate Barcodes: ");
for(i=0; i<ArrSize; i++)
{
for(j=i+1;j<ArrSize;j++)
{
if(arr[i]==arr[j])
{
printf("%d\n",arr[i]);
}
}
}
//Remove single duplicate
//Clear Screen
}
return 0;
}
The first problem with your code is this:
int i,j,k=1,...
...
while (k>=2000,k++)
^^^^^^
ups...
This will give the warning "left-hand operand of comma expression has no effect" which actually means that the line is the same as:
while (k++)
That will keep looping until you have integer overflow (which is undefined behavior). So you don't want to do that.
Since you initialize k to 1, I assume that you wanted to do:
while (k++ < 2000)
Now let's assume that you want:
while (k++ < 2000) // Will loop approx 2000 times
{
//Scanner Input
for(i=0; i< ArrSize; i++) // Will loop 2000 times
{
scanf("%d",&arr[i]);
}
So in the end your program calls scanf 2000 x 2000 = 4.000.000 times. Is that what you want? The purpose of the outer while is unclear.
Your program first reads 2000 integers and afterwards it seems you want to remove duplicates. That's a bad approach as you may end you doing a lot of memory move whenever you need to remove a duplicate element from the array.
A better approach is to check whether a newly scanned value is a duplicate before inserting it in the array. That could look something like:
for(i=0; i < ArrSize; )
{
int tmp;
if (scanf("%d", &tmp) != 1)
{
// Input error
exit(1);
}
// Check if tmp is already in the array
int duplicate = 0;
for (int j = 0; j < i; ++j)
{
if (tmp == arr[j])
{
duplicate = 1;
break;
}
}
if (duplicate)
{
printf("dup found\n");
}
else
{
arr[i] = tmp;
++i;
}
}
This should give you ArrSize unique elements.
Notice: In order to check if something is a duplicate, you'll need to scan through the array from start to the current number of elements. To improve performance you could consider another approach, e.g. a sorted tree, hash tables, etc so that check for duplicates can be done much faster. This gets more important as the number of array elements increase.
So half the problem is solved, I am still not sure how do I increase the pointer to the next position so on the next loop it will store another barcode number which will then be passed to the duplicate checker for checking then repeat the loop for the next scan.
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int i,j,k=1,arr[2000],counter=1;
//Welcome message
printf("Welcome to Yamato Transport (S) Pte. Ltd.\n");
printf("Barcode checker Ver 1.0\n");
while (k++ < 2000) // Will loop approx 2000 times
{
//Scanner Input
printf("Scan barcode\n");
for(i=0; i< counter; i++) // Will loop 1 time
{
scanf("%d",&arr[i]);
}
//check for duplicates
for(i=0; i < counter; )
{
int tmp;
if (scanf("%d", &tmp) != 1)
{
// Input error
exit(1);
}
// Check if tmp is already in the array
int duplicate = 0;
for (int j = 0; j < i; ++j)
{
if (tmp == arr[j])
{
duplicate = 1;
break;
}
}
if (duplicate)
{
printf("Duplicate Barcode\n");
}
else
{
arr[i] = tmp;
++i;
}
}
}
return 0;
}

ADD elements of an array with a given condition

There is an array of n students( stu[n]).If gender is boy then my code adds
for boy b, 2nd,4th,6th,........even position elements of array and
for girl g, 1st,3rd,5th....odd position elements of array.
1> Gender of boys denoted by b.
2> Gender of girls denoted by g.
Input info>>
The 1st line contains n, denoting the number of students in the class, hence the number of elements in the array.
Each of the subsequent lines contains the marks of n students .
The last line contains gender b/g;
Output info>>
The output should contain the sum of all the alternate elements of marks as explained above.
#include <stdio.h>
int main() {
int n,i;
scanf("%d",&n);//n denotes number of students.
int stu[n],sum=0;
for(i=1;i<=n;++i)
scanf("%d",&stu[i]);//for accepting input in array.
char gen;
scanf("%s",&gen);//for accepting input gender b/g.
for(i=1;i<=n;i++){
if(gen=='g' && i%2!=0){ //girl g adds alternate odd position elements.
sum=sum+stu[i];
printf("%d",sum);
}
else if(gen=='b' && i%2==0){ //boy b adds alternate even position elements.
sum=sum+stu[i];
printf("%d",sum);
}
}
//code
return 0;
}
Sample Input
3
3
2
5
b
Sample Output
8
explanation>>
marks=[3,2,5] and gender = b so it will add 3+5(even position 0,2 alternate elements). If gender in place of b is g then it will produce output = 2.
My code is shows output of 0 in all test cases.
You have the major problem in
int n,i;
int stu[n],sum=0;
here, n being a uninitialized local scoped variable with automatic storage, the initial value is indeterminate.
Now, since the address of the variable was never taken and it has a type that can have trap representation, attempt to use the value (int stu[n]) will invoke undefined behavior.
You need to scan in the value into n first, then use that to define the VLA stu. Something like
int n,i;
scanf("%d",&n);//n denotes number of students.
// **Note: please check for errors in input with scanf return value.**
int stu[n],sum=0; // here, n has the scanned value.
That said,
char gen;
scanf("%s",&gen);
is also horribly wrong, you want to scan in a char, not a string, and with the address of a plain char variable, %s conversion specification would be UB, again. You should use %c and discard any whitespaces which is present in buffer altogether.
You're making things more complicated than they need to be. Here is how you can possibly do:
#include <stdio.h>
int main(void)
{
int mark;
int b = 0;
int g = 0;
char students_marks[5];
for (int i=0; i<5; i++) {
scanf("%d", &mark);
students_marks[i] = mark;
}
for (int i=0; i<5; i++) {
if (i%2 == 0) b += students_marks[i];
if (i%2 == 1) g += students_marks[i];
}
printf("Boys: %d\nGirls: %d\n", b, g);
return 0;
}
You should probably not use an array, and just ignore the first data point. It is (probably) easier to use a linked list. Or maybe just use two lists, alternating the inputs between them. And I would definitely not use scanf. If you are new to C, do NOT waste your time learning the foibles of the scanf format string language. The only time scanf is ever useful is in introductory courses where instructors incorrectly believe that you will be able to get input more quickly than if you spend time learning other methods. But in fact you will end up burning more time learning when to use spaces in the format string that you saved by not learning fread. After your introduction to C, you will (almost) never use scanf. Also, it seems like a horrible design to put the discriminant at the end of the input. The values to be summed (the gender) should be given as a command line argument. That said, you could just do:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
FILE *
xfopen(const char *path, const char *mode)
{
FILE *rv;
if( (rv = fopen(path, mode)) == NULL ) {
perror(path);
exit(EXIT_FAILURE);
}
return rv;
}
int
main(int argc, char **argv)
{
int i;
int size; /* Should probably be size_t. Skipping that for now. */
FILE *in = argc > 1 ? xfopen(argv[1], "r") : stdin;
int sum = 0;
if( fscanf(in, "%d", &size) != 1 || size <= 0 ) {
fprintf( stderr, "invalid input\n" );
exit(EXIT_FAILURE);
}
int grades[size];
for( i = 0; i < size; i++ ) {
if(fscanf(in, "%d", grades + i) != 1) {
fprintf( stderr, "invalid input on line %d\n", i );
exit(EXIT_FAILURE);
}
}
char gender;
if(fscanf(in, " %c", &gender) != 1) {
fprintf( stderr, "invalid input on line %d\n", i );
exit(EXIT_FAILURE);
}
if(strchr("bBgG", gender) == NULL) {
fprintf( stderr, "invalid gender: %c\n", gender);
exit(EXIT_FAILURE);
}
for( i = tolower(gender) == 'b'; i < size; i += 2 ) {
sum += grades[i];
}
printf("sum: %d\n", sum);
}
Hmm… i changed your code a Little bit and hope this runs as described.
int main() {
int n, index, sum=0;
int* stu;
scanf("%d", &n); // input number of studens
if(n>0)
stu = malloc(n*sizeof(int)); // allocate memory
else
return 0;
for(index=0;index<n;index++)
scanf("%d", &stu[index]);
char gen;
scanf("%c", &gen);
for(index=0; index<n; index++){
if(gen=='g' && index%2!=0) {
sum += stu[index];
printf("%d", sum);
} else if(gen=='b' && index%2==0) {
sum += stu[index];
printf("%d", sum);
}
}
return 0;
}

A C program that sorts Hurricanes by name or year

I need to write a program that loads data from a file with Hurricane data (like year, name, states affected) The data file looks like this:
1960 Dnna Fl,NC
1972 Agnes FL
1969 Camile MS
The user will be able to select whether the hurricanes are sorted by year or name. The sort function should keep the year list and affected states list parallel with the hurricane names. Allow for a max of 30 hurricanes, but use constant macro for this number to permit easy future expansion of the database.
Here is what they want the output to look like if sorted by years.
Year Name States
1960 Donna FL,NC
1969 Camille MS
1972 Anges FL
I Think i'm not going about this problem right. I just can't figure out how to sort the array and print it. Every time I just try to print the array to make sure it is loaded with the right data, I just get a bunch of junk, or it just crashes.Here is the code that has worked best (if you can call it that)
so far.
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define Numof_Hurricane 23
char Hurrican_data[Numof_Hurricane][3];
char temp[Numof_Hurricane][3];
int i,j;
char HowSort;
int cmp ( const void *pa, const void *pb ) {
const char (*a)[4] = pa;
const char (*b)[4] = pb;
return strcmp(*a, *b);
}
// start of program
int main()
{
FILE *Hurrican;
Hurrican = fopen("hurricane_data.txt","r"); // the data file for Hurricanes
if (Hurrican==NULL)
{
printf("ERROR: File failed to open\n");
fclose(Hurrican);
}
for(i=0; i<30; i++)
{
for(j=0; j<3; j++)
{
fscanf(Hurrican," %s", &Hurrican_data[i][j]); //loads data into array
}
}
fclose(Hurrican);
printf("How would you like to sort the data?\n"
"(by Year or Name, use Y for year and N for name)"); // ask how user wants to sort it
scanf(" %c", &HowSort);
if (HowSort == 'Y'|| HowSort == 'y') //sort by year
{
printf("\nYou chose to sort by year");
//I plan on adding a function here to sort by year
// my atempt to sort by year
qsort(Hurrican_data, 1, sizeof Hurrican_data[0], cmp );
// To print sorted data
for ( i = 0 ; i < Numof_Hurricane ; i++ )
{
for ( j = 0 ; j < 4 ; j++ )
{
printf( "%s ", Hurrican_data[i][j] );
}
printf("\n");
}
}
else
{
printf("\nYou chose to sort by name");
// I plan to put a function here to sort by Name
}
return 0;
}
Among the things wrong in this code:
Incorrect fclose invoke
if (Hurrican==NULL)
{
printf("ERROR: File failed to open\n");
fclose(Hurrican); /// HERE
}
That fclose makes no sense, and is a recipe for a crash. You just determined the result of the fopen was NULL. Therefore, the file didn't open. Therefore, the file pointer isn't something you can close. There is no reason to continue the program if the file fails to open:
if (Hurrican==NULL)
{
perror("hurricane_data.txt: ");
return EXIT_FAILURE;
}
The array sizes are wrong.
Given that your data looks like this:
1960 Dnna Fl,NC
1972 Agnes FL
1969 Camile MS
and your loader loop tries to read this content into this:
#define Numof_Hurricane 23
char Hurrican_data[Numof_Hurricane][3];
using this loop:
for(i=0; i<30; i++) // HERE: 30??? What about that 23 ??
{
for(j=0; j<3; j++)
{
// HERE: Each of these can be no longer than TWO chars wide.
fscanf(Hurrican," %s", &Hurrican_data[i][j]);
}
}
This assumes there are always exactly 30 items in the file, which the assignments clearly states is possible, but not precise. "Allow for a max of 30 hurricanes..." means there could be thirty, but there could also be one, five, and even none. Really pouring salt on the wound, you're looping to thirty (overflowing buffers along the way, more on that below) on a core array of arrays that is only 23 elements wide. If there were thirty elements, you breach your primary array at the twenty-fourth line.
Further, your loader look is (a) unchecked, and (b) a recipe for buffer overflow on each read. Consider the very first string value on the very first line, 1960. That string is four characters long; five including the terminator, yet you're trying to shove it into a buffer only three characters wide.
Broken Sorting Algorithm
Your sorting loop is sorting the first character of the names. This is wrong.
A Different Approach
The algorithm is simple:
Define a structure, Hurricane, that holds three fields
year - a simple integer
name - a char buffer of reasonable length
states - a char buffer capable of holding a sufficient number of state abbreviations with comma separators.
Your overall data array is a sequence of up to thirty of these structures.
Read the data from the file one complete line at a time. A line length of 256 characters should be sufficient to hold the data.
For each line parse out the year, the name, and the list of strings.
Store these in the structure array as a complete entity.
Use this structure array for sorting operations.
The resulting code would look something like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_DATA 30
#define MAX_NAME_LEN 64
#define MAX_STATES_LEN 151
struct Hurricane
{
int year;
char name[MAX_NAME_LEN];
char states[MAX_STATES_LEN];
};
struct Hurricane data[MAX_DATA];
void print_data(const struct Hurricane ar[], int size)
{
for (int i=0; i<size; ++i)
printf("%d %s %s\n", ar[i].year, ar[i].name, ar[i].states);
}
void sort_year(struct Hurricane ar[], int size)
{
int swapped = 1;
while (swapped && size--)
{
swapped = 0;
for (int i=0; i<size; ++i)
{
if (ar[i].year > ar[i+1].year)
{
swapped = 1;
struct Hurricane tmp = ar[i];
ar[i] = ar[i+1];
ar[i+1] = tmp;
}
}
}
}
void sort_name(struct Hurricane ar[], int size)
{
int swapped = 1;
while (swapped && size--)
{
swapped = 0;
for (int i=0; i<size; ++i)
{
if (strcmp(ar[i].name, ar[i+1].name) > 0)
{
swapped = 1;
struct Hurricane tmp = ar[i];
ar[i] = ar[i+1];
ar[i+1] = tmp;
}
}
}
}
// start of program
int main()
{
int count=0, i;
char line[256];
char HowSort;
FILE *fp = fopen("hurricane_data.txt","r"); // the data file for Hurricanes
if (fp==NULL)
{
printf("ERROR: File failed to open\n");
fclose(fp);
}
// read until we are full or no more data
for (i=0; (i < MAX_DATA && fgets(line, sizeof(line), fp)); )
{
if (sscanf(line, "%d %63s %150s", &data[i].year, data[i].name, data[i].states) == 3)
++i; // only increment if we got good data
}
// save the number of successful reads.
count = i;
// close the file
fclose(fp);
printf("How would you like to sort the data?\n"
"(by Year or Name, use Y for year and N for name)"); // ask how user wants to sort it
scanf(" %c", &HowSort);
if (HowSort == 'Y'|| HowSort == 'y')
{
printf("\nYou chose to sort by year");
sort_year(data, count);
}
else if (HowSort == 'N' || HowSort == 'n')
{
printf("\nYou chose to sort by year");
sort_name(data, count);
}
print_data(data, count);
return EXIT_SUCCESS;
}
I didn't have the chance to test this, but it is probably very close to what you're trying to to. The sorting algorithm in both cases is a simple bubble sort. For a real-world equivalence we would create appropriate qsort comparison functions and use the standard library, especially if the number of elements was significantly larger than a few dozen. For our purposes here, however, this is sufficient. See the documentation and examples of qsort() here.
Most importantly, note that by using a structure to hold a record rather than splaying it across a sequence of character buffers, you not only get the benefit of proper types (int for the year, for example), you get better data management, and above all, much easier swapping of elements in the sorting routines (structure value swapping ftw).
Anyway, that's what I think you're trying to do.

Resources