struct field changed but it isn't expected - c

I'm trying to translate a sentence into morse code. I have a morse.txt file with this type of content :
'-','-','-','-','-',0, /* Caractère 0 */
'.','-','-','-','-',0, /* Caractère 1 */
'.','.','-','-','-',0, /* Caractère 2 */
In order to translate each letter from the sentence I thought about create a 2 dimension array in which we would find a letter and its translation in morse. Here's my struct
typedef struct
{
char lettre;
char *morse;
} t_morse;
I created a function returning that array :
t_morse *loadTab()
{
t_morse *tabMorse = malloc(LETTER_NUMBER * sizeof(t_morse));
ssize_t read;
size_t len = 0;
char index = 0, k = 0, j;
char *line = NULL;
FILE *f = fopen("morse.txt", "r");
if (f == NULL)
{
printf("Impossible d'ouvrir morse.txt\n");
exit(0);
}
while (read = getline(&line, &len, f) != -1 && line != NULL)
{
char *morse = malloc(6 * sizeof(char));
char *stringfinal = malloc(50 * sizeof(char));
strcpy(stringfinal, line);
k = 0;
for (j = 0; j < strlen(stringfinal); j++)
if (stringfinal[j] == '-' || stringfinal[j] == '.')
morse[k++] = stringfinal[j];
tabMorse[index].morse = morse;
tabMorse[index].lettre = index + 48;
printf("lettre : %c, morse : %s\n", tabMorse[index].lettre, tabMorse[index].morse);
index++;
free(morse);
free(stringfinal);
}
fclose(f);
for (index = 0; index < LETTER_NUMBER; index++)
{
printf("toto %c : %s\n", tabMorse[index].lettre, tabMorse[index].morse);
}
return tabMorse;
}
But it doesn't as it would be : when executing the programm, the first printf (printf("lettre : %c, morse : %s\n", tabMorse[index].lettre, tabMorse[index].morse);) show me the thing that I want. However after this when I want to iterate through that array and display the structs, the letter field is the right but in the morse field I get a "" string, and I don't know why.
You can see below, a screen of the stdout when launching the program :
Do you know why it acts like that ?

The immediate problem is that you call free(morse); around every iteration of the loop. So when you print it from the second loop the contents are undefined.
You also do not null terminate the morse[] string.

tabMorse[index].morse = morse;
...
free(morse);
Since tabMorse[index].morse is equal to morse, free(morse) is the same as free(tabMorse[index].morse), which is obviously not right.
You do not want to free the chunk of memory that you just stashed a pointer to. You need to keep it allocated so you can safely dereference the pointer later.

As others have noted (no use repeating), you cannot use pointers to heap memory that has been free()'d. (It's best to not duplicate pointers unless you really keep track of them.)
tabMorse[index].morse = morse;
/* 3 lines omitted */
free(morse);
Too much code hides problems such as this.
Take a step back and think about Morse Code. There are only two symbols, and no character is longer than 5 symbols (or is it 6 maximum?).
A byte (unsigned) has 8 bits that can be in one of two states.
Imagine "encoding" the Morse alphabet in the lowest bits of a byte, one byte per character. Because Morse code uses 1 to 5 symbols per character, another bit (on the left of the low bits) can be used as a flag meaning "the remaining bits on my right are to be used as 0=dot and 1=dash"... The Morse letter 'E' (one dot only) would be represented by 0b000000t0, where 't' would be the 'trigger' (always 1), and the lowest bit 0 would signify a single 'dot'.
The familiar "SOS" would be 0b00001000, 0b00001111, 0b00001000 ("... --- ...").
The code below has been adapted from something I wrote for Brail translation. The (incomplete) octal values in the table have NOT been checked as valid Brail but give you a start as to how you might, with the description above, encode 128 characters (7-bit ASCII) in Morse (replacing the Brail encoding). (The tables entries for 'S/s', 'O/o' and 'SP' have been adapted to be correct Morse characters.)
It seems this is a lot less code, and doesn't provide many corners for bugs to lurk.
void morsify( char c ) {
unsigned char oct[] = { // TODO: adapt these values from Brail to Morse
// CTRL codes
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
// CTRL codes
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
// punctuation
000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 002, 0, 0, 0,
// punctuation & digits
0, 001, 003, 011, 031, 021, 013, 033, 023, 012, 032, 0, 0, 0, 0, 0,
// # + A-O
0, 001, 003, 011, 031, 021, 013, 033, 023, 012, 032, 005, 007, 015, 035, 017,
// P-Z + braces
017, 037, 027, 010, 036, 045, 047, 072, 055, 075, 065, 0, 0, 0, 0, 0,
// ` + a-o
0, 001, 003, 011, 031, 021, 013, 033, 023, 012, 032, 005, 007, 015, 035, 017,
// p-z + braces
017, 037, 027, 010, 036, 045, 047, 072, 055, 075, 065, 0, 0, 0, 0, 0,
};
bool trig = false;
uint8_t morse = oct[ c ]; // fetch copy of bit pattern from table
for( uint8_t i = 0x80; i; i >>= 1 )
if( !trig && (i & morse) ) // keep scanning right until trigger bit encountered
trig = true;
else if( trig ) // output has been triggered
putchar( i & morse ? '-' : '.' ); // 1's = '-', 0's = '.'
putchar( ' ' ); // space between characters
}
int main() {
char str[] = "Stuff happens";
puts( str );
for( int i = 0; str[ i ]; i++ )
morsify( str[ i ] );
putchar( '\n' );
char str1[] = "SOS sos SOS";
puts( str1 );
for( i = 0; str1[ i ]; i++ )
morsify( str1[ i ] );
putchar( '\n' );
return (0);
}
Stuff happens
... ---. ..-.- .-- .-- ..-- --- --- ...- --.- ...
SOS sos SOS
... --- ... ... --- ... ... --- ...
If you want to "buffer-up" the characters, simply replace the putchar() with your buffering scheme. Then you could output one long string instead of each individual dot/dash & SP.

Related

checking array for values and then passing to new array. c

So given an array of:
input[3] = {0, 0, 0}
this outputs :
output[3] = {3, 0 ,0}
code:
void create_hist(double input[], int num_of_inputs, int output[])
{
int num_to_check = input[0];
int counter = 0;
for (int i = 0; i < num_of_inputs; i++)
{
int j = output[i];
if ((int)input[i] == num_to_check)
{
counter++; /* it was found */
}
output[j] = counter;
}
return;
}
but if I have a floating point array
input[5] = {0.0000, 1.0000, 2.0000, 3.0000, 4.000}
and I want to truncate the values to int, and count how many times each integer in the range 0 - 10 appears in the input array then output it to:
output[5] = {1, 1, 1, 1, 1}
output[0] = {1} //indicates how many times 0 appeared in the array
or
input[10] = {1.000, 4.000, 5.0000, 2.000, 4.000, 7.000, 9.000, 6.000, 0.000, 0.000}
and output
output[10] = {2, 1, 1, 0, 2, 1, 1, 1, 0, 1}
output[0] = {2} // this indicates how many times 0 appeared in the first array
Can anyone tell me how to do this?
You shouldn't use output[i] as an array index. It's a counter, not the value whose count you want. You should use (int)input[i] as the index.
You first need to initialize all elements of output to 0, then you increment the elements corresponding to the integer part of each input.
memset(output, 0, sizeof(output[0]) * MAX_INPUT_VALUE);
for (int i = 0; i < num_of_inputs; i++) {
output[(int)input[i]]++;
}

Using 2D arrays, my arrays don't appear

My programm compiles, and it is ok. When I start it and type "AB", they appear on one line, but when I type "BAAB", the "AB" goes under the "BA". I am stuck here for a long time. I will be very glas if you give a solution for this problem.
//it needs to read input from the keyboard and appear every letter constructed by astersks
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
char line[100] = { 'A', 'B' };
int i;
int row;
int col;
bool A[7][6] = { {0, 0, 1, 0, 0, 0}, //letter A
{1, 0, 0, 0, 1, 0},
{1, 0, 0, 0, 1, 0},
{1, 1, 1, 1, 1, 0},
{1, 0, 0, 0, 1, 0},
{1, 0, 0, 0, 1, 0},
{1, 0, 0, 0, 1, 0} };
bool B[7][6] = { {1, 1, 1, 0, 0, 0}, //letter B
{1, 0, 0, 1, 0, 0},
{1, 0, 0, 1, 0, 0},
{1, 1, 1, 1, 0, 0},
{1, 0, 0, 0, 1, 0},
{1, 0, 0, 0, 1, 0},
{1, 1, 1, 1, 0, 0} };
int main () {
//reads the input
printf ("Type a word or number, or both: ");
scanf ("%s", line);
// loop for every row of every letter
for (row = 0; row < 7; row++)
{
// loop for every inputed letter
for (i = 0; line[i]; i++)
{
// if letter is A do this...
if (line[i] == 'A')
{
// lopp for every column to read the asterisks
for (col = 0; col < 5; col++) {
if (A[row][col])
printf ("*");
else
printf (" ");
}
printf ("\n");
}
if (line[i] == 'B') {
for (col = 0; col < 5; col++) {
if (B[row][col])
printf ("*");
else
printf (" ");
}
}
}
}
return (0);
}
Trex, what you first need to understand is "What does my code do if I take NO input?". So comment out your initial printf and scanf and check:
//reads the input
// printf ("Type a word or number, or both: ");
// scanf ("%s", line);
Output:
$ ./bin/multi_array_mess
*
*** * *
* * * *
* * *****
**** * *
* ** *
* ** *
****
What values of line produce that output? {'A', 'B'} What happens if line contains anything other than AB? Try just 'A':
$ Type a word or number, or both: A
*
* *
* *
*****
* *
* *
* *
Then with 'B':
$ ./bin/multi_array_mess
Type a word or number, or both: B
*** * * * * **** * ** *****
It should be obvious that a newline is missing somewhere in the loop that prints B. Changing your logic to match the way you print 'A' similar to:
if (line[i] == 'B') {
for (col = 0; col < 5; col++) {
if (B[row][col])
printf ("*");
else
printf (" ");
}
printf ("\n");
}
Provides the desired output if you enter just 'B' in response to your prompt:
$ ./bin/multi_array_mess
Type a word or number, or both: B
***
* *
* *
****
* *
* *
****
What is printed if you enter anything other than 'A' or 'B'? NOTHING. What happens if you enter both 'A' and 'B'? (you get a mess).
So it looks just from tinkering with your program, it was designed to print either A of B using '*' as the character depending on the values of 0 or 1 in your arrays. You can either fix the logic to handle line containing both 'A' and 'B', or you can limit your input to one character at a time.
Since your intent appears to be able to handle multiple characters in line at a time, what happens if we just tweak the loop logic a bit. E.g.:
// loop for every inputed letter
for (i = 0; line[i]; i++)
{
// loop for every row of every letter
for (row = 0; row < 7; row++)
{
// if letter is A do this...
if (line[i] == 'A')
{
Give it a try...
Next, think about how you are prompting for input:
printf ("Type a word or number, or both: ");
Wouldn't it make more sense to limit your request to what your code will provide output for?
printf ("Please enter A or B, or both: ");
After receiving input, wouldn't it more sense to check what your user provided before blindly passing the input to the rest of your program? Something simple will do:
for (i = 0; i < (int)strlen (line); i++)
if (line[i] != 'A' || line[i] != 'B') {
fprintf (stderr, "error: invalid input '%c'.\n", line[i]);
return 1;
}
Now try your program again.
Printing Each Letter on One Row
OK. Now that I know what you are intending, it makes it a bit easier to help. In order to print each array as '*' or ' ' on the same row, you basically have to loop through each row, checking if a given letter is specified in line and print that row for every character you need to print. You can cut down on the code repetition by creating a function to print the row for each array (you can actually use a macro, but we'll leave that for later).
In keeping with the earlier discussion, I added a few sanity checks and created a new character array allowed that holds a list of the current characters you have created arrays for (the allowed characters). Just add to it as you add arrays. You will also note I moved all your global variables inside main. There is nothing wrong with using globals, but use them sparingly, and only when necessary.
Putting the pieces together, you could do something like:
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#define MAXL 100
#define ROWS 7
#define COLS 5
void prn_letter_row (bool a[][COLS+1], size_t row);
int main (void) {
char line[MAXL] = {0};
char allowed[] = "AB";
size_t i, row, len;
i = row = len = 0;
bool A[ROWS][COLS+1] = {{0, 0, 1, 0, 0, 0}, //letter A
{1, 0, 0, 0, 1, 0},
{1, 0, 0, 0, 1, 0},
{1, 1, 1, 1, 1, 0},
{1, 0, 0, 0, 1, 0},
{1, 0, 0, 0, 1, 0},
{1, 0, 0, 0, 1, 0}};
bool B[ROWS][COLS+1] = {{1, 1, 1, 0, 0, 0}, //letter B
{1, 0, 0, 1, 0, 0},
{1, 0, 0, 1, 0, 0},
{1, 1, 1, 1, 0, 0},
{1, 0, 0, 0, 1, 0},
{1, 0, 0, 0, 1, 0},
{1, 1, 1, 1, 0, 0}};
/* prompt for input */
while (!*line)
{
printf ("\nType a word or number, or both [A-B only]: ");
if (!fgets (line, MAXL, stdin))
fprintf (stderr, "error: no input provided - 'ctrl+d'.\n");
len = strlen (line); /* get length, remove trailing \n */
if (line[len-1] == '\n')
line[--len] = 0;
char *p = line;
while (*p) { /* check each character against 'allowed' */
if (!strchr (allowed, *p)) {
fprintf (stderr, "error: invalid character '%c'.\n", *p);
*line = 0;
}
p++;
}
}
printf ("valid: %s\n\n", line);
for (row = 0; row < ROWS; row++) {
for (i = 0; i < len; i++) {
switch (line[i]) {
case 'A' : prn_letter_row (A, row);
break;
case 'B' : prn_letter_row (B, row);
break;
}
}
putchar ('\n');
}
return 0;
}
/* print given row for letter */
void prn_letter_row (bool a[][COLS+1], size_t row)
{
size_t i;
putchar (' '); /* provide a space before each letter */
for (i = 0; i < COLS; i++)
if (a[row][i])
putchar ('*');
else
putchar (' ');
}
Use/Output
$ ./bin/chars_from_arrays
Type a word or number, or both [A-B only]: A
valid: A
*
* *
* *
*****
* *
* *
* *
$ ./bin/chars_from_arrays
Type a word or number, or both [A-B only]: B
valid: B
***
* *
* *
****
* *
* *
****
$ ./bin/chars_from_arrays
Type a word or number, or both [A-B only]: AB
valid: AB
* ***
* * * *
* * * *
***** ****
* * * *
* * * *
* * ****
Here is your fixed code
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <ctype.h>
char line[100] = {'A','B'};
int i;
int row;
int col;
// Support only latin aphabet, easly expandable
bool chars[26][7][6] = {
{ {0,0,1,0,0,0 }, //letter A
{1,0,0,0,1,0 },
{1,0,0,0,1,0 },
{1,1,1,1,1,0 },
{1,0,0,0,1,0 },
{1,0,0,0,1,0 },
{1,0,0,0,1,0 }},
{ {1,1,1,0,0,0 }, //letter B
{1,0,0,1,0,0 },
{1,0,0,1,0,0 },
{1,1,1,1,0,0 },
{1,0,0,0,1,0 },
{1,0,0,0,1,0 },
{1,1,1,1,0,0 }},
// to Z
};
int main()
{
printf ("Type a word or number, or both: ");
scanf ("%s",line);
//reads the input
for (row = 0;row<7;row++)
// loop for every row of every letter
{
for (i = 0; line[i]; i++) //loop for every inputed letter
{
for (col = 0;col < 6;col++) // lopp for every column to read the asterisks
{
if (chars[toupper(line[i]) - 'A'][row][col])
{
printf("*");
}
else
printf(" ");
}
}
printf("\n");
}
return (0);
}
You can add multiple character support by forming 3d array like
bool chars[26][7][6] = {
{ {0,0,1,0,0,0 }, //letter A
{1,0,0,0,1,0 },
{1,0,0,0,1,0 },
{1,1,1,1,1,0 },
{1,0,0,0,1,0 },
{1,0,0,0,1,0 },
{1,0,0,0,1,0 }},
{ {1,1,1,0,0,0 }, //letter B
{1,0,0,1,0,0 },
{1,0,0,1,0,0 },
{1,1,1,1,0,0 },
{1,0,0,0,1,0 },
{1,0,0,0,1,0 },
{1,1,1,1,0,0 }},
// to Z
};
Than access to array member
chars[toupper(line[i]) - 'A'][row][col];
in this case you may not use any character if checks only for loops
this will only works with small string sizes, because standard console support up to 80 characters in length, to deal with it you can setup console width, or perform some manipulation with console cursors to break out formed string properly (like SetConsoleCursorPosition) in Windows.
if you want to support all printable chars, your 3d array should start at whitespace char up to 128 character. For more info look to ASCII character table.

Convert Hexadecimal C Array to Matlab Vector

I am looking for a simple way to convert from c-code hex array to matlab
Available C-Code Format:
const uint16_t AUDIO_SAMPLE[] = {0x4952, 0x4646, 0x4f6e, 0xf, 0x4157, 0x4556, 0x6d66, 0x2074, 0x12, 0, 0x1}
Required Matlab Format:
AUDIO_SAMPLE = [18770 17990 20334 15 16727 17750 28006 8308 18 0 1]
Though it is simple to convert for small numbers, I have to convert a very big array. I am using embedded platform so the numbers can not be written to a simple text file for later read in matlab. Its preferable to write the conversion code in matlab.
Edit:
Till now able to get rid of 0x. Failed to get a vector after using eval function as given below:
a='0x4952, 0x4646, 0x4f6e'; %Given
b = strrep(a, '0x', '') ; %Returns 4952, 4646, 4f6e
x = eval( [ '[', b, ']' ] ) %
Copy the code that defines the array to a file called "clip.h".
Write a small c program that #include "clip.h" and use a simple loop to write the data in the desired format. Run the program on your desktop computer. It could look something like this:
#include <stdio.h>
#include <stdint.h>
#include "clip.h"
#define NUMBERS_PER_LINE 20
int main(void) {
int i;
int sample_length = (sizeof AUDIO_SAMPLE)/(sizeof AUDIO_SAMPLE[0]);
printf("AUDIO_SAMPLE = [ ");
for (i=0; i < sample_length; i++) {
printf("%" PRIu16 PRId16, AUDIO_SAMPLE[i]); // Use the format specifier for uint16_t.
if (i % NUMBERS_PER_LINE == NUMBERS_PER_LINE - 1) {
// Insert line continuation mark
printf(" ...\n ");
}
}
return 0;
}
The program will write the matlab code on stdout, so you need to redirect it to the desired file.
It proved tougher than I thought.
Contents of the text file audio.c
4952, 4646, 0x4f6e, 0xf, 0x4157, 0x4556, 0x6d66, 0x2074, 0x12, 0, 0x1,
0x2, 0xbb80, 0, 0xee00, 0x2, 0x4, 0x10, 0, 0x6166, 0x7463, 0x4,
0, 0xd3cf, 0x3, 0x6164, 0x6174, 0x4f3c, 0xf, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
The given file has 11 values in each line. Here follows the MATLAB code to convert HEX values to decimal numbers:
fp = fopen('audio.c', 'rt');
C = textscan(fp, '%s', 'CommentStyle', '#', 'Delimiter', '');
fclose(fp);
C = regexp(C{:}, '\w+', 'match');
C = cellfun(#(x)strrep(x,'0x',''), C, 'UniformOutput', false);
C = cellfun(#(x)hex2dec(x), C, 'UniformOutput', false);
result=cell2mat(C)'
allOneString = sprintf('%d, ' , result)
Finally I have string of decimal values separated by comma as follows:
18770, 17990, 20334, 15, 16727, 17750, 28006, 8308, 18, 0, 1, 2, 48000, 0, 60928, 2, 4, 16, 0, 24934, 29795, 4, 0, 54223, 3, 24932, 24948, 20284, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
Of course previous posts on SO were of immense help :)

How to print binary array as characters

I have an array that holds 28 ints which are all 1's and 0's. However, I need to print this information as 4 characters so how do I get each 7 bytes of data to become one bit in order to print.
Not sure this makes sense so I will illustrate what I need to:
Right now my array (in order) is this: 0101101111011101011000100010
But I need to somehow take those first 7 numbers (0101101) and print that out as Z and do that with the next 7, the next 7...
Thanks for your help!
I think this might be something along the lines you are looking for.
int to_int(int *bits) {
int power = 2;
int digit = 1;
int value = 0;
int i=0;
for(i=0; i <= 6; i++) {
if(bits[i] == 1) {
value += digit;
}
digit *= power;
}
return value;
}
int main() {
int myArray[28] = {0, 1, 0, 1, 1, 0, 1,
1, 1, 1, 0, 1, 1, 1,
0, 1, 0, 1, 1, 0, 0,
0, 1, 0, 0 ,0, 1, 0};
char theChars[5];
theChars[0] = to_char(&myArray[0]);
theChars[1] = to_char(&myArray[7]);
theChars[2] = to_char(&myArray[14]);
theChars[3] = to_char(&myArray[21]);
theChars[4] = '\0';
printf("%s\n",&theChars[0]);
}
Also, I don't think your expected output is correct.
Well, there is always the stupid way:
Cycle through each 7 blocks.
int bytes=7;
for(int i=0; i++;i<4){
double ASCII = 0;
for(int j=0; i++;j<bytes){
ASCII+=Math.pow(2, bytes-j-1)*array[i*bytes + j]
}
char c = (char) ASCII // you'll have some trouble with types here
}
Assuming your input array is called inputBits[] Try something like this:
const int input_bit_count = 28;
char output[input_bit_count / 7];
int outIdx = 0;
// step through the bit stream converting bits to 7-bit characters
for( int inIdx = 0; inIdx < input_bit_count; ){
// shift over and add the next bit to this character
output[outIdx] <<= 1;
if( inputBits[inIdx] != 0 ){
output[outIdx] |= 1;
}
inIdx++;
if( inIdx % 7 == 0)
// after each 7 bits, increment to next output character
outIdx++;
}
// done processing, now print it out
for( int chIdx = 0; chIdx < input_bit_count / 7; chIdx++ ){
printf( "%c", output[chIdx] );
}

Memory leak in C program, can't see where to free memory

I am writing a C program to generate Keys and test them in an encryption function. However since I have NEVER written a C program before, and I'm completely unused to having manage memory manually, I have run into a problem. I have a memory leak and to be honest, I don't know how to solve it. I understand I need to release the memory at some point but can't until I've run through all keys and I run out of memory before I get through all of them. Writing the program in a different language is NOT an option so please do not suggest that. The code that is leaking is shown below, any help would be appreciated.
EDIT: I know i haven't called a free function to free the memory. I don't see where I can put it because I need the memory until i run through all keys. Putting it outside the loops doesn't solve the problem because the leak occurs inside the loops
2nd EDIT: Posted the full program. I do not have the option of using data structures (i.e. the bool arrays) other than those shown because of how the DES encrypt function(which I did not write) works
#include <stdio.h>
#include <stdlib.h>
#include "des.h"
void dec2bin(bool *testaRR, bool *to_return, int convert);
int main(int argc, const char * argv[])
{
// insert code here...
bool testKey[56] = {
0, 1, 0, 0, 0, 0, 0, 1,
0, 1, 0, 0, 0, 0, 0, 1,
0, 1, 0, 0, 0, 0, 0, 1,
0, 1, 0, 0, 0, 0, 0, 1,
0, 1, 0, 0, 0, 0, 0, 1,
0, 1, 0, 0, 0, 0, 0, 1,
0, 1, 0, 0, 0, 0, 0, 1
};
bool testKey2[56] = {//intuitive key reversed for testing
1, 0, 0, 0, 0, 0, 1, 0,
1, 0, 0, 0, 0, 0, 1, 0,
1, 0, 0, 0, 0, 0, 1, 0,
1, 0, 0, 0, 0, 0, 1, 0,
1, 0, 0, 0, 0, 0, 1, 0,
1, 0, 0, 0, 0, 0, 1, 0,
1, 0, 0, 0, 0, 0, 1, 0
};
bool output[64];
bool input[64] = {//the reverse of below... DES bits are numbered left to right, in order of least to most significant so we must enter the bit values in reverse.
//forexample the binary vale of N is 01001110 but below is displayed as 01110010
1, 0, 0, 0, 1, 1, 0, 0,//1
0, 0, 0, 0, 1, 1, 0, 0,//0
1, 1, 0, 0, 0, 0, 1, 0,//C
1, 0, 1, 0, 0, 0, 1, 0,//E
1, 1, 0, 0, 1, 0, 1, 0,//S
0, 0, 1, 0, 1, 0, 1, 0,//T
1, 0, 1, 0, 0, 0, 1, 0,//E
0, 1, 1, 1, 0, 0, 1, 0 //N
};
int y = sizeof(input);
printf("(Input MSG: ");
for (int i = y-4; i >= 0; i-=4)
printf("%X", input[i]+2*input[i+1]+4*input[i+2]+8*input[i+3]);//this is the conversion to hex code
printf(")\n");
/*
use char[] to store the key as set of
*/
/*bool input[64] = {//this is the given plaintext message in the intuitive order (opposite of what it is)
0, 1, 0, 0, 1, 1, 1, 0,//N
0, 1, 0, 0, 0, 1, 0, 1,//E
0, 1, 0, 1, 0, 1, 0, 0,//T
0, 1, 0, 1, 0, 0, 1, 1,//S
0, 1, 0, 0, 0, 1, 0, 1,//E
0, 1, 0, 0, 0, 0, 1, 1,//C
0, 0, 1, 1, 0, 0, 0, 0,//0
0, 0, 1, 1, 0, 0, 0, 1 //1
};
int y = sizeof(input);
printf("(Input MSG: ");
for (int j = 0; j < y; j+=4)
printf("%X", input[j+3]+2*input[j+2]+4*input[j+1]+8*input[j]);//this is the conversion to hex code
printf(")\n");*/
bool test [8];
bool returned[8];
char keyphrase [8];
keyphrase[7] = 0;
for(int start = 65; start<=90; start++)
{
//dec2bin(test, returned, start);
keyphrase[0] = start;
for(int two = 65; two<=90; two++){
keyphrase[1]=two;
for(int three = 65; three<=90; three++){
keyphrase[2]=three;
for(int four = 65; four<=90; four++){
keyphrase[3]=four;
for(int five = 65;five<=90;five++){
keyphrase[4]=five;
for( int six = 65; six <=90; six++){
keyphrase[5]=six;
for(int seven = 65; seven <=90; seven++){
keyphrase[6]=seven;
printf("%s \n", keyphrase);
}
}}
}
}
}
//once i fix the memory leak I will be calling the EncryptDes Function here and checking the outputblk agains the given cipher text
}
free(keyphrase);
int k = sizeof(testKey);
printf("(Test Key: ");
for (int z = 0; z < k; z+=7)
printf("%d", testKey[z+7]+2*testKey[z+6]+4*testKey[z+5]+8*testKey[z+4]+16*testKey[z+3]+32*testKey[z+2]+64*testKey[z+1]+ 128*testKey[z]);//this is the conversion to hex code
printf(")\n");
//loop on the key (starting at
EncryptDES(testKey, output, input, 0);
int x = sizeof(output);
printf("(Output MSG: ");
for (int i = 0; i < x; i+=4)
printf("%X", output[i+3]+2*output[i+2]+4*output[i+1]+8*output[i]);//this is the conversion to hex code
printf(")\n");
return 0;
}
void dec2bin (bool *testaRR, bool *to_return, int convert)
{
printf("%d : ", convert);
printf("%c", convert);
printf("\n ");
//bool testaRR [8];
for(int st = 0; st<8; st++){
testaRR[st] = convert%2;
to_return[7-st] = testaRR[st];
//printf("%d :", 7-st);
//printf(" %d spot ", st);
convert = convert/2;
//testaRR stores the arrays in one direction
//to_return stores them in the other
//Example:
//65 = 01000001 testaRR least significant on the far right (m0st sig is in index 7)better for storage and keeping track of where the bits actually are in binary
//65 = 10000010 to_return least significant on the far left (same as DES) (most significant bit is index 0) good for printing to screen
}
You do not need dynamic memory management here.
Start with
char keyphrase[8];
keyphrase[7]=0;
instead of your malloc and you will be good to go. Your highest array index is 7 (the terminating NUL), and hence you need an array of 8 items (0..7).
If you really want to use malloc, simply a free() at the end will be fine, but you need to malloc 8 characters and set keyphrase[7] to 0 to do the terminating NUL still.
Here's a tested version that works:
#include <stdio.h>
/* compile with gcc -Wall -std=c99 keyphrase.c -o keyphrase */
int
main (int argc, char **argv)
{
char keyphrase[8];
keyphrase[7] = 0;
for (int start = 65; start <= 90; start++)
{
//dec2bin(test, returned, start);
keyphrase[0] = start;
for (int two = 65; two <= 90; two++)
{
keyphrase[1] = two;
for (int three = 65; three <= 90; three++)
{
keyphrase[2] = three;
for (int four = 65; four <= 90; four++)
{
keyphrase[3] = four;
for (int five = 65; five <= 90; five++)
{
keyphrase[4] = five;
for (int six = 65; six <= 90; six++)
{
keyphrase[5] = six;
for (int seven = 65; seven <= 90; seven++)
{
keyphrase[6] = seven;
printf ("%s \n", keyphrase);
}
}
}
}
}
}
}
}
The real problem is the use of printf. You did not NULL terminate keyphrase, so every time you printf you overflow.
Also, to avoid the memory leak, simply replace char *keyphrase = (char *)malloc(7); with char keyphrase[8];.
You're calling malloc on the first line but I don't see a single free to release what you allocated. After all the loops are completed (i.e. usage of the allocated data is complete) you must call free(keyphrase);
New answer as the program has been modified.
You say your program is using all memory 'because I'm watching the available memory go down from over 4 free GB to about 5 MB'.
I'm guessing the answer is not the loops but these lines:
//loop on the key (starting at
EncryptDES(testKey, output, input, 0);
int x = sizeof(output);
We can't see the source to or declaration of EncryptDES, but you aren't passing a length to it. If 0 is meant to be the length, this would explain it.
The next line however suggests that output is meant to be an array of 64 bytes (rather than 2 strings). But EncryptDES would have no way of knowing this.
I suggest you run the whole thing under valgrind to find out what is happening.

Resources