Sorting strings alphabetically in C language - c

I made a program that asks the user to enter a name if they select option 2 and it stores that name in the string, if the user selects option 3 then it will display that name. Now for option 4 it needs to alphabetize the names in order, so when i select option 3 again to view the names it would show them in alphabetical order. My friend told me to use strcpy(), and i attempted it but not too successfully.
This is my code:
//This is my code:
#include<stdio.h>
#include<string.h>
int main() {
int i = 0;
int j = 0;
while (1) {
int num;
char name[500][100],t[100];
printf("\nPress 1 to see author info\n");
printf("Press 2 to enter a name\n");
printf("Press 3 to view names\n");
printf("Press 4 to alphabatize names\n");
scanf("%d", &num);
char arr[100];
if (num == 1)
{
printf("----------------\n");
printf("name\n");
printf("132\n");
printf("----------------\n");
}
if (num == 2)
{
printf("Enter the name (no spaces)\n");
scanf("%s", arr);
strcpy(name[i], arr);
i++;
}
if (num == 3)
{
printf("\n******************************");
for (int j = 0; j<i; j++)
{
printf("\n%s\n", &name[j]);
}
printf("\n\n\n******************************");
}
if (num == 4)
{
for (i = 1; i < j; i++) {
for (j = 1; j < i; j++) {
if (strcmp(name[j - 1], name[j]) > 0) {
strcpy(t, name[j - 1]);
strcpy(name[j - 1], name[j]);
strcpy(name[j], t);
}
}
}
;
}
return(0)
system("pause");
}

If Barmar doesn't want to make the comment an answer:
As noted: the i you use in the outer loop is the total, you cannot use it, you need a fresh one, say k. Sorted alphabetically gives:
int k;
if (num == 4) {
for (j = 0; j < i; j++) {
for (k = 0; k < i - j - 1; k++) {
if (strcmp(name[k], name[k + 1]) > 0) {
strcpy(t, name[k]);
strcpy(name[k], name[k+1]);
strcpy(name[k+1], t);
}
}
}
}
I used a slightly different approach for the bubble sort, that's how I learned it, hope you can make sense of it.
Note: copying the full strings is not the best way to do it but I don't know if you already learned about pointers.

Modified your code. It seems that for this situation, switch case would be prettier and that your loop will never end. With what #Barmar said, your loop has a return 0; therefore terminates prematurely. I have changed some elements of your codes too as some of them are suited to be undisturbed etc. etc.
Change List
Besides the implementation of switch case
Name and position of char arrays. For t[100], since it is a temporary object/variable I moved it into case (4) (Refer to line 63
in the modified code) so that the creation happens on demand instead
of the original code where creation is made early. Renamed t to temp.
As for arr, I've renamed it so that it is clearer (nameIn to indicate
name Input)
Name of num. To make it easier to understand the code, I've set it to nameCount, to indicate the number of name, or the size.
Restructured loops so that their counters do not modifiy nameCount by any means and only use it as a mean of comparison.
Added exit condition for the loop to terminate, -1 as well as a default case should invalid input is provided. (Does not check for
alphabet input)
Modified Code
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main()
{
int nameCount = 0, num = 0;
while (num != -1)
{
char nameIn[100];
char name[100][100];
printf("\nPress 1 to see author info\n");
printf("Press 2 to enter a name\n");
printf("Press 3 to view names\n");
printf("Press 4 to alphabatize names\n");
scanf("%d", &num);
switch(num)
{
case (1):
{
printf("----------------\n");
printf("name\n");
printf("132\n");
printf("----------------\n");
break;
}
case (2):
{
printf("Enter the name (no spaces)\n");
scanf("%s", nameIn);
strcpy(name[nameCount], nameIn);
nameCount++;
break;
}
case (3):
{
printf("\n******************************");
for (int ctr = 0; ctr<nameCount; ctr++)
{
printf("\n%s\n", &name[ctr]);
}
printf("\n\n\n******************************");
break;
}
case (4):
{
for (int ctrLv1 = 0; ctrLv1 < nameCount-1; ctrLv1++)
{
printf("\nhere here");
for (int ctrLv2 = ctrLv1+1; ctrLv2 < nameCount; ctrLv2++)
{
printf("\nif fail?\n\n\n");
if (strcmp(name[ctrLv1], name[ctrLv2]) > 0)
{
char temp[100] = "";
strcpy(temp, name[ctrLv1]);
strcpy(name[ctrLv1], name[ctrLv2]);
strcpy(name[ctrLv2], temp);
}
}
}
break;
}
case (-1):
{
printf("\nExiting...\n");
break;
}
default:
{
printf("Invalid input");
break;
}
}
}
return(0);
}

Related

I'm trying to make a program in C in which you can play hangman but as soon as it prints the option to guess the letter the program terminates

The program isn't printing after giving me the first chance to guess.
#include <stdio.h>
#include <string.h>
int main() {
char menu;
int c = 0, flag = 0, life = 8;
printf("\nWelcome to Hangman!!!");
printf("\nThis is a game of hangman.");
printf("Player 1 enters a random word and the other has to guess it.");
printf("You get 8 lives in total i.e. you can have a maximum of 8 wrong guesses.");
printf("\n");
printf("Press n for new game\n");
printf("Press q to quit\n");
printf("\n");
scanf("%c", &menu);
int i = 0, j = 0;
char w[20], ch;
if (menu == 'q') {
printf("Exiting...");
printf("Thanks for playing");
}
else if (menu == 'n') {
printf("Player 1 enters a word\n");
scanf("%s", w);
int len = strlen(w);
for (int i = 0; i < len; i++) {
toupper(w[i]);
}
printf("\e[1;1H\e[2J");
char arr[len - 1];
for (int i = 0; i < len - 1; i++) {
arr[i] = '_';
printf("%c", arr[i]);
}
printf("\n");
while (life != 0) {
for (int i = 0; i < len - 1; i++) {
if (arr[i] == '_') {
flag = 1;
break;
}
else {
flag = 0;
}
}
if (flag == 0) {
printf("You Won!!\n");
printf("You Guessed The Word: %s", w);
break;
}
else {
char ans;
printf("Enter a letter between A-Z");
scanf("%c", ans);
toupper(ans);
for (int j = 0; j < len; j++) {
if (ans == w[j]) {
arr[j] = ans;
c++;
}
}
if (c == 0) {
life--;
}
c = 0;
for (int j = 0; j < len; j++) {
printf("%c", arr[j]);
}
printf("\n Lives Remaining= %d \n", life);
}
}
if (life == 0) {
printf("\n You Lost!!! \n");
printf("The Word Was: %s", w);
}
}
else {
printf("Invalid Character");
}
}
Output:
Welcome to Hangman!!!
This is a game of hangman.Player 1 enters a random word and the other has to >guess it.You get 8 lives in total i.e. you can have a maximum of 8 wrong >guesses.
Press n for new game
Press q to quit
n
Player 1 enters a word
Hello
Enter a letter between A-Z
PS C:\Users\arora\Desktop\Programs\C>
There are quite a few problems with your program. Here are the major ones:
You want to use use space prefix in the format string for scanf(" %c", ...) to ensure previous newlines are ignored.
scanf("%c", ans); should be &ans. It causes scanf() to fail rendering the remain of the program non-interactive. Without input from the user the core game logic doesn't work.
Here are some of the other issues:
#include <ctype.h>.
(not fixed) Consider changing the menu logic so 'q' quits, and any other letter starts a game.
Game prompt contains long lines that are hard to read for the player(s).
You use a printf() per line which makes it hard to read. Use a single call and multi-line strings as input.
Try to branch your code less by making use of early return. It makes it easier to read.
Check the return value of scanf(). If it fails then whatever variable it read doesn't have a well defined value.
Ensure that scanf() read no more than 19 bytes into a 20 byte array w. It takes a little macro magic to generate the 19 so I didn't make this change but it's a good idea to #define constants for magic values like the 20.
arr is not \0 terminated (len-1). Most c programmers expect a string so it's not worth the confusion to save 1 byte.
Use a function or macro for the ANSI escape to clear the screen.
Eliminate unused variables i, j.
Reduce scope of variables (declare variables close to where you use them).
The calculation of the flag variable is cumbersome.
(not fixed) The prompt "Enter a letter between A-Z" is somewhat ambiguous. Suggest "... between A and Z".
It's generally a good idea to leave user input as you read. If you care about the repeated toupper() you can create a copy of the user input with letters in upper case, and create another variable to hold the upper case version of the player's guess. This avoid you saying things like you entered the word "BOB" when the actual input was "bob".
You attempt to use toupper() to convert each letter to upper case but don't assign the result to anything so it does not do anything constructive.
Consider some functions to document what each your code does. I added some comments for now.
(mostly not fixed) Consider using better variable names (c, w, arr, flag).
(not fixed) Should you reject a word with your magic '_' value? In general should you validate that the word is reasonable (a-z, len > 0, len < 20)?
(not fixed) Consider, in arr, just storing if a letter was correctly guess (boolean). When evaluating the state show the letter from w if it is already guessed otherwise the _.
(not fixed) If you guess a correct letter again, it's considered a good guess. Should it?
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#define clear() printf("\e[1;1H\e[2J")
int main() {
printf(
"Welcome to Hangman!!!\n"
"\n"
"This is a game of hangman.\n"
"Player 1 enters a random word and the other has to guess it.\n"
"You get 8 lives in total i.e. you can have a maximum of 8 wrong guesses.\n"
"\n"
"Press n for new game\n"
"Press q to quit\n"
);
char menu;
if(scanf(" %c",&menu) != 1) {
printf("scanf failed\n");
return 1;
}
switch(menu) {
case 'q':
printf(
"Exiting..."
"Thanks for playing\n"
);
return 0;
case 'n':
break;
default:
printf("Invalid Character");
return 1;
}
printf("Player 1 enters a word\n");
char w[20];
if(scanf("%19s", w) != 1) {
printf("scanf failed\n");
return 1;
}
clear();
char arr[20];
int len=strlen(w);
for(int i=0;i<len;i++) {
arr[i]='_';
}
arr[len] = '\0';
int life=8;
for(;;) {
printf("%d Lives Remaining\n", life);
// read a guess from player
for(int i = 0; i < len; i++) {
printf("%c", arr[i]);
}
printf(" Enter a letter between A-Z ");
char guess;
if(scanf(" %c", &guess) != 1) {
printf("scanf failed\n");
return 1;
}
// determine if any of the letters are in the secret word
int c = 0;
for(int i=0; i<len; i++) {
if(toupper(guess) == toupper(w[i])) {
arr[i]=guess;
c = 1;
}
}
if(c==0) {
life--;
}
// game over?
int flag = 0;
for(int i = 0; i<len; i++) {
if(arr[i]=='_') {
flag=1;
break;
}
}
if(flag==0) {
printf("You Won!!\n");
printf("You Guessed The Word: %s\n",w);
break;
}
if(life==0) {
printf("\n You Lost!!!\n");
printf("The Word Was: %s\n", w);
break;
}
}
}

I can not input the names into the char array using scanf

I can not use scanf to enter a name in stdnames array.
when compiled it had no error , but as soon as i enter a name and
then press enter to write the other name it gives an error and shuts the program.
How should I go about it ?
int main(int argc, char* argv[])
{
float marks[50];
/*char *stdnames[100]={"Arvind Thillainathan","Robert Lang"};*/
//I want to stores names like the above one
char *stdnames[100];
int totalNames = 0;
int i = 0, w=0,h=0;
printf("How many names do you want to enter ??\n");
scanf("%d",&totalNames);
assert(totalNames != 0);
for(int count = 0; count < totalNames; count++)
{
printf("Enter name of student\n");
scanf("%s",stdnames[count]);
//From here the problem starts
}
getres(marks,totalNames);
for(i = 0; i < totalNames; i++)
{
int v = 1;
printf("\n");
printf("IELTS Marks of %s\n\n",stdnames[i]);
for(h = w; h < w+5; h++)
{
if(v==1)
{
printf("Listening : %0.1f\n", marks[h]);
}
else if(v==2)
{
printf("Reading : %0.1f\n", marks[h]);
}
else if(v==3)
{
printf("Writing : %0.1f\n", marks[h]);
}
else if(v==4)
{
printf("Speaking : %0.1f\n", marks[h]);
}
else
{
printf("Overall : %0.1f\n\n", marks[h]);
}
v++;
//if(h==10)
//{
// break;
//}
}
w+=5;
}
return 0;
}
By
char *stdnames[100];
you got an array of (pointers to char).
The NEXT BIG QUESTION is
Who will allocate memory for each of these pointers?
A small answer would be - You have to do it yourself like below :
stdnames[count]=malloc(100*sizeof(char)); // You may replace 100 with desired size
or
stdnames[count]=malloc(100); // sizeof(char) is almost always 1
You need to put this line before the scanf statement.
Note: Don't forget to free the allocated memory once these variables become irrelevant. Do it like :
free(stdnames[count]);

delete repetition in strings

i want to write code in c language to delete any character in string s1 which matches any character in the string s2 . using only for loops. that is my trial has failed -_- .
for example if s1="ahmed" and s2="omnia" should edit s1 to >> s1="hed"
#include <stdio.h>
#include <stdlib.h>
int i,j;
int k;
int counter=0;
int main()
{
char s1[100];
char s2[10];
char temp[100];
printf("\n enter string 1: ");
scanf("%s",s1);
printf("\n enter string 2: ");
scanf("%s",s2);
printf("\n%s",s1);
printf("\n%s",s2);
for(j=0;j<9;j++)
{
for(i=0;i<9;i++)
{
if(s1[i]!=s2[j]&&s1[i]!='\0')
{
temp[counter++]=s1[i]; //add unique items to temp
k=counter; //size
temp[counter]='\0';
}
}
}
for(i=0;i<k;i++)
{
s1[i]=temp[i];
}
printf("\nstring 1 after delete : ");
printf("%s",s1);
return 0;
}
how can i compare one item with nested items then achieve a condition ??
Why are you including the null character statements inside the if statement?
Try these two statements after the two for loops, like this. And please indent your code.
for(j=0;j<strlen(s1);j++) //Why is it 9 in your code? It should be the respective lengths
{
for(i=0;i<strlen(s2);i++)
{
if(s1[i]!=s2[j]&&s1[i]!='\0')
{
temp[counter++]=s1[i];
}
}
}
k=counter;
temp[counter]='\0';
and include:#include<string.h>
I don't see any coding errors here, only your logic is flawed.
This should work
for (j = 0; j < 9; j++)
{
for (i = 0; i < 9; i++)
{
if (s1[j] == s2[i] && s1[i] != '\0')
{
break;
}
else if (i == strlen(s2))
{
temp[counter++] = s1[j];
}
}
}
temp[counter] = '\0';
for (i = 0; i < counter; i++)
{
s1[i] = temp[i];
}
printf("\nstring 1 after delete : ");
printf("%s", s1);
In your original code you kept reading the original string from the beginning, instead of advancing the iterator each time.
So in the first iteration you compared 'ahmed' against 'omnia' which is fine.
In the second iteration though, you compared 'ahmed' against 'omnia', instead of 'hmed' against 'omnia', and that's why you got a large repetition of the original string in your output.
Also, I'd memset the memory of s1 and s2 first to 0.

C Programming - comparing a const char array to a user input [duplicate]

This question already has answers here:
Why is "a" != "a" in C?
(11 answers)
Closed 8 years ago.
I cannot figure out why this code is jumping straight to pattern 5. I've looked at it several times and I just don't see it. Any help would be greatly appreciated. I am guessing it has something to do with the way that I've initialized arrays and the way I am comparing them. I have tried using 'strcmp' and currently trying to compare direct array positions. Both of these have compiled successfully, but I just can't seem to get it to work.
char one[3][3];
const char *pattern[] = {"p1","p2","p3","p4","p5"};
printf("%s Commands are {'p1', 'p2', 'p3', 'p4', 'p5'\n", prompt);
printf("Enter your first pattern choice: ");
scanf("%2s",one[0]);
printf("Enter your second pattern choice: ");
scanf("%2s",one[1]);
printf("Enter your third choice: ");
scanf("%2s",one[2]);
for (int i = 0; i < 2; i++)
{
do{
if (one[i] == "p1")
{
printf("\n1.1");
patternOne();}
else if (one[i] == "p2")
{
printf("\n1.2");
patternTwo();}
else if (one[i] == "p3")
{
printf("\n1.3");
patternThree();}
else if (one[i] == "p4")
{
printf("\n1.4");
patternFour();}
else
{
printf("\n1.5");
patternFive();
}
}
while (i < 3);
For string comparison use strcmp() function from string.h.
You are not comparing strings in C style, so it is evaluating to else.
Your expected code will probably be:
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
char one[3][3];
const char *pattern[] = { "p1", "p2", "p3", "p4", "p5" };
printf("Enter your first pattern choice: ");
scanf("%2s", one[0]);
printf("Enter your second pattern choice: ");
scanf("%2s", one[1]);
printf("Enter your third choice: ");
scanf("%2s", one[2]);
for (int i = 0; i < 2; i++)
{
if (strcmp(one[i],"p1") == 0)
{
printf("\n1.1");
patternOne();
}
else if (strcmp(one[i], "p2") == 0)
{
printf("\n1.2");
patternTwo();
}
else if (strcmp(one[i], "p3") == 0)
{
printf("\n1.3");
patternThree();
}
else if (strcmp(one[i], "p4") == 0)
{
printf("\n1.4");
patternFour();
}
else if (strcmp(one[i], "p5") == 0)
{
printf("\n1.5");
patternFive();
}
else
{
printf("Unknown input.");
}
}
return(0);
}
Changes made:
Removed the inner do-while loop as i was incremented only by the
outer for loop. Since i was not incremented inside the do-while it
can cause infinite loop.
Added an else if cluse to handle p5 input and added a separate else
to indicate that un-expected output was encountered.
Replaced if else conditions with strcmp() equallent condition
and included string.h in the file.
Edit (to answer the comment):
If you want it to display all 3 results, change:
for (int i = 0; i < 2; i++)
To
for (int i = 0; i <= 2; i++)
Currently, for i < 2 it loops for i = {0, 1} and skips for i = 2 as condition fails. If you change condition to i <= 2, it will loop for i = {0, 1, 2}.

Sorting array from typedef struct in C

Problem: Trying to sort an array coming from a typedef struct I created (phonebook).
Goal: Trying to build a phonebook that allows users to add, delete, sort, and print the phonebook.
Where I'm at: I've got everything working except the sort. I've cobbled together a sort function from reading various web forums/examples, but can't get it to work.
Issue I'm having: After adding entries (which works fine), if you try to sort entries, the function zeroes out values of those entries and when you print the phonebook, it shows all entries as blank. It should sort them alphabetically by last name.
Here's the sort algorithm I have in place:
void Sort (phone phonebook[])
{
phone temp;
int i; int j;
for (i=0; i<19; i++)
{
for (j=i+1; j<19; j++)
{
if (strcmp(phonebook[i].Surname, phonebook[j].Surname) > 0)
{
temp=phonebook[i];
phonebook[i]=phonebook[j];
phonebook[j]=temp;
}
}
}
}
Any ideas?
Full code here:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//typedef struct to define what's in the phonebook
typedef struct PhoneBookContacts
{
char Name[20];
char Surname[20];
char PhoneNumber[20];
} phone;
//Function prototypes
void AddEntry (phone[]);
void DeleteEntry (phone[]);
void PrintEntry (phone[]);
void Sort (phone[]);
int counter = 0; //Global counter variable used to keep track of number of contacts
//Begin main function
int main (void)
{
phone phonebook[20]; //Phonebook instance
char userChoice; //Variable to use to select menu choice
while (userChoice != 'Q') {
printf ("***************\n");
printf ("Please enter a command:\n");
printf("'A': Add an entry\n");
printf("'D': Delete an entry\n");
printf("'S': Sort entries\n");
printf("'P': Print the phonebook\n");
printf("'Q': Quit\n");
printf ("***************\n");
scanf("%s", &userChoice); //Stores menu choice into variable userChoice
// Add Contact
if (userChoice == 'A')
AddEntry(phonebook);
//Remove Contact
if (userChoice == 'D')
DeleteEntry (phonebook);
//Print Contacts
if (userChoice == 'P')
PrintEntry(phonebook);
//Sort Contacts
if (userChoice == 'S')
Sort(phonebook);
//Quit
if (userChoice == 'Q') {
printf("Phonebook will now quit.");
return 0;
}
}
}
//Function Definition to Add Contacts to the Phonebook
void AddEntry (phone phonebook[]) {
counter++; //global counter increase
printf("\nFirst Name: ");
scanf("%s", phonebook[counter-1].Name); //counter-1 b/c arrays start at 0
printf("Last Name: ");
scanf("%s", phonebook[counter-1].Surname);
printf("Phone Number (XXX-XXX-XXXX): ");
scanf("%s", phonebook[counter-1].PhoneNumber);
printf("\n%s added to phonebook\n", phonebook[counter-1].Name); //tell user friend added
}
void DeleteEntry (phone phonebook[])
{
int x = 0;
char deleteName[20]; // Temp string to compare to existing phonebook
char deleteSurname[20]; //temp string
char nullStr[20] = {"\0"}; // empty string to remove phonenumber
printf("\nEnter name: ");
scanf("%s", deleteName); //place into temp string
printf("Enter Surname: ");
scanf("%s", deleteSurname); //place into temp string
for (x = 0; x < counter; x++)
{
if (strcmp(deleteName, phonebook[x].Name) == 0) //compare deleteName to phonebook.Name
{
for (x = 0; x < counter; x++)
{
if (strcmp(deleteSurname, phonebook[x].Surname) == 0) //If deleteSurname matches phonebook.Surname
{
strcpy(phonebook[x].Name, nullStr); //Put null into Name
strcpy(phonebook[x].Surname, nullStr); //Null into Surname
strcpy(phonebook[x].PhoneNumber, nullStr); //Null into PhoneNumber
printf("Contact removed from phonebook.\n");
counter--;
break;
}
}
}
else printf("Invalid entry--try again.\n");
}
}
// Function def to print contacts
void PrintEntry (phone phonebook[]) {
int x = 0;
printf("\nPhonebook entries:\n");
for ( x = 0; x < counter; x++) {
printf("\n(%d)\n", x+1); //Show contact number
printf("Name: %s %s\n", phonebook[x].Name, phonebook[x].Surname); //Name
printf("Number: %s\n", phonebook[x].PhoneNumber); //Number
}
}
void Sort (phone phonebook[]) {
phone temp;
int i; int j;
for (i=0; i<19; i++) {
for (j=i+1; j<19; j++) {
if (strcmp(phonebook[i].Surname, phonebook[j].Surname) > 0) {
temp=phonebook[i];
phonebook[i]=phonebook[j];
phonebook[j]=temp;
}
}
}
}
You can use the already implemented sorting function qsort function available at stdlib.h:
int SortFunc(void* a, void* b) {
phone *p1 = (phone*)a;
phone *p2 = (phone*)b;
return strcmp(p1->Surname, p2->Surname);
}
void Sort (phone phonebook[]) {
qsort(phonebook, counter, sizeof(phone), &SortFunc);
}
The function is usually Quicksort, but that's up to the C library implementation to decide.
Update:
The blank listing is because the sorting is reversed and always sorting all the 19 items of the phonebook, comparing the empty ones against the real ones. If you have less than 19 entries on the phonebook, the actual data is going to be present at the end of the phonebook array.
Your original Sort function was always working almost OK. Just change the end condition on the two for.
void Sort (phone phonebook[]) {
phone temp;
int i; int j;
for (i=0; i<counter; i++) {
for (j=i+1; j<counter; j++) {
if (strcmp(phonebook[i].Surname, phonebook[j].Surname) > 0) {
temp=phonebook[i];
phonebook[i]=phonebook[j];
phonebook[j]=temp;
}
}
}
}
I've also updated my Sort above.
First things first, you have a buffer overflow issue here:
char userChoice;
:
scanf("%s", &userChoice);
That scanf will write two bytes when you enter one character (the character plus a null terminator). This corrupted the first name of the first phonebook entry in my environment but, since it's undefined behaviour, it could do anything!
You can get around this by using:
char userChoice[] = "something that's not Q";
:
scanf("%s", userChoice);
:
if (*userChoice == 'A') // for all of these.
That won't stop a buffer overflow if you enter enough text but it will if you limit yourself to single character commands. If you want a truly robust user input function, see here.
Now to your specific problem. It looks like you have a bit of a bubble sort going on there, but your logic is slightly off. Assuming you don't want to use qsort (which would be the better way for real code), you just need to fix up a couple of things.
Your outer loop is okay, as is your inner loop, but the inner loop body should be comparing elements j and j+1, not j and i. That's because it works by swapping adjacent elements if they're out of order.
In addition, a forward focused bubble sort will place the highest element at the end of the list on the first pass, so you can't start j at i+1 on the second pass, simply because the first element may not be correct yet.
The following psuedo-code is your classic bubble sort:
didSwap = true
while didSwap:
didSwap = false
for i = 0 to lastidx - 1:
if array[i] > array[i+1]:
temp = array[i]
array[i] = array[i+1]
array[i+1] = temp
didSwap = true
Read that, understand how it works, then implement it on your own. If you have trouble with that, I've included a working version below:
void Sort (phone phonebook[]) {
phone temp;
int i; int didSwap;
didSwap = 1;
while (didSwap) {
didSwap = 0;
for (i = 0; i < counter - 1; i++) {
if (strcmp(phonebook[i].Surname, phonebook[i+1].Surname) > 0) {
temp=phonebook[i];
phonebook[i]=phonebook[i+1];
phonebook[i+1]=temp;
didSwap = 1;
}
}
}
}
for (i=0; i<19; i++)
{
for (j=i+1; j<19; j++)
{
if (strcmp(phonebook[i].Surname, phonebook[j].Surname) > 0)
{
temp=phonebook[i];
phonebook[i]=phonebook[j];
phonebook[j]=temp;
}
}
}
Three problems with your code. First is the logic of your algorithm. Bubble sort works by fixing the order of two adjacent element. In your code, after the first iteration of your inner for loop, it's not going to compare two adjacent elements.
The second problem, again in sorting algorithm, your counters i and j are both going to 19, even when there is less entries than that. This might mess up the sorting as they will be reading invalid(uninitialized) entry. you should check the upper bound for the counter.
The next one is in the deletion
if (strcmp(deleteName, phonebook[x].Name) == 0) //compare deleteName to phonebook.Name
{
for (x = 0; x < counter; x++)
{
if (strcmp(deleteSurname, phonebook[x].Surname) == 0) //If deleteSurname matches phonebook.Surname
{
strcpy(phonebook[x].Name, nullStr); //Put null into Name
strcpy(phonebook[x].Surname, nullStr); //Null into Surname
strcpy(phonebook[x].PhoneNumber, nullStr); //Null into PhoneNumber
printf("Contact removed from phonebook.\n");
counter--;
break;
}
}
}
The code above will not check properly whether the first and last name since you're checking them separately. You only need one for loop with if( strcmp(deleteSurname, phonebook[x].Surname) == 0 && strcmp(deleteName, phonebook[x].Name) == 0 )

Resources