0

So Im making a project and I litteraly tried to do the same as a friend but for some reason i keep getting the error: assignment to expression with array type, idk how to avoid.

So I have a struct called Aeroporto and a list lista_A made out of Aeroportos. I'm asking for the user to define what is going to be inside each Aeroporto and if there's nothing wrong with the input he provides then it would save the Aeroporto in the list list_A but its not working.

I ve not been able to progress for an entire day and i really could use a way out

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

#define LEN_ID 3
#define LEN_P 30
#define LEN_CIDADE 50
#define AT 40

#define STR(x) #x

#define XSTR(x) STR(x)

typedef struct aeroporto
{
    char id[LEN_ID + 1];
    char pais[LEN_P + 1];
    char cidade[LEN_CIDADE + 1];
} Aeroporto;

int soMaiusculas(char s[])
{
    int i = 0, len = strlen(s);
    for (;i<len;i++)
    {
        if (s[i]< 'A' || s[i]>'Z')
            return 0;
    }
    return 1;
}

int main()
{   
    char input, p_id[LEN_ID ], p_pais[LEN_P ], p_cidade[LEN_CIDADE ], c;
    int i = 0; 
    Aeroporto lista_a[AT];
    
    scanf("%c",&input);

    while (input != 'q'){
        if (input == 'a')
        {
            scanf("%" XSTR(LEN_ID) "s",p_id);
            scanf("%" XSTR(LEN_P) "s",p_pais);
            scanf("%" XSTR(LEN_CIDADE) "[^\n]", p_cidade);  
            scanf("%*c");
            printf("airport %s, %s, %s\n",p_id, p_pais, p_cidade);
            if (!soMaiusculas(p_id))
                printf("invalid airport ID\n");
            else if (i==AT)
                printf("too many airports\n");
            /*else if (existeAero(lista_a, id))*/
            
            else{
                lista_a[i].id = p_id; //Now this is where the error is happening but following my //friend's advice it should work no?
                lista_a[i].pais = p_pais;
                lista_a[i].cidade = p_cidade;
                i++;
            }
        }
        scanf("%c",&input);
    }
    return 0;```
tomhoq
  • 59
  • 1
  • 6

2 Answers2

1

To reiterate the comments:

Unfortunately, your friend is incorrect here. You can not assign one array directly to another array. You must copy each element one by one.

For strings, the standard library provides the function strcpy that does this for us.

For general use cases, memcpy and memmove exist.

So

lista_a[i].id = p_id;
lista_a[i].pais = p_pais;
lista_a[i].cidade = p_cidade;

should be

strcpy(lista_a[i].id, p_id);
strcpy(lista_a[i].pais, p_pais);
strcpy(lista_a[i].cidade, p_cidade);

Also, your temporary buffers should be one byte larger:

char input, p_id[LEN_ID + 1], p_pais[LEN_P + 1], p_cidade[LEN_CIDADE + 1];

As an aside, there are several things that can go wrong with your parsing scheme.

The return value of the *scanf family of functions returns the number of successful conversions that occurred, and should always be tested in case of parsing failure, or to check for error.

A field-width specifier (%42s) is the maximum number of characters permitted to be read. The minimum is always 1. All airport codes are exactly 3 characters in length.

Additionally, your string inputs can bleed into one another:

  • If ABCDEF is submitted as the airport ID, DEF will be the first characters read into the country buffer. Similar situation for the country and city buffers.
  • If the string submitted for the city exceeds 50 characters, the 52nd character will bleed into your control statements.

scanf offers very little in the way of recovering from bad inputs.

Consider using a line-based approach, using functions like fgets or getline and parsing with sscanf.

Oka
  • 23,367
  • 6
  • 42
  • 53
  • Hey I sent you a reply but its not showing up for me so if you havent received it please tell me :( – tomhoq Mar 23 '22 at 12:51
  • I only see this single comment. – Oka Mar 23 '22 at 13:08
  • Ok i just wanted to tell you thank you this was super useful and fixed my code! I am a little bit scared to use fgets or getline so for now i will keep the scanf. From what i getline uses pointers? and we havent learned about pointers but they seem rather complex so i dont want to mess up big time again. I am starting to use fgets on another function and its proving to be quite useful so thank you! – tomhoq Mar 23 '22 at 14:36
  • You cannot avoid pointers for long in C - in fact, you are already using them in this example! `&input` is a pointer, and your character arrays [*decay*](https://stackoverflow.com/questions/33291624/why-do-arrays-in-c-decay-to-pointers) to pointers when you pass them to functions. It will make sense, in time. Good luck! – Oka Mar 23 '22 at 15:51
0

This is the error-generating statement:

lista_a[i].id = p_id;

That statement assigns a pointer (p_id) to an array (lista_a[i].id). This is not a valid assignment because a pointer is not assignable to a char array and besides, the pointers generally occupy more than the 3 bytes in your array. I am guessing that you really want to copy the contents of p_id into to the id field. Since both arrays are the same length (LEN_ID), this would be a good way to do the copy:

strncpy(lista_a[i].id, p_id, LEN_ID-1);

I'm suggesting strncpy rather than strcpy because it's safer—if the p_id string does not contain a zero termination for some reason strncpy will refuse to write beyond the end of the destination. (It will, however, also not zero-terminate, so if you want to be safe from that too, you'll need to take a little extra care.)

Howlium
  • 1,218
  • 1
  • 8
  • 19