Seemingly random return values - c

I'm trying to make a simple assembler for a very simple MIPS processer. Unfortunately, C has been giving me a lot of trouble, specifically, strcasecmp has not been returning valid/correct results. The results are correct sometimes.. but usually not, and I can't grasp why in the world this would be the case. Beyond any suggestions for a fix, could someone explain why these errors are occurring?
NOTE I do not think the error is due to passing the register table. Same errors occur when register table is declared inside the convert register function
Thanks!!!
the function that should return the value corresponding to the register name. Note that RegisterTable is declared in main. I did this so I could iterate through and test every Register name in the table from main
int ConvertRegisterName(char * rname,REG_NAME_PAIR RegisterTable[32])
{
int i;
int j=0;
for (i=1; i<32; i++,i++)
{
if (!(strcasecmp(RegisterTable[i].reg_number,rname) & strcasecmp(RegisterTable[i].reg_name,rname)))
{
j=i;
return j;
break;
}
}
if(!j)
{
printf("Error with register name \n");
return j;
}
}
The main function
int main(int argc,char *argv[])
{
REG_NAME_PAIR RegisterTable[32];
RegisterTable[1].reg_name = "at";
RegisterTable[1].reg_number = "$1";
RegisterTable[2].reg_name = "v0";
RegisterTable[2].reg_number = "$2";
RegisterTable[3].reg_name = "v1";
RegisterTable[3].reg_number = "$3";
RegisterTable[4].reg_name = "a0";
RegisterTable[4].reg_number = "$4";
RegisterTable[5].reg_name = "a1";
RegisterTable[5].reg_number = "$5";
RegisterTable[6].reg_name = "a2";
RegisterTable[6].reg_number = "$6";
RegisterTable[7].reg_name = "a3";
RegisterTable[7].reg_number = "$7";
RegisterTable[8].reg_name = "t0";
RegisterTable[8].reg_number = "$8";
RegisterTable[9].reg_name = "t1";
RegisterTable[9].reg_number = "$9";
RegisterTable[10].reg_name = "t2";
RegisterTable[10].reg_number = "$10";
RegisterTable[11].reg_name = "t3";
RegisterTable[11].reg_number = "$11";
RegisterTable[12].reg_name = "t4";
RegisterTable[12].reg_number = "$12";
RegisterTable[13].reg_name = "t5";
RegisterTable[13].reg_number = "$13";
RegisterTable[14].reg_name = "t6";
RegisterTable[14].reg_number = "$14";
RegisterTable[15].reg_name = "t7";
RegisterTable[15].reg_number = "$15";
RegisterTable[16].reg_name = "s0";
RegisterTable[16].reg_number = "$16";
RegisterTable[17].reg_name = "s1";
RegisterTable[17].reg_number = "$17";
RegisterTable[18].reg_name = "s2";
RegisterTable[18].reg_number = "$18";
RegisterTable[19].reg_name = "s3";
RegisterTable[19].reg_number = "$19";
RegisterTable[20].reg_name = "s4";
RegisterTable[20].reg_number = "$20";
RegisterTable[21].reg_name = "s5";
RegisterTable[21].reg_number = "$21";
RegisterTable[22].reg_name = "s6";
RegisterTable[22].reg_number = "$22";
RegisterTable[23].reg_name = "s7";
RegisterTable[23].reg_number = "$23";
RegisterTable[24].reg_name = "t8";
RegisterTable[24].reg_number = "$24";
RegisterTable[25].reg_name = "t9";
RegisterTable[25].reg_number = "$25";
RegisterTable[26].reg_name = "k0";
RegisterTable[26].reg_number = "$26";
RegisterTable[27].reg_name = "k1";
RegisterTable[27].reg_number = "$27";
RegisterTable[28].reg_name = "gp";
RegisterTable[28].reg_number = "$28";
RegisterTable[29].reg_name = "sp";
RegisterTable[29].reg_number = "$29";
RegisterTable[30].reg_name = "fp";
RegisterTable[30].reg_number = "$30";
RegisterTable[31].reg_name = "ra";
RegisterTable[31].reg_number = "$31";
int i;
for (i=1; i<32; i++)
{
printf("i is %d\n",i);
printf("Register Name is %s \n" ,RegisterTable[i].reg_name);
printf("this is the return value %d",ConvertRegisterName(RegisterTable[i].reg_name,RegisterTable));
printf("\n");
printf("Register Number %s\n",RegisterTable[i].reg_number);
printf("this is the return value %d",ConvertRegisterName(RegisterTable[i].reg_number,RegisterTable));
printf("\n");
printf("\n");
}
}
The REG_NAME_PAIR struct
typedef struct
{
char *reg_name;
char *reg_number;
} REG_NAME_PAIR;

The conversion function could probably be simplified and corrected to something like this:
int ConvertRegisterDesc(const char * token, REG_NAME_PAIR RegisterTable[])
{
for (int i = 1; i != 32; ++i)
{
if (strcasecmp(RegisterTable[i].reg_number, token) == 0 ||
strcasecmp(RegisterTable[i].reg_name, token) == 0 )
{
return i;
}
}
printf("Error with register name \n");
return 0;
}
Now ConvertRegisterDesc("foo", RegisterTable) returns the index of an entry whose name or value is (a case variant of) "foo", and 0 if no such entry could be found.

You seem to be using the & operator instead of &&.
& does bitwise and, not logical and. So for example:
0x01 & 0x02 == 0 - because no bit is set on both
0x01 && 0x02 == 1 - because both 0x01 and 0x02 evaluate to true.

Related

why is this else block executed twice?

I have the following code which correctly calculates the jaccard similarity between an input char array and an existing array of char arrays. jacc_sim_rec[] is used to record the similarities which satisfy a minimum threshold value. The for loop is used to iterate through the multidimensional array and the loop is supposed to continue checking similarity if minimum threshold is not satisfied at if (jacc_sim < SIM_THRESHOLD); else record the result at
else
{
jacc_sim_rec[j] = jacc_sim;//keep record of similarity
++j;//record number of highly similar elements
}
my problem is, the whole statements in the else block is executed twice every time the threshold value is satisfied.
int j=0;
void calc_jac_sim( char*INCOMING, int grp)
{
unsigned long i, j11 = 0, j01 = 0, j10 = 0,m=0;
char *m11, *m01, *m10;
float jacc_sim = 0.0;
char r1[SBF_LEN] = { NULL };
char r2[SBF_LEN] = { NULL };
char r3[SBF_LEN] = { NULL };
int cnt = SBF_LEN - 1;
clear_jacc_sim_info();
for (int i = 0; i <= SBF_REC[grp]; ++i)
{
while (cnt >= 0)
{
r1[cnt] = SBF[grp][i][cnt] & INCOMING[cnt];
r2[cnt] = ~SBF[grp][i][cnt] & INCOMING[cnt];
r3[cnt] = SBF[grp][i][cnt] & ~INCOMING[cnt];
cnt--;
}
m11 = ( char*)r1;
m01 = ( char*)r2;
m10 = ( char*)r3;
for (m = SBF_LEN * sizeof( char); m--;
j11 += NumberOfSetBits(*m11++),
j01 += NumberOfSetBits(*m01++),
j10 += NumberOfSetBits(*m10++));
jacc_sim = j11 / (float)(j11 + j01 + j10);
if (jacc_sim < SIM_THRESHOLD);
//continue;//do nothing
else
{
jacc_sim_rec[j] = jacc_sim;//keep record of similarity
++j;//record number of highly similar elements
}
}
}
I don't understand the code, but I'll bet the problem is that you're not reinitializing cnt each time through the for loop, so you only fill in r1, r2, and r3 when i = 0.
Change that loop to:
for (int cnt = SBF_LEN - 1; cnt >= 0; cnt--)
{
r1[cnt] = SBF[grp][i][cnt] & INCOMING[cnt];
r2[cnt] = ~SBF[grp][i][cnt] & INCOMING[cnt];
r3[cnt] = SBF[grp][i][cnt] & ~INCOMING[cnt];
}
I'm also not sure why this needs to count down instead of up, like a typical loop, but it shouldn't make a difference.

Format any number in Indian currency style using C language

Indian Currency format is 12345 → "12,345" (for odd length) and 123456 → "1,23,456" (for even length). I have included all possibilities such as
1. Minus sign: "-12,345".
2. Decimal Point: "-12,345.345" or "12,345.123".
3. Zero Condition 000000.123 → "0.123".
4.Minus and Zero Condition '-000000.123' -> "-0.123"
int currencyFormatter(char av_currency[], int av_strLen, char *ap_formattedNumber)
{
char flag = 'N'; //Taking a Flag to know whether thier is a decimal Point in Currency or not
int lengthOf = 0, index = 0, i = 0, j = 0;
char *decAr = NULL;
char *tmpCurrency = NULL;//Taking two Pointers one for Array with Commas(tmpCurrency) and decAr pointer for decimal Point array
char *s = NULL;
s = strstr(av_currency, ".");//Checking for decimal Point in array
if (s > 0)
{
flag = 'D'; // Changing Flag to show Decimal Point is Present in Array
s = strchr(av_currency, '.');
index = s - av_currency; //Index at which Decimal Point is present
av_strLen = strlen(av_currency) - index; // calculated formula to know length of an array needed to contain decimal point and Numbers after that
decAr = (char*)malloc(av_strLen*sizeof(char*));//allocated Memory using malloc
decAr[av_strLen] = '\0';
memmove(decAr, &av_currency[index], av_strLen); //memmove from decimal till end of array.
av_currency[index] = '\0';
if (!decAr)//Handled Null Condition for Pointer
{
return -1;//All errors for Negative Number
}
}
lengthOf = strlen(av_currency) + (strlen(av_currency) / 2); // Derived Formula(It Works for Indian Currency Format) to know the length of an array is needed to contain numbers and Commas Together.
tmpCurrency = (char*)malloc(lengthOf*sizeof(char*));
strrev(av_currency); //Reversed Array as commas comes at multiple of 3. eg=12345 reverse=54321 wdComma=543,21 index is 3 if number would had been bigger commas would had come at 3,6.
while (av_currency[i] != '\0')
{
if (j % 3 == 0 && j >= 3 && av_currency[i] != '-')//all Commas come at multiple of 3 when you reverse an amount
{
tmpCurrency[j] = ',';//If an , is found Increment only J as
is used as index number to store in tmpcurrency
j++;
continue;
}
tmpCurrency[j] = av_currency[i];//storing the Value in tmpCurrency
i++;//Incrementing
j++;//Incrementing
}
tmpCurrency[j] = '\0';//Null Condition
if (!tmpCurrency) // Checking for NULL Pointer
{
return -2; //all errors for Negative value
}
flag == 'D' ? strcpy(av_currency, (strcat(strrev(tmpCurrency), decAr))) : strcpy(av_currency, (strrev(tmpCurrency)));//Ternary Operator
strcpy(ap_formattedNumber,av_currency);//Copying formated number into original array
free(tmpCurrency);//Releasing the memory
free(decAr);//Releasing the Memory
return 0;
}
I have solution for above question.
Please try this code.
#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <stdlib.h>
char *printComma(double input_number,char *demo,char ap_it[],char ap_type[])
{
char *result = NULL;
char *lp_decimal_number = NULL;
char *main_number = NULL;
char *decimal_pos = NULL;
char zero[1] = {0};
int i = 0;
int j = 0;
int z = 0;
int cnt = 0;
int decimal_index = 0;
int lp_decimal_numberLen = 0 ;
int flag_dec = 0;
int flag_minus = 0 ;
int length_main;
int k = 0;
int length_demo=0;
sprintf(demo,"%lf",input_number);
if(strcmp(ap_type,"P") == 0)
{
if(strcmp(ap_it,"A") == 0 || strcmp(ap_it,"B") == 0)
{
sprintf_s(demo,40,"%0.4lf",input_number);
}
else
{
sprintf_s(demo,40,"%0.2lf",input_number);
}
}
else
{
sprintf_s(demo,40,"%.0lf",input_number);
}
length_demo = strlen(demo); // finds the length of original string
result = (char *)malloc((length_demo+10)*sizeof(char));
main_number = (char *)malloc((length_demo+50)*sizeof(char));
z = strspn(demo[0] == '-' ? (demo + 1) : demo , "0");
if(z != 0)
{
if(demo[0] != '-')
{
memcpy(main_number,&demo[z],length_demo);
main_number[length_demo]='\0';
}
else
{
puts(main_number);
main_number[length_demo]='\0';
flag_minus=1;
}
}
else
{
memcpy(main_number,&demo[0],length_demo);
main_number[length_demo]='\0';
}
length_main=strlen(main_number);
decimal_pos = strstr(main_number,".");
if(decimal_pos > 0)
{
decimal_index = decimal_pos - main_number ; // Getting postion of decimal
lp_decimal_numberLen = length_main - decimal_index; // Calculating the endpoint for decimal number
if(length_main > 3) //Copying the decimal part to a separate array
{
lp_decimal_number = (char *) malloc(lp_decimal_numberLen+1);
memcpy( lp_decimal_number, &main_number[decimal_index], lp_decimal_numberLen );
lp_decimal_number[lp_decimal_numberLen] = '\0';
flag_dec=1;
main_number[decimal_index]='\0';
}
}
//logic for comma starts here
strrev(main_number);
i = 0;
while(main_number[i] != '\0')
{
if (j%3 == 0 && j>=3 && main_number[i]!='-' && main_number[i]!='$')
{
result[j] = ',';
cnt++;
j++;
continue;
}
else if(cnt==1 || cnt==2)
{
result[j] = main_number[i];
}
else
{
result[j] = main_number[i];
}
i++;
j++;
}
result[j] = '\0';
if(flag_dec==0)
{
if(flag_minus==0)
return(strrev(result));
else
{
strcat(result,"-");
return(strrev(result));
}
}
else
{
if(flag_minus==0)
return(strcat(strrev(result),lp_decimal_number));
else
{
strcat(result,"-");
return(strcat(strrev(result),lp_decimal_number));
}
}
}
int main()
{
double number;
char num[25] = {0};
char it_type[] = "A";
char ap_type[] = "P";
char *formattedNumber = NULL;
printf("\n Enter the number n: ");
scanf("%lf",&number);
formattedNumber=printComma(number,num,it_type,ap_type);
printf("\n Final Result = %s ",formattedNumber);
getch();
return 0;
}
Do only positive values with your function!
Check if the value is negative before calling the function; call the function with the positive value; if it was negative to start with, add the minus sign afterwards.
int needssign = 0;
if (val < 0) needssign = 1;
indianformat(res, abs(val));
if (needssign) sprintf(res, "-%s", res);
Or make your current function a helper function and use the code above for the new improved function for formatting in Indian format.

C: How to increment after entering an if statement

I am trying to enter an if statement when my counter reaches the value 51, and then increment the counter inside the if statement so that it is never true again:
void imu_raw_handler (const lcm_recv_buf_t *rbuf, const char *channel,
const imu_raw_t *msg, void *userdata) {
for(counter = 1; counter < 51; counter++)
{
gyro_roll = (gyro_roll + gyro_roll_old*(counter-1))/counter;
gyro_pitch = (gyro_pitch + gyro_pitch_old*(counter-1))/counter;
gyro_yaw = (gyro_yaw + gyro_yaw_old*(counter-1))/counter;
accel_x = (accel_x + accel_x_old*(counter-1))/counter;
accel_y = (accel_y + accel_y_old*(counter-1))/counter;
accel_z = (accel_z + accel_z_old*(counter-1))/counter;
}
if (counter == 51){
// set zero points
axo = accel_x;
ayo = accel_y;
azo = accel_z;
gro = gyro_roll;
gpo = gyro_pitch;
gyo = gyro_yaw;
printf("Ready for Takeoff\n");
counter++;
}
}
Edit: My main function looks like this. It is supposed to subscribe to a streaming topic for as long as it is running. I define a counter as a global variable.
int main()
{
lcm_t *lcm = lcm_create(NULL);
imu_raw_t_subscribe(lcm, "IMU_RAW", imu_raw_handler, NULL);
// Enter read loop
while (1) {
if(!lcm_handle_timeout(lcm, 1000)) {
printf("Failed read from IMU_RAW channel\n");
}
}
lcm_destroy(lcm);
}
But this will repeatedly print my message forever rather than making counter = 52 and never happening again. Why does this not work?
The problem most likely exists outside these code snippets. Please check if you have no prints somewhere else.
The problem is because you call that function in a while, and because of
for(counter = 1; counter < 51; counter++)
the counter will become again 51 (everytime the function is called) and then will enter again in that if (counter == 51).
To resolve that you could declare a global variable int ok = 0; and use it like this:
void imu_raw_handler (const lcm_recv_buf_t *rbuf, const char *channel,
const imu_raw_t *msg, void *userdata) {
for(counter = 1; counter < 51; counter++)
{
gyro_roll = (gyro_roll + gyro_roll_old*(counter-1))/counter;
gyro_pitch = (gyro_pitch + gyro_pitch_old*(counter-1))/counter;
gyro_yaw = (gyro_yaw + gyro_yaw_old*(counter-1))/counter;
accel_x = (accel_x + accel_x_old*(counter-1))/counter;
accel_y = (accel_y + accel_y_old*(counter-1))/counter;
accel_z = (accel_z + accel_z_old*(counter-1))/counter;
}
if (ok == 0){ //will enter here once, only if you don't modify the ok anytime
// set zero points
axo = accel_x;
ayo = accel_y;
azo = accel_z;
gro = gyro_roll;
gpo = gyro_pitch;
gyo = gyro_yaw;
printf("Ready for Takeoff\n");
ok = 1; //this will be done once
}
}
I hope this is correct.
The for loop right before the if uses the counter variable, so every time the loop is finished, counter will be 51.
My guess is that the loop shouldn't be there at all, it doesn't seem to make any sense.

Why the code block is not Autovectorized by VC2013

The code block is from mozilla firefox's qcms transform_util.c
void build_output_lut(struct curveType *trc,
uint16_t **output_gamma_lut, size_t *output_gamma_lut_length)
{
if (trc->type == PARAMETRIC_CURVE_TYPE) {
float gamma_table[256];
uint16_t i;
uint16_t *output = malloc(sizeof(uint16_t)*256);
if (!output) {
*output_gamma_lut = NULL;
return;
}
compute_curve_gamma_table_type_parametric(gamma_table, trc->parameter, trc->count);
*output_gamma_lut_length = 256;
for(i = 0; i < 256; i++) {
output[i] = (uint16_t)(gamma_table[i] * 65535);
}
*output_gamma_lut = output;
} else {
if (trc->count == 0) {
*output_gamma_lut = build_linear_table(4096);
*output_gamma_lut_length = 4096;
} else if (trc->count == 1) {
float gamma = 1./u8Fixed8Number_to_float(trc->data[0]);
*output_gamma_lut = build_pow_table(gamma, 4096);
*output_gamma_lut_length = 4096;
} else {
//XXX: the choice of a minimum of 256 here is not backed by any theory,
// measurement or data, however it is what lcms uses.
*output_gamma_lut_length = trc->count;
if (*output_gamma_lut_length < 256)
*output_gamma_lut_length = 256;
*output_gamma_lut = invert_lut(trc->data, trc->count, *output_gamma_lut_length);
}
}
}
For this loop:
for(i = 0; i < 256; i++) {
output[i] = (uint16_t)(gamma_table[i] * 65535);
}
VC2013 will show:
e:\mozilla\hg\nightly\mozilla-central\gfx\qcms\transform_util.c(490) : info C5002: 由于“500”,循环未向量化
MSDN (http://msdn.microsoft.com/en-us/library/jj658585.aspx) shows:
// Code 500 is emitted if the loop has non-vectorizable flow.
// This can include "if", "break", "continue", the conditional
// operator "?", or function calls.
// It also encompasses correct definition and use of the induction
// variable "i", in that the increment "++i" or "i++" must be the last
// statement in the loop.
But the loop above has no if/break/continue, I don't know why it can't be vectorized.
I suspect that this is due to the fact that variable "i" lies in scope of "if"-statement. Thus it does not belong entirely to "for-loop" scope like it would have been in
for(int i = 0; /* etc. */
At such, the compiler's logic would have been like: "I need not only to make gammatable filles with needed values, but to assign same value to "i" as at loop end". Therefore, no vectorization.

C arrays calling functions

below is my code for your reference. Rx_Buf contains one of the two values from Rfid_Tag[][]. I am getting tht value from another function and I want to find and confirm. the problem is its not working. Rfid_Tag[][] has different values i.e. its corrupted. I am not sure how a global variable defined is getting corrupted. I tried declaring it const, extern still the same problem.When i run this as standalone program it works perfectly, but when I call this function from main.c its not working. Can anyone pleasee help me with this.
Thanks
#define NUMBER_OF_RFID_TAGS 2
#define RFID_DATA_LENGTH 17
unsigned char Rfid_Tag[NUMBER_OF_RFID_TAGS][RFID_DATA_LENGTH]= {
{0x96,0x12,0xf1,0x6e,0xda,0x57,0x98,0x02,0x00,0xe1,0x50,0x00,0x00,0x00,0x00,0x00,0x11},
{0x96,0x72,0xe9,0x6e,0xda,0x2f,0x98,0x02,0x00,0xe1,0x50,0x00,0x00,0x00,0x00,0x00,0x11}
};
int RFID_check(char *Rx_Buf)
{
//unsigned char ucRfidReceivedData[RFID_DATA_LENGTH]= *Rx_Buf; //{0x00,0x01,0x2,0x03,0x04,0x5,0x06,0x07,0x8,0x09,0x0A,0xB,0x0C,0x0D,0xE,0x0F,0x10};
unsigned count = 0;
int found = false;
for(int i = 0; i < NUMBER_OF_RFID_TAGS; i++){
count = 0;
for(int j = 0; j < RFID_DATA_LENGTH; j++){
if(Rfid_Tag[i][j] == Rx_Buf[j]){
count++;
//PORTR.DIR = 0xff;
//PORTR.OUTTGL = 0xff;
}
}
if(count == RFID_DATA_LENGTH){
found = true;
break;
}
}
if(found == true){
PORTR.DIR = 0xff;
PORTR.OUTTGL = 0x0f;
RFID_accept();
}
else{
RFID_error();
PORTR.DIR = 0xff;
PORTR.OUTTGL = 0x00;
}
return 0;
}

Resources