For one of my assignments I have to have a user input a list of names and while they are inputting them, they have to be sorted alphabetically as they go. I was wondering (1) when declaring an array of strings which is best to use:
char test[10][10];
or
char *test[10];
and (2) the best way to write an insertion method, I know how to write an insertion sort method and there are many examples online on it but they deal mainly with just 1D arrays, so I'm a little lost on how to do this. Thanks!
The declarations you show are very different. The first is an array of arrays of char, and the second is an array of pointers to char (also known as a jagged array).
Both could be treated similarly, like arrays of strings, but there are quite a few semantic differences. For example, in the first your strings are limited to nine character (plus terminator) while in the second the strings could be of any length (fitting in memory).
There's also a difference in how the two arrays decays (what happens when you use plain test when a pointer is expected). The first will decay to a pointer to an array of char, i.e. char (*)[10]. The second will decay to pointer to pointer to char, i.e. char **.
Now for the big question: Which should you use? Well that really depends on use-case. Will you have only fixed-sized strings where the size is known from the start (and the total size is small enough to fit on the stack where local variables normally are stored)? Then you can use the first. If you don't know the length of the strings, or if they could differ by more than a few characters, then the second is probably a better choice.
The second question depends a lot on the choice of arrays. If you have arrays of arrays (the first declaration) then you need to copy strings around using strcpy. If you chose array of pointers (the second declaration) you could just assign the pointers around.
I don't want to solve assignments here, so I'll just give a brief push into the right direction:
What you want is a linked list; then, whenever the user enters a new name, you can insert the new entry directly into it at the correct position.
A first start could look like this:
struct entry { char name[10]; struct entry* next; };
struct entry* root = NULL;
void addname(char* na) {
if (root == NULL) {
root = (struct entry*)malloc(sizeof(struct entry));
sprintf(entry->name, "%s", na);
}else{
// HERE, walk through all entries! Once you reach one, where next is lex. greater then you create a new entry, and link it into that position of the chain
}
}
Related
I am working on a standard deviation program in C and am having difficulty with the intended input.
I must accept an unknown number of floats and I am not sure how to go about storing them and allocating memory for them.
Sample input:
82.5
1000.6699
10
11.11
-45
#
Any advice is appreciated.
New user, sorry for little mistakes
You can allocate an array to hold your values, and you can use realloc() to grow that array.
Because realloc() has some overhead, I would probably allocate enough memory for, maybe, 16 values. And when you fill it, then resize it to hold up to an additional 16 values and so on. This way, your code doesn't resize the memory for every value.
There're really only two ways. The first is to define a struct:
typedef struct {
int value;
element* next;
} element;
Then, you have what's called a linked list. You can access the nth element by iterating through the linked element structs, and you know you've reached the end when the element.next is a null pointer (and element->next is a SegFault or returns nonsense).
The second way is to "play it safe" and define a fixed-length array that is the maximum size you will need. Something like:
int my_array[65535];
This is advantageous because arrays are much faster than linked lists (you don't have to iterate to access the nth element) but if the array length is highly variable this can allocate much more memory than is necessary. It's up to you which you prefer.
before you mark this as a duplicate please notice that I'm looking for a more general solution for arrays of arbitrary dimensions. I have read many posts here or in forums about making 2D or 3D arrays of integers but these are specific solutions for specific dimensions. I want a general solution for an array of any dimension.
First I need to have a type of intlist as defined below:
typedef struct{
int l // length of the list
int * e // pointer to the first element of the array
}intlist;
this actually fills the gap in C for treating arrays just as pointers. using this type I can pass arrays to functions without worrying about loosing the size.
then in the next step I want to have a mdintlist as multidimensional dynamically allocated arrays. the type definition should be something like this:
typedef struct Mdintlist{
intlist d // dimension of the array
/* second part */
}mdintlist;
there are several options for the second part. on option is that to have a pointer towards a mdintlist of lower dimension like
struct Mdintlist * c;
the other options is to use void pointers:
void * c;
I don't know how to continue it from here.
P.S. one solution could be to allocate just one block of memory and then call the elements using a function. However I would like to call the elements in array form. something like tmpmdintlist.c[1][2][3]...
Hope I have explained clearly what I want.
P.S. This is an ancient post, but for those who may end up here some of my efforts can be seen in the Cplus repo.
You can't! you can only use the function option in c, because there is no way to alter the language semantics. In c++ however you can overload the [] operator, and even though I would never do such an ugly thing (x[1][2][3] is alread y ugly, if you continue adding "dimensions" it gets really ugly), I think it would be possible.
Well, if you separate the pointers and the array lengths, you end up with much less code.
int *one_dem_array;
size_t one_dem_count[1];
int **two_dem_array;
size_t two_dem_count[2];
int ***three_dem_array;
size_t three_dem_count[3];
This way you can still use your preferred notation.
int num_at_pos = three_dem_array[4][2][3];
I'm not really a fan of C, but I did homework for this exercise though. So far, what I got is that in C, initializing an array, as far as I know, is not like JavaScript. C has fixed arrays, and not initialized by a particular value. So NULL checking won't work in this case.
I have an array of structures. How would I know if that index in an array is empty or not (filled with a struct or not)?
#define LIST_LENGTH 30
//This is the struct that is inserted in the array
typedef struct node{
char fName[30];
char mName[30];
char lName[30];
char id[8];
} NODE;
typedef struct {
int size; //size is the struct's total capacity (at 30)
int length; //tracks how many elements are added, but not where
NODE nodes[LIST_LENGTH]; //This is the array in question
} List;
//somewhere in my code, I have to insert a value to the array at a specific position.
//if that position is occupied, I have to find the nearest empty position
//to the right, and shift the values rightward for that spot to be empty
Also, we are constrained to using arrays for this exercise. If we were granted to use linked-lists, this would be a walk in the park since we already know how to use dynamic lists.
How do I go about it? Or am I looking at the problem at the wrong angle (besides having to use arrays instead of linked-lists)?
One option would be to use some kind of sentinel value in your struct. For example, you could check if the id field is zero length, which would indicate an unoccupied spot in the array.
The downside is that you have to initialize all the elements properly when you create the array. You would also have to reset the sentinel value if you "remove" an element from the array.
As mentioned in one of the other answers, you could also change to have an array of pointers to the structures, in which case you could directly check for NULL.
Arrays in C do not have positions that are empty. If the array exists, all the elements in it exist.
An element might not be initialized, but there is no general way to determine that, except by tracking it yourself in your program. E.g., as soon as the array is allocated, initialize everything in it. Or maintain a number N indicating that the first N elements of the array have been initialized.
If you want to know whether each individual element has been initialized or not, you must maintain that information yourself, either in a separate array or by adding a flag to the structure, so that each element has its own flag saying whether the rest of the structure in that element has been initialized. You will, of course, need to initialize these flags.
Add 'set/valid' field to your NODE typedef and each time you insert NODE into List just set 'set/valid' to one for example. This way you can always tell if this is valid array element etc.
I have an array of structures. How would I know if that index in an array is empty (not filled with a struct)?
What you can do is either add a flag to the structure, isInitialized, to store whether it has been filled or not
//This is the struct that is inserted in the array
typedef struct node{
char fName[30];
char mName[30];
char lName[30];
char id[8];
int isInitialized;
} NODE;
and initialize all its instances within the array to 0.
Or you can initialize the structure with an illegal or "useless" value (e.g. all strings to length zero, or a special ID).
int isInitialized(NODE *s)
{
/* Since C strings are zero-terminated, char id[8] is at most one
seven-char string terminated by a binary zero. It can never be
normally a sequence of eight 0xFF. */
return memcmp(s->id, 0xFF, 8);
}
// You still have to manually mark nodes free at the beginning.
void initialize(NODE *s)
{
memset(s->id, 0xFF, 8);
}
if (isInitialized(&(myList->nodes[15])))
{
...
}
One caveat to the above code is that now "id" can not safely be taken and printed: an initialization check must be performed, otherwise printf() could fail to find the terminating zero and proceed onwards, and in the case of the last structure, maybe exceed the boundaries of accessible memory and determine a protection fault crash. One could reason, however, that since it does not make sense to print an uninitialized structure (where the saving binary zero could have been lacking anyway), such a check would have had to be performed regardless.
Or you could keep a counter of how many structures have been used so far (this assumes that you never mark as available a structure "in the middle" of the array).
If you have an array of pointers to structures, then you will be able to store NULL in the pointers to not-yet-initialized structures (i.e., the pointer array is allocated, the structures it points to are not yet necessarily so); but here you preallocate the structures, so you have to do it differently.
I've been doing (in C)
char array[100];
if (array == NULL)
something;
which is very wrong (which I have finally learned since my program doesn't work). What is the equivalent where I could test a new array to see if nothing has been put in it yet?
Also, how do you make an array empty/clean it out?
I know there are other posts out on this topic out there, but I couldn't find a straightforward answer.
An array declared with
char array[100]
always has 100 characters in it.
By "cleaning out" you may mean assigning a particular character to each slot, such as the character '\0'. You can do this with a loop, or one of several library calls to clear memory or move memory blocks.
Look at memset -- it can "clear" or "reset" your array nicely.
If you are working with strings, with are special char arrays terminated with a zero, then in order to test for an empty array, see this SO question. Otherwise if you have a regular character array not intended to represent text, write a loop to make sure all entries in the array are your special blank character, whatever you choose it to be.
You can also declare your character array like so:
char* array = malloc(100);
or even
char* array = NULL;
but that is a little different. In this case the array being NULL means "no array has been allocated" which is different from "an array has been allocated but I have not put anything in it yet."
I'm writing a program in which you enter words via the keyboard or file and then they come out sorted by length. I was told I should use linked lists, because the length of the words and their number aren't fixed.
should I use linked lists to represent words?
struct node{
char c;
struct node *next;
};
And then how can I use qsort to sort the words by length? Doesn't qsort work with arrays?
I'm pretty new to programming.
Thank you.
I think there is a bigger issue than the sorting algorithm which you should pick. The first of these is that the struct that you're defining is actually not going to hold a list of words, but rather a list of single letters (or a single word.) Strings in C are represented as null-terminated arrays of characters, laid out like so:
| A | n | t | h | o | n | y | \0 |
This array would ideally be declared as char[8] - one slot for each letter, plus one slot for the null byte (literally one byte of zeros in memory.)
Now I'm aware you probably know this, but it's worth pointing this out for clarity. When you operate on arrays, you can look at multiple bytes at a time and speed things up. With a linked list, you can only look at things in truly linear time: step from one character to the next. This is important when you're trying to do something quickly on strings.
The more appropriate way to hold this information is in a style that is very C like, and used in C++ as vectors: automatically-resized blocks of contiguous memory using malloc and realloc.
First, we setup a struct like this:
struct sstring {
char *data;
int logLen;
int allocLen;
};
typedef struct string sstring;
And we provide some functions for these:
// mallocs a block of memory and holds its length in allocLen
string_create(string* input);
// inserts a string and moves up the null character
// if running out of space, (logLen == allocLen), realloc 2x as much
string_addchar(string* input, char c);
string_delete(string* input);
Now, this isn't great because you can't just read into an easy buffer using scanf, but you can use a getchar()-like function to get in single characters and place them into the string using string_addchar() to avoid using a linked list. The string avoids reallocation as much as possible, only once every 2^n inserts, and you can still use string functions on it from the C string library!! This helps a LOT with implementing your sorts.
So now how do I actually implement a sort with this? You can create a similar type intended to hold entire strings in a similar manner, growing as necessary, to hold the input strings from the console. Either way, all your data now lives in contiguous blocks of memory that can be accessed as an array - because it is an array! For example, say we've got this:
struct stringarray {
string *data;
int logLen;
int allocLen;
};
typedef struct stringarray cVector;
cVector myData;
And similar functions as before: create, delete, insert.
The key here is that you can implement your sort functions using strcmp() on the string.data element since it's JUST a C string. Since we've got a built-in implementation of qsort that uses a function pointer, all we have to do is wrap strcmp() for use with these types and pass the address in.
If you know how you want the items sorted, you should use an insertion sort when reading the data so that once all the input has been entered, all you have to do is write the output. Using a linked list would be ok, though you'll find that it has O(N2) performance. If you store the input in a binary tree ordered by length (a balanced tree would be best), then your algorithm will have O(NlogN) performance. If you're only going to do it once, then go for simplicity of implementation over efficiency.
Pseudocode:
list = new list
read line
while not end of file
len = length(line)
elem = head(list)
while (len > length(elem->value))
elem = elem->next
end
insert line in list before elem
read line
end
// at this point the list's elements are sorted from shortest to longest
// so just write it out in order
elem = head(list)
while (elem != null)
output elem->value
elem = elem->next
end
Yes, the classic "C" library function qsort() only works on an array. That is a contiguous collection of values in memory.
Tvanfosson advice is pretty good - as you build the linked list, you can insert elements at the correct position. That way, the list is always sorted.
I think the comment you made that you were told to use a linked list is interesting. Indeed a list can be a good data structure to use in many instances, but it does have draw backs; for example, it must be traversed to find elements.
Depending on your application, you may want to use a hash table. In C++ you could use a hash_set or a hash_map.
I would recommend you you spend some time studying basic data structures. Time spent here will server you will and better put you in a position to evaluate advice such as "use a linked list".
There are lots of ways to handle it... You can use arrays, via dynamic memory allocation, with realloc, if you feel brave enough to try.
The standard implementation of qsort, though, needs each element to be a fixed length, which would mean having an array-of-pointers-to-strings.
Implementing a linked list, though, should be easy, compared to using pointers to pointers.
I think what you were told to do was not to save the strings as list; but in a linked list:
struct node {
char *string;
node *next;
}
Then, all you have to do is, every time you read a string, add a new node into the list, in its ordered place. (Walk the list until the current string's length is greater than the string you just read.)
The problem of words not being a fixed length is common, and it's usually handled by storing the world temporarily in a buffer, and then copying it into a proper length array (dynamically allocated, of course).
Edit:
In pseudo code:
array = malloc(sizeof(*char))
array_size = 1
array_count = 0
while (buffer = read != EOF):
if(array_count == array_size)
realloc(array, array_size * 2)
array_count++
sring_temp = malloc(strlen(buffer))
array[array_count] = string_temp
qsort(array, array_count, sizeof(*char), comparison)
print array
Of course, that needs a TON of polishing. Remember that array is of type char **array, ie "A pointer to a pointer to char" (which you handle as an array of pointers); since you're passing pointers around, you can't just pass the buffer into the array.
You qsort a linked list by allocating an array of pointers, one per list element.
You then sort that array, where in the compare function you are of course receiving pointers to your list elements.
This then gives you a sorted list of pointers.
You then traverse your list, by traversing the array of pointers and adjusting each element in turn. rearranging its order in the list to match the order of your array of pointers.