Need suggestion on Code conversion to Matlab_extension 1 - c

This is an extension of the previously asked question: link. In a short, I am trying to convert a C program into Matlab and looking for your suggestion to improve the code as the code is not giving the correct output.
C program:
void prga(unsigned char S[], unsigned char out[], int len) {
int i=0,j=0,x,t;
unsigned char key;
for (x=0; x < len; ++x) {
i = (i + 1) % 256;
j = (j + S[i]) % 256;
t = S[i];
S[i] = S[j];
S[j] = t;
out[x] = S[(S[i] + S[j]) % 256];
}
}
Matlab program:
function [out, i, j, S]=rc4out(i, j, S)
%for x = 1:length(key) % It should not work here as no key mentioned
i = mod( (i+1), 256);
j = mod( j + S(i), 256);
t = S(i);
S(i) = S(j+1);
S(j+1) = t;
out = mod(S(S(i) + S(j+1), 256));

EDIT:
Try this it do the same think as the c function: The lengh of S should be >= 256 or you will exceed it as mod() could return such index. I suggest you to change 256 in the function with the lenght provided to solve this issue.
Here you don't need the key variable.
function out = prga(S, len)
i=0; j=0; x=[]; t=[];
for x=0:len-1
i = mod(i+1, 256);
j = mod(j+S(i+1), 256);
t = S(i+1);
S(i+1) = S(j+1);
S(j+1) = t;
out(x+1) = S(mod(S(i+1)+S(j+1), 256)+1);
end
end
Or you can use the key variable to controle the loop
function out = prga(S, key)
i=0; j=0; x=[]; t=[];
for x=0:length(key)-1
i = mod(i+1, 256);
j = mod(j+S(i+1), 256);
t = S(i+1);
S(i+1) = S(j+1);
S(j+1) = t;
out(x+1) = S(mod(S(i+1)+S(j+1), 256)+1);
end
end

Related

Generate random name to struct element in C

I want to generate random names to book.author and book.title
but when i print nothing shows.
typedef struct Book{
char title[20];
char author[20];
int pages;
double price;
}Book;
int randInit(int min, int max){
return min + rand()%(max -min +1);
}
void rand_Init_Book(Book *b){
int len =randInit(10,20);
for(int i =1 ; i < 1;i++)
{
b->title[i] = (char)randInit('a','z');
}
len =randInit(10,20);
for(int i =1 ; i < randInit(10,20);i++)
{
b->author[i] = randInit('a','z');
}
b->pages = randInit(5,2000);
b->price = (100 + rand()%(10000-100))/100.;
}
The names will not be actual names, just some string. When I exit the loop and i want to print it says that the string is empty. I've tried with strcpy whit another string but the same result.
No iteration
for(int i =1 ; i < 1;i++) never iterates as i < 1 is immediately false.
Code fails to index properly
Array's are zero-based indexed.
// for(int i =1 ; i < randInit(10,20);i++)
for(int i = 1; i < randInit(10,20); i++)
Excessive length
char author[20]; can hold a string up to 19 characters + the final null character.
// len =randInit(10,20);
len = randInit(10, 20 - 1);
No need to repeatedly find a random length
// for(int i =1 ; i < randInit(10,20);i++)
for(int i = 0; i < len;i++)
Missing null character
A string needs a final null character.
Tips
Improve formatting - use an auto formatter.
Avoid naked magic numbers like 10.
Example:
#define NAME_LENGTH_MIN 10
void rand_Init_Book(Book *b) {
int len = randInit(NAME_LENGTH_MIN, sizeof b->title - 1);
for (int i = 0; i < len; i++) {
b->title[i] = (char) randInit('a', 'z');
}
b->title[len] = '\0';
len = randInit(NAME_LENGTH_MIN, sizeof b->author - 1);
for (int i = 0; i < len; i++) {
b->author[i] = (char) randInit('a', 'z');
}
b->author[len] = '\0';
b->pages = randInit(5, 2000);
b->price = (100 + rand() % (10000 - 100)) / 100.0;
}

How to get rid of segmentation fault?

#include <stdio.h>
#include <inttypes.h>
#include <stdlib.h>
#include <stdio.h>
#include <stddef.h>
int getCharNum(int a) { return a / (8 * sizeof(char)); }
int getBitNum(int a) { return a % (8 * sizeof(char)); }
int fromCharNum(int a) { return a * 8 * sizeof(char); }
int get2DimI(int a) { return getCharNum(a) / 187500; }
int get2DimJ(int a) { return getCharNum(a) % 187500; }
void rle_compress(char *src, char *dst, int ls, int *ld) {
uint8_t t[129];
int i, j = 0, k = 0, keep;
char out[187500];
t[0] = src[j];
while (j++ < ls) {
t[1] = src[j];
if (t[0] != t[1]) {
i = 1;
if (j < ls)
do
t[++i] = src[++j];
while (j < ls && i < 128 && t[i] != t[i - 1]);
if ((keep = t[i] == t[i - 1]))
--i;
out[k++] = (char)i;
t[0] = t[i];
if (!keep)
continue;
}
i = 2;
do
t[1] = src[++j];
while (++i < 130 && t[0] == t[1]);
out[k++] = i + 125;
out[k++] = t[0];
t[0] = t[1];
}
ld = &k;
dst = out;
}
void rle_extract(char *src, char *dst, int ls) {
int i, j, l = 0, k = 0, max;
char out[187500];
j = 0;
while (k + 2 < ls) {
i = src[k++]; //segfault
j = src[k++];
max = i + (i < 128 ? 1 : -126);
while (max--)
out[l++] = j;
}
dst = out;
return 0;
}
int main(void) {
int32_t n = 0;
scanf("%d", &n);
int32_t a[n];
int32_t b[] = { -1, -1, -1 };
char **count;
count = (char**)malloc(1000 * sizeof(char*));
int count_l[] = { [999] = 0 };
for (int i = 0; i < 1000; ++i) {
count[i] = (char*)malloc(187500 * sizeof(char));
char *temp = NULL;
rle_compress(count[i], temp, 187500, &count_l[i]);
free(count[i]);
count[i] = temp;
}
for (int i = 0; i < n; i++)
scanf("%d", &a[i]);
for (int i = 0; i < n; i++) {
char *src = count[get2DimI(a[i]) / 187500];
char dst[187500];
rle_extract(src, dst, count_l[i / 187500]);
dst[get2DimJ(a[i])] ^= 1 << (getBitNum(a[i]));
rle_compress(dst, count[get2DimI(a[i]) / 187500], 187500, &count_l[i]);
}
int32_t mv = 187500000 / (8 * sizeof(char));
int j = 0;
for (int i = 0; i < mv; i++) {
char *src = count[i / 187500];
char dst[187500];
rle_extract(src, dst, count_l[i / 187500]);
int32_t x = dst[i % 187500];
if (x == 0)
continue;
for (int k = 0; k < 8 * sizeof(char); k++) {
if ((x >> (k)) & 1) {
b[j++] = fromCharNum(i) + k;
}
}
//free(dst);
}
int m1 = min(b[0], min(b[1], b[2])),
m3 = max(b[0], max(b[1], b[2])),
m2 = b[0] + b[1] + b[2] - m1 - m3;
printf("%d %d %d", m1, m2, m3);
for (int i = 0; i < 1000; ++i)
free(count[i]);
free(count);
return 0;
}
How to fix this code?
I'm trying to compress byte array (which should compress greatly as n should be <=1500000 and numbers are from 0 to 1.5*10^9), but code gives me segfault on all testing inputs which I've tried. Without compress everything worked like a charm, but needed a lot of memory (and limits are 64MiB).
The code is obscure but there are some major problems:
void rle_extract(char *src, char *dst, int ls) does not take the output buffer from its caller, nor does it return a pointer to it: dst = out; just updates the argument value, not the caller's variable passed as an argument. Furthermore return 0; from a void function is incorrect too.
in any case, rle_extract should not return its local out buffer because it is only defined during the execution of the function and is discarded as soon as the function returns.
You should either pass the buffer as an argument or allocate it locally and return the pointer to the caller.
There might be other problems, there is no explanation for what the code is supposed to do.

unexpected result while working with array

sir i am a new programmer.So i am facing some new problems which I really need to solve. Like I write a code
#include<stdio.h>
main(){
int ara[] ={10,20,30,40,50,60,70,80,90,100},i,temp,j;
for(i=0,j=9;i<10;i++,j--){
ara[i]=ara[j];
printf("%d\n",ara[i]); }
}
I thought the result would be 100,90,80,70,60,50,40,30,20,10 but the result is not like this...Would anyone please tell me why the result shows 100,90,80,70,60,60,70,80,90,100
After printing value 60, i.e. half of the array when you try to access elements further, actually you will access those elements which are of the locations after mid of the array. because you are assigning them using ara[i] = ara[j]..so you will end up with repetition after half of array.
As:-
ara[0] = ara[9]
ara[1] = ara[8]
ara[2] = ara[7]
ara[3] = ara[6]
ara[4] = ara[5]
ara[5] = ara[4]
The simplest solution may be creating a temporary array:-
#include<stdio.h>
main(){
int ara[] ={10,20,30,40,50,60,70,80,90,100},i,temp[10],j;
for(i = 9, j = 0; i >= 0; i--, j++){
temp[j]=ara[i];
}
for(i = 0; i < 10; i++){
printf("%d\n", temp[i]);
}
}
What you are doing in this code?
reversing an array
Why are you printing 100,90,80,70,60,50,60,70,...
because when you reach the 6th one (ara[4]), you've already swapped it with 4th one (ara[6])
You need to save in the temporary variable the value which is written first
Some examples
char *reverse(char *str)
{
char tmp;
int len;
if (str != NULL)
{
len = strlen(str);
for (int i = 0; i < len / 2; i++)
{
tmp = *(str + i);
*(str + i) = *(str + len - i - 1);
*(str + len - i - 1) = tmp;
}
}
return str;
}
int *reverseints(int *data, size_t size)
{
int tmp;
if (data != NULL)
{
for (int i = 0; i < size / 2; i++)
{
tmp = *(data + i);
*(data + i) = *(data + size - i - 1);
*(data + size - i - 1) = tmp;
}
}
return data;
}

Selection Sort using pointers

I have the following code:
void sortStrings(char strings[5][32])
{
int i = 0, j = 0, wall = 0;
int min = i;
for (int i = wall; i < 5; i++){
min = i;
for (j = wall; j < 5; j++){
if (strcmp(strings[j], strings[min]) < 0){
min = j;
}
}
swapStrings(strings[min], strings[wall]);
wall++;
}
}
What this code does is sorts a 2d array of strings by alphabetical order, I have tested it and it works correctly, now my question is how could I implement this code WITHOUT using array operations (aka using pointers and pointer operations only).
This is what I have so far and it is crashing when I try to run it so what am I doing wrong?
{
int i = 0, j = 0, wall = 0;
char *p = strings;
int min;
for (i = wall; i < 5; i++){
min = i;
for (j = wall; j < 5; j++){
if (*(p + j) < *(p + min)){
min = j;
}
}
swapStrings(*(p + j),*(p + wall));
wall++;
}
}
Here is the swapStrings method I am using for reference:
void swapStrings(char string1[], char string2[])
{
char temp[32];
strcpy(temp, string1);
strcpy(string1, string2);
strcpy(string2, temp);
}
The expected output is: if I were to enter in 5 strings, lets say they are:
hello
goodbye
how
are
you
It should return:
are
goodbye
hello
how
you
Thank you.
You have two things wrong:
p have to be char** and not char*
Comparing yourself between strings need a loop such:
int t = 0;
while (*(*(p + j)+t) && (*(*(p + j) + t) == *(*(p + min) + t)))
t++;
if (*(*(p + j) + t) < *(*(p + min) + t)) {
min = j;
}
Maybe you want to write your function for compare.

Stack around the variable 's' was corrupted

I got this error in my rc4 algorithm, it works well, but i got this error every time when the message is too big, like 1000kB, here is the code:
char* rc4(const int* key, int key_size, char* buff, int buff_size){
int i, j, k;
int s[255], rk[255]; //rk = random_key
char* encrypted = alloc_char_buffer(buff_size);
for (i = 0; i < 255; i++){
s[i] = i;
rk[i] = key[i%key_size];
}
j = 0;
for (i = 0; i < 255; i++){
j = (j + s[j] + rk[i]) % 256;
SWITCH(s + i, s + j);
}
i = 0;
j = 0;
for (k = 0; k < buff_size; k++){
i = (i + 1) % 256;
j = (j + s[i]) % 256;
SWITCH(s + i, s + j);
//try{
//}
//catch ()
encrypted[k] = (char)(s[(s[i] + s[j]) % 256] ^ (int)buff[k]);
}
encrypted[buff_size] = 0;
return encrypted;
}
at the end o the last loop i got this error, i think this is some type of buffer overflow error, the only variable able to do that is the 'encrypted' but at the end of the loop, the value of the variable 'k' have the exactly same value of 'buff_size' that is used to alloc memory for 'encrypted', if someone can help i'll thank you
the 'encrypted' is "non-null terminated", so if the string have 10 bytes i will allocate only 10 bytes, not 11 for the '\0'
if you need, here is the code for alloc_char_buffer(unsigned int)
char* alloc_char_buffer(unsigned int size){
char* buff = NULL;
buff = (char*)calloc(size+1, sizeof(char));
if (!buff)
_error("program fail to alloc memory.");
return buff;
}
SWITCH:
//inversão de valores
void SWITCH(int *a, int *b){
*(a) = *(a) ^ *(b); //a random number
*(b) = *(a) ^ *(b); //get a
*(a) = *(a) ^ *(b); //get b
}
char* encrypted = alloc_char_buffer(buff_size);
/* ... */
encrypted[buff_size] = 10;
Here is the problem. You allocate buff_size elements. Thus, the last valid index is buff_size-1, not buff_size.
Another issue:
j = (j + s[j] + rk[i]) % 256;
Thus the range of j is [0, 255], but the legal index of s is only [0, 254]. You should either declare s as a 256-element array or review the algorithm implementation.
Your following line is creating the problem as you are trying to access beyond your allocated memory.
encrypted[buff_size] = 10;
Additionally, you should avoid use calloc instead of writing your own function alloc_char_buffer. It would allocate memory and initialize with 0.
calloc(buff_size, sizeof(char));

Resources