I am trying to implement recursive bubblesort for array of structures. But, it is giving wrong output when I sort the array by Employee name. I am not able to figure out what I am missing. Any help is appreciated.
#include<stdio.h>
#include<stdlib.h>
// GLOBAL VARIABLES
char *stringDataType = "string";
char *integerDataType = "integer";
// Employee structure
struct Employee
{
char *name;
int age;
};
// Method to swap two structures by reference.
void Swap(struct Employee *first, struct Employee *second)
{
struct Employee temp = *first;
*first = *second;
*second = temp;
}
// Method to check if the first string is greater than second string or not
// 1 if the first string is greater
// -1 if the seond string is greater
// 0 if both the strings are equal
int IsGreaterThan(char **first , char **second)
{
int index = 0;
while(*((*first)+index) == *((*second)+index))
{
index++;
}
if(*((*first)+index) > *((*second)+index))
{
return 1;
}
else if(*((*first)+index) < *((*second)+index))
{
return -1;
}
else
{
return 0;
}
}
// Method to check if the first structure is greater than second structure or not
// 1 if the first structure is greater
// -1 if the seond structure is greater
// 0 if both the structure are equal
int IsStructGreaterThan(struct Employee *first, struct Employee *second)
{
int index = 0;
return IsGreaterThan(&(*first).name, &(*second).name);
}
// Bubble Sort Method
void BubbleSort(struct Employee array[], int size, char *dataType, int swapped)
{
int i;
if(swapped == 0 || size == 0)
{
return;
}
for(i = 0; i < size - 1; i++)
{
swapped = 0;
if(dataType==stringDataType && (IsStructGreaterThan(&array[i], &array[i+1]) == 1) || dataType==integerDataType && array[i].age > array[i+1].age)
{
Swap(&array[i], &array[i + 1]);
swapped = 1;
}
}
BubbleSort(array, size-1, dataType, swapped);
}
// Entry point of the program
int main()
{
struct Employee array[] = {{"John", 45}, {"Mary", 23}, {"Celina", 79}, {"Mike", 41}};
int arraySize = 4;
int index;
printf("Before Sorting : \n");
for(index = 0; index < arraySize; index++)
{
printf("(%s, %d) ", array[index].name, array[index].age);
}
printf("\n");
int swapped = 1;
BubbleSort(array, arraySize, stringDataType, swapped);
printf("After Sorting by name : \n");
for(index = 0; index < arraySize; index++)
{
printf("(%s, %d) ", array[index].name, array[index].age);
}
printf("\n");
BubbleSort(array, arraySize, integerDataType, swapped);
printf("After Sorting by age : \n");
for(index = 0; index < arraySize; index++)
{
printf("(%s, %d) ", array[index].name, array[index].age);
}
printf("\n");
return 0;
}
OUTPUT
Before Sorting :
(John, 45) (Mary, 23) (Celina, 79) (Mike, 41)
After Sorting by name :
(John, 45) (Celina, 79) (Mary, 23) (Mike, 41)
After Sorting by age :
(Mary, 23) (Mike, 41) (John, 45) (Celina, 79)
Strings should be compared by strcmp() instead of comparison operators.
You could change IsStructGreaterThan() into
int IsStructGreaterThan(struct Employee *first, struct Employee *second)
{
return strcmp(first->name, second->name);
}
put swapped = 0 before the for-loop, not inside it, and fix the string comparison as per other answers.
Related
I have made one program, where you enter a few characters (10 max). It makes you a list, count average length of surnames, tell about how much different names. But the problem is, when I enter the last number (10) - it sorts me it incorrectly (like 39399349349, 3443993). Beneath I will present my code. I am newbie in C, so please don't shut on me) I am convinced that sorting function is incorrect, but don't know what exactly(
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct people {
int num[10];
char surname[20];
char name[10];
} peoples[10], c;
int compare_people_num(const void *a, const void *b);
int main()
{
int i, j, k = 0, l = 0, m = 0, n = 0;
float s = 0;
char str[100];
system("chcp 1251 > nul");
for (i = 0, j = 0; i < 10; i++, j++)
{
printf("Enter number, surname, name %d of your human: ", i + 1);
fgets(str, sizeof str, stdin);
sscanf(str, "%d %s %s", &peoples[j].num, &peoples[j].name, &peoples[j].name);
while (str[n] != '\n')
{
if (str[n] != ' ')
{
peoples[j].num[k] = str[n];
}
else
break;
n++;
k++;
}
n++;
k = 0;
while (str[n] != '\n')
{
if (str[n] != ' ')
{
peoples[j].surname[k] = str[n];
}
else
break;
n++;
k++;
}
n++;
k = 0;
while (str[n] != '\n')
{
if (str[n] != '\0')
{
peoples[j].name[k] = str[n];
}
else
break;
n++;
k++;
}
n = 0;
k = 0;
}
for (i = 0; i < 10; i++)
{
for (j = i + 1; j < 10; j++)
{
if (!strcmp(peoples[i].name, peoples[j].name))
m = 1;
}
if (m == 0)
l++;
m = 0;
s = s + strlen(peoples[i].surname);
}
for (i = 0; i < 9; i++)
for (j = 0; j < 9; j++)
if (strcmp(peoples[j].num, peoples[j+1].num) > 0)
{
qsort(peoples, 10, sizeof(struct people), &compare_people_num);
}
for (i = 0; i < 10; i++)
{
printf("%d ", peoples[i].num);
printf("%s ", peoples[i].name);
printf("%s ", peoples[i].surname);
printf("\n");
}
printf("\nYou have %d different names\n", l);
printf("Avarege lenght of surname is = %f\n", s / 10);
}
int compare_people_num(const void *a, const void *b)
{
const struct people *p1 = a;
const struct people *p2 = b;
return p1->num - p2->num; // Change order to reverse sort
}
I went through your code and removed things that weren't needed. In both your input and sorting, it seemed like you were doing things twice. I tried to document the changes I made and explain why they should be made.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// It's generally a good idea to use #define when you have some global constants
// I made some of the constants larger than what you showed to prevent issues
#define MAX_NAME_LEN 40
#define MAX_SURNAME_LEN 40
#define NUM_PEOPLE 10
#define BUFF_LEN 100
// Separate your struct...
struct person {
int num;
char name[MAX_NAME_LEN];
char surname [MAX_SURNAME_LEN];
};
// ... and array decleration
static struct person people[NUM_PEOPLE];
// I added this function, to make it easier to display a person
void print_person (const struct person * p) {
printf("Person %d %s %s\n", p->num, p->name, p->surname);
}
// This function will print out every person in the people array
void print_people (void) {
for (int i=0; i<NUM_PEOPLE; i++) {
print_person(&people[i]);
}
}
// Compares two people by number
int compare_people_num (const void * a, const void * b) {
struct person * p0 = (struct person *) a;
struct person * p1 = (struct person *) b;
return p0->num - p1->num;
}
// Compares two people by name
int compare_people_name (const void * a, const void * b) {
struct person * p0 = (struct person *) a;
struct person * p1 = (struct person *) b;
return strcmp(p0->name, p1->name);
}
int main (void) {
int i;
char buffer[BUFF_LEN];
for (i=0; i<NUM_PEOPLE; i++) {
printf("Enter number, surname, and name of person %d: ", i+1);
fflush(stdout); // fflush makes sure that our text is shown to the user
fgets(buffer, BUFF_LEN, stdin); // Read user input in to buffer
// It's unclear what you were doing here
// This sscanf line takes a line of text, and splits it into a number and two words
// It then stores that number in people[i].num, and stores the words in name and surname
// However, right after this, you have several while loops that appear to be manually doing the same
// thing all over again. If you want to read all of the input in, just the line below is enough
sscanf(buffer, "%d %s %s", &people[i].num, people[i].name, people[i].surname);
}
// We've read all of the people in now
// Uncomment the next line to check out the output at this state:
// print_people();
// To count names, we first need to sort the people by their name
// We do this using a qsort call
qsort(people, NUM_PEOPLE, sizeof(struct person), compare_people_name);
// Once the names are sorted, we'll calculate how many different names there are
// We start the count at 1, and start checking from the second person (index 1)
// This is because the first person will always be unqiue, and we can't compare to
// person negative 1
int n_names = 1;
for (i=1; i<NUM_PEOPLE; i++) {
char * current = people[i].name;
char * previous = people[i-1].name;
if (!strcmp(current, previous)) {
n_names ++;
}
}
// Now we have to sort the people based on their num field
// Again, in your code, it looked like you were doing this more than nessecary
// We just have to call qsort once, as such
qsort(people, NUM_PEOPLE, sizeof(struct person), compare_people_num);
// We will also do a loop through to calculate the average surname length
float avg_surname_len = 0;
for (i=0; i<NUM_PEOPLE; i++) {
avg_surname_len += (float)strlen(people[i].surname);
}
avg_surname_len /= (float)NUM_PEOPLE;
// We're all done! The people are sorted by number.
print_people();
printf("There are %d unique names\n", n_names);
printf("The average surnames is %f characters\n", avg_surname_len);
}
I have a C program that takes an array of strings, sorts using selection sort, and also searches a string in the sorted list. The selection sort doesn't work.
The code to display the string is OK. I also tried to verify if the smallest string is identified and yes it does. But it is not moved in its correct position as the selection sort should work. In the main function after displaying the unsorted strings, the program terminates. Where am I not doing the right thing?
Here is the code for the entire program:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void doDisplay(char *council[15], int size) {
int i;
for (i = 0; i < 15; i++) {
//printf("\n%s", council[i]);
puts(council[i]);
}
}
void select(char *council[15], int size) {
int pass, i, smallest;
char temp[];
for (pass = 0; pass < size; pass++) {
smallest = pass;
for (i = pass + 1; i < size; i++) {
if (strcmp(council[i], council[i - 1]) < 0) {
smallest = i;
}
}
printf("Value of smallest is: %d\n", smallest);
if (smallest != pass) {
strcpy(temp, council[pass]);
strcpy(council[pass], council[smallest]);
strcpy(council[smallest], temp);
}
}
}
int BinSearch(char *council[15], char *name, int min, int max) {
int mid;
min = 0;
max = 15;
while (min < max) {
int mid = (min + max) / 2;
if (strcmp(council[mid], name) == 0) {
printf("%s", name);
return 1;
} else
if (strcmp(council[mid], name) > 1) {
max = mid - 1;
BinSearch(council, name, min, max);
} else {
min = mid + 1;
BinSearch(council, name, min, max);
}
}
}
int main() {
int result = 0;
char *key;
char *council[15] = {
"Bert", "Jeff", "Gary", "Neba", "Chang",
"Olga", "Nora", "Mary", "Vera", "Rani",
"Neil", "Jill", "Cain", "Lara", "Bart"
};
printf("Before Sorting\n");
doDisplay(council, 15);
select(council, 15);
printf("\nAfter Sorting");
doDisplay(council, 15);
printf("Enter search key: ");
gets(key);
scanf("%s", &key);
result = BinSearch(council, &key, 0, 15);
return 0;
}
There are multiple problems in your code:
the strings in the array are string literals, modifying them has undefined behavior. You should swap the pointers, not the string contents
char temp[]; is an invalid definition. Arrays must be defined with an fixed length either specified between the brackets or determined from the initializer at compile time.
the test strcmp(council[mid], name) > 1 is incorrect, you should compare to 0.
gets() is obsolete, do not use this function.
scanf("%s", &key); is invalid: key is an uninitialized pointer, passing its address is a type mismatch. You should pass an array of sufficient length.
Here is a modified version:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void doDisplay(char *council[], int size) {
int i;
for (i = 0; i < size; i++) {
puts(council[i]);
}
}
void select(char *council[], int size) {
int pass;
for (pass = 0; pass < size; pass++) {
int smallest = pass;
int i;
for (i = pass + 1; i < size; i++) {
if (strcmp(council[i], council[smallest]) < 0) {
smallest = i;
}
}
if (smallest != pass) {
char *temp = council[pass];
council[pass] = council[smallest];
council[smallest] = temp;
}
}
}
int BinSearch(char *council[], const char *name, int size) {
int min = 0, max = size;
while (min < max) {
int mid = min + (max - min) / 2;
int cmp = strcmp(council[mid], name)
if (cmp == 0) {
return mid;
} else
if (cmp > 0) {
max = mid;
} else {
min = mid + 1;
}
}
return -1;
}
int main() {
char *council[15] = {
"Bert", "Jeff", "Gary", "Neba", "Chang",
"Olga", "Nora", "Mary", "Vera", "Rani",
"Neil", "Jill", "Cain", "Lara", "Bart"
};
int length = sizeof(council) / sizeof(council[0]);
char key[20];
int result;
printf("Before Sorting\n");
doDisplay(council, length);
select(council, length);
printf("After Sorting\n");
doDisplay(council, length);
printf("Enter search key: ");
scanf("%19s", key);
result = BinSearch(council, key, length);
if (result < 0) {
printf("%s not found\n", key);
} else {
printf("%s found at %d\n", key, res);
}
return 0;
}
Good afternoon, i am trying to do a program that checks whether if a expression has its parentheses balanced or not but because of some problem that i can't quite find out the program is crashing, could somebody help me find a way so that the program works?
In
a * b - (2 + c)
Out
Correct
or
In
)3+b * (2-c)(
Out
Incorrect
The program should check only for parantheses and i am supposed to implement linear lists on the code.
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define SUCESSO 1 //Succes
#define FALHA -1 //Failure
#define CELULA_INVALIDA 0 //Invalid key
#define TAMANHO_MAXIMO 1000 //Max size
typedef struct{
char exp[1000];
unsigned int chave; //key
}celula; //node
typedef struct{
celula celulas[TAMANHO_MAXIMO]; //vector of nodes
unsigned int tamanho; //size of the list
}fila; //list
int criarFilaVazia(fila * ent){ //create an empty list
ent->tamanho = 0;
return(SUCESSO);
}
int insFinal(fila * ent, celula node){ //put a node on the end of the list
unsigned int i;
celula aux;
if(ent->tamanho == TAMANHO_MAXIMO){
return(FALHA);
}
else{
ent->celulas[ent->tamanho] = node;
ent->tamanho++;
return(SUCESSO);
}
}
void mostrarCelula(celula ent){ //show node
printf("%s \n", ent.exp);
}
void mostrarFila(fila ent){ //show entire list
unsigned int i;
if(ent.tamanho == 0){
printf("Fila vazia");
}
else{
printf("A fila possui %u element \n", ent.tamanho);
for(i=0; (i < ent.tamanho); i++){
printf("Elemento %u \n \n", (i+1));
mostrarCelula(ent.celulas[i]);
}
}
}
int main(){
int i, j;
fila exp;
celula aux;
scanf("%s", &aux.exp);
getchar();
aux.chave = 0;
insFinal(&exp, aux);
for(i = 0; i < strlen(exp.celulas[0].exp); i++){//checks all the array
if(exp.celulas[0].exp[i] == '('){//if there is an opening
for(j = i; j < strlen(exp.celulas[0].exp); j++){
if(exp.celulas[0].exp[j] == ')'){//should be and ending
exp.celulas[0].exp[i] = 0;//removes if balanced
exp.celulas[0].exp[j] = 0;
}
}
}
}
//checks for remaining parentheses and prints the output
for(i = 0; i < strlen(exp.celulas[0].exp); i++){
if(exp.celulas[0].exp[i] == '(' || exp.celulas[0].exp[i] == ')'){
printf("Incorreta"); //incorrect
}
else{
printf("Correta"); //correct
}
}
return 0;
}
[enter image description here][1]
Error message: https://i.stack.imgur.com/aeSn5.png
it says ex06 stopped working
Your program is crashing inside insFinal because the ent parameter passed in from main has uninitialized data. Hence, undefined behavior. Ammend these two lines at the beginning of main:
fila exp;
celula aux;
With this:
fila exp = {0};
celula aux = {0};
That will zero-init both.
The thing I don't get is what all these data structures are used for. Nor do I understand the double-nested for loop for checking the balance. Checking for a balanced set of parentheses in an expression should be as simple as this:
int areParenthesesBalanced(const char* str)
{
int balance = 0;
int len = str ? strlen(str) : 0;
for (int i = 0; i < len; i++)
{
if (str[i] == '(')
{
balance++;
}
else if (str[i] == ')')
{
balance--;
if (balance < 0)
{
return 0;
}
}
}
return (balance == 0) ? 1 : 0;
}
int main() {
char str[1000];
scanf("%s", str);
if (areParenthesesBalanced(str))
{
printf("Incorreta\n");
}
else
{
printf("Correta\n");
}
return 0;
}
I have the following struct
struct candidates
{
char name[20];
int votes;
};
struct candidates electionCandidates[];
I need to read in from a file and update the names electionCandidates[0] through 7.
I can do so with the following
for (i = 0; i < 7; i++)
{
fgets(electionCandidates[i].name, 20, (FILE*)fp);
}
But I need to do this in a function.
I have tried
void Initialize(struct candidates* EC[]);
Initialize(&electionCandidates);
void Initialize(struct candidates* EC[])
{
int i;
FILE *fp;
fp = fopen("elections.txt", "r");
for (i = 0; i < 7; i++)
{
fgets(EC[i].name, 20, (FILE*)fp);
}
fclose(fp);
}
Keeps saying it doesn't see name. Or the whole thing could be wrong. I am not sure.
Any help would be appreciated.
You need to look at your Initialize() function signature, and turn on your compiler warnings (or pay attention to them if they're already on). You are declaring Initialize() to take an array of pointers to struct candidates, which is not what you are passing - an array of struct candidates. The array decays to a pointer, so struct candidates *EC is what your argument should look like (or, alternately, struct candidates EC[], which is equivalent in this case), not struct candidates *EC[]. And then call your function without the &...
Given
struct candidates
{
char name[20];
int votes;
};
struct candidates electionCandidates[];
You want
void Initialize(struct candidates EC[])
{
/* ... */
}
Initialize(electionCandidates);
When passed as a function argument, the array of structs decays to a pointer to its first element.
I got it loading the names and everything but I guess I need to point to SPOIL in this? It is not reading or doing the votes/spoiled votes, giving 0 for both.
#include <stdio.h>
struct candidates
{
char name[20];
int votes;
};
struct candidates electionCandidates[7];
void Initialize(struct candidates EC[]);
void Processvotes(struct candidates EC[], int BadVote);
void printResults(struct candidates EC[], int BadVote);
int main()
{
int i, SPOIL = 0;
Initialize(electionCandidates);
Processvotes(electionCandidates, SPOIL);
printResults(electionCandidates, SPOIL);
}
void Initialize(struct candidates EC[])
{
int i;
FILE *fp;
fp = fopen("elections.txt", "r");
for (i = 0; i < 7; i++)
{
fgets(EC[i].name, 20, (FILE*)fp);
}
fclose(fp);
}
void Processvotes(struct candidates EC[], int BadVote)
{
int TVOTE, i;
FILE *fp;
fp = fopen("elections.txt", "r");
fscanf(fp, "%d", &TVOTE);
for (i = 0; i < 365; i++)
{
if (TVOTE == 1)
EC[0].votes++;
if (TVOTE == 2)
EC[1].votes++;
if (TVOTE == 3)
EC[2].votes++;
if (TVOTE == 4)
EC[3].votes++;
if (TVOTE == 5)
EC[4].votes++;
if (TVOTE == 6)
EC[5].votes++;
if (TVOTE == 7)
EC[6].votes++;
if (TVOTE < 1 || TVOTE > 7)
BadVote++;
}
fclose(fp);
}
void printResults(struct candidates EC[], int BadVote)
{
int i, Win = 0, WinSCORE = 0, Runner = 0, RunnerSCORE = 0;
for (i = 0; i < 7; i++)
{
if (EC[i].votes > WinSCORE)
{
WinSCORE = EC[i].votes;
Win = i;
}
if (EC[i].votes == WinSCORE)
{
RunnerSCORE = EC[i].votes;
Runner = i;
}
}
if (WinSCORE == RunnerSCORE)
{
printf("There was a tie between %s and %s who both got a total of %d votes each. There were %d spoiled votes\n", EC[Win].name, EC[Runner].name, WinSCORE, BadVote);
}
else
printf("%s won the election with a total of %d votes. There was a total of %d spoiled votes.\n", EC[Win].name, WinSCORE, BadVote);
}
I'm trying write a program that takes a list of names, sorts those names, and allows the user to search for a name from that list. The program compiles, but once the user has entered "y" to search for a name and has entered the name he wishes to search for, the program just freezes.
I appreciate any help!
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#define NUM_OF_NAMES 8
#define NAME_SIZE 5
void printNames(char names[][NAME_SIZE], int size);
void bubbleSortNames(char names[][NAME_SIZE], int last);
bool binarySearchNames(char list[][NAME_SIZE], int end, char target[], int *location);
int main()
{
char nameList[NUM_OF_NAMES][NAME_SIZE] = {"Bob", "Sue", "Jake","Rod", "Jon", "Ash", "Deb", "Kay"};
char searchText[NAME_SIZE];
char userChoice;
int searchLocation;
printf("\n\n\nLIST BEFORE SORTING\n");
printNames(nameList, NUM_OF_NAMES);
bubbleSortNames(nameList, NUM_OF_NAMES);
printf("\n\n\nLIST AFTER SORTING\n");
printNames(nameList, NUM_OF_NAMES);
printf("\n\n\nWould you like to search for a name? (y/n) ");
scanf(" %s", &userChoice);
while(userChoice == 'y')
{
printf("\n\n\nPlease try to search for a name: ");
scanf("%s", searchText);
if(!(binarySearchNames(nameList, NUM_OF_NAMES, searchText, &searchLocation)))
printf("\n\n\nThe name %s was not found.\n", searchText);
else
printf("\n\n\nThe name %s was found at location %d!", searchText, searchLocation);
}
printf("\n\n\nThank you for using this program.\n\n\n");
return 0;
}
/********************************
Prints the names from the array.
********************************/
void printNames(char names[][NAME_SIZE], int size)
{
int index;
for(index = 0; index < size; index++)
puts(names[index]);
return;
}
/*******************************
Sorts the names from the array.
*******************************/
void bubbleSortNames(char names[][NAME_SIZE], int last)
{
char temp[NAME_SIZE];
int current;
int walker;
for(current = 0; current < last; current++)
{
for(walker = last; walker > current; walker--)
{
if(strcmp(names[walker], names[walker - 1]) < 0)
{
strncpy(temp, names[walker - 1], sizeof(temp) - 1);
strncpy(names[walker - 1], names[walker], sizeof(names[walker - 1]) - 1);
strncpy(names[walker], temp, sizeof(names[walker]) - 1);
}
}
}
return;
}
/*********************************
Searches for names to be printed.
*********************************/
bool binarySearchNames(char list[][NAME_SIZE], int end, char target[], int* location)
{
int first = 0,
last,
mid;
last = end;
while(first <= last);
{
mid = (first + last) / 2;
if(strcmp(target, list[mid]) > 0)
first = mid + 1;
else if(strcmp(target, list[mid]) < 0)
last = mid - 1;
else
first = last + 1;
}
*location = mid + 1;
return (strcmp(target, list[mid]) == 0);
}
In function binarySearchNames:
while(first <= last) you put a ;
This results in an endless loop.
Try using a debugger when encountering such problems.
scanf(" %s", &userChoice);
Have you tried removing the space before the %s and replacing the %s with a %c? Both could cause issues.