paulo1205
(usa Ubuntu)
Enviado em 16/08/2019 - 03:39h
Nick-us escreveu:
Pode ser falta de conhecimento base como você diz. Vou tentar explicar o que até agora entendi.
Quando declaro:
char Text[] = "ABC";
Entendo que eu tenho um vetor/array de caracteres que é o mesmo que: A,B,C ou seja, entendo que o C armazena apenas 1 Caracter então é como se ele fizesse uma lista para esse armazenamento. Por isso ele: Armazena:
Text[0] = A
Text[1] = B
Text[2] = C
Text[3] = Caracter Terminador 0 ou \0
Permita-me perguntar: qual material você está usando para lhe apresentar o C? A pergunta é porque parece que há algumas lacunas importantes no conhecimento que você demonstra, e também alguma mistura de conceitos e terminologia.
Discorrendo rapidamente sobre
arrays .
Arrays (também chamados de vetores) são conjuntos com uma
quantidade finita de
elementos de dados
de um mesmo tipo , dispostos em posições adjacentes na memória. A forma de declarar um
array é informando o tipo de cada elemento, seguido pelo nome da variável que vai designar o
array e pela contagem do número de elementos do
array , expressa entre colchetes. O trecho abaixo mostra alguns exemplos de declarações de
arrays , com comentários que explicam o sentido de cada declaração.
int i_arr[50]; // declara ‘i_arr’ como um array contendo 50 elementos do tipo int.
double d_arr[20]; // declara ‘d_arr’ como um array contendo 20 elementos do tipo double.
char c_arr[100]; // declara ‘c_arr’ como um array contendo 100 elementos do tipo char.
Os tipos de cada elemento do
array não são restritos a tipos nativos, mas podem também ser de tipos derivados ou de tipos compostos.
char *pc_arr[10]; // declara ‘pc_arr’ como um array contendo 10 elementos do tipo “ponteiro para char”.
struct tm time_table[15]; // declara ‘time_table’ como um array contendo 15 elementos do tipo “struct tm”.
float f_mat[20][10]; // declara ‘f_mat’ como um array contendo 20 elementos do tipo “array contendo 10 elementos do tipo float”.
Declarados dessa maneira, os valores inciais dos elementos do
array podem ser ou zerados, se o
array tiver alocação estática (variáveis globais ou as declaradas dentro de blocos, mas com o modificador
static ), ou podem ser desconhecidos/indeterminados, se o
array tiver alocação automática (dentro de blocos e sem a especificação
static ).
Muitas vezes, no entanto, é interessante fazer com que os
arrays possuam valores iniciais específicos atribuídos a seus elementos desde o momento de sua declaração. Nesses casos, é possível colocar, após a declaração do
array , um sinal de igual (
= ) seguido de uma lista de valores entre chaves, separados entre si por vírgulas, como no exemplo abaixo.
unsigned primeiros_naturais[10]={0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
A quantidade de valores iniciais não precisa ser necessariamente igual ao tamanho do
array , mas pode ser menor. Nesse caso, os valores contidos na lista serão gravados nas primeiras posições do
array , e as posições seguintes serão forçosamente preenchidas com zeros.
char nome[50]={'P', 'a', 'u', 'l', 'o'}; // Ocupa as cinco primeiras posições, e as 45 seguintes são preenchidas com zeros (caracteres nulos).
Outra possibilidade que a lista de valores iniciais oferece é fazer com que o compilador conte a quantidade de elementos na lista de inicialização e ajuste o tamanho do
array para se acomodar exatamente essa quantidade de elementos. Para tanto, deve-se omitir a quantidade de elementos entre os colchetes (deixando-a realmente vazia), e a lista de valores iniciais tem de estar presente.
unsigned algarismos_pares[]={0, 2, 4, 6, 8}; // Tamanho calculado automaticamente para abrigar os 5 elementos listados.
char bilabiais[]={'b', 'm', 'p'}; // Tamanho calculado automaticamente para abrigar os 3 elementos listados. NOTE QUE esta declaração NÃO DECLARA UMA STRING, mas apenas um array com três caracteres, pois não existe o byte terminador '\0' que caracterizaria uma string.
double d_arr[]; // PROBLEMA: compilador não tem como calcular tamanho; no mínimo vai produzir uma mensagem de alerta, se não de erro, durante a compilação.
Como caso particular, uma forma alternativa de especificar listas de elementos inicias,
válida apenas para arrays com elementos do tipo char (e suas variantes
signed char e
unsigned char ) é colocar uma sequência de caracteres entre aspas. Essa forma de lista de inicialização, projetada para facilitar o uso de
strings , produz um efeito equivalente ao de ter os mesmos caracteres como elementos individuais numa lista de inicialização usando chaves, mas acrescentando ao final um caráter a mais, com o valor nulo, que serve como indicador do fim de
string , conforme a convenção de representação usada pelas funções de manipulação de
strings da biblioteca padrão do C. Efeito semelhante foi estendido para
arrays de caracteres largos (
wchar_t ).
char nome[]="Paulo"; // equivalente a “char nome[]={'P', 'a', 'u', 'l', 'o', '\0'};”, que, por sua vez é equivalente a “char nome[6]={'P', 'a', 'u', 'l', 'o', '\0'};”.
unsigned char objeto[]="bola"; // equivalente a “unsigned char objeto[5]={'b', 'o', 'l', 'a', '\0'}.”.
wchar_t login[]=L"paulo1205"; // equivalente a “wchar_t login[10]={L'p', L'a', L'u', L'l', L'o', L'1', L'2', L'0', L'5', L'\0'};”.
Declarações de
arrays reservam um espaço na memória e, eventualmente (no caso de alocação estática ou no da presença de uma lista de inicialização) atribuem valores iniciais nessas posições alocadas pela declaração. Dali para frente, a variável que designa o
array como um todo não pode mais ser alterada pois, caso contrário, ela não indicaria mais aquele mesmo
array , naquela região de memória, alocada desde a compilação. Elementos individuais podem ser alterados, mas o
array como um todo, não.
int a[5]={0, 1, 2, 3, 4}, b[5]={1, 3, 5, 7, 9}, c[10];
int i;
for(n=0; n<5; n++){
a[n]*=2; // OK: Elemento, por elemento, altera os valores contidos em a, fazendo com que cada um valha o dobro do que valia inicialmente.
c[n*2]=a[n]; // OK: Altera os valores dos elementos de c, usando os valores dos elementos de a.
c[n*2+1]=b[n]; // OK: Altera os valores dos elementos de c, usando os valores dos elementos de b.
}
// Agora a contém {0, 2, 4, 6, 8}, e c contém {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}.
a=b; // ERRO: não posso manipular o array inteiro de uma vez (até porque aqui, ‘a’ não indica mais o array inteiro, mas é apenas um ponteiro constante para o primeiro elemento).
b=c; // ERRO: pelo mesmo motivo.
Entendo que ele guardou no Caso não uma String ABC. E sim cada Letra separadamente como se fosse numa variavel diferente, se posso chamar Text[0]... e etc... como variáveis diferentes.
As duas coisas são verdadeiras. Isto é: você tem os elementos individuais
'A' ,
'B' ,
'C' e
'\0' em
Text[0] até
Text[3] , mas também tem uma
string , indicada por
Text sem aplicar índices, o que resulta num ponteiro para o primeiro elemento.
Isso é mesmo um pouco confuso no início (ainda mais se você já usou outras linguagens de programação que tratem
strings de uma forma mais amigável).
O problema é que C não tem um tipo de dados dedicado para representar
strings . Em lugar disso, a linguagem e sua biblioteca de funções se valem do fato de que
strings tipicamente indicam sequências de caracteres na memória, e então usam aquilo que a linguagem tem de mais parecido, que são os
arrays de caracteres, para armazenar aquilo que
a aplicação — não a linguagem em si — vai tratar como se fossem
strings .
Para que isso funcione em nível de aplicação, todas as operações de
strings têm de respeitar algumas convenções:
• a
string fica armazenada em um
array de caracteres (que pode ter sido declarado como
array no código fonte do programa ou residir em memória alocada dinamicamente, através de ponteiros sob rígido controle do programador);
• o conteúdo da
string é considerado a partir de um ponteiro para seu primeiro elemento;
• o final da
string é indicado por um caráter nulo, que funciona como um terminador da
string ;
• o terminador não conta como parte da
string (por exemplo, a função
strlen () não inclui o terminador como parte do comprimento da
string ), mas mesmo assim ele tem de ser armazenado no mesmo
array que contém a
string (caso contrário, não se pode mais dizer que o
array contém uma
string .
Com base nessas convenções, se você quer que sua
string tenha, por exemplo, 50 caracteres úteis, terá de declarar (ou alocar dinamicamente) um
array com pelo menos 51 caracteres de tamanho, e garantir que sempre haverá um caráter nulo no 51º elemento desse
array ).
Acontece que quando apenas declaro um vetor de char como char Text[] = "ABC"; que seria o mesmo que char Text[4] = "ABC";
Eu tenho 4 CAMPOS Cada campo desse com 1 Caracter armazenado.
Cuidado com a terminologia. É melhor você dizer que tem quatro
elementos nesse
array .
A ideia de
campo tem mais a ver com estruturas do que com
arrays . Campos distintos podem ter tipos de dados distintos, qualificadores de acesso (
const ,
volatile etc.) distintos e atributos distintos, ao passo que elementos de um mesmo
array têm necessariamente um só tipo de dados, qualificadores e atributos.
Então pensei. Uma Struct embora ela possa ter elementos dentro dela. Mas até então não estou falando desses elementos, e sim do VETOR.
Não compreendi o que você quis dizer. E, de novo, atenção com a terminologia: a estrutura tem
campos . Um dos campos pode até ser um
array , e esse campo
array pode ter os seus elementos, mas por mais que tais elementos estejam dentro do bloco maior chamado estrutura, o acesso a eles está num nível hierárquico diferente: antes de chegar ao elemento, você tem de passar pelo campo.
Por exemplo:
#include <stdio.h>
struct {
char Names[5];
int Num;
} List[] = { {"AAAA", 7}, {"BBB", 9}, {"C", 10} };
int main() {
if(List[0].Num == 7) // FUNCIONA
puts("OK 7");
puts(List[0].Names); // Imprime AAAA
if(List[0].Names == "AAAA") // NÃO FUNCIONA Não encontra
puts("OK A");
}
Funciona, sim. Só que não faz o que você possivelmente gostaria que fizesse.
O operador de comparação
== compara diretamente os valores que aparecem de cada um dos seus lados. No seu caso, você tem um ponteiro para caracteres de um lado e um ponteiro para caracteres do outro lado (ambos gerados a partir do decaimento automático de
arrays para ponteiros, algo que é previsto e prescrito pela linguagem), e o que o operador de comparação faz é simplesmente testar se esses dois ponteiros designam o mesmo endereço de memória, o que seguramente nunca será o caso, porque um deles indica um campo da estrutura, e o outro, algo que está necessariamente fora da estrutura.
No Caso acima, eu entendo que minha Struct declarada List[] = { {"AAAA", 7}, {"BBB", 9}, {"C", 10} };
É o mesmo que List[4] = { {"AAAA", 7}, {"BBB", 9}, {"C", 10} };
OU List[3] = { {"AAAA", 7}, {"BBB", 9}, {"C", 10} };
Como eu disse acima, a
aparente extensão de tamanho se aplica apenas a
array de caracteres com inicialização a partir de constantes literais
strings . Nem o seu vetor tem elementos do tipo
char , nem sua lista de inicialização esta na forma de
string entre aspas.
... “Principium sapientiae timor Domini, et scientia sanctorum prudentia.” (Proverbia 9:10)