1

How to check if the string is already in an array of structures? The array is inside a structure and I don't know how to compare arrays inside the structure in C.

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

struct song {
    char title[30];
    char artist[30];
    char album[30];
};

typedef struct playlist {
    char sname[30];
    char asongs[10];
    int scount;

    struct song music;
} songlist;

void addPlaylist(struct playlist *menu, int i) {
    printf("Enter playlist name: ");
    scanf("%s", menu[i].sname);

    for (int j = 0; j < i; j++) {
        if (strcmp(menu[i].sname, menu[j].sname) == 0) {
            printf("already exists!\n");
        } else {
            printf("Successfully added playlist!\n");
        }
    }
}

int main() {
   //menu. if choice == 1, go to addPlaylist func
}

I am asking the user for the name of playlist, and when a string is entered, it should be on the array sname.

When the user wants to add another playlist and enters a playlist name that is already in the array sname, the program should print already exists!; otherwise, it should add on the array.

The array is inside a structure and I'm trying to compare the arrays to check if the user's input (which is a string) already exists inside the array. I tried using for loop but I am not sure about my conditions and the components inside the strcmp function.

EDIT For example, if the user already entered multiple names like:

favorites
vibes
mood

and then, the user decided to add more playlist names then accidentally entered the name vibes which already exists in the array.

If vibes already exists, I want the program to print already exists!

I want to know how to properly check if the entered string already exists (especially if the string is inside a structure).

EDIT

Here's the output:

enter image description here

As you can see there's also problem in printing the successfully... and already...

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • Note that the expression `menu->sname` is the same as `(*menu).sname`, which in turn is the same as `menu[0].sname`. Is that what you want? And if it is, why don'y you write the more clear variant? – Some programmer dude May 22 '22 at 14:21
  • You are going to need a way to tell the calling function whether the name was added or not because at some point, you need to increment the number of items in the playlist, and your existing design has no way to convey that information. – Jonathan Leffler May 22 '22 at 14:25
  • @User617290653251457439 There is a typo if(strcmp(menu->sname, menu[i].sname)==0) { You need to write if(strcmp(menu[j].sname, menu[i].sname)==0) { – Vlad from Moscow May 22 '22 at 14:26
  • @VladfromMoscow — that appears to be fixed now. And the arrow needed to be replaced by a dot operator. – Jonathan Leffler May 22 '22 at 14:28
  • @VladfromMoscow i tried that but theres an error. it says that ```error: invalid type argument of '->' (have 'struct playlist')``` – User617290653251457439 May 22 '22 at 14:28
  • If you want to access array, you modify argument 'struct playlist *menu' to 'struct playlist **menu'. – linuxias May 22 '22 at 14:36
  • @linuxias too many errors are appearing in the compiler – User617290653251457439 May 22 '22 at 15:20

2 Answers2

1

The code which demonstrates the requested adding behavior. See in-code comments for details.

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

struct song {
    char title[30];
    char artist[30];
    char album[30];
};

typedef struct playlist {
    char sname[30];
    char asongs[10];
    int scount;

    struct song music;
} songlist;

void addPlaylist(struct playlist *menu, int i) {
    char sname[30]; // use local variable for new input
    printf("Enter playlist name: ");
    scanf("%s", sname); // read into local variable

    // go over all lists to check if it already exists
    for(int j=0; j<i; j++) {
        if(strcmp(sname, menu[j].sname)==0) {
            printf("Playlist '%s' already exists!\n", sname);
            return;
        } 
    }

    // go over all lists to search for first empty entry
    for(int j=0; j<i; j++) {
        if(menu[j].sname[0] == '\0') {
            strcpy(menu[j].sname, sname);
            printf("Successfully added playlist '%s'!\n", menu[j].sname);
            return;
        } 
    }

    // No empty entry found
    printf("No space for new Playlist. Please remove one!\n");
}

int main() {
    songlist playlists[10];
    for (int i=0; i<10; i++) {
        playlists[i].sname[0] = '\0'; // use string termination char to indicate unused entry
        playlists[i].asongs[0] = '\0';
        playlists[i].scount = 0;
        playlists[i].music.title[0] = '\0';
        playlists[i].music.album[0] = '\0';
        playlists[i].music.artist[0] = '\0';
    }
    char input;
    do {
        printf("======= MENU =======\n");
        printf("[1] Add Playlist\n");
        printf("[2] Add Song to Playlist\n");
        printf("[3] Remove Song from Playlist\n");
        printf("[4] View a Playlist\n");
        printf("[5] View All Data\n");
        printf("[6] Exit\n");
        scanf(" %c", &input);

        switch (input) {
            case '1': addPlaylist(playlists, 10); break;
            case '2': break;
            case '3': break;
            case '4': break;
            case '5': break;
            case '6': break;
            default: printf("Unknown selection!\n"); break;
        }
    } while (input != '6');

   return 0;
}
$ gcc -Wall playlist.c
$ ./a.out
======= MENU =======
[1] Add Playlist
[2] Add Song to Playlist
[3] Remove Song from Playlist
[4] View a Playlist
[5] View All Data
[6] Exit
1
Enter playlist name: vibes
Successfully added playlist 'vibes'!
======= MENU =======
[1] Add Playlist
[2] Add Song to Playlist
[3] Remove Song from Playlist
[4] View a Playlist
[5] View All Data
[6] Exit
1
Enter playlist name: mood
Successfully added playlist 'mood'!
======= MENU =======
[1] Add Playlist
[2] Add Song to Playlist
[3] Remove Song from Playlist
[4] View a Playlist
[5] View All Data
[6] Exit
1
Enter playlist name: favorites
Successfully added playlist 'favorites'!
======= MENU =======
[1] Add Playlist
[2] Add Song to Playlist
[3] Remove Song from Playlist
[4] View a Playlist
[5] View All Data
[6] Exit
1
Enter playlist name: vibes
Playlist 'vibes' already exists!
======= MENU =======
[1] Add Playlist
[2] Add Song to Playlist
[3] Remove Song from Playlist
[4] View a Playlist
[5] View All Data
[6] Exit
6
$ 
Franck
  • 1,340
  • 2
  • 3
  • 15
1

There is a problem in addPlaylist: you should return from the function when you find a match, returning 0 to the caller so it does not add the last entry, and you should test all entries before printing Successfully added playlist!, returning 1 to the caller.

// return 1 if the playlist was added at offset i
int addPlaylist(struct playlist *menu, int i) {
    char sname[30];

    printf("Enter playlist name: ");
    if (scanf("%29s", sname) != 1)
        return 0;

    for (int j = 0; j < i; j++) {
        if (strcmp(sname, menu[j].sname) == 0) {
            printf("already exists!\n");
            return 0;
        }
    }
    strcpy(menu[i].sname, sname);
    printf("Successfully added playlist!\n");
    return i;
}
chqrlie
  • 131,814
  • 10
  • 121
  • 189
  • I tried you code but when I find a match, the matched string still adds in the array – User617290653251457439 May 23 '22 at 01:02
  • @User617290653251457439: you should post the code for a full program. It is unclear why you pass an index `i` to `addPlaylist`. I amended the answer to not modify the `menu` if the `sname` is present already, but the caller should test the return value of `addPlaylist` to update the menu entry count. – chqrlie May 23 '22 at 07:18