views:

222

answers:

4

I have a function defined as the following (in C):

gchar **Scan_Return_File_Tag_Field_From_Mask_Code (File_Tag *FileTag, gchar code)
{
    switch (code)
    {
        case 't':    /* Title */
            return &FileTag->title;
        case 'a':    /* Artist */
            return &FileTag->artist;
        case 'b':    /* Album */
            return &FileTag->album;
        case 'd':    /* Disc Number */
            return &FileTag->disc_number;
        case 'y':    /* Year */
            return &FileTag->year;
        case 'n':    /* Track */
            return &FileTag->track;
        case 'l':    /* Track Total */
            return &FileTag->track_total;
        case 'g':    /* Genre */
            return &FileTag->genre;
        case 'c':    /* Comment */
            return &FileTag->comment;
        case 'p':    /* Composer */
            return &FileTag->composer;
        case 'o':    /* Orig. Artist */
            return &FileTag->orig_artist;
        case 'r':    /* Copyright */
            return &FileTag->copyright;
        case 'u':    /* URL */
            return &FileTag->url;
        case 'e':    /* Encoded by */
            return &FileTag->encoded_by;
        case 'i':    /* Ignored */
            return NULL;
        default:
            Log_Print(LOG_ERROR,"Scanner: Invalid code '%%%c' found!",code);
            return NULL;
    }
}

I am trying to add a new condition to the switch statement, such as

case 'f':

In which it would return the first character of &FileTag->artist.

I have scoured all of the internet looking for a solution, but have come up empty handed. Anyone have any ideas?

Update: If it helps, this function is part of the application EasyTag. From what I have seen looking through the code, this is where the new file name for easytag's file sorting feature is determined. I am trying to add a new variable to allow the application to sort music into directories like so: <First letter of artist name>/<Artist>/<Album>/<Tracks>

There is always the chance that I may be looking at the wrong function, but to the best of my knowledge I am.

Another Update: I got this function working as I wanted (pointers are funny little things), but it does not, as pointed out below, do what I had expected it to. Thanks for all the help and patience!

A: 

Don't scour the internet. Code it yourself. Add this:

        case 'f':    /* Artist */
            return &FileTag->artist;

That's assuming &FileTag->artist is of type gchar **.

pmg
+1  A: 

I'm not quite sure why your code returns a pointer to a pointer, but that makes your desired operation slightly more difficult. Since you need to return the address of a pointer, and not just a pointer itself, you have to allocate that new pointer somewhere (and then who will free it?). If you don't mind the memory leak you can ignore the problem and just allocate a pointer and return its address. Or, you can create a new member of File_Tag that holds a short string that contains the first character of artist.

The glib string functions will be helpful for this, a quick look through the list shows g_strdup_printf() might be useful:

gchar *first = g_strdup_printf("%c", FileTag->artist[0]);

Then allocate somewhere to store first and return the address of that.

Update: Using http://codesearch.google.com I seem to have found where this function you're changing is used, and it looks like the return value is used to change the field that is returned.

    // Get the target entry for this code
    dest = Scan_Return_File_Tag_Field_From_Mask_Code(FileTag,mask_item->code);

    // We display the text affected to the code
    if ( dest && ( OVERWRITE_TAG_FIELD || *dest==NULL || strlen(*dest)==0 ) )
        ET_Set_Field_File_Tag_Item(dest,mask_item->string);

I'm not sure what exactly you want to do if your code returns a new string that contains the first character of the artist name. The above code would change what your newly allocated string points to, which would have no effect on the actual artist name.

Greg Hewgill
I was thinking along those lines... But I get "format ‘%c’ expects type ‘int’, but argument 2 has type ‘gchar *’" when I try that...
Luke Cycon
Are you sure you used `artist[0]` and not just `artist`?
Greg Hewgill
Word for word (a copy-paste) I have "gchar *first = g_strdup_printf("%c", "
Luke Cycon
Greg Hewgill
I see.. Not sure why I added that. Alas, that works but it complains now about "return from incompatible pointer type"... This is the problem I have been repeatedly running in to
Luke Cycon
Are you returning `first` itself, or are you allocating space to hold the `first` pointer and returning the address of it? I get the feeling that you're not very familiar with the use of pointers in C and need a tutorial on that topic.
Greg Hewgill
I understand the concept, and have used pointers... But I have just moved to C from Java, so yes, the concept of pointers is still somewhat elusive, despite my efforts to understand them fully.
Luke Cycon
And you got one occurrence of the function, but look in the same file circa line 779. That is the algorithm that determines the new file name
Luke Cycon
A: 

If possible, I would just get the whole artist string and then simply access the first letter from wherever you call the function:

gchar **artist = Scan_Return_File_Tag_Field_From_Mask_Code (File_Tag *FileTag, 'f')
printf("%c", *artist[0]);

If that is not an option, you could allocate new memory for your character, but that is rather tricky because you want to return a pointer to a pointer. So you would have to allocate also memory for that pointer. maybe you could change that ...

Lucas
That isn't an option. This is code from other sources that I am tweaking to fit my needs. The calling algorithm is too complex to rewrite
Luke Cycon
+1  A: 

If the goal is to return a pointer to a string that comprises only the first letter and you don't care about thread-safety, then the following should work

static char buf[2];
static char *pbuf = buf;
...
case 'f':
    buf[0] = FileTag->artist[0];
    return &pbuf;

I find it odd, however, that you're returning a pointer to a pointer to a "char" rather that simply a pointer to a "char".

Steve Emmerson