I'm writing a simple Base64 decoding function in C. The output of this function looks correct (based on comparing the result with existing tools) when using the printf() debugging lines as below:
unsigned char * b64decode(char *line)
{
char *idx;
unsigned char *decode;
int i,j,len,dlen,hold = 0;
idx = strchr(line, '\n'); //index of newline
len = idx - line; //lenght of string
dlen = 3 * (len / 4); //decoded length
decode = malloc((sizeof(unsigned char) * dlen) + 1);
pad = 0;
for (i = 0; i <= len; i++) { //deindex from ASCII
line[i] = deindex(line[i]);
}
for(i = 0, j = u0; i < len; i++,j++) {
hold |= (line[i] << 18);
hold |= (line[++i] << 12);
hold |= (line[++i] << 6);
hold |= line[++i];
decode[j] = hold >> 16;
printf("%d ", decode[j]);
decode[++j] = (hold >> 8) & 0xFF;
printf("%d ", decode[j]);
decode[++j] = hold & 0xFF;
printf("%d ", decode[j]);
hold = 0;
}
if (pad) //terminate before padding
decode[dlen - pad] = '\0';
return decode;
}
Which produces the (partial) output:
29 66 31 77 11 15 2 31 79 19 78 60 26 105 101 31 73 28 14 78 19 1 11 7
78 27 1 22 69 54 0 30 1 73 100 32 84 29 29 67 51 83 78 101 82 6 0 71 84
28 13 69 77 7 4 12 83 18 60 12 30 8 73 26 9 17 79 20 76 33 26 71 43 0 5
29 71 89 17 4 9 0 100 38 7 83 0 55 22 6 12 26 23 65 29 1 82 84 48 95 0 32
19 10 5 71 79 18 72 8 69 78 101
The problem arises when I try to access this array after exiting the for loop with those printf() lines. This for loop (maximum i value is arbitrary) ...
for (i = 0; i < 100; i++) {
printf("%d ", decode[i]);
}
Produces this output...
29 66 31 77 11 15 2 31 79 19 78 60 26 105 101 31 73 28 14 78 19 1 11 7 78
27 1 22 69 54 0 30 1 73 100 32 84 29 29 67 51 83 78 101 82 6 0 71 84 28
13 69 77 7 4 12 83 18 60 12 30 8 73 26 9 17 79 20 76 33 26 71 43 0 5 29
71 89 17 4 9 0 100 38 7 83 0 55 22 6 12 26 23 65 29 1 82 84 48 95 0 32 19
10 5 71 79 168 187 158 23 131 127 0 0 168 187 158 23 131 127 0 0 0 0 0 0
0 0 0 0 65 0 0 0 0 0 0 0 88 187 158 23 131 127 0 0 88 187 158 23 131 127
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 64 0
0 0 0 0 0 0 16 16 0 0 0 0 0 0 72 85 73 102
Can anyone let me know what I'm doing wrong?
OK folks, found the issue. The function as shown here works, the issue turned out to be with a realloc() called on *decode in error in the function which handles my function above. Fixing this produced the correct results.
Guess this is a swift lesson in providing more context!
Related
My code takes in a text document argument and sorts the integers but when I run testing, it fails a simple white space at the end instead of a \n but I figure out how to stop the final number in the array with a new line instead of a space. Here is the code:
/* display values */
for (i = 0; i < count; i++ ) {
printf ("%ld ", sorted[i]);
}
Here is the test result and the issue:
Program Output
1: 1 2 3 4 5 5 7 8 9 9 9 10 10 11 11 12 14 17 18 20 20 20 24 24 25 25 26 26 27 27 28 28 29 30 30 30 30 31 33 35 35 36 38 40 40 41 42 42 42 47 47 47 48 48 48 48 50 50 51 52 52 52 54 54 57 57 57 57 57 60 61 61 62 62 62 63 64 66 66 66 67 67 69 70 72 72 73 73 75 77 80 82 83 83 83 84 85 86 87 88 88 88 89 91 92 93 94 94 96 97 97 99 [blank space]
Expected Program Output
1: 1 2 3 4 5 5 7 8 9 9 9 10 10 11 11 12 14 17 18 20 20 20 24 24 25 25 26 26 27 27 28 28 29 30 30 30 30 31 33 35 35 36 38 40 40 41 42 42 42 47 47 47 48 48 48 48 50 50 51 52 52 52 54 54 57 57 57 57 57 60 61 61 62 62 62 63 64 66 66 66 67 67 69 70 72 72 73 73 75 77 80 82 83 83 83 84 85 86 87 88 88 88 89 91 92 93 94 94 96 97 97 99
2: [new line]
I tried putting in a \n in printf ("%ld ", sorted[i]); after sorted[i] but it needs to go at the close of the array and I'm not certain how (or where) to add it with cause more issues.
/* display values */
for (i = 0; i < count; i++ ) {
printf ("%ld ", sorted[i]);
}
This outputs a space after each number. If that's not what you want, don't do it. Maybe you want this:
/* display values */
if (count > 0)
printf ("%ld", sorted[0]);
for (i = 1; i < count; i++ ) {
printf (" %ld", sorted[i]); // space before every number but first
}
If one doesn't want to duplicate code.
#include <stdio.h>
int main(void) {
const size_t count = 100;
size_t i;
/* display values */
for (i = 0; i < count; i++ ) {
printf ("%s%ld", i ? " " : "", i + 1 /*sorted[i]*/ );
}
fputc('\n', stdout);
return 0;
}
I expect it to be slower, but I think the intent of the code is clearer.
Code:
for(int i = 1; i <= 100; i++){
if(i % 10 == 1)
printf("\n%d", i);
else printf("%4d",i);
}
Results:
(blank line)
1 2 3 4 5 6 7 8 9 10
11 12 13 14 15 16 17 18 19 20
21 22 23 24 25 26 27 28 29 30
31 32 33 34 35 36 37 38 39 40
41 42 43 44 45 46 47 48 49 50
51 52 53 54 55 56 57 58 59 60
61 62 63 64 65 66 67 68 69 70
71 72 73 74 75 76 77 78 79 80
81 82 83 84 85 86 87 88 89 90
91 92 93 94 95 96 97 98 99 100
How can I remove the first blank line without doing something like:
for(int i = 1; i <= 100; i++){
if(i == 1 || i % 10 == 1)
printf("\n%d", i);
else printf("%4d",i);
}
And how can I 'indent' the columns? As the last column isn't properly arranged, and I have no idea how to fix it using printf's.
At last, sorry for wrinting '(blank line)' as I don't know how to make a blank line, and thanks for the help.
Rather than printing a newline at the start of a line, print it at the end instead:
for (int i = 1; i <= 100; i++){
printf("%4d",i);
if (i % 10 == 0)
printf("\n");
}
This prints each number in a 4 character field, then prints a newline if the last number is divisible by 10.
Output:
1 2 3 4 5 6 7 8 9 10
11 12 13 14 15 16 17 18 19 20
21 22 23 24 25 26 27 28 29 30
31 32 33 34 35 36 37 38 39 40
41 42 43 44 45 46 47 48 49 50
51 52 53 54 55 56 57 58 59 60
61 62 63 64 65 66 67 68 69 70
71 72 73 74 75 76 77 78 79 80
81 82 83 84 85 86 87 88 89 90
91 92 93 94 95 96 97 98 99 100
The style is strange, a newline doesn't belong at the start of a string literal. A printf call should print the line and then output a newline if necessary:
"\nBad style"
"Good style\n"
To print the values correctly, change the logic. Always print the values of i, and then check if i is divisible by 10, and print the newline if it is.
for(int i = 1; i <= 100; i++)
printf("%*d%c", (i % 10 == 1)? 0 : (i == 2) ? 4 : 3, i, (i % 10) ? ' ' : '\n');
I have always done something like this:
#include <stdio.h>
int main (void) {
for (int i = 0; i < 100; i++) {
if (i && i % 10 == 0) putchar ('\n');
printf ("%4d", i + 1);
}
putchar ('\n');
return 0;
}
You can also you separate format strings to accomplish the same thing:
char *fmt = "%4d",
*fmtn = "%4d\n";
for (int i = 0; i < 100; i++)
printf ((i+1) % 10 == 0 ? fmtn : fmt, i + 1);
putchar ('\n');
(note: in both cases the loop is indexed from 0 to accommodate indexing arrays)
Example Use/Output
$ ./bin/arraycols
1 2 3 4 5 6 7 8 9 10
11 12 13 14 15 16 17 18 19 20
21 22 23 24 25 26 27 28 29 30
31 32 33 34 35 36 37 38 39 40
41 42 43 44 45 46 47 48 49 50
51 52 53 54 55 56 57 58 59 60
61 62 63 64 65 66 67 68 69 70
71 72 73 74 75 76 77 78 79 80
81 82 83 84 85 86 87 88 89 90
91 92 93 94 95 96 97 98 99 100
Hi I am trying to perform this on MATLAB
A =
64 2 3 61 60 6 7 57
9 55 54 12 13 51 50 16
17 47 46 20 21 43 42 24
40 26 27 37 36 30 31 33
32 34 35 29 28 38 39 25
41 23 22 44 45 19 18 48
49 15 14 52 53 11 10 56
8 58 59 5 4 62 63 1
I want to select values from A based on F
F =
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
-1 -1 -1 -1 -1 -1 -1 -1
0 0 0 0 0 0 0 0
-1 -1 -1 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1 -1
I want this output
u =
40 26 27 37 36 30 31 33
41 23 22 44 45 19 18 48
49 15 14 52 53 11 10 56
8 58 59 5 4 62 63 1
This means that I want all the values corresponding to '-1' in a matrix. i tried u=A(F==-1) ... but it gives me a single column with all the values like this:
u =
40
41
49
8
26
23
15
58
27
22
14
59
37
44
52
5
36
45
53
4
30
19
11
62
31
18
10
63
33
48
56
1
This will do it:-
u=-A.*F;
u(all(u==0,2),:)=[] %Removing rows containing zeros
Another solution:-
u=reshape(A(F==-1),4,8)
// code to sort array of 16 numbers, but output isnt quite correct.
// must use pointers to array addresses
// final output is -451 993 384 201 89 77 38 28 16 12 7 1 0 -2 -5 -17
// as you can see -451 isn't in the right place.
output
-451 7 993 1 0 16 -5 12 89 28 77 384 -2 38 -17 201
-451 -17 993 7 1 16 0 12 89 28 77 384 -2 38 -5 201
-451 993 -17 7 1 16 0 12 89 28 77 384 -2 38 -5 201
-451 993 7 -17 1 16 0 12 89 28 77 384 -2 38 -5 201
-451 993 7 1 -17 16 0 12 89 28 77 384 -2 38 -5 201
-451 993 16 7 1 -17 0 12 89 28 77 384 -2 38 -5 201
-451 993 16 7 1 0 -17 12 89 28 77 384 -2 38 -5 201
-451 993 16 12 7 1 0 -17 89 28 77 384 -2 38 -5 201
-451 993 89 16 12 7 1 0 -17 28 77 384 -2 38 -5 201
-451 993 89 28 16 12 7 1 0 -17 77 384 -2 38 -5 201
-451 993 89 77 28 16 12 7 1 0 -17 384 -2 38 -5 201
-451 993 384 89 77 28 16 12 7 1 0 -17 -2 38 -5 201
-451 993 384 89 77 28 16 12 7 1 0 -2 -17 38 -5 201
-451 993 384 89 77 38 28 16 12 7 1 0 -2 -17 -5 201
-451 993 384 89 77 38 28 16 12 7 1 0 -2 -5 -17 201
-451 993 384 201 89 77 38 28 16 12 7 1 0 -2 -5 -17
total exchanges: 68
#include <stdio.h>
#define N 16
int xchg();
int main() {
int numbers[16] = {7, 1, 993, -5, 0, 16, -451, 12, 89, 28, 77, 384, -2, 38, -17, 201};
int cntr, cntr2, cntr3;
int chgNum;
for(cntr = 0; cntr < N; cntr++){
for(cntr2 = 1; cntr2 < N; cntr2++){
chgNum += xchg(&numbers[cntr], &numbers[cntr2]);
}
for(cntr3 = 0; cntr3 < N; cntr3++){
if(cntr3 == 15){
printf("%d", numbers[cntr3]);
}
else {
printf("%d ", numbers[cntr3]);
}
}
printf("\n");
}
printf("total exchanges: %d\n", chgNum);
return 0;
}
int xchg(int *p1, int *p2) {
int tmp = 0;
if(*p2 < *p1){
tmp = *p1;
*p1 = *p2;
*p2 = tmp;
return 1;
}
else {
return 0;
}
}
You need to change your loop in main.
for(cntr2 = cntr+1; cntr2 < N; cntr2++){
You might also want to check if xchg is giving you the direction ascending/descending sort order or if you need to invert your exchange condition.
Also: you forgot to initialize chgNum to zero.
Ok the problem is that the inner for loop starts at 1, after the first iteration it will be wrong it needs to start at the position that the first loop is at, i.e. cntr2 = cntr.
A few other things:
The forward declaration of the `xchng` function isn't correct.
The if else print statement doesn't do anything it will print the same thing no matter what.
If you are incrementing a number using `++` operator and it isn't being assigned to anything, always use `++(int)`, it requires fewer operations.
Finally, there are some nasty variable names, it doesn't hurt to be more descriptive. Also you define a macro which is the size of the array, but you don't define the array using it, int numbers[N] would make more sense as then at least you can see why the the macro is used in the loop.
I have a matrix A(97x13) ranging from 0 to 90
I would like to find in specific rows which values are lower than 45.
find(A(:,[4,7,10])<45);
My problem is that I don't know how to relate the resulting indices with the entire A matrix.
Can someone help me with that?
The result is in the form of a linear index. You can convert to row and column using ind2sub:
cols = [4,7,10];
ind = find(A(:,cols)<45);
[r, c] = ind2sub([size(A,1) numel(rows)], ind);
c = cols(c); %// change from "1,2,3" to "4,7,10"
To save some running time, you can use a "manual" version of ind2sub:
cols = [4,7,10];
ind = find(A(:,cols)<45);
r = mod(ind-1,size(A,1))+1;
c = cols(ceil(ind/size(A,1)));
Example:
A =
8 66 87 57 4 24 10 82 3 55
24 44 50 62 80 31 59 81 67 56
73 53 47 36 83 62 45 31 46 78
3 22 21 34 72 13 71 63 44 73
84 42 45 89 9 65 65 18 82 52
gives
r =
3
4
1
c =
4 4 7
Use ind2sub to get rows and columns, for example:
>> A=round(rand(5,3)*90)
A =
85 19 18
79 27 20
50 42 15
56 21 20
53 76 39
>> [I,J] = ind2sub(size(A), find(A(:,[1,3])<45))
I =
1
2
3
4
5
J =
2
2
2
2
2
>>