Thread: error subscripted value is neither an array nor pointer nor vector

  1. #16
    Registered User
    Join Date
    May 2010
    Posts
    4,632
    As I said a single instance is a single instance not an array.

    If you want to dynamically allocate an array of some type you need allocate enough memory for the number of elements you want.

    For example to allocate an array of int of size 4 you would do something like:

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    int main(void)
    {
        int *dynamic;
    
        dynamic = malloc(sizeof(int) * 4);  // Allocate an array with 4 elements
    
        // Assign some "random" values to the elements.
        dynamic[0] = 4;
        dynamic[1] = 2343;
        dynamic[2] = 36;
        dynamic[3] = 45;
    
        // Print the array contents.
        for(int i = 0; i < 4; ++i)
            printf("%d ", dynamic[i]);
    
        printf("\n");
    
        return 0;
    }

  2. #17
    Registered User
    Join Date
    May 2010
    Posts
    4,632
    Here is a more through example showing how to work with dynamically allocated single instances and using the structure.

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    typedef struct
    {
        int door_number;
        char *p_street_name;
        char *p_city;
        struct Address *next;
    }Address;
    
    int main(void)
    {
        int *dynamic;
    
        dynamic = malloc(sizeof(int) * 4);
    
        dynamic[0] = 4;
        dynamic[1] = 2343;
        dynamic[2] = 36;
        dynamic[3] = 45;
    
        for(int i = 0; i < 4; ++i)
            printf("%d ", dynamic[i]);
    
        printf("\n");
    
        // Single instance:
        int *single;
        single = malloc(sizeof(int)); // Dynamically allocate a single instance.
    
        // Assign a value to this instance.
        *single = 5;
    
        printf("%d\n", *single);
    
        // Now dynamically allocate a single instance of your structure:
        Address *single_structure;
        single_structure = malloc(sizeof(Address));
        single_structure->door_number = 21343;
    
        printf("%d\n", single_structure->door_number);
    
        // Now an array of that structure.
        Address *multiple;
        multiple = malloc(sizeof(Address) * 2);
        multiple[0].door_number = 123;
        multiple[1].door_number = 345;
    
        for(int i = 0; i < 2; ++i)
            printf("%d ", multiple[i].door_number);
    
        printf("\n");
    
    
        return 0;
    }
    To use those "strings" you will still need to either statically or dynamically allocate memory for them before you try to use them.

  3. #18
    Registered User
    Join Date
    Apr 2019
    Posts
    808
    following flp's suggestion of putting in the missing tag i got the program to compile with no errors and run however declaring an extra pointer to keep track of where we are on the list misses an element(s) out (1 in my case but having played about i susspect that if i had 5 calls it would still only print out the first 2 and the last one. here is the code
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    typedef struct Address
    {
        int door_number;
        char *p_street_name;
        char *p_city;
        struct Address *next;
    }Address;
    
    int main()
    {
        Address *first = NULL;
        Address *new_address = NULL;
        Address *next_instance = NULL;
        Address *t;
    
        new_address = malloc(sizeof(Address));
        if (!new_address)
        {
            printf("error in memory allicating memory!");
            return 1;
        }
        new_address->door_number = 3;
        new_address->p_street_name = "some street";
        new_address->p_city = "some town";
        new_address->next = NULL;
    
        first = new_address;
        next_instance = new_address;
    
        new_address = malloc(sizeof(Address));
    
        if (!new_address)
        {
            printf("error in memory allicating memory!");
            goto clear_memory;
        }
        new_address->door_number = 5;
        new_address->p_street_name = "some other street";
        new_address->p_city = "some other town";
        new_address->next = NULL;
        first->next = new_address;
        next_instance = new_address;
    
        new_address = malloc(sizeof(Address));
    
        if (!new_address)
        {
            printf("error in memory allicating memory!");
            goto clear_memory;
        }
        new_address->door_number = 5;
        new_address->p_street_name = "another street";
        new_address->p_city = "jhkhhkhhkhkhjk town";
        new_address->next = NULL;
        next_instance->next = new_address;
    
        new_address = malloc(sizeof(Address));
    
        if (!new_address)
        {
            printf("error in memory allicating memory!");
            goto clear_memory;
        }
        new_address->door_number = 20;
        new_address->p_street_name = "yet another street";
        new_address->p_city = "yet another town";
        new_address->next = NULL;
        next_instance->next = new_address;
    
        t = first;
        while (t)
        {
            printf("door number = %d street = %s city = %s\n", t->door_number, t->p_street_name, t->p_city);
            t = t->next;
        }
    
        t = first;
    clear_memory:
    
        while (t)
        {
            next_instance = t->next;
            printf("freeing\n");
            free(t);
            t = next_instance;
        }
    
        return 0;
    }
    coop

  4. #19
    TEIAM - problem solved
    Join Date
    Apr 2012
    Location
    Melbourne Australia
    Posts
    1,907
    Quote Originally Posted by cooper1200 View Post
    following flp's suggestion of putting in the missing tag i got the program to compile with no errors and run however declaring an extra pointer to keep track of where we are on the list misses an element(s) out (1 in my case but having played about i susspect that if i had 5 calls it would still only print out the first 2 and the last one. here is the code
    Code:
     **Snip**
    coop
    Make another struct that keeps track of the list
    Code:
    struct linkedList
    {
      
    struct Address *Head; int count; // does come in handy...
    };
    And then make functions that pass this in, such as initialize, addToStart, addAfter, addBefore, addEnd, delete/AtStart/After/Before/AtEnd, distroyList, printList, orderBy, cloneList, findAddressByName, findAddressBy…
    Last edited by Click_here; 05-23-2019 at 06:49 PM.
    Fact - Beethoven wrote his first symphony in C

  5. #20
    Registered User
    Join Date
    Apr 2019
    Posts
    808
    sorry i don't understand what you mean. if i have a struct that has a member pointing to first and a second member counting the elements in the list how do i move past the second element of the list as i have no reference to it.

  6. #21
    Registered User
    Join Date
    Apr 2019
    Posts
    808
    ok this is my understanding of what i am trying to do (i hope it keeps the formatting)
    Code:
    /*
              *new_p = malloc.....
              *first = new_p
              *current = first
                 head node
              ---------------
              |      |      |
     *first ->| data |*point| --->null
              |      |      |
              ---------------
                     ^
                     |
              *current
              
    as there is only one item (the head) in the list both first and 
    current point to the head of the list.
    
              *new_p = malloc.....
              *first->next = new_p
              *current = new_p
                    head                     2nd element
              ---------------              ---------------
              |      |      | first->next  |      |      |
     *first ->| data |*point|------------->| data |*point|-->null
              |      |      |              |      |      |
              ---------------              ---------------
                                                  ^
                                                  |
                                           *current
    
    now there are two elements *first points to the 1st (the head) and both first->next 
    and *current point to the second element.
    
              *new_p = malloc.....
              *current->next = new_p
              *current = new_p
    
                   head                      2nd element                    3rd element
              ---------------              ---------------                ---------------
              |      |      | first->next  |      |      | current->next  |      |      |
     *first ->| data |*point|------------->| data |*point|--------------->| data |*point|-->null
              |      |      |              |      |      |                |      |      |
              ---------------              ---------------                ---------------
                                                                                 ^
                                                                                 |
                                                                          *current
                                                                          
    first still points to the head of the list, first->next points to the 2nd element
    current->next points to the 3rd element and then current is updated to point at the 3rd
    element.  more and more nodes can be added by setting current->next to the new address and
    current to point at the new element.
    */
    coop

  7. #22
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Traditionally, head is used to name a pointer to the first node of the linked list, tail is used to name a pointer to the last node of the linked list, and if the name is used, then current is used to name a pointer to the current node when you're iterating over the linked list.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  8. #23
    Registered User
    Join Date
    Apr 2019
    Posts
    808
    here is my effort to put the above into code
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    typedef struct Address
    {
        int door_number;
        char *street;
        char *city;
        struct Address *next;
    }Address;
    
    void add_address(Address *first, Address *current);
    void print_list(Address *first);
    void delete_list(Address *first);
    
    int main()
    {
        Address *first = NULL, *current = NULL;
    
        add_address(first, current);
        add_address(first, current);
        add_address(first, current);
        add_address(first, current);
        add_address(first, current);
    
        print_list(first);
        delete_list(first);
    
        return 0;
    }
    void add_address(Address *first, Address *current)
    {
        char my_str[20];
        Address *p_new_element;
    
        //get a new block of memmory and test the pointer isnt null
        p_new_element = malloc(sizeof(Address));
        if (!p_new_element)
        {
            printf("memmory allocation error");
            return;
        }
        //get door number and assign it to the new elements member 'door_number'
        printf("Please enter the door number: ");
        scanf(" %d", &p_new_element->door_number);
    
        //get street name and assign it to my_str
        printf("Please enter street name: ");
        scanf(" %s", my_str);
        //create memory for the street name and assign the pointer address->street to point to it
        p_new_element->street = malloc(strlen(my_str) + 1);
        //copy contents of my_str into the memmory location pointed to by address->street
        strcpy(p_new_element->street, my_str);
    
        //get city name
        printf("Please enter city name: ");
        scanf(" %s", my_str);
        //create memory for the city name and assign the pointer address->city to point to it
        p_new_element->city = malloc(strlen(my_str) + 1);
        //copy contents of my_str into the memmory location pointed to by address->city
        strcpy(p_new_element->city, my_str);
    
        if (first == NULL) // no list yet so make p_new_element the head
        {
            first = p_new_element;
            first->next = NULL;
            current = first;
            return;
        }
        if (first->next == NULL) //only one element in the list
        {
            first->next = p_new_element;
            current = p_new_element;
            current->next = NULL;
            return;
        }
        //more than 2 elements
        current->next = p_new_element;
        current = p_new_element;
        current->next = NULL;
    }
    
    void print_list(Address *first)
    {
        int count = 1;
        Address *temp = first;
    
        while (temp)
        {
            printf("address no %d is door number %d street %s city %s\n", count, temp->door_number,
                                                                           temp->street, temp->city);
            count++;
            temp = temp->next;
        }
    }
    
    void delete_list(Address *first)
    {
        int count = 1;
        Address *temp = NULL;
    
        printf("freeing memmory....\n");
        while (first)
        {
            temp = first->next; // set temp to point at the next element in the list
            printf("freeing element %d's street name\n", count);
            free(first->street); //free the memmory block that holds firsts street name
            printf("freeing element %d's city name\n", count);
            free(first->city); //free the memmory block that holds firsts city name
            printf("freeing struct %d's memmory\n", count);
            free(first); //free the memmory block that holds the first element
            first = temp; // set first to point at the next memmory block;
            count++;
        }
        printf("finished freeing all allocated memmory\n");
    }
    of course it doesn't work
    i input 5 lots of addresses then it doesn't print any of them then says freeing memory and then jumps straight to memory freed. on stepping through the code first is never changed from being set to null despite add address being passed a pointer to first.
    coop

  9. #24
    Registered User
    Join Date
    Apr 2019
    Posts
    808
    the more i try this the more confused im getting i just don't get the point of this at all. yes it saves memory by only having the number of entries you require and can be fluid however7
    {
    Code:
    int count = 0
    Address *multiple;
    
    multiple = malloc(sizeof(Address));
    count++;
    
    //need more 
    multiple = realloc(multiple, sizeof(Address) * (count + 1));
    count++
    achieves the same thing.
    coop

  10. #25
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733
    Quote Originally Posted by cooper1200 View Post
    the more i try this the more confused im getting i just don't get the point of this at all. yes it saves memory by only having the number of entries you require and can be fluid however7
    {
    Code:
    int count = 0
    Address *multiple;
    
    multiple = malloc(sizeof(Address));
    count++;
    
    //need more 
    multiple = realloc(multiple, sizeof(Address) * (count + 1));
    count++
    achieves the same thing.
    coop
    Drop the count + 1 and leave just count in there, also initialise count to 1, if the allocation fails the decrement it, 9 times out of 10 you'll never reach the decrement and save yourself an operation when repeating this say 1000 times

  11. #26
    Registered User
    Join Date
    Apr 2019
    Posts
    808
    thanks.... is this bad programming practice then??? why have the facility of linked lists if a thicko like me can come up with a simple way round them
    coop

  12. #27
    Registered User
    Join Date
    Apr 2019
    Posts
    808
    ok another attempt at getting linked lists to work. the wind was blowing from the east this time so i tried passing the address of *first to the function
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    typedef struct Address
    {
        int door_number;
        char *street;
        char *city;
        struct Address *next;
    }Address;
    
    void add_address(Address **first, Address **current);
    void print_list(Address *first);
    void delete_list(Address **first);
    
    int main()
    {
        Address *first = NULL, *current = NULL;
    
        add_address(&first, &current);
        add_address(&first, &current);
        add_address(&first, &current);
        //add_address(first, current);
        //add_address(first, current);
    
        print_list(first);
        delete_list(&first);
    
        return 0;
    }
    void add_address(Address **first, Address **current)
    {
        char my_str[20];
        Address *p_new_element;
    
        //get a new block of memmory and test the pointer isnt null
        p_new_element = malloc(sizeof(Address));
        if (!p_new_element)
        {
            printf("memmory allocation error");
            return;
        }
        //get door number and assign it to the new elements member 'door_number'
        printf("Please enter the door number: ");
        scanf(" %d", &p_new_element->door_number);
    
        //get street name and assign it to my_str
        printf("Please enter street name: ");
        scanf(" %s", my_str);
        //create memory for the street name and assign the pointer address->street to point to it
        p_new_element->street = malloc(strlen(my_str) + 1);
        if (!p_new_element->street)
        {
            printf("error in getting memmory for street name");
            return;
        }
        //copy contents of my_str into the memmory location pointed to by address->street
        strcpy(p_new_element->street, my_str);
    
        //get city name
        printf("Please enter city name: ");
        scanf(" %s", my_str);
        //create memory for the city name and assign the pointer address->city to point to it
        p_new_element->city = malloc(strlen(my_str) + 1);
        if (!p_new_element->city)
        {
            printf("error in getting memmory for city name");
            return;
        }
        //copy contents of my_str into the memmory location pointed to by address->city
        strcpy(p_new_element->city, my_str);
    
        if (*first == NULL) // no list yet so make p_new_element the head
        {
            *first = p_new_element;
            *first->next = NULL;
            *current = *first;
            return;
        }
        if (*first->next == NULL) //only one element in the list
        {
            *first->next = p_new_element;
            *current = p_new_element;
            *current->next = NULL;
            return;
        }
        //more than 2 elements
        *current->next = p_new_element;
        *current = p_new_element;
        *current->next = NULL;
    }
    
    void print_list(Address *first)
    {
        int count = 1;
        Address *temp = first;
    
        while (temp)
        {
            printf("address no %d is door number %d street %s city %s\n", count, temp->door_number,
                                                                           temp->street, temp->city);
            count++;
            temp = temp->next;
        }
    }
    
    void delete_list(Address **first)
    {
        int count = 1;
        Address *temp = NULL;
    
        printf("freeing memmory....\n");
        while (*first)
        {
            temp = *first->next; // set temp to point at the next element in the list
            printf("freeing element %d's street name\n", count);
            free(*first->street); //free the memmory block that holds firsts street name
            printf("freeing element %d's city name\n", count);
            free(*first->city); //free the memmory block that holds firsts city name
            printf("freeing struct %d's memmory\n", count);
            free(*first); //free the memmory block that holds the first element
            *first = temp; // set first to point at the next memmory block;
            count++;
        }
        printf("finished freeing all allocated memmory\n");
    }
    this produces 9 errors lines: 77 81 83 85 89 91 116 118 120; all saying error first is a pointer did you mean ->. well yes that's why i used the -> operator duh!! i guess the wind changed again without me noticing
    coop

  13. #28
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733
    First point, since I posting from a phone I can't tell what lines those are exactly but I'll assume they're down at the last function where you try to use a pointer (first) to another pointer or list of pointers, in that scenario you must enclose *first in brackets or change it for first[0] otherwise the compiler will think your referencing first 1st before de-referencing the contents of first when you want it the other way round, de-referencing first then referencing the contents,
    2nd point as I mentioned above leave filling to another function like this:
    Code:
     Address useraddr() { Address tmp; scanf(...);... return tmp;}
    then your variables can be automatically filled properly by the compiler instead when you assign the result to them

  14. #29
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733
    Quote Originally Posted by cooper1200 View Post
    thanks.... is this bad programming practice then??? why have the facility of linked lists if a thicko like me can come up with a simple way round them
    coop
    Simply put the more operations the longer a task takes, best practice is to always keep an eye out for ways to shorten the time, that way when you get to time critical functions you'll have already developed the necessary habit and trained your brain to spot most unnecessary operations or poorly used operations, as for linked lists there are cases for it such as trees but yes it doesn't fit everything.

  15. #30
    Registered User
    Join Date
    Apr 2019
    Posts
    808
    ok finally using awsdert's suggestion of replacing *first with (*first) worked. here is the code
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    typedef struct Address
    {
        int door_number;
        char *street;
        char *city;
        struct Address *next;
    }Address;
    
    void add_address(Address **first, Address **current);
    void print_list(Address *first);
    void delete_list(Address **first);
    
    int main()
    {
        Address *first = NULL, *current = NULL;
    
        add_address(&first, &current);
        add_address(&first, &current);
        add_address(&first, &current);
        //add_address(first, current);
        //add_address(first, current);
    
        print_list(first);
        delete_list(&first);
    
        return 0;
    }
    
    void add_address(Address **first, Address **current)
    {
        char my_str[20];
        Address *p_new_element;
    
        //get a new block of memmory and test the pointer isnt null
        p_new_element = malloc(sizeof(Address));
        if (!p_new_element)
        {
            printf("memmory allocation error");
            return;
        }
    
       //get door number and assign it to the new elements member 'door_number'
        printf("Please enter the door number: ");
        scanf(" %d", &p_new_element->door_number);
    
        //get street name and assign it to my_str
        printf("Please enter street name: ");
        scanf(" %s", my_str);
        //create memory for the street name and assign the pointer address->street to point to it
        p_new_element->street = malloc(strlen(my_str) + 1);
        if (!p_new_element->street)
        {
            printf("error in getting memmory for street name");
            return;
        }
        //copy contents of my_str into the memmory location pointed to by address->street
        strcpy(p_new_element->street, my_str);
    
        //get city name
        printf("Please enter city name: ");
        scanf(" %s", my_str);
        //create memory for the city name and assign the pointer address->city to point to it
        p_new_element->city = malloc(strlen(my_str) + 1);
        if (!p_new_element->city)
        {
            printf("error in getting memmory for city name");
            return;
        }
        //copy contents of my_str into the memmory location pointed to by address->city
        strcpy(p_new_element->city, my_str);
    
        if (*first == NULL) // no list yet so make p_new_element the head
        {
            *first = p_new_element;
            (*first)->next = NULL;
            *current = *first;
            return;
        }
        if ((*first)->next == NULL) //only one element in the list
        {
            (*first)->next = p_new_element;
            *current = p_new_element;
            (*current)->next = NULL;
            return;
        }
        //more than 2 elements
        (*current)->next = p_new_element;
        *current = p_new_element;
        (*current)->next = NULL;
    }
    
    void print_list(Address *first)
    {
        int count = 1;
        Address *temp = first;
    
        while (temp)
        {
            printf("address no %d is door number %d street %s city %s\n", count, temp->door_number,
                                                                           temp->street, temp->city);
            count++;
            temp = temp->next;
        }
    }
    
    void delete_list(Address **first)
    {
        int count = 1;
        Address *temp = NULL;
    
        printf("freeing memmory....\n");
        while (*first)
        {
            temp = (*first)->next; // set temp to point at the next element in the list
            printf("freeing element %d's street name\n", count);
            free((*first)->street); //free the memmory block that holds firsts street name
            printf("freeing element %d's city name\n", count);
            free((*first)->city); //free the memmory block that holds firsts city name
            printf("freeing struct %d's memmory\n", count);
            free(*first); //free the memmory block that holds the first element
            (*first) = temp; // set first to point at the next memmory block;
            count++;
        }
        printf("finished freeing all allocated memmory\n");
    }
    however on this youtube video at approx 13 minuets he uses a double pointer and doesn't use the (*first) he used *first->next = null etc etc so why do i have to use (*first) and he didn't?
    coop

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Subscripted value is neither array nor pointer ?
    By prietito1 in forum C Programming
    Replies: 2
    Last Post: 08-08-2012, 12:42 AM
  2. subscripted value is neither array nor pointer: 2 files
    By pochis40 in forum C Programming
    Replies: 6
    Last Post: 05-27-2011, 03:16 PM
  3. Replies: 1
    Last Post: 05-08-2010, 10:03 PM
  4. Replies: 9
    Last Post: 03-16-2009, 02:18 AM
  5. subscripted value is neither array nor pointer
    By new_to_c in forum C Programming
    Replies: 8
    Last Post: 04-01-2007, 02:43 PM

Tags for this Thread