How to printf a vector in C - c

I have three diferent vectors with the name of diferents towns inside:
V_NombrePueblos listTown1={"Abrera","Granollers","Cardedeu","Manresa","Martorell"};
V_NombrePueblos listTown2={"Astorga","Benavente","Bembibre","Camarzana","Ferrol"};
V_NombrePueblos listTown3={"Arteijo","Betanzos","Cariño","Cedeira","Cerdido"};
The user tell me the number of vector and the position for print the town. I think in use a function with a switch inside for do this:
typedef char nameList[8];
void returnTown(int listTown, int position){
nameList numList;
if (listTown==0){
strcpy(numList, "listTown1");
}
if (listTown==1){
strcpy(numList, "listTown2");
}
if (listTown==2){
strcpy(numList, "listTown3");
}
switch (position){
case 1:
printf("%s", numList[0]);
break;
case 2:
printf("%s", numList[1]);
break;
case 3:
printf("%s", numList[2]);
break;
case 4:
printf("%s", numList[3]);
break;
case 5:
printf("%s", numList[4]);
break;
But when I try to print example:
returnTown(0,1)
The console doesn't show nothing, with the previus code the console should show "Abrera"
The problem is in the printf insede the switch,
If I put:
printf("%s",listTown1[0] )
The code show "Abrera" fine, but I need pass the name of the vector like a varName, because sometimes will be listTown1, other times listTown2 or listTown3...
Any idea?
Thanks

Copying names of variables doesn't mean refering variables.
To refer variables, you should use pointers.
You will want something like this:
void returnTown(int listTown, int position){
V_NombrePueblos* numList;
switch (listTown){
case 0: numList = &listTown1; break;
case 1: numList = &listTown2; break;
case 2: numList = &listTown3; break;
default: return;
}
if (1 <= position && position <= 5){
printf("%s", (*numList)[position - 1]);
(rest part of this function isn't shown because I respect the original code snippet)

What you are trying to do won't work in C - you can't build variable names dynamically like that.
Any time you find yourself defining a bunch of variables with the same type and with ordinal names (var1, var2, etc.), that's a real strong hint you want to use an array. In this case, you could do something like
/**
* I am *assuming* that vNombrePueblos is a typedef name for char *[5],
* based on the declarations in your code.
*
* The size of the listTowns array is taken from the number of initializers;
* in this case, 3.
*/
vNombrePueblos listTowns[] = {
{"Abrera","Granollers","Cardedeu","Manresa","Martorell"},
{"Astorga","Benavente","Bembibre","Camarzana","Ferrol"},
{"Arteijo","Betanzos","Cariño","Cedeira","Cerdido"}
};
This way instead of trying to figure out which listTownN variable you want, you just index into this array. To print out the correct town, all you need is the two indices:
/**
* You need to pass the list of towns as an argument to your function;
* since arrays lose their "array-ness" under most circumstances, you also
* have to pass the array size to make sure you don't try to access something
* past the end of it.
*/
void returnTown( vNombrePueblos listTowns[], int numTowns, int town, int position )
{
if ( town < numTowns )
printf( "%s\n", listTowns[town][position] );
else
fprintf( stderr, "No such entry\n" );
}
You'll need to keep track of the number of entries in listTowns yourself - arrays in C don't carry any metadata about their size, and under most circumstances (such as when you pass it as an argument to a function) an expression of type "array of T" will "decay" into an expression of type "pointer to T", so the sizeof arr / sizeof arr[0] trick won't work to get the number of elements.

Related

Char** array first element being modified magically

I am sorry for the vague title, but I am having a very hard time figuring out how to describe this issue. I am trying to add data to an array and somehow it is all getting written to index 0 despite my explicitly indicating otherwise. I have created a minimal sample.
Expected Behavior
With command line arguments as -u rwx -g rw -o r:
bins[0] == "111"
bins[1] == "110"
bins[2] == "100"
Actual Behavior
Indices 0, 1 and 2 all end up as "100". If you put a printf() to check their value inside the various case statements, you will find that, for instance, when case 'g': runs, bins[1] == "110" AND bins[0] == "110". When case 'o': runs, all three indices will will hold the value "100".
Minimal functional sample
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void processPerms(char *targets, char **perms, char **bins, const size_t arrSize) {
for(int i = 0; i < arrSize; i++) {
//This string will be modified
//so that the right bits will
//be set.
char binDig[] = "000";
//We decide which, if any, bit
//to set based upon the current
//letter being considered.
for(int k = 0; k < strlen(perms[i]); k++) {
switch(perms[i][k]) {
case 'r':
binDig[0] = '1';
break;
case 'w':
binDig[1] = '1';
break;
case 'x':
binDig[2] = '1';
break;
}
}
//Here, we check the target
//whose index corresponds to
//the index of the permissions
//string we just accessed.
//They will always be in
//an order where the related
//target and perm str are in
//the same array position.
switch(targets[i]) {
case 'u':
bins[0] = binDig;
//bins[0] == "111"
break;
case 'g':
bins[1] = binDig;
//bins[0] == "110"
break;
case 'o':
bins[2] = binDig;
//bins[0] == "100" && bins[1] == "100"
break;
}
}
}
int main(int argc, char *argv[]) {
const size_t arrSize = (argc-1)/2;
char *targets = (char*)calloc(arrSize, sizeof(char));
char **perms = (char**)calloc(arrSize, sizeof(char*));
//Copying just the letters
//of the args into these
//arrays.
for(int i = 0; i < arrSize; i++) {
targets[i] = argv[i+(i+1)][1];
}
for(int i = 0; i < arrSize; i++) {
perms[i] = argv[i*2+2];
}
//This array should hold three
//strings which shall be binary
//representations of the
//permissions
char **bins = (char**)calloc(3, sizeof(char*));
processPerms(targets, perms, bins, arrSize);
return 0;
}
bins[2] = binDig;
This will make you point to a variable which has automatic storage duration. This is a gateway to undefined behavior when you are returning it from the function. The life time of the variable is over as in this case and accessing it is UB.(Dereferencing a pointer to variable beyond its lifetime is Undefine d behavior).
A easy solution would be to use (This is part of POSIX standard but it is common enough) (In case you don't have this, you can allocate memory and copy to it the content of the array binDig).
bins[2] = strdup(binDig);
(Make the same changes for bins[0] and bins[1]).
Making this change as mentioned gives the expected behavior of being bins[0] equal to "111" and so on. The only thing is that, you need to free the dynamically allocated memory (including as that of returned by strdup
when you are done working with it). Similarly, don't cast the return value of malloc,calloc etc(because void* to char* is an implicit conversion). And check the return value of malloc/calloc.
The lifetime of you binDig array is limited by one iteration of the outer for cycle. This binDig array gets destroyed at the end of each iteration and created anew at the beginning of the next iteration.
This means that everything you do during each iteration of the outer cycle is lost when that iteration ends. The value of bins[] that you assigned during that iteration begins to point to some indeterminate location in memory where nothing exists anymore. Any attempts to access data through the corresponding bins[] entries lead to undefined behavior.
In real life each iteration of the cycle will typically recreate binDig at exactly the same location in memory, which creates an illusion of all of your bins[] pointers remaining valid but pointing to the same value. But this is a mere illusion. The behavior is already undefined at that point.
When the outer cycle ends the binDig array disappears forever and all your bins[] pointers become hopelessly invalid for good. But that's just the last straw. Your program died well before that moment.

How to properly pass array pointers to function in C

A different question may have been asked about this program, however in this C code I have three functions: one to print records, one to add a record and one to delete a record.
What I don't understand is why the (add) and (delete) do not make changes in the main function, so when I use the print all records function it prints changes, but it doesn't show changes, what is wrong?
Details are in the comments, please feel free to run the code to visualise the problem.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*The program is to store student record (firstname,lastname and score), it should not be more
than 15 records and the names should not be more than 20 chars, array pointersnare being used
instead of arrays, the (add_record) and (delete_record) functions must
do thsi change in the main function, so when you print all records, the changes are shown*/
void print_records(char **firstname,char **lastname,float *score,int *the_size)
{
int i;
printf("Printing All record(s)...\n");
for (i=0;i<*the_size;i++) /*loop to print records of all arrays in correct format*/
{
printf("Firstname : %s, Lastname : %s, Score : %f\n",firstname[i],lastname[i],score[i]);
}
}
void add_new_record (char **firstname,char **lastname,float *score,int the_size)
{
printf("Add new record in the format :\nFirstname Lastname Score\n");
/*the strategy here is to check if all 15 elemts are used, if they are, use realloc
to add one more, if not add the record after the last record*/
if (the_size == 15)
{
firstname=realloc(firstname,16*sizeof(char*));
firstname[15]=malloc((20+1)*sizeof(char));
lastname=realloc(lastname,16*sizeof(char*));
lastname[15]=malloc((20+1)*sizeof(char));
score=realloc(score,16*sizeof(float));
scanf("%s %s %f",firstname[15],lastname[15],&score[15]);
printf("New Record Added Successfully !\n");
printf("Firstname : %s, Lastname : %s, Score : %f\n",firstname[15],lastname[15],score[15]);
}
else if (the_size<15)
{
scanf("%s %s %f",firstname[the_size],lastname[the_size],&score[the_size]);
printf("New Record Added Successfully !\n");
printf("Firstname : %s, Lastname : %s, Score : %f\n",firstname[the_size],lastname[the_size],score[the_size]);
}
}
void delete_record (char **firstname,char **lastname,float *score,int the_size)
{
char *str=malloc(20*sizeof(char)); /*String entered by user must be 20 or less chars*/
int i,ctr=0;
char *temp_first=malloc(20*sizeof(char));/*temp array to swap firstname must be 20 or less chars*/
char *temp_last=malloc(20*sizeof(char)); /*temp array to swap lastname must be 20 or less chars*/
float temp_score;/*ctr is the counter used to check if there are no matchs in the end*/
printf("Enter the lastname of record(s) to delete : ");
scanf("%s",str);
/* the strategy here is to move the element to be deleted to the last index and use
relloc to shrink the size by 1 (-1) */
for (i=0;i< the_size;i++)
{
if (strcmp(str,lastname[i])==0)
{
printf("Deleting Record for %s %s...\n",firstname[i],lastname[i]);
temp_score=score[i];
score[i]=score[the_size-1];
score[the_size-1]=temp_score;
strcpy(temp_first, firstname[i]); /*using strcpy function to swap strings*/
strcpy(firstname[i], firstname[the_size-1]);
strcpy(firstname[the_size-1], temp_first);
strcpy(temp_last, lastname[i]);
strcpy(lastname[i], lastname[the_size-1]);
strcpy(lastname[the_size-1], temp_last);
score=realloc(score,(the_size-1)*sizeof(float));
firstname=realloc(firstname,(the_size-1)*sizeof(char*));
lastname=realloc(lastname,(the_size-1)*sizeof(char*));
ctr++;
the_size--;
}
}
if (!ctr) /*if ctr=0 (no increment), then print,there is no match*/
{
printf ("Sorry, no available record for %s",str);
}
free(temp_first);
free(temp_last);
free(str);
}
void main()
{
char **firstname;
char **lastname;
float *score;
int number_of_records,i,j=-1,ctr=1,row=15,col=20;
/*ctr is to keep track of the student's number (makes it easier to
the user), it starts with (1)*/
firstname=malloc(row*sizeof(char*));
for(i=0;i<row;i++)
{
firstname[i]=malloc((col+1)*sizeof(char));
}
lastname=malloc(row*sizeof(char*));
for(i=0;i<row;i++)
{
lastname[i]=malloc((col+1)*sizeof(char));
}
printf("\nPlease indicate number of records you want to enter (min 2, max 15): ");
scanf("%d",&number_of_records);
score=malloc(row*sizeof(float));
printf("\nPlease input records of students\n(enter a new line after"
"each record), with following format:\nfirst name last name score ");
for (i=0;i<number_of_records;i++)
{
printf("\nEnter record for student %d : ",ctr);
scanf("%s %s %f",firstname[i],lastname[i],&score[i]);
ctr++; /*ctr is to keep track of student number
(makes it easy to the user) */
}
while (j!=0) /*Main menu will keep looping after using a function as long as j is not 0
When the user enters 0 (zero) the loop will stop and therefore the program will terminate*/
{
printf("\nSelect desired function by pressing the corresponding key number\n");
printf("\n********** Main Menu **********\n");
printf("\n>>> Print records (press 1)\n");
printf("\n>>> Add a new Record (press 2 )\n");
printf("\n>>> delete record (press 3)\n");
printf("\n>>> Exit the program (press 0)\n");
scanf("%d",&j); /*getting j from the user (j is used for selection and for the while loop)*/
if (j==1)
{
print_records(firstname,lastname,score,&number_of_records);
}
else if (j==2)
{
add_new_record(firstname,lastname,score,number_of_records);
}
else if (j==3)
{
delete_record(firstname,lastname,score,number_of_records);
}
else if (j==0)
{
printf("Exitting program ...\n");
}
}
}
As other answers have observed, in C, all arguments are passed by value. That means the function gets a copy of the caller's value, therefore changes to that value are not visible to the caller. In other words, given
void f(any_type arg) {
arg = any_value;
}
The caller will never detect any change, regardless of what type any_type is or what value any_value is. Note carefully, however, the difference between that, and this:
void f(any_type *arg) {
*arg = any_value;
}
In that case, it is not the function argument (a pointer) that is being modified, it is the thing pointed to. The argument is a copy of the caller's value, so the two point to the same thing. The caller cannot detect changes to the argument, but after the call, it can detect changes to the thing it points to.
Your code exhibits some issues of this type, some of them responsible for your main problems. Most importantly, these have to do with your record keeping on the number of elements in your list (variable number_of_records in main()). Your addition and deletion functions work more or less ok, except that they cannot communicate the revised list size back to main.
There are additional issues in add_new_record() when there are already 15 records; if you can, I would just disallow that case. If you must support it, then you have multiple things to clean up. Some of them to do with pass-by-value issues, others to do with what your code should do when the list initially contains 16 or more records.
Update:
Since you're having so much trouble working this out, here's a revised version of delete_record(). It implements a lot more than the minimal changes required to get the desired output upon record deletion, as there was in fact a goodly number of other issues that I might as well call out as long as I'm going to the trouble. See new and modified comments.
/*
* Can realloc() *firstname, *lastname, and *score and return the updated
* values to the caller. Most importantly, can update *the_size and have
* the caller see the result.
*/
void delete_record (char ***firstname, char ***lastname, float **score, int *the_size)
{
int i;
int initial_size = *the_size;
char str[21]; /* no need to malloc a fixed-length local array */
printf("Enter the lastname of record(s) to delete : ");
fflush(stdout); /* The prompt might not appear if you don't flush */
/*
* Note the field width in the format below. Without it, a user can
* easily cause a buffer overflow.
*/
scanf("%20s", str);
/*
* The strategy for each element to delete (there may be more than one)
* is to free the element's name components (else their allocated memory
* leaks), copy the last (at that time) element's components into
* place (for the name components, just the pointers), and later
* realloc to shrink the overall size to exactly fit the remaining
* elements (once we know how many that is).
*/
for (i = 0; i < *the_size; )
{
if (strcmp(str, (*lastname)[i]) == 0)
{
printf("Deleting Record for %s %s...\n", (*firstname)[i], (*lastname)[i]);
free((*firstname)[i]);
free((*lastname)[i]);
(*firstname)[i] = (*firstname)[*the_size - 1];
(*lastname)[i] = (*lastname)[*the_size - 1];
(*score)[i] = (*score)[*the_size - 1];
*the_size -= 1; /* not the same as *the_size-- */
/* don't increment i, else we miss testing the new i'th element */
} else {
i += 1;
}
}
if (*the_size != initial_size)
{
void *temp;
/*
* Always check the return value of realloc(), even when you're
* shrinking the allocation. Usually, though, you'd want at least
* some kind of diagnostic in the event of failure.
*/
temp = realloc(*firstname, sizeof(char *) * (*the_size));
if (temp)
{
*firstname = temp;
}
temp = realloc(*lastname, sizeof(char *) * (*the_size));
if (temp)
{
*lastname = temp;
}
temp = realloc(*score, sizeof(float) * (*the_size));
if (temp)
{
*score = temp;
}
}
else /* there is no match */
{
printf ("Sorry, no available record for %s",str);
}
}
Your main() would call that like so:
delete_record(&firstname, &lastname, &score, &number_of_records);
Similar changes are needed to add_record(), though you do have the separate issue I already called out there with increasing the number of entries past 16.
Additionally, you're making extra work for yourself by using separate arrays of first name, last name, and score. It would be much easier to define a struct encompassing all three, and use just one dynamic array whose elements are instances of that struct.
First, you're declaring the arguments of add_ as pointers (presumably because you want the function to change the value of the variables whose addresses you pass):
add_new_record (char **firstname, char **lastname, float *score, int the_size) {
But then you simply assign the locals, not the things they point to:
firstname = realloc(firstname,16*sizeof(char*));
score = realloc(score,16*sizeof(float));
If you want to change the variables to which these point, you have to
dereference them for assignment:
*firstname = malloc(16);
*score = 1.0;
Now the original firstname pointer points to a valid chunk of memory (presumably you'll want to strcpy() some actual name there), and the original float variable to which score points is now 1.0.
There are other problems, but that's the primary reason this function doesn't change what you think it should, because you didn't tell it to.

Trying to find frequency of certain characters in a string but the results are very far off

I am trying to write a program which calculates and prints the GC content of a string of DNA(which is input through a txt file). That is, the percentage of G's and C's in a string of DNA. Here is my function for the GC percentage:
void updateGCCount(char s[], int *gc, int *at) {
char c[MAXLENGTH];
int i,GCcount,ATcount;
float len,GCpercentage;
GCcount=0;
ATcount=0;
for(i=0;c[i]!='\0';++i)
{
if(c[i]=='G' || c[i]=='C')
{
++GCcount;
*gc=GCcount;
}
if(c[i]=='A' || c[i]=='T')
{
++ATcount;
*at=ATcount;
}
}
strcpy(c,s);
len=strlen(c);
GCpercentage=*gc/len;
printf("GC-content: %.2f\n",GCpercentage);
}
This is my function definition, and the part which is supposed to correctly print the GC percentage is what I am not sure about. Below is my main program which utilizes the input text file.
#include "genomics.h"
int main(){
char s[MAXLENGTH];
int gc, at;
scanf("%s",s);
printf("Sequence : %s\n",s);
updateGCCount(s, &gc, &at);
return 0;
}
Any help or advice on why I am not getting a correct value for the GCpercentage would be great. Thank you in advance
You're doing your tests on char array "c":
char c[MAXLENGTH];
...
for(i=0;c[i]!='\0';++i)
{
if(c[i]=='G' || c[i]=='C')
{
++GCcount;
*gc=GCcount;
}
if(c[i]=='A' || c[i]=='T')
{
++ATcount;
*at=ATcount;
}
}
If should be on s, the array that you passed in. The c array is probably superflous, you should be able to get the length from s as well
c is not initialize, so *gc and *at are not updated at all and they contain garbage..
here you should use s instead of c
for(i=0;c[i]!='\0';++i)
{
if(c[i]=='G' || c[i]=='C')
{
++GCcount;
*gc=GCcount;
}
if(c[i]=='A' || c[i]=='T')
{
++ATcount;
*at=ATcount;
}
}
That's a strongly un-idiomatic program. Consider the following.
#include <stdio.h>
#include <stdlib.h> /* for exit(3) */
float count_gc(const char* s)
{
You have no need to pass information back via variables passed in by reference. Functions return values -- typically 'the answer'.
You're simply scanning the content of the argument string s, so there's no need to copy it anywhere.
As others have pointed out, you were scanning the contents of the array c[] before you copied anything in to it -- you were counting 'G' and 'C' in a (probably large) random block of memory. Keeping things simple avoids mistakes like that.
int nvalid = 0;
int gccount = 0;
float result;
for (; *s != '\0'; s++) {
Although the for loop you wrote isn't wrong, it's somewhat un-idiomatic. Here, we examine the character pointed to by the pointer s, and then increment the pointer, until we find ourselves pointing at the \0 that terminates the string. Yes, this means we 'lose' the initial value of the argument, but we don't need it after the loop, so that doesn't matter.
switch (*s) {
A switch is a more natural construction here. You're looking for a small set of possible values that *s (that is, the character the pointer is currently pointing at) may have.
case 'G':
case 'C':
nvalid++;
gccount++;
break;
case 'A':
case 'T':
nvalid++;
break;
default:
/* unexpected character -- ignore it */
break;
Every switch statement should have a default clause -- one should always think of what's supposed to happen if none of the case clauses match. In this case, we just ignore this character.
}
}
if (nvalid == 0) {
fprintf(stderr, "No valid letters found!\n");
result = 0.0;
} else {
/* Multiply by 1.0 to convert integer gccount to a float */
result = 1.0*gccount / nvalid;
}
return result;
We return the result to the caller rather than printing it out inside the function. Functions shouldn't 'chatter', but leave all of the I/O in one place, typically leaving the main function (or something higher up) to look after that.
}
int main(int argc, char** argv)
{
if (argc != 2) {
/* Give the user a hint on how to call the program */
fprintf(stderr, "Usage: gcat <string>\n");
exit(1);
}
printf("Sequence GC-content = %g\n", count_gc(argv[1]));
}
I run that with:
% cc -o gcat gcat.c
% ./gcat "GCAT ATx foo"
Sequence GC-content = 0.333333
%
With C, it's very easy to tie yourself in knots, very quickly. Aim for simplicity always.

Remove an element from an array of structures in C?

I'm new to C, and honestly have no idea where to start with removing a particular element from an array of structures.
If you wish, you can view and copy my code in its entirety here: http://pastebin.com/Zbrm2xyL
Mostly I'm concerned with the function 'rmv_student', which is supposed to remove the struct with a matching id number from the array 'st_array' without messing with the other elements of that array after prompting the user for confirmation. Function 'rmv_student' is as follows:
void rmv_student(long id) // BROKEN
{
int i; // iterator
char response; // used to confirm deletion
for( i = 0; i < MAX; i++){
if ( st_array[i].id == id){
printf("Are you sure you want to delete %s %s, %d?\n", st_array[i].first_name, st_array[i].last_name, st_array[i].id);
puts("You will not be able to undo the deletion.");
puts("Enter 'y' to delete or 'n' to return to the main menu.");
response = getchar();
switch (response){
case 'y':
// delete
case 'Y':
// delete
case 'n':
main();
case 'N':
main();
default:
puts("Please enter 'y' or 'n'.");
rmv_student(id);
}
}
}
if ( i == MAX ){
printf("\nThere are no students with ID %d.\n\n", id);
main();
}
}
I have two questions.
Are my switch cases correct? Will this test the user's input character correctly?
How do I go about deleting the struct?
Before you ask. Yes, this is homework. As such, I'm not looking for a handout, just a point in the right direction. Any other suggestions are welcome.
Note: I am aware that I don't really need the function 'menu_test_input', but I'm leaving it for now.
Use loops and return statements instead of recursive calling! Remember that when the called function returns the code will continue after the call.
Instead do something like the following pseudo-code
do
{
print_prompt()
get_response()
} while (response is not legal)
if (response is yes)
do_the_actual_deletion
If you want to remove element X of array A, then move the element X + 1 to X, move element X + 2 to X + 1, etc. When done then decrease the size by one. No actual "removing" involved.
There are two possible solutions to your problem, which one you should use depends on whether the order of the array elements is important to you.
The fast solution: Copy the last element in the array to the position of the element you want to delete, then simply decrement your count of elements in the array.
int* array = ...;
int elementCount = ...;
...
int deletionIndex = ...;
array[deletionIndex] = array[--elementCount]; //the deletion is actually a one liner :-)
This solution is the preferred one whenever you are operating with an unsorted array, it takes only a constant amount of time, regardless of where you do the deletion.
The long solution: Move all elements behind the deleted element one position to the front.
//setup is the same as for the fast solution
elementCount--;
for(int i = deletionIndex; i < elementCount; i++) array[i] = array[i+1];
Not exactly difficult, but considerably more complex than the fast solution.
You need to use this whenever you need to preserve the relative order of the array elements. The price for the ordering is that the runtime depends on the amount of elements that need to be moved.
you have to use break;
case 'y':
//your code
break;
case 'Y':
//your code
break;
case 'n':
break;
...
......
or the code will run all your cases.
proper use - http://www.tutorialspoint.com/cprogramming/switch_statement_in_c.htm

Iterate through int array of unknown length

I am trying to iterate through an array that will contain up to a maximum of 4 elements - no other knowledge of the array-length exists.
Pseudo Code
void insert_vals(uint8_t num, uint8_t *match_num, uint8_t *value)
{
uint8_t i;
while(data_exists) // how do I determine if data exists in 'value'?
{
switch(num)
{
case 0:
{
switch(match_num[i])
{
case 0:
hw0reg0 = value[i];
case 1:
hw0reg1 = value[i];
case 2:
hw0reg2 = value[i];
case 3:
hw0reg3 = value[i];
}
}
case 1:
{
switch(match_num[i])
{
case 0:
hw1reg0 = value[i];
case 1:
hw1reg1 = value[i];
case 2:
hw1reg2 = value[i];
case 3:
hw1reg3 = value[i];
}
}
// etc. 2 other cases
}
i++;
}
}
Calling Example (Pseudo Code)
/*
* num: hardware device select from 1 - 4
* match_num: 4 possible matches for each hardware device
* value: 32-bit values to be assigned to 4 possible matches
* NOTE: This function assumes hardware devices are selected
* in a consecutive order; I will change this later.
*/
// example calling code - we could have configured 4 hardware devices
insert_vals(0, [0, 1], [0x00000001, 0x000000FF]); // arg2 and arg3 equal in length
How can I accomplish this?
In a character array, C will automatically add '\0' to the end of the array, but this does not seem to be the case for an integer array. If I was somehow able to determine the length of match_num and value (see if statement) at runtime originally, then that would allow me to create a for loop.
Edit
Since I know that there will be a maximum of 4 elements, couldn't I do something similar to the following?
void insert_vals(uint8_t num, uint8_t *match_num, uint32_t *value)
{
int i;
for(i = 0; i < 4; i++)
{
if(value[i] == -1)
break;
else
{
// Assign data
}
}
}
You can't get the length of an array pointed to given only the pointer. Either you have to pass the length, or it must be constant (always 4) with some sentinel value in the unused elements -- a value that is somehow invalid for your computations (like NUL is for strings).
Is there a value you can guarantee it's not in the "usable" data? (e.g. 0 is no valid character for character strings, therefore Mr. Kernighan and Mr. Ritchie decided to pick it as a "end of array" marker. You could do the same with any value.
Say you know your integer values are between 0 to 512, so you could initialize the whole array e.g. to 1024, then fill it and iterate through it until a number >512 occurs (which has to be your end of array marker).
Another possibility is to pass the number of elements in the array along with the array.

Resources