community, I have little experience with C and I am on the learning curve right now.
I am working on a little project that involves dividing a 32-char string into 4 strings of 8 chars each in C.
The 32-char string should resemble a 32-bit instruction. Those "32 bits" are divided into 4 "8-bit" strings that I want to print out as Hex. The code below is what I got so far. The data types I am using are the ones I am using in the rest of my code. I intend to feed the unsigned char t variable into an Substitution Box program that will give me equivalent of that t char from the S-Box lookup table.
The code below seems to me like it should work
unsigned char inst[] = "10101010101010101111111100111101";
unsigned char in[8];
for (int i = 0; i < 33; i++){
if (i%8 == 0 && i != 0) {
unsigned char t = (unsigned char) strtol(in, NULL, 2);
printf("%x \n", t);
}
in[i%8] = inst[i];
printf("%c ", in[i%8]);
}
but the output looks like this:
1 0 1 0 1 0 1 0 3d
1 0 1 0 1 0 1 0 3d
1 1 1 1 1 1 1 1 3d
0 0 1 1 1 1 0 1 3d
I can see that in[i%8] = inst[i]; line is reading the chars from inst[] correctly, but the
if (i%8 == 0 && i != 0) {
unsigned char t = (unsigned char) strtol(in, NULL, 2);
printf("%x \n", t);
}
conditional statement prints the wrong hex.
The output should look like something like this
1 0 1 0 1 0 1 0 aa
1 0 1 0 1 0 1 0 aa
1 1 1 1 1 1 1 1 ff
0 0 1 1 1 1 0 1 3d
Any help would be appreciated.
Problems with the current code:
"4 strings of 8 chars each" is char in[4][8+1]; and not char in[8]. You need room for null termination.
32 bits means iterate from 0 to 31, not from 0 to 32.
There's no need to copy byte per byte. It's slow and makes everything needlessly complicated.
This seems to be the requirements:
Split the original string in 4 sub strings.
Convert each sub string to an integer.
Display the result as hex
In which case you can simply iterate 4 times over the input string:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main (void)
{
const char* inst = "10101010101010101111111100111101";
char in [4][8+1];
puts("Bin Hex");
for(size_t i=0; i<4; i++)
{
memcpy(in[i], &inst[i*8], 8);
in[i][8] = '\0';
unsigned long val = strtoul(in[i], NULL, 2);
printf("%.8s %.2lX\n", in[i], val);
}
}
Output:
Bin Hex
10101010 AA
10101010 AA
11111111 FF
00111101 3D
The problem is your in is not NUL terminated.
Thus passing in to strol invokes the undefined behavior.
Do as below.
unsigned char in[9]; //+1 to hold the NUL char.
....
if (i%8 == 0 && i != 0) {
in[8] = '\0'; //NUL terminate the string.
unsigned char t = (unsigned char) strtol(in, NULL, 2);
printf("%x \n", t);
}
Related
I'm working on a program which reads every integer in csv file and copies it into a buffer so that I can later use it to construct a binary search tree with it. I'll show my code, then I'll explain the issue I'm having:
Code -
int *createBuffer(int count) {
FILE *file = fopen(FILE1, "r");
int buffer[count + 1];
int *bufferPointer = buffer;
int number;
int ch;
int i = 0;
while (1) {
ch = fgetc(file);
if(ch == EOF){
break;
}
if (fscanf(file, "%i", &number)) {
buffer[i] = number;
i++;
}
}
return bufferPointer;
}
Count refers to the number of commas that are present in the file so I can allocate enough space for each number in the array. The file pointer points to the file I'm opening in read-only mode. The buffer is created using the aforementioned count variable. bufferPointer is the pointer to the buffer that I'm returning from the function. The while loop runs until the variable ch is equal to EOF at which point it breaks. The if statement's purpose is basically to scan the file for integers and read them into number, and then copy number into the next buffer index. Finally, the buffer pointer is returned.
This code is giving me extremely strange results. When I print the buffer, I get the result:
9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 850045856 0 -2141008008 32767 0 0 214814639 1 0 0 -2141007448 32767 0 0 214814639 1 -487430544 32766 539243238 32767 -2141007448 32767 6 0 -487430496 32766 539279361 32767 0 0 0 0 0 0 0 0 -487430272 32766 539271526 32767 92 68 68 0 0 0 69 0 -2141007976 32767 0 0 42 68 55 46 10 40 44 100 75 63 19 13 10 95 43 47 47 49 59 40 0 0 -2141006600 %
The reason this is strange is because although I am getting some garbage values, the entire sequence from 42...40 matches numbers in my data file. I'm not exactly sure where I'm going wrong in this code so if anyone knows, please do share.
As always, if you take the time to answer or attempt to answer this question, thank you for your time. If you need further clarification, don't hesitate to ask.
This is a "fixed" version of your code. But you will notice that it does not print the first character. Lets say, if the first number in your file is, 220, then it will print 20.
The reason is - your program first takes away a character from file in c=fgetc(file). So at first iteration, it takes away the first character 2 from 220 and then stores 20 in the memory. Thought this problem does not occur for the rest of the iterations because the first character is comma in those cases.
To go around that problem, we can just put c=getc(file) at the end of the loop. This way, after entering the loop, it reads the first number, gets rid of the comma, reads next number, gets rid of the comma....
#include<stdio.h>
#include<stdlib.h>
int *createBuffer(int count) {
FILE *file = fopen("filename.txt", "r");
int* buffer = (int*)malloc(sizeof(int)*(count + 1));
int number;
int ch;
int i = 0;
while (1) {
if (fscanf(file, "%i", &number)) {
buffer[i] = number;
i++;
}
ch = fgetc(file);
if(ch == EOF){
break;
}
}
return buffer;
}
void main(){
int* arr = createBuffer(10);
for(int i=0; i<10; i++){
printf("%d ",arr[i]);
}
printf("\n");
}
I have a text file that contains:
1 1 1
1 2 2
1 3 2
1 7 5
1 8 4
1 9 4
1 10 2
...
and this is my function:
void addRatings()
{
int n,m,l;
int a[50][100];
MovieR = fopen("d://ratings.txt","r");
l = LineNum(MovieR);
MovieR = fopen("d://ratings.txt","r");
for(int i=0;i<l;i++)
{
fscanf(MovieR,"%[^\t]\t%[^\t]\t%[^\t]\n",&n,&m,&a[n][m]);
}
}
Now I want to get the first and second column for n and m
then I want to give third column to the a[n][m].
How can I do that?
You need to read the third value into a temporary variable, and then store that value into the array if and only if the following conditions are met:
fscanf returned 3, meaning that it actually found three numbers
the value for n is between 0 and 49 inclusive
the value for m is between 0 and 99 inclusive
And the code doesn't need to count the number of lines (using LineNum()). The loop should end when fscanf runs out of numbers to read, i.e. returns something other than 3.
The resulting code looks something like this:
void addRatings(void)
{
int a[50][100] = {{0}}; // initialize all ratings to 0
FILE *MovieR = fopen("d://ratings.txt", "r");
if (MovieR != NULL)
{
int n, m, rating;
while (fscanf(MovieR, "%d%d%d", &n, &m, &rating) == 3) // loop until end-of-file
{
if (n < 0 || n > 49 || m < 0 || m > 99) // check for valid indexes
break;
a[n][m] = rating;
}
fclose(MovieR);
}
}
Lets say combinationlength=4.
My logic is create the array {0,0,0,0} add 1 to the last element until first element gets the value 1.Until then if with the addition of 1 the array[3] ends up in a 2 result then make it 0 and then traverse the array(reversed) given a counter variable and every first non 1 element make it 0 while making all elements before the value that first non 1 equal to 0.This is for 8 repetitions.How close am i?Can someone help me finish this?
Also this doesnt run for some reason.Nothing gets printed and ends after 2 seconds.
I just noticed i am skipping a step but anyways.
I want in every iteration to have an array like the sequence.And not added printf("0"); and shortcuts like that.
void print(int combinationlength){
int i,j,count;
int a=combinationlength-1;
int c=combinationlength-1;
int b;
int array[4]={0};
while(array[0]!=1){
array[a]++;
if(array[a]==2){
array[a]=0;
for(b=a;b<=c-1;b--){
if(array[b]==0)
array[b]=1;
}
c--;
}
for(count=0;count<combinationlength;count++){
printf("%d",array[count]);
}
printf("\n");
}
return 0;
}
UPDATED:(also updated my explanation above this ^^ block of code)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(){
int i,j,count;
int a=4-1;
int c=4-1;
int b;
int array[4]={0};
while(array[0]!=1){
array[a]++;
if(array[a]==2){
array[a]=0;
for(b=a-1;b>c-1;b--){
if(array[b]==0) array[b]=1;
else array[b]=0;
}
c--;
}
for(count=0;count<4;count++){
printf("%d",array[count]);
}
printf("\n");
}
return 0;
}
The hardcoded number 4 is supposed to be the input variable.
So, I'm still not entirely sure I understand what you want. If I understood correctly, you want every combination of bits (i.e. zeros and ones) of a certain length. Doing the additions manually in an array feels very wasteful, so lets instead use what the CPU already has to offer - integer addition.
An example program, printing all the combinations of a certain length would look something like this:
#include <stdio.h>
void print(int len){
for (unsigned long sortOfAnArray = 0; sortOfAnArray < (1U << len); sortOfAnArray++) {
for (int i = len - 1; i >= 0; i--) {
printf("%lu", (sortOfAnArray >> i) & 1);
}
printf("\n");
}
}
int main(void) {
print(5);
return 0;
}
To explain the steps, sortOfAnArray is our integer, stored in binary, we add 1 to it on every iteration so that we get the different combinations.
In order to print it, we have to access elements individually, we do this with a combination of a bitshift and logical and (sortOfAnArray >> i) & 1. So, we shift the bits in the array by i to the right, and check if it has a 1 on the first position, in other words, we checked if sortOfAnArray[i]==1 (if this was an array).
We use unsigned due to the standard and long in case you want up to 64 bits available (although long long would be even safer there).
EDIT
To further explain how we extract a bit from the integer.
Assume we have the integer
`unsigned long long foo = 27`
if we look at the bit representation of that, we get 00...011011, where the total number of bits is 64, but there's just a lot of zeros, hence the dots. Now, say we want to know the value of the 1st bit from the right. We can find that out by using the logical and operation
`foo & 1`
This will apply the logical and to every pair of bits at the same position in the two integers (foo and 1), in this case this will give us 1:
foo -- 00...011011
1 -- 00...000001
foo & 1 -- 00...000001
If foo had 0 as the rightmost bit, the result would instead be 0, so this essentially allows us to read whether the first bit is set to 0 or 1.
How do we generalise this to the other bits?
We have two options, we can either move the bit in the 1 (1 << n shifts the 1 bit n moves to the left), if we use the logical and then, we will get 0 if foo has a 0 in the n-th position or some nonzero value (2^n) if it has a 1.
The other option is to instead shift the bits of foo to the right, the upside of doing this is if foo had a 1 in the n-th position, the result will now be 1 rather than 2^n, whereas if it was 0 the result is still 0. Other than that the two approaches are equivalent.
This is how we come up with the final solution, that is, to access the n-th element (0-based counting) as follows:
(foo >> n) & 1
we move the bits of foo to the right by n and look if the first bit is set to 0 or 1. Essentially, the integer is storing 64 bits (we don't need to use all of them, of course) the same way we would do that in an array, but the approach is much more efficient. Among other things, we don't need to implement our own addition for the array, as you had attempted initially.
Your problem statement is confusing:
if with the addition of 1 the array[3] ends up in a 2 result then make it 0 and then traverse the array(reversed) given a counter variable and every first non 1 element make it 0 while making all elements before the value that first non 1 equal to 0.
This basically means you want the first 0 element to remain 0 while making all elements before that first 0 set to 0.
As a consequence, the array contents would alternate between { 0, 0, 0, 0 } and { 0, 0, 0, 1 }, which is probably not the intent.
Let's assume your problem is to simulate a base-2 counter with 4 binary digits and you count from 0 to 8. Your code is a bit too complicated (pun intended ;-). You should simplify and use fewer index variables:
#include <stdio.h>
int main() {
int i;
int array[4] = { 0 };
while (array[0] != 1) {
for (i = 0; i < 4; i++) {
printf("%d ", array[i]);
}
printf("\n");
for (i = 4; i-- > 0; ) {
array[i] += 1;
if (array[i] == 2) {
array[i] = 0;
} else {
break;
}
}
}
return 0;
}
Output:
0 0 0 0
0 0 0 1
0 0 1 0
0 0 1 1
0 1 0 0
0 1 0 1
0 1 1 0
0 1 1 1
Note how you can write a for loop that counts down from the length of the array, enumerating all valid index values while using the exact length of the array and using a test i-- > 0 that is correct for both signed and unsigned types. This trick is sometimes referred to as the downto operator, not a real operator but one can make it look like one as i --> 0.
EDIT: to print the complete set of binary combinations, keep looping until i is -1:
#include <stdio.h>
int main() {
int i;
int array[4] = { 0 };
for (;;) {
for (i = 0; i < 4; i++) {
printf("%d ", array[i]);
}
printf("\n");
for (i = 4; i-- > 0; ) {
array[i] += 1;
if (array[i] == 2) {
array[i] = 0;
} else {
break;
}
}
if (i < 0) {
/* the array is too small, all combinations exhausted */
break;
}
}
return 0;
}
An integer already consists (most of the time) of 4 bytes = 32 bits. You can use a simple integer instead of an array.
However printing an integer in binary format is a bit tricky, I used the answer of this question to do it.
#include <stdio.h>
#define BYTE_TO_BINARY_PATTERN "%c%c%c%c%c%c%c%c"
#define BYTE_TO_BINARY(byte) \
(byte & 0x80 ? '1' : '0'), \
(byte & 0x40 ? '1' : '0'), \
(byte & 0x20 ? '1' : '0'), \
(byte & 0x10 ? '1' : '0'), \
(byte & 0x08 ? '1' : '0'), \
(byte & 0x04 ? '1' : '0'), \
(byte & 0x02 ? '1' : '0'), \
(byte & 0x01 ? '1' : '0')
int main(void) {
int a = 0;
int limit = 4;
while( (a & (1 << limit)) == 0)
{
printf("0b"BYTE_TO_BINARY_PATTERN"\n", BYTE_TO_BINARY(a));
a++;
}
return 0;
}
Output:
0b00000000
0b00000001
0b00000010
0b00000011
0b00000100
0b00000101
0b00000110
0b00000111
0b00001000
0b00001001
0b00001010
0b00001011
0b00001100
0b00001101
0b00001110
0b00001111
Little explanation:
In the while loop I use a so called bit mask. (1 << limit) results in a binary 1 at the position limit, so in this case it would be 0b00010000. With the binary & I check if a has that bit, if yes the while loop ends.
Whenever I have to do something involving iteration over combinations, I automatically think of Grey Codes / reverse binary coding. Below is my own implementation (it uses a different formula than the wiki, but still covers all the values). Note they won't be in order, but it does cover all combinations 0->2^n-1 and it is very fast since it only needs to change one value each time.
#include <stdio.h>
int main(int argc, char** argv) {
unsigned int length = 4;
unsigned int array[4] = {0, 0, 0, 0};
int i, j;
for (i = 0; i < 1 << length; i++) {
array[__builtin_ctz(i)] ^= 1;
printf("Array Values: ");
for (j = 0; j < length; j++) {
printf("%d ", array[j]);
}
printf("\n");
}
return 0;
}
Output:
Array Values: 0 0 0 0
Array Values: 1 0 0 0
Array Values: 1 1 0 0
Array Values: 0 1 0 0
Array Values: 0 1 1 0
Array Values: 1 1 1 0
Array Values: 1 0 1 0
Array Values: 0 0 1 0
Array Values: 0 0 1 1
Array Values: 1 0 1 1
Array Values: 1 1 1 1
Array Values: 0 1 1 1
Array Values: 0 1 0 1
Array Values: 1 1 0 1
Array Values: 1 0 0 1
Array Values: 0 0 0 1
Note I use the __builtin_ctz() method to count trailing zeros quickly. I don't know if its implemented on any other compilers, but GCC supports it.
this program is "calculating" all subsets of the array source. I need to store the resulting values in another 2D filed named polje. If I just use the printf("%d %d %d ", source[i][0], source[i][1], source[i][2]); the code works fine but something fails when it is trying to copy everything into the resulting field. I suppose I am dogin something wrong in the indexing of the array polje.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char** argv) {
int f;
int i,j;
int source[2][3] = {{0,3,5},{3,4,2}};
int currentSubset = 3;
int polje[8][3];
for(i=0;i<8;i++){
for(j=0;j<3;j++){
polje[i][j]=0;
}}
int tmp;
while(currentSubset)
{
tmp = currentSubset;
for( i = 0; i<3; i++)
{
if (tmp & 1)
{
printf("%d %d %d ", source[i][0], source[i][1], source[i][2]); //writes out everything I want
polje[currentSubset][0]=source[i][0];
polje[currentSubset][1]=source[i][1];
polje[currentSubset][2]=source[i][2];
}
tmp >>= 1;
}
printf("\n");
currentSubset--;
}
for(i=0;i<8;i++){
for(j=0;j<3;j++){
printf("%d ", polje[i][j]);
}printf("\n");}
return (EXIT_SUCCESS);
}
The output field should be:
0 3 5
3 4 2
3 4 2
0 0 0
0 3 5
0 0 0
0 0 0
0 0 0
But instead it is:
0 3 5
3 4 2
3 4 2
0 0 0
*0 0 0*
0 0 0
0 0 0
0 0 0
tmp is a bit mask with only two bits, so the inner loop should be for ( i = 0; i < 2; i++ ).
Also the correct index into the polje array is polje[currentSubset * 2 + i][0] since each subset in polje takes two spaces and i is either 0 or 1.
I think you just have a logic error. Your loop's skeleton is:
currentSubset = 3;
while ( currentSubset )
{
// ...
polje[currentSubset][...] = ...;
// ...
currentSubset--;
}
So you never write to any rows except the first three.
I want to generate permutations of string of 5 0s followed by the permutations of 4 0s and a single 1, followed by the permutations of 3 0s with 2 1s etc? My code is as follows:
#include<stdio.h>
int main(){
int i,j,k,l,s[5];
for(i=0;i<5;i++)
s[i]=0;
for(k=0;k<5;k++)
printf("%d ",s[k]);
printf("\n");
printf("---------------------------------------------\n");
for(i=0;i<5;i++){
for(j=0;j<5;j++)
if(i==j)
s[j]=1;
else
s[j]=0;
for(k=0;k<5;k++)
printf("%d ",s[k]);
printf("\n");
}
printf("---------------------------------------------\n");
for(i=0;i<5;i++){
for(k=0;k<5;k++)
s[k]=0;
s[i]=1;
for(j=i+1;j<5;j++){
s[j]=1;
for(k=0;k<5;k++)
printf("%d ",s[k]);
printf("\n");
for(k=j;k<5;k++)
s[k]=0;
}
}
printf("---------------------------------------------\n");
for(i=0;i<5;i++){
for(j=i+1;j<5;j++){
for(k=0;k<5;k++)
s[k]=0;
s[i]=1;
s[j]=1;
for(l=j+1;l<5;l++){
s[l]=1;
for(k=0;k<5;k++)
printf("%d ",s[k]);
printf("\n");
for(k=l;k<5;k++)
s[k]=0;
}
}
}
}
So output is
0 0 0 0 0
---------------------------------------------
1 0 0 0 0
0 1 0 0 0
0 0 1 0 0
0 0 0 1 0
0 0 0 0 1
---------------------------------------------
1 1 0 0 0
1 0 1 0 0
1 0 0 1 0
1 0 0 0 1
0 1 1 0 0
0 1 0 1 0
0 1 0 0 1
0 0 1 1 0
0 0 1 0 1
0 0 0 1 1
---------------------------------------------
1 1 1 0 0
1 1 0 1 0
1 1 0 0 1
1 0 1 1 0
1 0 1 0 1
1 0 0 1 1
0 1 1 1 0
0 1 1 0 1
0 1 0 1 1
0 0 1 1 1
Output is ok. However in my code I use
different for loops for different cases.
Is it possible to use better approach so
that length of the code is reduced?
One approach follows. This solution needs O(n) space and each output string requires O(n) time.
#include <stdio.h>
#include <stdlib.h>
char *buf;
// Print combinations of m 1's in a field of n 0/1's starting at s.
void print_combinations(char *s, int n, int m)
{
// If there is nothing left to append, we are done. Print the buffer.
if (m == 0 && n == 0) {
*s = '\0';
printf("%s\n", buf);
return;
}
// Cut if there are more 1's than positions left or negative numbers.
if (m > n || m < 0 || n < 0) return;
// Append a 0 and recur to print the rest.
*s = '0';
print_combinations(s + 1, n - 1, m);
// Now do the same with 1.
*s = '1';
print_combinations(s + 1, n - 1, m - 1);
}
int main(void)
{
int n = 5;
buf = malloc(n + 1);
for (int m = 0; m <= n; m++) {
print_combinations(buf, n, m);
printf("-----\n");
}
return 0;
}
You could use a recursive function like so - you don't have to print the result when finished, you could add it to a list etc.
The function works by starting with an empty string. At each step you add one more character - in this case you add either a 0 or a 1.
If a 1 is added we account for this by decrementing the ones value on the next call to the function. (In a more general case you could pass a list of all the elements to be permuted - then the process would be to pick from this list, add it to your permutation and remove it from the list. You repeat that until the list is empty and you have permuted all of the elements in the list.)
When the string reaches the desired length we have finished and so we return.
#include <stdio.h>
void recurse(char *str, int length, int maxLength, int ones)
{
if (length == maxLength)
{
// we are finished
printf("%s\n", str);
return;
}
if (ones > 0)
{
// put a 1 into the new string
str[length] = '1';
recurse(str, length + 1, maxLength, ones - 1);
}
if (ones < maxLength - length)
{
// there are still spaces for 0s
// put a 0 into the string
str[length] = '0';
recurse(str, length + 1, maxLength, ones);
}
}
int main()
{
const int maxLength = 5;
char buffer[maxLength + 1];
buffer[maxLength] = 0;
int ones;
for (ones = 0; ones <= maxLength; ones++)
{
printf("Ones: %i\n", ones);
recurse(buffer, 0, maxLength, ones);
printf("\n");
}
return 0;
}
The output looks like this:
Ones: 0
00000
Ones: 1
10000
01000
00100
00010
00001
Ones: 2
11000
10100
10010
10001
01100
01010
01001
00110
00101
00011
Ones: 3
11100
11010
11001
10110
10101
10011
01110
01101
01011
00111
Ones: 4
11110
11101
11011
10111
01111
Ones: 5
11111
Finally, unless you really want to/need to learn/use C, I would recommend using C++ because you get really nice features like std::vector and std::set and so many other things which will make your life so much easier. I would have written this completely different in C++.