0

I'm trying to write a program to break down words into segments/syllables if they are entered in a specific format. I want to enter a word in the format:

[d-i-s][c-o-#][v-er-#]

and store it in the format:

syllable[0]=dis
syllable[1]=co
syllable[2]=ver

So far I have managed to break it into syllables using the delimiter ']' and save it as a char** in the format below:

syllable[0]=[d-i-s
syllable[1]=[c-o-#
syllable[2]=[v-er-#

So now I just want to clean it up and strip out the unnecessary characters! I thought I would make a new array and copy over the letters from the old array so long as they aren't [ - #. But for the life of me I cannot work out how to copy the right letters into another array!!

I know that I cant just do:

cleanArray[i][j] = dirtyArray[i][k] 

Because cleanArray[i] is a char* and I can't edit it right? but what can I do?

I've read a lot of similar questions which have suggested strncpy and snprintf (how to copy char array to another char array in C?, strcpy and printf a multidimensional char array C) but I've tried those and I can't make them work. I've even tried putting cleanArray into 3 dimensions in the hope that I would then be able to save the individual letters into cleanArray[i][j] as char*s, which is probably completely wrong.

What is the right way of going about this? Sorry if it's obvious but I've spent hours on it and am now very, very, confused.. I would really appreciate any advice you can give!

Here's my code:

char** cleanStrings (char**dirtyList, int arrayLength)
{
    int i, j, k;
    char** cleanList = (char**)calloc(arrayLength, CHARLEN);

    for (i=0; i<arrayLength; i++)
    {
        k= 0;
        cleanList[i] = (char*)calloc(10,CHARLEN);

        for (j=0; j<strlen(dirtyList[i]+1);j++)
        {

            if (dirtyList[i][j] == '[') continue;
            else if (dirtyList[i][j] == '#') continue;
            else if (dirtyList[i][j] == '-') continue;
            else 
                //i know this is wrong, but what is the right way of doing it?
                cleanList[i][k] = dirtyList[i][j];

                k++;    
        }
    }   
    return cleanList;
}

EDIT

Thanks for all your comments, I've now got it working! Contrary to what I thought, as Barmar points out there is nothing wrong with:

cleanArray[i][j] = dirtyArray[i][k]

My code didn't work because I made a lot of other mistakes like: -casting the return values of calloc -not allocating the memory properly for calloc -incorrect brackets

I also had the code in a header file which I think contained problems of its own.

sally2000
  • 788
  • 4
  • 14
  • Instead of cleaning the strings afterwards, why don't you make sure you only add the "clean" strings to begin with? Like, if you hit a `'['` you know a syllable is starting, and then you *skip over* the opening bracket. You also skip over the dashes and hashes. And when you reach the closing bracket `']'` you end the syllable and add it to the table. Loop to search for the next syllable start, etc. and on and on until you reach the end of the input. – Some programmer dude Jun 01 '17 at 11:45
  • There's nothing wrong with `cleanList[i][k] = dirtyList[i][j];`. – Barmar Jun 01 '17 at 11:50
  • `(char**)calloc(arrayLength, CHARLEN)` should be `calloc(arrayLength,sizeof(char *))` – Barmar Jun 01 '17 at 11:54
  • really? why doesn't it work then? it runs but then crashes the console – sally2000 Jun 01 '17 at 11:54
  • You're not allocating a big enough array because you're giving the wrong argument to `calloc()` – Barmar Jun 01 '17 at 11:54
  • Also, [don't cast malloc](http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc) – Barmar Jun 01 '17 at 11:55
  • wait, do you mean dont cast calloc? – sally2000 Jun 01 '17 at 11:56
  • They're the same. – Barmar Jun 01 '17 at 11:56

2 Answers2

3

Assuming that you are using calloc size parameter wrong. One of these char** cleanList = (char**)calloc(arrayLength, CHARLEN); or cleanList[i] = (char*)calloc(10,CHARLEN); is wrong. You also should not cast the return value of a malloc() / calloc(). For legibility and code flow purposes I also replaced ifs statements. You also wrote for (j=0; j<strlen(dirtyList[i]+1);j++) instead of for (j=0; j<strlen(dirtyList[i])+1;j++) because strlen() calculates the length of the string without \0.Here is the code with few changes.

char** cleanStrings (char**dirtyList, int arrayLength)
{
    int i, j, k;
    char **cleanList = calloc(arrayLength,sizeof * cleanList);

    for (i=0; i<arrayLength; i++)
    {
        k= 0;
        cleanList[i] = calloc(10,sizeof * cleanList[i]);

        for (j=0; j<strlen(dirtyList[i])+1;j++)
        {

            if ((dirtyList[i][j] != '[') && (dirtyList[i][j] != '#') && (dirtyList[i][j] != '-') ){
                cleanList[i][k] = dirtyList[i][j];
                k++;
            }

        }
    }   
    return cleanList;
}
simo-r
  • 733
  • 1
  • 9
  • 13
  • 1
    `k++` should be inside the `if`. – Barmar Jun 01 '17 at 12:09
  • i put the k++ inside the the if but when i run your code i get the same problem as mine... it runs then crashes the console – sally2000 Jun 01 '17 at 12:13
  • 1
    @sally2000 I made a new code edit, watch now. Can you please post your full code if it doesn't work= – simo-r Jun 01 '17 at 12:28
  • the function was part of a long header file so i was copying out the relevant parts of the header to a separate file so I could post it all here. but when i ran the new files together it worked! – sally2000 Jun 01 '17 at 12:31
  • so i don't know what was causing the original problem but it must have been something else entirely – sally2000 Jun 01 '17 at 12:32
2

You're not allocating enough memory for cleanList. I assume CHARLEN is sizeof(char), which is 1 byte. But the elements of cleanList are char*, which is either 4 or 8 bytes, the allocation is much too small. It should be:

char **cleanList = calloc(arrayLength, sizeof(char *));

The general rule when using malloc or calloc is that the multiplier is always sizeof (T), where T is the destination type with one less *. So if you're assigning to char **, it's sizeof(char *).

Barmar
  • 741,623
  • 53
  • 500
  • 612
  • 1
    A better way would be to use the actual (dereferenced) variable instead of the type, like `sizeof *cleanList`, then it would always be correct. – Some programmer dude Jun 01 '17 at 12:02
  • @Someprogrammerdude Lots of variations, also `sizeof cleanList[0]` – Barmar Jun 01 '17 at 12:05
  • I've changed the sizes to sizeof(char*) for the char** and sizeof(char) for the char* respectively and I get the same issue! The program runs and then crashes – sally2000 Jun 01 '17 at 12:06
  • Are you sure `calloc(10,CHARLEN)` is big enough? Why not `calloc(sizeof(dirtyList[i])+1, CHARLEN)`? – Barmar Jun 01 '17 at 12:07
  • If that's not it, then it's time for you to step through the program in the debugger, so you can see what's happening when it gets the error. – Barmar Jun 01 '17 at 12:09