Link to home
Start Free TrialLog in
Avatar of kuntilanak
kuntilanakFlag for United States of America

asked on

struct question

what is wrong with the following code?

seems like when I do :

   song->artist = temp->artist;
 

and so on it fails
typedef struct Songs
{
    char title[20], artist[20], album[20], genre[20], duration[6];
    int year;
    struct Song *next_song;
} Song;
 
 
Song* temp = head_p;
            Song* song = (Song*) malloc(sizeof(Song));
            song->artist = temp->artist;
            song->title = temp->title;
            song->album = temp->album;
            song->genre = temp->genre;
            song->duration = temp->duration;
            song->year = temp->year;

Open in new window

Avatar of kuntilanak
kuntilanak
Flag of United States of America image

ASKER

is the correct way to do something like:
 memcpy(song->artist, temp->artist, 20);

Open in new window

Avatar of Infinity08
>> is the correct way to do something like:

That's indeed what you need to do for strings :)
btw, I assume that head_p is pointing to a valid Song struct ? And that the error you mentioned was a compile time error, and not a runtime error ?
>>btw, I assume that head_p is pointing to a valid Song struct ? And that the error you mentioned was a >>compile time error, and not a runtime error ?

true... now I have just one more error at the very end of my code.. after main returns 0.. it says

I hate this kind of error as it can be anywhere
ece.c:354: error: syntax error at end of input

Open in new window

That probably means a missing ; somewhere or an unmatched { or something similar. If you don't find it yourself, can you post your entire code here ?
yes.. thank you infinity..
#include <stdio.h>
#include <string.h>
 
typedef struct Songs
{
    char title[20], artist[20], album[20], genre[20], duration[6];
    int year;
    struct Song *next_song;
} Song;
 
FILE *input, *output;
Song *head_p, *temp, *current = NULL;
 
int numberOfSongs = 0;
 
void printSong(Song* song){
 printf("Title : %s\n", song->title);   
 printf("Artist : %s\n", song->artist);
 printf("Album : %s\n", song->album);
 printf("Duration : %s\n", song->duration);
 printf("Genre : %s\n", song->genre);
 printf("Year : %d\n",song->year);   
}
 
 
Song* insertDeleteInterface(){
    Song* new_song = (Song*) malloc(sizeof(Song));
    printf("Please enter a song title: ");
    scanf("%s", new_song->title);
    printf("\nPlease enter a song artist: ");
    scanf("%s", new_song->artist);
    printf("\nPlease enter a song album: ");
    scanf("%s", new_song->album);
    printf("\nPlease enter a song genre: ");
    scanf("%s", new_song->genre);
    printf("\nPlease enter a song duration: ");
    scanf("%s", new_song->duration);
    printf("\nPlease enter a song year: ");
    scanf("%d", new_song->year);
    return new_song;
}
 
 
void insertSong(void){
    current->next_song = (Song*)insertDeleteInterface();
    numberOfSongs++;
}
 
void deleteSong(Song* song){
    Song* temp = head_p;
    Song* prev = NULL;
    while (temp != NULL){
        if ((strcmp(temp->artist, song->artist) == 0) && (strcmp(temp->title, song->title) == 0) && (strcmp(temp->album, song->album) == 0) && (strcmp(temp->genre, song->genre) == 0) && (strcmp(temp->duration, song->duration) == 0) && (temp->year == song->year)){
         prev->next_song = temp->next_song;
         free(*song);   
        }
        
        prev = temp;
        temp = (Song*)temp->next_song;
        
    }        
}
 
 
void exportDatabase(void){
   output = fopen("database.dat", "w");
    Song* temp = head_p;
    while (temp != NULL){
        fprintf(output, "%s %s %s %s %s %d\n", temp->title, temp->artist, 
        temp->album, temp->genre, temp->duration, temp->year);
        temp = head_p->next_song;
    }
    
}
 
 
void printDatabase(void){
    Song* temp = head_p;
    while(temp != NULL){
        printSong(temp);
        temp = head_p->next_song;
    }
}
 
 
void searchByDatabase(void){
    /*sortByTitle();*/
    int choice = -1;
    char artist[20], title[20], album[20], duration[20], genre[10];
    int year;
    while ( choice < 1 || choice > 6){
        printf("How do you want to search for songs?\n");
        printf("1. Artist\n");
        printf("2. Title\n");
        printf("3. Album\n");
        printf("4. Genre\n");
        printf("5. Duration\n");
        printf("6. Year\n");
        scanf("%d", &choice);
    }
    Song* temp = head_p;
        switch(choice){
            case 1:
               printf("Please enter an artist name: ");
               scanf("%s", artist);
               while (temp != NULL){
                 if (strcmp(temp->artist, artist) == 0)
                     printSong(temp);
                 temp = temp->next_song;   
                }  
                break;
            case 2:
                printf("Please enter a title name: ");
                scanf("%s", title);
                while (temp != NULL){
                 if (strcmp(temp->title, title) == 0)
                     printSong(temp);
                 temp = temp->next_song;   
                }  
                break;
            case 3:
                 printf("Please enter an album name: ");
                scanf("%s", album);
                while (temp != NULL){
                 if (strcmp(temp->album, album) == 0)
                     printSong(temp);
                 temp = temp->next_song;   
                }  
                break;
            case 4:
                 printf("Please enter a genre: ");
                scanf("%s", genre);
                while (temp != NULL){
                 if (strcmp(temp->genre, genre) == 0)
                     printSong(temp);
                 temp = temp->next_song;   
                }  
                break;
            case 5:
                 printf("Please enter a duration time: ");
                scanf("%s", duration);
                while (temp != NULL){
                 if (strcmp(temp->duration, duration) == 0)
                     printSong(temp);
                 temp = temp->next_song;   
                }  
                break;
            case 6:
                 printf("Please enter the song's year: ");
                scanf("%s", year);
                while (temp != NULL){
                 if (strcmp(temp->year, year) == 0)
                     printSong(temp);
                 temp = temp->next_song;   
                }  
                break;
            default:
                printf("Invalid input!");
    }    
}
 
void sortByTitle(){
 
 
 
}
 
 
void sortDatabase(void){
    int i, j, result;
    int choice = -1;
    Song arrayDatabase[numberOfSongs];
    while (choice < 0 || choice > 6){
        printf("Select an attributes to sort the database (number)\n");
        printf("1. Artist\n");
        printf("2. Title\n");
        printf("3. Album\n");
        printf("4. Genre\n");
        printf("5. Duration\n");
        printf("6. Year\n");
        printf("Enter your choice: "); 
        scanf("%d", &choice);
    }
          
    for (i = 0; i < numberOfSongs; i++){
            Song* temp = head_p;
            Song* song = (Song*) malloc(sizeof(Song));
            memcpy(song->artist, temp->artist, 20);
            memcpy(song->title, temp->title, 20);
            memcpy(song->album ,temp->album, 20);
            memcpy(song->genre ,temp->genre, 20);
            memcpy(song->duration, temp->duration, 6);
            song->year = temp->year;
            memcpy(&(arrayDatabase[i]), song, sizeof(Song));   
    } 
    
    
    for (i=0; i<numberOfSongs-1; i++) {
      for (j=0; j<numberOfSongs-1-i; j++){
        if (choice == 1)
            result = strcmp(arrayDatabase[j+1].artist, arrayDatabase[j].artist);
        else if (choice == 2)
            result = strcmp(arrayDatabase[j+1].title, arrayDatabase[j].title);
        else if (choice == 3)
            result = strcmp(arrayDatabase[j+1].album, arrayDatabase[j].album);
        else if (choice == 4)
            result = strcmp(arrayDatabase[j+1].genre, arrayDatabase[j].genre);
        else if (choice == 5)
            result = strcmp(arrayDatabase[j+1].duration, arrayDatabase[j].duration);
        else 
            result = arrayDatabase[j+1].year < arrayDatabase[j].year;
            
        if (result < 0) {      
          /* swap a[j] and a[j+1]      */
         Song* tmp = (Song*) malloc(sizeof(Song));
         memcpy(tmp, &arrayDatabase[j], sizeof(Song));         
         memcpy(&arrayDatabase[j], &arrayDatabase[j+1], sizeof(Song));
         memcpy(&arrayDatabase[j+1],tmp, sizeof(Song));
        }
       }
    }
 
    temp = head_p;
    i = 0;
    while(temp != NULL){
     memcpy(temp->title, &arrayDatabase[i].title, 20);
     /*
     temp->artist = arrayDatabase[i].artist;
     temp->genre = arrayDatabase[i].genre;
     temp->year = arrayDatabase[i].year;
     temp->duration = arrayDatabase[i].duration;
     temp->duration = arrayDatabase[i].album;
     temp = temp->next_song;
     */
     i++;     
    }    
}
 
 
void deleteByDatabase(void){
    int choice = -1;
    char artist[20], title[20], album[20], genre[20], duration[20], year[4];
    while (choice < 0 || choice > 6){
        printf("Select an attribute to delete from the database, please enter a number\n");
        printf("1. Artist\n");
        printf("2. Title\n");
        printf("3. Album\n");
        printf("4. Genre\n");
        printf("5. Duration\n");
        printf("6. Year\n");
        printf("Enter your choice: "); 
        scanf("%d", &choice);
    }
    
    Song* temp = head_p;
    switch(choice){
         case 1:
             printf("Please enter an artist name:");
             scanf("%s", artist);
         case 2:
             printf("Please enter a title:");
             scanf("%s", title);
         case 3:
             printf("Please enter an album name:");
             scanf("%s", album);
         case 4:
             printf("Please enter a genre:");
             scanf("%s", genre);
         case 5:
             printf("Please enter a duration");
             scanf("%s", duration);
         case 6:
            printf("Please enter a year:");
             scanf("%d", year);
        default:
            printf("Error in choice!\n");
            
    while (temp != NULL){
        if (choice == 1 && strcmp(temp->artist, artist) == 0)
            deleteSong(temp);
        else if (choice == 2 && strcmp(temp->title, title) == 0)
            deleteSong(temp);
        else if (choice == 3 && strcmp(temp->album, album) == 0)
            deleteSong(temp);
        else if (choice == 4 && strcmp(temp->genre, genre) == 0)
            deleteSong(temp);
        else if (choice == 5 && strcmp(temp->duration, duration) == 0)
            deleteSong(temp);
        else if (choice == 6 && strcmp(temp->year, year) == 0)
            deleteSong(temp);
        temp = temp->next_song;
    }
        
}
 
 
int main(void)
{
    input = fopen("music.dat", "r");
    char delete[20];
    int choice = -1;
    while (!feof(input)){
        Song* temp = (Song*)malloc(sizeof(Song));        
        fscanf(input, "%s%s%s%s%s%d", temp->title, temp->artist, temp->album, temp->genre, temp->duration, temp->year);
        numberOfSongs++;
        if (current == NULL)
            head_p = temp;
        else
            current->next_song = temp;
        current = temp;
        temp->next_song = NULL;           
    } 
    
    while(choice!=7)
    {
    printf("Welcome to your cTunes interface.\n");
    printf("What do you want to do?\n");
    /*
    printf("1. Insert songs into database\n2. Delete songs from the      
    database\n3. Export your database to a file\n4. Sort the songs in the 
    database\n5. Search for songs by a certain attribute\n
    6. delete all songs of a certain attribute\n7. Exit the program\n");
   */
    scanf("%c", &choice);
    }
    switch(choice){
        case 1://insert song            
            insertSong(); 
            break;
        case 2://delete function
            deleteSong(insertDeleteInterface());
            break;
        case 3:
            printDatabase();
            break;
        case 4://sort songs
            sortDatabase();
            break;
        case 5://search by attribute
            searchByAttribute();
            break;
        case 6://delete by attribute
            deleteByAttribute();
            break;
        case 7:
            printf("Goodbye, come again soon.\n");
        break;
        default:
            printf("Invalid choice.\n");
    }
return 0;
}

Open in new window

hi,
correct,

you have 2 storage area (dynamic or not)
if you do
song->artist = temp->artist
you overwrite the address of the first buffer with the second.

If you had

Struct Song1,Song2
you could do
Song1=Song2

But you cannot becouse you are using lists an then dynamic areas.
To minimize coding and errors I'ld do in this way:

1) malloc the structure

2) cast type Song*  to char* and do a massive copy
memcpy( (char*)song, (char*)temp, sizeof(struct Song))

3) adjust the differences using correclty pSong* pointer
song->next_song = .....
song->other = x++
memcpy( song->..., ...., ....)

bye
vic


erhmm.. yes the struct thing is resolved.. there's one error in the code I pasted above... don't know where it is
The switch in the deleteByDatabase function is missing the closing }
thanks for pointing that out
So, does it work better now ?
it does except I got the following warnings:

the insertDeleteInterface() function returns a Song*, so I don't know why it gives me that error
ece.c: In function `insertSong':
ece.c:45: warning: assignment from incompatible pointer type
current->next_song = (Song*)insertDeleteInterface();

Open in new window

Avatar of efn
efn

You don't need the cast to Song* because that's what insertDeleteInterface returns anyway.  But I don't think that's what's giving you the warning.

I'd suggest changing the declaration of next_song from "struct Song *" to "struct Songs *", since Song is a typedef for struct Songs and it hasn't even been defined yet at the point of declaration.  If you substitute "struct Songs" for "Song" with the current code, you would get "struct struct Songs *", which doesn't make any sense.
I'll try to do that and see if it helps
Ok, just one more problem that needs to be fixed:



ece.c: In function `deleteByAttribute':
ece.c:287: warning: comparison between pointer and integer
 
 
temp->year == year

Open in new window

That's code you haven't posted.  I can't tell what's the pointer and what's the integer, but the compiler is probably right to warn you.  Could you supply some context?  Not necessarily your whole program, but maybe the whole function.  The declarations of temp and year are especially important.
it's actually the line 289 on my original code I posted above.. however as year is not a str so therefore I can't use strcmp and therefore I just compare it directly... and that's what I did....

it should say:

if (temp->year == year)
ASKER CERTIFIED SOLUTION
Avatar of Infinity08
Infinity08
Flag of Belgium image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
thanks for pointing that out