user25976 user25976 - 2 months ago 7
C Question

Populating multidimensional array in C language

I am trying to populate a multidimensional array that matches the structure of another array.

I have one array initilized in the following way:

static char frequencyEn[][7] =
{
['A'] = ".082",
['B'] = ".015",
['C'] = ".028",
['D'] = ".043",
['E'] = ".127",
['F'] = ".022",
['G'] = ".020",
['H'] = ".061",
['I'] = ".070",
['J'] = ".002",
['K'] = ".008",
['L'] = ".040",
['M'] = ".024",
['N'] = ".067",
['O'] = ".075",
['P'] = ".019",
['Q'] = ".001",
['R'] = ".060",
['S'] = ".063",
['T'] = ".091",
['U'] = ".028",
['V'] = ".010",
['W'] = ".024",
['X'] = ".002",
['Y'] = ".020",
['Z'] = ".0O1"
};


This array holds values of average letter frequencies in english language. The second array I am trying to initilize and populate will hold the actual letter frequencies of a supplied text.

The eventual goal is to compare the values of two different arrays. I'm not yet working on the code that will compare the two arrays--only the part where I populate a second array with the counted values.

Letter frequency of a string is counted in this way. How can I initialize a new array and populate it with these letter frequency values? I am looking to create an array with the same structure as the previously presented array:

char *count(char *eText)
{
char * cryptText = "Some encrypted text.";
char string[100];
int c = 0, count[26] = {0};
int accum = 0;

while ( cryptText[c] != '\0' )
{

if ( cryptText[c] >= 'a' && cryptText[c] <= 'z' ){
count[cryptText[c]-'a']++;
accum++;
}

else if (cryptText[c] >= 'A' && cryptText[c] <= 'Z'){
count[cryptText[c]-'A']++;
accum++;
}
c++;
}

for ( c = 0 ; c < 26 ; c++ )
{
if( count[c] != 0 )
printf( "%c %f\n", c +'a', ((double)count[c])/accum);
}
}


I'm trying to figure out how I can populate a new array with the same structure as the first array. Currently, the code gives me this type of printed output:

b 0.103448
c 0.034483
d 0.034483
e 0.034483
g 0.034483
i 0.068966
j 0.068966
k 0.068966
l 0.034483
n 0.034483
p 0.034483
q 0.137931
r 0.103448
s 0.034483
u 0.034483
v 0.034483
x 0.034483
z 0.068966


How can I add these values to an array in this way:

char frequencyCurrent[][]=
{
['A'] = ".000",
['B'] = ".103"
...
}


In case it is helpful to see things in context, this is more code to show how the initialized array is used:

#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

char * cryptText = 0;

static char clef[][7] =
{
['A'] = "X",
['B'] = "Y",
['C'] = "Z",
['D'] = "A",
['E'] = "B",
['F'] = "C",
['G'] = "D",
['H'] = "E",
['I'] = "F",
['J'] = "G",
['K'] = "H",
['L'] = "I",
['M'] = "J",
['N'] = "K",
['O'] = "L",
['P'] = "M",
['Q'] = "N",
['R'] = "O",
['S'] = "P",
['T'] = "Q",
['U'] = "R",
['V'] = "S",
['W'] = "T",
['X'] = "U",
['Y'] = "V",
['Z'] = "W"

};

static char frequencyEn[][7] =
{
['A'] = ".082",
['B'] = ".015",
['C'] = ".028",
['D'] = ".043",
['E'] = ".127",
['F'] = ".022",
['G'] = ".020",
['H'] = ".061",
['I'] = ".070",
['J'] = ".002",
['K'] = ".008",
['L'] = ".040",
['M'] = ".024",
['N'] = ".067",
['O'] = ".075",
['P'] = ".019",
['Q'] = ".001",
['R'] = ".060",
['S'] = ".063",
['T'] = ".091",
['U'] = ".028",
['V'] = ".010",
['W'] = ".024",
['X'] = ".002",
['Y'] = ".020",
['Z'] = ".0O1"
};

enum { MAX_CLEF = sizeof(clef) / sizeof(clef[0]) };

static char *prompt(FILE *fp, const char *prompt, char *buffer, size_t buflen)
{
printf("%s", prompt);
fflush(0);
return fgets(buffer, buflen, fp);
}

static void substitute(FILE *fp, const char *buffer, const char *pad1, const char *pad2)
{
int c;
const char *pad = pad1;
int col = 0;
for (int i = 0; (c = buffer[i]) != '\0'; i++)
{
if (col == 0)
{
fputs(pad, fp);
col += strlen(pad);
pad = pad2;
}

col++;
c = toupper(c);
if (c < MAX_CLEF && clef[c][0] != '\0')
{
fputs(clef[c], fp);
col += strlen(clef[c]);
}
else
{
putc(c, fp);
col++;
}
if (col > 72)
{
putc('\n', fp);
col = 0;
}
}
}

char *count(char *eText)
{
char string[100];
int c = 0, count[26] = {0};
int accum = 0;
char *frequencies[2]

while ( cryptText[c] != '\0' )
{

if ( cryptText[c] >= 'a' && cryptText[c] <= 'z' ){
count[cryptText[c]-'a']++;
accum++;
}

else if (cryptText[c] >= 'A' && cryptText[c] <= 'Z'){
count[cryptText[c]-'A']++;
accum++;
}
c++;
}

for ( c = 0 ; c < 26 ; c++ )
{
if( count[c] != 0 )
printf( "%c %f\n", c +'a', ((double)count[c])/accum);
}
}


int main(void)
{
char * buffer = 0;

long length;
FILE * plainTextFile = fopen ("plaintext.txt", "rb");
FILE * cipherTextFile = fopen("ciphertext.txt", "w+");

if (plainTextFile)
{
fseek (plainTextFile, 0, SEEK_END);
length = ftell (plainTextFile);
fseek (plainTextFile, 0, SEEK_SET);
buffer = malloc (length);
if (buffer)
{
fread (buffer, 1, length, plainTextFile);
}
fclose (plainTextFile);
}

if (buffer)
{
printf("%s", buffer);
}
else {
printf("failure");
}

substitute(cipherTextFile, buffer, "", " ");

if (cipherTextFile)
{
fseek (cipherTextFile, 0, SEEK_END);
length = ftell (cipherTextFile);
fseek (cipherTextFile, 0, SEEK_SET);
cryptText = malloc (length);
if (cryptText)
{
fread (cryptText, 1, length, cipherTextFile);
}
fclose (cipherTextFile);
}

if (cryptText)
{
printf("%s", cryptText);
}
else {
printf("failure");
}

}

Answer

The predefined array you have is not very usable. You store floating point values as strings, and the index of the array goes from 0 to the ASCII value of 'Z' instead of 0 to 25.

Instead, define frequencyEn like this:

double frequencyEn[] = { 
    .082, .015, .028, .043, .127, .022, 
    .020, .061, .070, .002, .008, .040, 
    .024, .067, .075, .019, .001, .060, 
    .063, .091, .028, .010, .024, .002, 
    .020, .001 };

You can then compare as follows:

if (frequencyEn[c] == ((double)count[c] / accum))

However, floating point math is not exact, so you instead need to check if it's "close"

if (fabs(frequencyEn[c] - ((double)count[c] / accum)) < 0.00001)
Comments