problem with dynamic array and pointers in selection sort - arrays

i make a program of selection sort using dynamic array and pointers but after running this code i found that array is being sorted if we give the size input like 4 and 6 but does't sort properly if the size input is like 5 and 7 etc ...i also did bubble sort program before this using same technique of pointers and dynamic array but it gave perfect sorted array in all the condition , i also try to debuge the code but still don't understand why this is happening if anyone having idea about this then please help me out .
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
int main()
{
int * ptr,temp,min;
int size,i,j,s;
printf("Enter the size of array:");
scanf("%d",&size);
ptr = (int *)(calloc (size,sizeof(int)));
if(ptr == NULL)
printf("No memory");
else
{
printf("\n=== RANDOM ELEMENTS OF ARRAY ===\n");
for(s=0;s<size;s++)
*(ptr+s) = rand()%100;
for(s=0;s<size;s++)
printf("\nElement [%d] = %d ",s,*(ptr+s));
// selection sort algorithm
for(i=0;i< size-1;i++)
{
min = i;
for(j=i+1;j<size;j++)
{
if(*(ptr+j) < *(ptr+min))
{
min = j;
}
temp = *(ptr+i);
*(ptr+i) = *(ptr+min);
*(ptr+min) = temp;
}
}
// End of algorithm
printf("\n\n======= SORTED ELEMENTS =======\n\n");
for(s=0;s<size;s++)
printf("Element [%d] = %d \n",s,*(ptr+s));
}
}

Your Selection Sort algorithm seems to be wrong. You have to replace the element in the current index with the minimum after the inner for loop finishes iteration:
for(i=0;i< size-1;i++)
{
min = i;
for(j=i+1;j<size;j++)
{
if(*(ptr+j) < *(ptr+min))
{
min = j;
}
}
temp = *(ptr+i);
*(ptr+i) = *(ptr+min);
*(ptr+min) = temp;
}
Now, it should work for all input sizes.

Clearing away a couple of unnecessary confusion factors...
*(ptr + index)
Is identical to
ptr[index]
But the second is much easier to read.
Next, in the following section the variable min is introduced,
if(*(ptr+j) < *(ptr+min))
{
min = j;
}
...but is not necessary for a simple sort. Just stick with i and j and the sort will proceed correctly for either even or odd sets of values. Finally, to eliminate the memory leak, call free(ptr); when ptr is no longer needed. Following is a cleaned up version, with corrections.
int main(void)//added void
{
int * ptr,temp/*,min*/;
int size,i,j,s;
printf("Enter the size of array:");
scanf("%d",&size);
ptr = calloc (size,sizeof(int));//casting is required in C++
//but unnecessary in C.
//(and can be problematic)
if(ptr == NULL)
{
printf("No memory");
}
else
{
printf("\n=== RANDOM ELEMENTS OF ARRAY ===\n");
for(s=0;s<size;s++)
ptr[s] = rand()%100;
for(s=0;s<size;s++)
printf("\nElement [%d] = %d ",s,ptr[s]);
// selection sort algorithm
for(i=0;i< size-1;i++)
{
for(j=i+1;j<size;j++)//removed if section introducing 'min'
{
if(ptr[j] < ptr[i])
{
temp = ptr[i];
ptr[i] = ptr[j];
ptr[j] = temp;
}
}
}
// End of algorithm
printf("\n\n======= SORTED ELEMENTS =======\n\n");
for(s=0;s<size;s++)
printf("Element [%d] = %d \n",s,*(ptr+s));
free(ptr);
}
return 0;//added
}
BTW, this was tested with size == 3 and
ptr[0] = 3;
ptr[1] = 2;
ptr[2] = 1;
along with several other odd and even counts of random values

Related

last number in a function array

I want to write a function where I have a given array and number N. The last occurrence of this number I want to return address. If said number cannot be found I want to use a NULL-pointer
Start of the code I've made:
int main(void) {
int n = 3;
int ary[6] = { 1,3,7,8,3,9 };
for (int i = 0; i <= 6; i++) {
if (ary[i] == 3) {
printf("%u\n", ary[i]);
}
}
return 0;
}
result in command prompt:
3
3
The biggest trouble I'm having is:
it prints all occurrences, but not the last occurrence as I want
I haven't used pointers much, so I don't understand how to use the NULL-pointer
I see many minor problems in your program:
If you want to make a function, make a function so your parameters and return types are explicit, instead of coding directly in the main.
C arrays, like in most languages, start the indexing at 0 so if there are N element the first has index 0, then the second has 1, etc... So the very last element (the Nth) has index N-1, so in your for loops, always have condition "i < size", not "i <= size" or ( "i <= size-1" if y'r a weirdo)
If you want to act only on the last occurence of something, don't act on every. Just save every new occurence to the same variable and then, when you're sure it was the last, act on it.
A final version of the function you describe would be:
int* lastOccurence(int n, int* arr, int size){
int* pos = NULL;
for(int i = 0; i < size; i++){
if(arr[i] == n){
pos = &arr[i]; //Should be equal to arr + i*sizeof(int)
}
}
return pos;
}
int main(void){
int n = 3;
int ary[6] = { 1,3,7,8,3,9 };
printf("%p\n", lastOccurence(3, ary, 6);
return 0;
}
Then I'll add that the NULL pointer is just 0, I mean there is literally the line "#define NULL 0" inside the runtime headers. It is just a convention that the memory address 0 doesn't exist and we use NULL instead of 0 for clarity, but it's exactly the same.
Bugs:
i <= 6 accesses the array out of bounds, change to i < 6.
printf("%u\n", ary[i]); prints the value, not the index.
You don't actually compare the value against n but against a hard-coded 3.
I think that you are looking for something like this:
#include <stdio.h>
int main(void)
{
int n = 3;
int ary[6] = { 1,3,7,8,3,9 };
int* last_index = NULL;
for (int i = 0; i < 6; i++) {
if (ary[i] == n) {
last_index = &ary[i];
}
}
if(last_index == NULL) {
printf("Number not found\n");
}
else {
printf("Last index: %d\n", (int)(last_index - ary));
}
return 0;
}
The pointer last_index points at the last found item, if any. By subtracting the array's base address last_index - ary we do pointer arithmetic and get the array item.
The cast to int is necessary to avoid a quirk where subtracting pointers in C actually gives the result in a large integer type called ptrdiff_t - beginners need not worry about that one, so just cast.
First of all, you will read from out of array range, since your array last element is 5, and you read up to 6, which can lead in segmentation faults. #Ludin is right saying that you should change
for (int i = 0; i <= 6; i++) // reads from 0 to 6 range! It is roughly equal to for (int i = 0; i == 6; i++)
to:
for (int i = 0; i < 6; i++) // reads from 0 to 5
The last occurrence of this number I want to return as address.
You are printing only value of 3, not address. To do so, you need to use & operator.
If said number cannot be found I want to use a NULL-pointer
I don't understand, where do you want to return nullpointer? Main function can't return nullpointer, it is contradictory to its definition. To do so, you need to place it in separate function, and then return NULL.
If you want to return last occurence, then I would iterate from the end of this array:
for (int i = 5; i > -1; i--) {
if (ary[i] == 3) {
printf("place in array: %u\n", i); // to print iterator
printf("place in memory: %p\n", &(ary[i])); // to print pointer
break; // if you want to print only last occurence in array and don't read ruther
}
else if (i == 0) {
printf("None occurences found");
}
}
If you want to return an address you need yo use a function instead of writing code in main
As you want to return the address of the last occurence, you should iterate the array from last element towards the first element instead of iterating from first towards last elements.
Below are 2 different implementations of such a function.
#include <stdio.h>
#include <assert.h>
int* f(int n, size_t sz, int a[])
{
assert(sz > 0 && a != NULL);
// Iterate the array from last element towards first element
int* p = a + sz;
do
{
--p;
if (*p == n) return p;
} while(p != a);
return NULL;
}
int* g(int n, size_t sz, int a[])
{
assert(sz > 0 && a != NULL);
// Iterate the array from last element towards first element
size_t i = sz;
do
{
--i;
if (a[i] == n) return &a[i];
} while (i > 0);
return NULL;
}
int main(void)
{
int n = 3;
int ary[] = { 1,3,7,8,3,9 };
size_t elements = sizeof ary / sizeof ary[0];
int* p;
p = g(n, elements, ary); // or p = f(n, elements, ary);
if (p != NULL)
{
printf("Found at address %p - value %d\n", (void*)p, *p);
}
else
{
printf("Not found. The function returned %p\n", (void*)p);
}
return 0;
}
Working on the specified requirements in your question (i.e. a function that searches for the number and returns the address of its last occurrence, or NULL), the code below gives one way of fulfilling those. The comments included are intended to be self-explanatory.
#include <stdio.h>
// Note that an array, passed as an argument, is converted to a pointer (to the
// first element). We can change this in our function, because that pointer is
// passed BY VALUE (i.e. it's a copy), so it won't change the original
int* FindLast(int* arr, size_t length, int find)
{
int* answer = NULL; // The result pointer: set to NULL to start off with
for (size_t i = 0; i < length; ++i) { // Note the use of < rather than <=
if (*arr == find) {
answer = arr; // Found, so set our pointer to the ADDRESS of this element
// Note that, if multiple occurrences exist, the LAST one will be the answer
}
++arr; // Move on to the next element's address
}
return answer;
}
int main(void)
{
int num = 3; // Number to find
int ary[6] = { 1,3,7,8,3,9 }; // array to search
size_t arrlen = sizeof(ary) / sizeof(ary[0]); // Classic way to get length of an array
int* result = FindLast(ary, arrlen, num); // Call the function!
if (result == NULL) { // No match was found ...
printf("No match was found in the array!\n");
}
else {
printf("The address of the last match found is %p.\n", (void*)result); // Show the address
printf("The element at that address is: %d\n", *result); // Just for a verification/check!
}
return 0;
}
Lots of answers so far. All very good answers, too, so I won't repeat the same commentary about array bounds, etc.
I will, however, take a different approach and state, "I want to use a NULL-pointer" is a silly prerequisite for this task serving only to muddle and complicate a very simple problem. "I want to use ..." is chopping off your nose to spite your face.
The KISS principle is to "Keep It Simple, St....!!" Those who will read/modify your code will appreciate your efforts far more than admiring you for making wrong decisions that makes their day worse.
Arrays are easy to conceive of in terms of indexing to reach each element. If you want to train in the use of pointers and NULL pointers, I suggest you explore "linked lists" and/or "binary trees". Those data structures are founded on the utility of pointers.
int main( void ) {
const int n = 3, ary[] = { 1, 3, 7, 8, 3, 9 };
size_t sz = sizeof ary/sizeof ary[0];
// search for the LAST match by starting at the end, not the beginning.
while( sz-- )
if( ary[ sz ] == n ) {
printf( "ary[ %sz ] = %d\n", sz, n );
return 0;
}
puts( "not found" );
return 1; // failed to find it.
}
Consider that the array to be searched is many megabytes. To find the LAST match, it makes sense to start at the tail, not the head of the array.
Simple...

Can someone explain to me how can i access a void* item that is inside a void** array, taking in account void** belongs to a struct

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct student{
int grade;
int enrollCode;
}student;
typedef struct colVoidStar{
int capacity;
int num_itens_curr;
void **arr;
int current_pos;
}colVoidStar;
colVoidStar *colCreate(int capacity){
if(capacity > 0){
colVoidStar *c = malloc(sizeof(colVoidStar));
if(c != NULL){
c->arr = (void**)malloc(sizeof(void*)*capacity);
if( c->arr != NULL){
c->num_itens_curr = 0;
c->capacity = capacity;
return c;
}
free(c->arr);
}
free(c);
}
return NULL;
}
int colInsert(colVoidStar *c, void *item){
if(c != NULL){
if(c->num_itens_curr < c->capacity){
c->arr[c->num_itens_curr] = (student*)item;
c->num_itens_curr++;
return 1;
}
}
return 0;
}
void *colRemove(colVoidStar *c, void *key, int compar1(void* a, void* b)){
int(*ptrCompar)(void*, void*) = compar1;
student* eleRemoved;
if(c != NULL){
if(c->num_itens_curr > 0){
int i = 0;
for(i; i < c->num_itens_curr; i++){
if(ptrCompar((void*)key, (void*)c->arr[i]) == 0){
eleRemoved = (student*)c->arr[i];
for(int j = i; j < c->num_itens_curr; j++){
c->arr[i] = c->arr[i + 1];
c->arr[i + 1] = 0;
}
return (void*)eleRemoved;
}
return NULL;
}
}
}
return NULL;
}
int compar1(void *a, void*b){
int key;
student *item;
key = *(int*)a;
item = (student*)b;
return (int)(key - item->enrollCode);
}
int main(){
int finishProgram = 0, choose, capacity, returnInsert, removeEnroll;
colVoidStar *c;
student *a, *studentRemoved;
while(finishProgram != 9){
printf("-----------------panel-----------------------\n");
printf("Type: \n");
printf("[1] to create a collection;\n");
printf("[2] to insert a student;\n");
printf("[3] to remove some student of collection;\n");
printf("--------------------------------------------------------\n");
scanf("%d", &choose);
switch(choose){
case 1:
printf("Type the maximum of students the collection will have: \n");
scanf("%d", &capacity);
c = (colVoidStar*)colCreate(capacity);
if(c == NULL){
printf("Error in create collection!\n");
}
break;
case 2:
if(c->num_itens_curr < capacity){
a = (student*)malloc(sizeof(student));
printf("%d student:(type the Grade and the Enroll code, back-to-back)\n", c->num_itens_curr + 1);
scanf("%d %d", &a->grade, &a->enrollCode);
returnInsert = colInsert(c, (void*)a);
if(returnInsert == 1){
for(int i = 0; i < c->num_itens_curr; i++){
printf("The student added has grade = %d e enrollCode = %d \n", (((student*)c->arr[i])->grade), ((student*)c->arr[i])->enrollCode);
}
}else{
printf("the student wasn't added in the collection\n");
}
}else{
printf("it's not possible to add more students to the colletion, since the limit of elements was reached!");
}
break;
case 3:
printf("Type an enrollcode to remove the student attached to it:\n");
scanf("%d", &removeEnroll);
studentRemoved = (student*)colRemove(c, &removeEnroll, compar1(&removeEnroll, c->arr[0]));
if(studentRemoved != NULL)
printf("the student removed has grade = %d and enrollcode %d.", studentRemoved->grade, studentRemoved->enrollCode);
else
printf("the number typed wasn't found");
break;
}
}
return 0;
}
---> As you can realize, what I'm trying to do, at least at this point, is access and remove an item(student* that initially will assume a void* type) of a student's collection(void** arr) using a sort of enrollment code. However, I'm having problems with Segmentation Fault and can't understand why and how can solve them, hence my question up there. Debugging the code I found out the errors lies at: if(ptrCompar((void)key, (void**)*c->arr[i]) == 0) inside of Remove function and return (int)(key - item->matricula) inside of Compar1.
Besides, if you can point me out some articles/documentations/whatever that helps me to understand how to cope with problems like that, I'll appreciate it a lot.
Here are the problems I see in colRemove:
(Not really a problem, just a matter of style) Although the function parameter int compar1(void* a, void* b) is OK, it is more conventional to use the syntax int (*compar1)(void* a, void* b).
(Not really a problem) Having both compar1 and ptrCompar pointing to the same function is redundant. It is probably better to name the parameter ptrCompar to avoid reader's confusion with the compar1 function defined elsewhere in the code.
The function is supposed to be general-purpose and shouldn't be using student* for the eleRemoved variable. Perhaps that was just for debugging? It should be void*.
After the element to be removed has been found, the remaining code is all wrong:
c->num_itens_curr has not been decremented to reduce the number of items.
The code is accessing c->arr[i] and c->arr[i + 1] instead of c->arr[j] and c->arr[j + 1].
c->arr[j + 1] may be accessing beyond the last element because the loop termination condition is off by 1. This may be because c->num_itens_curr was not decremented.
The assignment c->arr[j + 1] = 0; is not really needed because all but the last element will be overwritten on the next iteration, and the value of the old last element does not matter because the number of items should be reduced by 1.
(Not really a problem) There is unnecessary use of type cast operations in the function (e.g. casting void * to void *).
Here is a corrected and maybe improved version of the function (using fewer variables):
void *colRemove(colVoidStar *c, void *key, int (*ptrCompar)(void* a, void* b)){
void* eleRemoved = NULL;
if(c != NULL){
int i;
/* Look for item to be removed. */
for(i = 0; i < c->num_itens_curr; i++){
if(ptrCompar(key, c->arr[i]) == 0){
/* Found it. */
eleRemoved = c->arr[i];
c->num_itens_curr--; /* There is now one less item. */
break;
}
}
/* Close the gap. */
for(; i < c->num_itens_curr; i++){
c->arr[i] = c->arr[i + 1];
}
}
return eleRemoved;
}
In addition, this call of colRemove from main is incorrect:
studentRemoved = (student*)colRemove(c, &removeEnroll, compar1(&removeEnroll, c->arr[0]));
The final argument should be a pointer to the compar1 function, but the code is actually passing the result of a call to the compar1 function which is of type int. It should be changed to this:
studentRemoved = (student*)colRemove(c, &removeEnroll, compar1);
or, removing the unnecessary type cast of the the void* to student*:
studentRemoved = colRemove(c, &removeEnroll, compar1);
The colInsert function is also supposed to be general-purpose so should not use this inappropriate type cast to student*:
c->arr[c->num_itens_curr] = (student*)item;
Perhaps that was also for debugging purposes, but it should just be using item as-is:
c->arr[c->num_itens_curr] = item;
As pointed out by #chux in the comments on the question, the expression key - item->enrollCode in the return statement of compar1 may overflow. I recommend changing it to something like this:
return key < item->enroleCode ? -1 : key > item->enrolCode ? 1 : 0;
or changing it to use this sneaky trick:
return (key > item->enroleCode) - (key < item->enroleCode);

print list and separate values by a comma comma and end with a dot

printf("Open lockers: ");
for(int i = 0; i < sizeof(lockers); i++){
if (lockers[i] == true){
if(i == sizeof(lockers) - 1){
printf(" %d.", i +1);
}else
printf(" %d,", i +1);
}
}
//This is what i got but it doesn't work for when i change list size
I would approach this by maintaining some additional state which keeps track of whether or not it is the first open locker which needs to be reported. And then, just print period outside the loop, only once.
printf("Open lockers: ");
int first = 1;
for (int i=0; i < sizeof(lockers); i++) {
if (lockers[i] == true) {
if (first == 0) {
printf(", ");
}
else {
first = 0;
}
printf("%d", i + 1);
}
}
printf(".");
Demo
Note: In the demo I replaced your bool lockers array with an int array. But the rest of the logic remains the same.
One option is to use a variable like pad in this code:
const char *pad = "";
printf("Open lockers:");
for (int i = 0; i < sizeof(lockers); i++)
{
if (lockers[i])
{
printf("%s %d", pad, i + 1);
pad = ",";
}
}
putchar('.');
Another variant is:
const char *pad = ":";
printf("Open lockers");
for (int i = 0; i < sizeof(lockers); i++)
{
if (lockers[i])
{
printf("%s %d", pad, i + 1);
pad = ",";
}
}
putchar('.');
Note that sizeof(lockers) only works if sizeof(lockers[0]) == 1. I left it because that's what you used, but I'd normally have a variable set to the maximum value and use that in the loop.
Your loop condition is probably wrong
for(int i = 0; i < sizeof(lockers); i++){
if (lockers[i] == true){
You do not show us, what lockers is. As you use it with an index it could be an array or a pointer to an array.
If lockers is an array, sizeof will result in the size in bytes. Unless the elements are of type char, you will end up accessing the array beyond its allocated memory.
You can get the number of elements using sizeof(array)/sizeof(array[0]).
int lockers[10];
With a definition like that you would access 40 integer elements whily you only have 10.
If lockers is a pointer to an array, sizeof will only result in the size of a pointer (probably 4 or 8 bytes) and you will not access all elements of your array where your pointer points to if the array has more elements than 4 or 8.
int *lockers = malloc(20 * sizeof(int));
With a definition like that you would only access 1 or 2 elements instead of 20.
Update:
In the comments I found the missing information. It would help a lot if you put it into the question instead of comments.
You are lucky, sizeof(lockers[i]) is 1 which will work for your loop.

C - Print the most frequent strings

in these days I have been posting some code because I am doing an exercise, finally it seems that I have ended it, but I noticed it doesn't work.
The exercise asks in input:
- N an integer, representing the number of strings to read
- K an integer
- N strings
The strings can be duplicates. In the output there is a print of the K strings most frequent, ordered according to their frequency (decreasing order).
Example test set:
Input:
6
2
mickey
mouse
mickey
hello
mouse
mickey
Output:
mickey // Has freq 3
mouse // Has freq 2
I hope I explained the exercise in a good way, as this is my attempt.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct _stringa {
char* string;
int freq;
} stringa;
int compare(const void *elem1, const void *elem2) {
stringa *first = (stringa *)elem1;
stringa *second = (stringa *)elem2;
if (first->freq < second->freq) {
return -1;
} else if (first->freq > second->freq) {
return 1;
} else {
return 0;
}
}
int BinarySearch(stringa** array, char* string, int left, int right) {
int middle;
if (left==right) {
if (strcmp(string,array[left]->string)==0) {
return left;
} else {
return -1;
}
}
middle = (left+right)/2;
if ((strcmp(string,array[middle]->string)<0) || (strcmp(string,array[middle]->string)==0) ) {
return BinarySearch(array, string, left, middle);
} else {
return BinarySearch(array, string, middle+1, right);
}
}
int main (void)
{
char value[101];
int n = 0;
int stop;
scanf("%d", &n); // Number of strings
scanf("%d", &stop); // number of the most frequent strings to print
stringa **array = NULL;
array = malloc ( n * sizeof (struct _stringa *) );
int i = 0;
for (i=0; i<n; i++) {
array[i] = malloc (sizeof (struct _stringa));
array[i]->string = malloc (sizeof (value));
scanf("%s", value);
int already;
already = BinarySearch(array, value, 0, i); // With a binary search, I see if the string is present in the previous positions of the array I am occupying. If it is not present, I copy the string into the array, otherwise, I use the value of binary search (which is the position of the element in the array) and I update the frequency field
if (already==-1) {
strcpy(array[i]->string,value);
array[i]->freq = 1;
} else {
array[already]->freq += 1;
}
}
stringa **newarray = NULL; // New struct array of strings
newarray = malloc ( n * sizeof (struct _stringa *) );
int k = 0;
for (i=0; i<n; i++) { // I use this loop to copy the element that don't have a frequency == 0
if (array[i]->freq != 0) {
newarray[k] = malloc(sizeof(struct _stringa));
newarray[k] = malloc(sizeof(value));
newarray[k]->string = array[i]->string;
newarray[k]->freq = array[i]->freq;
k++;
}
}
qsort(newarray, n, sizeof(stringa*), compare);
i=0;
while ((newarray[i]!= NULL) && (i<k)) {
printf("%s ", newarray[i]->string);
printf("%d\n", newarray[i]->freq);
i++;
}
// Freeing operations
while (--n >= 0) {
if (array[n]->string) free (array[n]->string);
if (array[n]) free (array[n]);
}
if (array) free (array);
if (newarray) free (newarray);
return 0;
}
Thank you in advance to anyone who will have the time and patience to read this code.
EDIT:
I forgot to add what it's not working right.
If I don't use the qsort for debugging reasons, and I use this input for example:
5
2 // random number, I still have to do the 'print the k strings' part,
hello
hello
hello
hello
hello
It prints:
hello 3 (freq)
hello 2 (freq)
So it doesn't work properly. As you suggested in the comments, the binary search is flawed as it works only on an ordered list. What I could do is order the array each time, but I think this would be counter-productive. What could be the idea to get rid of the problem of locating only the strings that are not present in the array?
If you want an efficient method without sorting, use a hash table.
Otherwise, simply put the each unique string in an array and scan it linearly, simple and reliable.
On modern hardware, this kind of scan is actually fast due to caches and minimising indirection. For small numbers of items an insertion sort is actually more efficient than qsort's in practice. Looking at the "Tim sort" algorithm for instance, which is stable and avoids qsort's poor performance with nearly sorted data, it mixes merge and insertion sorts to achieve n Log n, without extreme cases on real data.

Perform Selection Sort On 2D Char Array

I currently have a 2D char array size: [5][256].
The array can hold either numbers or letters.
I have been tasked with using the Selection Sort to sort the strings into ascending order.
My idea is to convert each row into ASCII and then sort the values in ascending order then convert back to chars.
Ive implemented a 2D Array Selection sort for another task, however, it doesnt work here as i coded it to work with 2 columns not 256 like here (not sure how to change it).
What i need help with is how do i use the ASCII value for each row and use it in a selection sort.
Been trying to figure this out for hours now, driving me mental.
Any help is appreciated.
Im not necessarily looking for someone to code everything for me, more of a kick in the right direction. Im new to C and not aware of every function C can do.
Here is my current code in full:
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
char arc5Strings[5][256];
int nCount, nCount2, nCount3, nCount4, nCount5, nCount6, nCount7;
int fMinVal[1][2] = {1,1};
int nMinValPosition;
int nMoves;
int nRow;
int fTemp[1][2] = {1,1};
int fTemp2[1][2] = {1,1};
//input the values
for(nCount=0; nCount < 5; nCount++)
{
printf("Please input string %d/5: ", nCount + 1);
fgets(arc5Strings[nCount], 256, stdin);
}
printf("\n\n");
//print entire array
for(nCount3 = 0; nCount3 < 5; nCount3++)
{
for(nCount4 = 0; arc5Strings[nCount3][nCount4] != '\0'; nCount4++)
{
printf("%d ", arc5Strings[nCount3][nCount4]);
//ASCII values outputted in a line instead of in array format when using %c
}
}
return 0;
}
Old 2D Array selection sort i devised - extracted from code:
//-----------------------------------
//set up the switch
for(nCount5 = 0; nCount5 < 5; nCount5++)
{
fMinVal[0][0] = arc5Strings[nCount5][0]; //min value is row 0 col 1
nMinValPosition = nCount5;
for(nCount6 = nCount5 + 1; nCount6 < 5; nCount6++)
{
if(arc5Strings[nCount6][1] < fMinVal[0][0])
{
fMinVal[0][0] = arc5Strings[nCount6][0];
nMinValPosition = nCount6;
}
/* Perform the switch - actually switch the values */
if(fMinVal[0][0] < arc5Strings[nCount5][0])
{
fTemp[0][1] = arc5Strings[nCount5][1];
fTemp2[0][0] = arc5Strings[nCount5][0];
arc5Strings[nCount5][1] = arc5Strings[nMinValPosition][1];
arc5Strings[nCount5][0] = arc5Strings[nMinValPosition][0];
arc5Strings[nMinValPosition][1] = fTemp[0][1];
arc5Strings[nMinValPosition][0] = fTemp2[0][0];
nMoves++;
}
}
}
//------------------------------
printf("\n\n");
printf("The sorted list, in ascending order, using selection sort, is:\n\n");
for(nCount3 = 0; nCount3 < 5; nCount3++)
{
for(nCount4 = 0; arc5Strings[nCount3][nCount4] != '\0'; nCount4++)
{
printf("%c", arc5Strings[nCount3][nCount4]);
}
}
printf("\n %d moves were made to sort this list\n", nMoves);
EDIT - RESULTS OF GEORGE'S ANSWER:
Input1 = 90
Input2 = 70
Input3 = abc
Input4 = 500
Input5 = 200
Sorted Array Results:
200
90
70
abc
500
You're on the right track. I would implement this as follows:
for(i=0;i<5;i++)
{
indexOfCurrentSmallest = i;
for(j=i;j<5;j++)
{
for(k=0;k<255;k++)
{
if(arc5Strings[j][k] < arc5Strings[indexOfCurrentSmallest][k])
{
//we found a new possible smallest
indexOfCurrentSmallest = j;
break;
}
else if(arc5Strings[j][k] > arc5Strings[indexOfCurrentSmallest][k])
{
//no point in searching further, the one we are looking at is already larger than the one we found.
break;
}
}
}
//here, we have found the actual smallest, let's do a swap
for(q=0;q<255;q++)
{
temp = arc5Strings[i][q];
arc5Strings[i][q] = arc5Strings[indexOfCurrentSmallest][q];
arc5Strings[indexOfCurrentSmallest][q] = temp;
}
}
I haven't tested this code, but it should be roughly what you're looking for. Basically, it compares ASCII values starting at the left, until it finds a difference, and stores the index for later swapping after comparing all 5 strings.
EDIT I've now tested the code above, and it works now.
First find each string length
int length[5];
for(i = 0, i < 5, i++){
length[i] = strlen(arc5Strings[i]);
}
Sort the lengths. Those with the same, compare the value of the first letter.
Thats it.
valter

Resources