1

I have 2 questions. First question is that, I'm trying to find the frequency of the sentence and put them into another array. However, the output of the new frequency nfreq is different from what is appended in for loop.

void append(char* s, char c) 
{
    int len = strlen(s);
    s[len] = c;
    s[len+1] = '\0';
}

int main()
{

    char str[] = "test sentence";
    char nstr[] = "";
    int freq[256] = {};
    int nfreq[256] = {};

    for(int i = 0; str[i] != '\0'; i++)
    {
        freq[str[i]]++;
    }
     
    printf("\nCharacter   Frequency\n");

    int j = 0;

    for(int i = 0; i < sizeof(freq) / sizeof(int); i++)
    {
        if(freq[i] != 0)
        {
            printf("%5c%10d\n", i, freq[i]);  
            char c = i;
            append(nstr, c);
            int f = freq[i];
            nfreq[j] = f;
            printf("Num in nfreq[%d] is %d\n", j, nfreq[j]);
            j++;
        }
    }

    for(int i = 0; i < strlen(nstr); i++)
    {
        printf("%d ", nfreq[i]);
    }
    printf("\n");

    printf("size of nfreq : %lu\n", sizeof(nfreq) / sizeof(nfreq[0]));
    printf("size of str : %lu\n", strlen(str));
    printf("size of nstr : %lu\n", strlen(nstr));
    printf("nstr is : %s\n", nstr);

    return 0;
}

The frequency of each letter is

Character   Frequency
              1
    c         1
    e         4
    n         2
    s         2
    t         3

and nfreq should have those {1, 1, 4, 2, 2, 3} in its array with the code above and it even says Num in nfreq[0] is 1 and etc in the loop, but when I try to check what's in nfreq outside the loop, it outputs {116, 1, 4, 2, 2, 3} this instead. What is this 116 and it should be 1 for the frequency of ' '.

Also the second question is that, if I were not to declare the size of an int array, int nfreq[] = {} like so in the beginning, does the size of this array, after appending int with for loop, changes dynamically? Or does it stay 0?

I tried fixing it by not declaring the size (which I don't think it matters) of nfreq array. Thanks in advance for your help :)

Edit : Sorry I forgot to add append function.

Brian
  • 11
  • 2
  • You are playing with fire... `char` may be a signed type so it shouldn't be used as array index. – Support Ukraine Jan 28 '23 at 07:47
  • Don't use `strlen` in a loop test when the string is loop-invariant. It immediately turns an O(n) loop into an O(n^2) loop. You wouldn't recalculate the string length every time if you were doing it by hand, right? So why do you write code that does? – Tom Karzes Jan 28 '23 at 07:53
  • @TomKarzes Would the compiler be able optimize it out with -O0? – Harith Jan 28 '23 at 08:00
  • 1
    @Haris Well, -O0` disables optimization, so the call would not be moved out of the loop. But even with optimization enabled, it would need to know that `strlen` is the library version of the function, and that the string doesn't change in the loop. In any case, it's a bad habit to put `strlen` calls in a loop test. It's a common beginner's mistake (and also something you see from people who are used to languages like Python, where string lengths are kept with the string). – Tom Karzes Jan 28 '23 at 09:58

2 Answers2

0
char nstr[] = "";

nstr is an array of one character.

append(nstr, c);
...
s[len+1] = '\0';

len is 0, so len + 1 is 1. This line is writing out-of-bounds to nstr. nstr is char [1]. You can only nstr[0] = something. nstr[1] is invalid.

Do:

char nstr[256] = "";

if I were not to declare the size of an int array, int nfreq[] = {} like so in the beginning, does the size of this array, after appending int with for loop, changes dynamically?

Notes: the {} is technically invalid, use {0} Is an empty initializer list valid C code? . int nfreq[] = {} is technically invalid code, it doesn't make sense, if it would, then nfreq would have zero size.

There are no "dynamic" changes of array size. Array has constant size. Writing out-of-bounds to an array is an error in the code.

KamilCuk
  • 120,984
  • 8
  • 59
  • 111
0

Invalid initialization:

int freq[256] = {};

is invalid. ISO C forbids empty initializer braces. An initializer-list must contain at least one initializer.

Perhaps:

int freq[256] = { 0 };

Re:

if I were not to declare the size of an int array, int nfreq[] = {} like so in the beginning, does the size of this array, after appending int with for loop, changes dynamically? Or does it stay 0?

Answer: No.

int nfreq[] = {};

is not a valid statement. The space doesn't change dynamically.

Either declare an automatic array with fixed size like this:

int nfreq[SIZE] = { 0 }; 

or dynamically allocate memory with malloc(), and reallocate with realloc() as necessary.


Incorrect format specifier:

strlen() and sizeof() returns a type size_t. %lu might not be the correct format specifier for size_t. Use %zu instead. See also:


Writing to out of bounds memory:

void append(char* s, char c) 
{
    int len = strlen(s);
    s[len] = c;
    s[len+1] = '\0';
}

You didn't allocate any memory for the array that has decayed to a pointer in append(). So this writes to out of bounds memory, and exhibits undefined behaviour.

Harith
  • 4,663
  • 1
  • 5
  • 20