   C - padding string of binary digits [UPDATED]
  Hi,I've got a problem with C.  Actually, I fucking hate it but I've got to use it for an assignment, I know what GDNet's policy is regarding this but I'm totally stuck.Essentially, I've got to convert a decimal number to a binary string.  As we've not been taught how to do this and we're allowed to borrow small snippets of code provided it's appropriately referenced, I found this:// Do loop to do the decimal-binary conversion// Modelled on a method found at http://www.daniweb.com/code/snippet87.html, accessed March 19th 2008 (although not completely identical)int remainder;char operandString[80];bzero(operandString,80);char revbin[80]; // Where we store the reversed binary string after conversion is donebzero(revbin,80);int z = 0;int doRev=0;do{remainder = operand % 2;operand = operand / 2;operandString[z++] = remainder +'0';}while(operand > 0);while (z >= 0) {revbin[doRev++] = operandString[--z];}// End duplicated code segmentThis works fine, except for one problem; the binary string needs to be padded out to 5 digits e.g. the binary digit 1 needs to be 00001, 12 in decimal needs to be 01100 instead of just 1100 etc.  The motivation behind this is that it needs to form the first 5 bits of a 32-bit binary instruction line (we're making a really primitive assembler which takes in an ASCII file with an assembly syntax and converts it to 32 32bit binary lines).I'm completely stuck and C doesn't seem to provide any obvious ways of achieving this unless I'm missing something.Any ideas as to where to go?  Thanks in advance,ukd.[Edited by - ukdeveloper on March 19, 2008 10:14:06 PM]
  I would probably use a for loop that loops through each bit of the number (from 4 to 0) and mask the number against that bit. If the bit it 1 I would store a '1' and if it's a 0 I would store a '0'.Normally I would post source code here to do this for you, but since it's for a class assignment, I'll let you turn that into code.;  Thanks, I'll probably have to take a look into that.I've got another problem though... not sure how to even begin explaining it (I FUCKING HATE C):Right.  Essentially, what I'm trying to do is build up a 32 character string to represent a line of binary.  Here's my code for doing so:void loadAndParseFile(){char line[32]; // Line won't ever be 32 long at this point; this is a hack to avoid a segfaultchar temp_OpCode[3];char lineRemainder[2]; // The remaining part of the linechar* binOpCode;char* binInstructionPart;//char* binInstructionLine;int lineNumber = 0;printf("Reading... ");while ( fgets ( line, sizeof line, fHandle ) != NULL ){//printf("lineNumber: %i\n",lineNumber);char* binInstructionLine;bzero(temp_OpCode,3); // Zero this array's memorystrncat(temp_OpCode,line,3); // Stick the first three characters of the line into the temp_OpCode string; the opcode is stored in the first three bitslineArray[lineNumber] = new_assemblerLine(); // Create a new line object// Get the binary representation of the opCode and assign it to the structbinOpCode = formulateOpCode(temp_OpCode);sprintf(lineArray[lineNumber].opCode,binOpCode);//printf("lineRemainder: %s",lineRemainder);// Get the binary representation of the instruction and assign it to the struct//binInstructionPart = completeInstruction(binOpCode,lineRemainder);//sprintf(lineArray[lineNumber].actualInstruction,binInstructionPart);binInstructionLine = completeInstruction(binOpCode);//printf("binInstructionLine: %s\n",binInstructionLine);sprintf(lineArray[lineNumber].finalInstruction,binInstructionLine);//printf("This thing: %s\n",lineArray[lineNumber].finalInstruction);lineNumber++;}printf("done.\n");}char* instructionLine;// Converts the opCode we pass in to binary and passes it to the function we use to formulate the  instruction// Easier to formulate all of this into one function, but more modular if we don't...char* formulateOpCode(char temp_OpCode[])//char* formInstruction(char temp_OpCode[]){char* opCode; // Used for binary representation of the op codechar* instructionLine; // The completed instruction we will be passing backif( strcmp(temp_OpCode,"JMP") == 0 ) // Code 0{opCode="000";}else if ( strcmp(temp_OpCode,"JRP") == 0 ) // Code 1{opCode="001";}else if ( strcmp(temp_OpCode,"LDN") == 0 ) // Code 2{opCode="010";}else if ( strcmp(temp_OpCode,"STO") == 0 ) // Code 3{opCode = "011";}else if ( strcmp(temp_OpCode,"SUB") == 0 ) // Codes 4 and 5{opCode = "100";}else if ( strcmp(temp_OpCode,"CMP") == 0 ) // Code 6{opCode = "110";}else if ( strcmp(temp_OpCode,"STP") == 0 ) // Code 7{opCode = "111";}else // If the instruction isn't any of the above...{printf("Unrecognised instruction \"%s\" found in source file.  Exiting.\n",temp_OpCode);exit(-1);}return opCode;}// Gets the actual instruction substance and returns it i.e. everything after the opcode// Bits 0-4 represent the line number, bits 13-15 are the opcodechar* completeInstruction(char opCode[]){char tempBinOpcode[3]; // A string we use to hold the binary digits from the conversion of the opcode to binary from decimal//strncat(tempBinOpcode,opCode,3);char toInt[2]; // Where we store the integer converted to a stringint operand = 1; // Hardcoded; will be read from file later on// Do loop to do the decimal-binary conversion// Modelled on a method found at http://www.daniweb.com/code/snippet87.html, accessed March 19th 2008 (although not completely identical)int remainder;char operandString[80];bzero(operandString,80);char revbin[80]; // Where we store the reversed binary string after conversion is donebzero(revbin,80);int z = 0;int doRev=0;do{remainder = operand % 2;operand = operand / 2;operandString[z++] = remainder +'0';}while(operand > 0);while (z >= 0) {revbin[doRev++] = operandString[--z];}// End duplicated code segmentchar* instructionLine;int count = 0;for(count = 0; count < 32; count++){instructionLine[count]='0';}// Puts the opcode into bits 13-15 on instruction line stringint addOpCode = 0;for (addOpCode = 12; addOpCode <=14; addOpCode++){instructionLine[addOpCode] = opCode [addOpCode - 12];}//printf("instructionLine afterwards: %s\n",instructionLine);return instructionLine;}The struct I'm referring to looks like this:#define oLength 3#define iLength 29#define lineLength 32typedef struct assemblerLine_t{char opCode[oLength];char actualInstruction[iLength];char finalInstruction[lineLength];}assemblerLine;What's happening is this, essentially: When I debug inside the completeInstruction function, everything's great; binInstructionLine has the correct value, and so does lineArray[lineNumber].finalInstruction after I run the sprintf.However, when I go to here:printf("Which file would you like to write to?: ");char outPath[max_filename_length];gets(outPath);fOut = fopen(outPath,"w");int outputCounter = 0;for(outputCounter = 0; outputCounter <= maxLinesAllowed; outputCounter++){//printf("Printing %s to file...\n",lineArray[outputCounter].finalInstruction);fprintf(fOut,"%s\n",lineArray[outputCounter].opCode);}}printf("\n");and do a printf on ANY of the array items, it shows me that the finalInstruction variable inside the struct has the finalInstruction line of ALL of the structs in the array and not just its own one.  I know this is really difficult to explain, it's like the pointer inside my other function is persistent or something and is shoving the original value in with the new one.When I run the for-loop with the fprint inside, I see that the file written has 32 lines in it.  However, line 1 has what I describe above, line 2 has slightly less as if one of the struct's values has been removed, line 3 another removed value... I can see this by putting a delimiter in the print statement.This makes no sense at all.  When I remove any calls to the completeInstruction() function and printf/fprintf lineArray[index].opCode it's got all the correct data and is formatted properly, so the problem obviously lies in the completeInstruction function but I don't understand what or where it is.  I wonder, as I've said, if there's a pointer somehow retaining its value and ending up with old data being put in with the new?Thanks in advance, I'm stressed and frustrated with this.ukd.   ;  I think you're really overcomplicating this, consider this example:char DecNumberStr[]="13";char BinNumberStr[6];int BinStrIndex=0;int n=16;int DecNumber=atoi(DecNumberStr);while(n>=1){    if(DecNumber >= n)    {   BinNumber[BinStrIndex]='1';    }    else    {   BinNumber[BinStrIndex]='0';    }    BinStrIndex++;    n>>1;};Quote:Original post by ukdeveloperThis works fine, except for one problem; the binary string needs to be padded out to 5 digits e.g. the binary digit 1 needs to be 00001, 12 in decimal needs to be 01100 instead of just 1100 etc.  The motivation behind this is that it needs to form the first 5 bits of a 32-bit binary instruction line (we're making a really primitive assembler which takes in an ASCII file with an assembly syntax and converts it to 32 32bit binary lines).The answer is right in front of you already. You don't need anything complicated. But you do need to understand the code you found instead of just borrowing it.How many times will the first loop in your code execute? How do you know? (Hint: it isn't a constant number).How many times will the second loop execute? (Answer: the same number of times as the first loop). What does each iteration of the first loop do? And each iteration of the second? How many digits will get put into the output array?Now, think about it. If you want the output to have five digits always, how many digits need to get put into the output array? Therefore, how many times do you want the second loop to run? Therefore, how many times do you want the first loop to run? How will you make it run that many times exactly? :)Finally, consider the buffer sizes. What makes more sense for those buffer sizes?Then, double-check: if the input value is small, what will happen all the "extra" times through the loop? If it's big, what will happen to the overflow? Are these behaviours acceptable?   