c_introducao_vetores.html 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486
  1. <!--
  2. Introdução à Programação - 2017 - Prof. Leoônidas de Oliveira Brandão
  3. Introdução aos vetores em C
  4. LInE (Laboratory of Informatics in Education) - http://www.usp.br/line
  5. IME - USP
  6. Material didático
  7. Pode usar livrevemente este material para fins não comerciais, devendo sempre fazer referência à autoria.
  8. Sugestões/apontamento são bem vindos: leo@ime.usp.br (favor indicar no assunto "material de introducao 'a programacao")
  9. Prof. Leônidas de Oliveira Brandão
  10. http://www.ime.usp.br/~leo
  11. http://line.ime.usp.br
  12. http://www.matemtica.br
  13. -->
  14. <meta http-equiv='Content-Type' content='text/html; charset=UTF-8'>
  15. <meta name='keywords' content='mac0122, material, professores, leonidas de oliveira brandao'>
  16. <link rel='stylesheet' type='text/css' href='css_img_js_conf/all.css'>
  17. <link rel='stylesheet' type='text/css' href='css_img_js_conf/line_introducao_programacao.css'>
  18. <script src="css_img_js_conf/defineLInE.js"></script> <!-- para referencias 'a documentos internos -->
  19. <div class="pagina">
  20. <!--
  21. <center><p>[
  22. <a href="#" title=""></a> &nbsp; | &nbsp;
  23. <a href="#memoria" title=""></a> &nbsp; &nbsp;
  24. ]</p>
  25. </center>
  26. -->
  27. <p class="secao">Introdução aos vetores em <i>C</i></p>
  28. <p>
  29. Como explicado no
  30. <a href="#" onclick="trocaPagina('introducao_vetores.html')" title="introducao aos vetores">texto introdutório ao conceito de vetores</a>,
  31. um vetor é uma sequência de dados ocupando posições consecutivas de memória e por isso existe uma ordem
  32. natural entre seus elementos, o primeiro elemento, o segundo e assim por diante.
  33. A grande vantagem de usar vetor é poder trabalhar com muitas variáveis utilizando um único
  34. nome para esse "agregado" de variáveis.
  35. Para isso existe uma sintaxe especial para pegar cada elemento do vetor, em posições específicas, como o primeiro elemento ou o décimo elemento.
  36. </p>
  37. <p>
  38. A linguagem <i>C</i> trata o conceito de vetor de um modo bastante próximo ao modo como é possível implementar esse conteito.
  39. Ilustraremos isso mostrando que podemos usar
  40. <i><a href="#" onclick="trocaPagina('introducao_apontadores_c.html')" title="ver apontadores em C">apontadores</a></i> para pegar elementos dos
  41. vetores.
  42. </p>
  43. <bloco1>Neste texto:
  44. <a class="" title="definir e imprimir um vetor" href="#define">definir/imprimir vetor</a>;
  45. <a class="" title="definir e imprimir string" href="#string">definir "string"</a>;
  46. <a class="" title="funcoes da biblioteca string.h" href="#strcmp">funções para "string"</a>;
  47. <a class="" title="vetor e apontadores" href="#apontador">vetor e apontador</a>;
  48. <a class="" title="definir e imprimir uma matriz" href="#matriz">definir/imprimir matriz</a>;
  49. <a class="" title="trabalhr com vetor/matriz dinamica (via apontador)" href="#dinamica">vetor/matriz dinâmicas</a>.
  50. </bloco1>
  51. <!-- secao -->
  52. <a name="define">
  53. <p class="secao">1. Definindo e imprimindo um vetor</p>
  54. </a>
  55. <p>
  56. Pode-se construir um vetor em <i>C</i> fornecendo todos seus elementos, como em:
  57. <tt><verm>int</verm> vet[] = {21, 22, 23, 24};</tt>.
  58. </p>
  59. <p>
  60. Pode-se também construir de modo "dinâmico", dependendo dos valores que variáveis assumem em meio ao código.
  61. Para isso deve-se declarar o máximo de posições que o vetor ocupará (como <tt><def>#define</def> MAX 10 ... <verm>int</verm> vet[MAX];</tt>)
  62. e depois define-se cada elemento, por exemplo, usando um comando de atribuição, como:
  63. <tt>vet[i] = 10+i;</tt>, que define o valor do elemento na posição <i>i</i> como o valor <tt>10+i</tt>.
  64. </p>
  65. <p>
  66. No exemplo a seguir construímos um vetor com <i>MAX</i> elementos,
  67. iniciando no <i>10+i</i> e seguindo até o <i>10+n-1</i>.
  68. Nesse exemplo indicamos, em um comentário, como usar apontador (<i>*(v+i)=10+i</i>) para definir os elementos de um vetor
  69. (usando <i>aritmética de ponteiros</i>).
  70. </p>
  71. <div class="exemplo"><i>Exemplo 1</i>. Construir um vetor e imprimir seus elementos.
  72. </div><!-- class="exemplo" -->
  73. <div class="codigo">
  74. <pre><incl1>#include</incl1> &lt;stdio.h&gt;
  75. // Declarar uma constante (para ser usada como dimensao maxima do vetor)
  76. <def>#define</def> MAX 10
  77. // Funcao para imprimir elementos de vetor em uma mesma linha
  78. // Nao precisa saber do total alocado para o vetor efetivo, pois para pegar o elemento i basta
  79. // saber a primeira posicao, digamos 'apont' e pegar '*(apont + i)'
  80. <verm>void</verm> imprime_vetor1 (<verm>int</verm> vet[], <verm>int</verm> tam) {
  81. <verm>int</verm> i;
  82. for (i=0; i&lt;tam; i++)
  83. <verd>printf</verd>("%d ", vet[i]);
  84. <verd>printf</verd>("\n"); <cyan>// ao final quebre a linha</cyan>
  85. }
  86. // Esta funcao define os valores para o vetor (passagem por referencia/endereco)
  87. // Lembrando: todo vetor e' passado por referencia 'a funcao (logo
  88. // alterar seus valores localmente implica em alterar os valores do
  89. // parametro efetivo!
  90. // Por ser vetor como parametro, nao precisa declarar a dimensao (nao precisa reservar espaco, e' apenas uma referencia)
  91. // Mas se fosse matriz precisaria saber dimensao coluna
  92. <verm>void</verm> definirVetor (<verm>int</verm> v[], <verm>int</verm> tam) {
  93. <verm>int</verm> i;
  94. for (i=0; i&lt;tam; i++) <cyan>// definir vetor/lista com: (10,11,12,13,...10+n-1)</cyan>
  95. v[i] = 10+i; <cyan>// Aqui altera' o 'parametro efetivo'! Tambem pode-se usar como apontador: *(v+i) = 10+i;</cyan>
  96. }
  97. <verm>int</verm> main (<verm>void</verm>) {
  98. <verm>int</verm> n=10, vet[MAX]; <cyan>// alocar MAX posicoes para o vetor 'vet' (pode-se usar menos)</cyan>
  99. definirVetor(vet, n); <cyan>// parametro efetivo 'vet' por ser vetor, se alterado na funcao, altera o efetivo!</cyan>
  100. <cyan>// Imprime o vetor/lista de uma so' vez (na mesma linha)</cyan>
  101. <verd>printf</verd>("\nO vetor: ");
  102. imprime_vetor1(vet, n); <cyan>// em C NAO e' possivel imprimir todos os dados de um vetor => fazer uma funcao...</cyan>
  103. return 0;
  104. }</pre>
  105. </div><!-- class="codigo" -->
  106. <p>
  107. <b>Importante</b>.
  108. Em <i>C</i>, usar um <i>vetor como parâmetro (formal) em função</i> implica que esta usando <b>passagem por referência (ou endereço)</b>!
  109. <br/>
  110. Portanto, dentro da função, se alterar o valor de qualquer elemento do vetor (<i>parâmetro formal</i>), isso implicará que, durante a execução,
  111. o seu <i>parâmetro efetivo</i> (aquele que é <i>passado efetivamente</i> para função) terá o elemento correspondente alterado.
  112. Por este motivo, no exemplo acima, ao fazer uma atribuição dentro da função (<tt>v[i] = 10+i;</tt>), estamos na verdade
  113. alterando os valores do <i>parâmetro efetivo</i> <tt>vet</tt>,
  114. por esse motivo usamos o nome <b style="color:#0000aa">passagem por referência (ou endereço)</b>,
  115. é como se o <i>parâmetro formal</i> <tt>v[]</tt> fosse uma <b>referência</b> (um "apelido") para o <i>parâmetro efetivo</i> <tt>vet[]</tt>.
  116. <br/>
  117. Se tiver dúvidas,
  118. <a href="#" onclick="trocaPagina('introducao_parametros_funcoes.html')" title="examine o texto sobre parametros de funcoes">reveja o texto sobre
  119. parâmetros de funções</a>.
  120. </p>
  121. <!-- secao -->
  122. <a name="string">
  123. <p class="secao">2. Defininido uma <i>cadeia de caracteres</i> ("string")</p>
  124. </a>
  125. <p>
  126. Em <i>C</i> é possível definir um vetor com caracteres, formando uma palavra, ou seja, uma <i>cadeia de caracteres</i>,
  127. que abreviadamente é denominada "<i>string</i>".
  128. Para isso pode-se fazer uma atribuição como constante ou ler os dados como palavra. Isso é ilustrado no exemplo abaixo.
  129. </p>
  130. <div class="exemplo"><i>Exemplo 2</i>. Trabalhando com "strings". Uma "string" fixa e digitar uma frase, imprimindo o número
  131. de caracteres nela.
  132. </div><!-- class="exemplo" -->
  133. <div class="codigo">
  134. <pre><incl1>#include</incl1> &lt;stdio.h&gt;
  135. <incl1>#include</incl1> &lt;string.h&gt; <cyan>// para usar a funcao 'strlen(...)'</cyan>
  136. <verm>void</verm> main (<verm>void</verm>) {
  137. <verm>int</verm> i;
  138. <verm>char</verm> string[] = "0123456789abcdefghih"; <cyan>// (1) - define a "string"</cyan>
  139. <cyan>// Imprimir cada caractere da string com seu codigo ASCII</cyan>
  140. <verd>printf</verd>("Imprime caracteres e seus codigos ASCII na forma de tabela\nColuna 1 => caractere; coluna 2 => seu codigo ASCII\n"); <!--" -->
  141. for (i=0; i&lt;strlen(string); i++)
  142. <verd>printf</verd>("%20c : %3d\n", string[i], string[i]); <cyan>// em C inteiro pode ser "lido" como caractere e vice-versao (via codigo ASCII)</cyan>
  143. <cyan>// Pode-se imprimir como uma frase toda usando o formatador %s</cyan>
  144. <verd>printf</verd>("Frase: %s\n", string);
  145. <cyan>// A string tem 20 caracteres, testando os caracteres 19 'h' e 20 '\n'</cyan>
  146. <verd>printf</verd>("A string tem 20 caracteres, testando os caracteres 19 '%c' e 20 '\\n' em ASCII=%d\n", string[19], string[20]);
  147. }</pre>
  148. </div><!-- class="codigo" -->
  149. <p>
  150. Deve-se notar que em <i>C</i>, ao fazer a leitura de uma "string" (por exemplo, via teclado com <tt><verd>scanf</verd>("%s", &string);</tt>),
  151. automaticamente é inserido o caractere '\0' ao final da "string".
  152. Assim, no exemplo acima ao declarar a "string" com o comando
  153. <tt><verm>char</verm> string = "0123456789abcdefghih";</tt>, essa terá 20 caracteres "úteis" (a última posição "útil" será a posição 19,
  154. com o caractere 'h') e na posição 20 existirá o caractere '\0' (cujo código ASCII é o zero - 0).
  155. </p>
  156. <!-- secao -->
  157. <a name="apontador">
  158. <p class="secao">3. Vetores e apontadores</p>
  159. </a>
  160. <p>
  161. Uma vantagem didática da utilização da linguagem <i>C</i> em um curso introdutório de programação é que
  162. essa é uma linguagem que não esconde muitos detalhes de como os conceitos são implementados.
  163. Isso possibilita mostrarmos os fundamentos da computação, os
  164. princípios elementares que permitem a construção de sistemas mais sofisticados.
  165. Nesse sentido o conceito de vetor é ilustrativo, pois sua implementação depende da existência de apontadores.
  166. </p>
  167. <p>
  168. Ao declarar um vetor, significa que associamos um nome de variável (o "nome do vetor") a uma sequência de
  169. posições de memória, todas de mesmo tipo (logo de mesmo tamanho).
  170. Na verdade essa variável guarda o endereço inicial do vetor, o endereço de seu primeiro elemento.
  171. <center>
  172. <img src="img/int_vet_apontador_menor.png" title="representacao de vetor em memoria com indicacao de endereco ocupado"/>
  173. </center>
  174. </p>
  175. <p><sabermais title="Para quem deseja saber como funciona">
  176. Por exemplo, ao declarar o vetor com <tt><verm>int</verm> v[5];</tt>, são reservadas 5 posições de memória, cada uma com o número de <i>bytes</i>
  177. suficientes para armazenar um dado do tipo <i>int</i> (cada <i>int</i> geralmente ocupa 2 <i>bytes</i> ou 16 <i>bits</i>).
  178. Vamos supor que <i>sizeof(int)</i> devolve o número de <i>bytes</i> ocupados por qualquer número inteiro
  179. (essa função existe precisamente com este sentido na biblioteca <tt>stdlib.h</tt>).
  180. Assim, se o primeiro elemento do vetor está na posição de memória <i>X</i>, então o endereço do segundo será <i>X+sizeof(int)</i> e assim
  181. por diante até o último desses 5 elementos, que estaria na posição <i>X+5*sizeof(int)</i>.
  182. </sabermais></p>
  183. <p>
  184. O nome de um vetor em <i>C</i> é na verdade uma variável
  185. <i><a href="#" onclick="trocaPagina('introducao_apontadores_c.html')" title="ver apontadores em C">apontadora</a></i>
  186. e esse fato retoma a observação de <i>C</i> não esconder detalhes.
  187. Além disso a linguagem permite calculemos a posição de um elemento de vetor somando ao seu endereço inicial o número de elementos que
  188. desejamos pular (e.g. <tt>v+3</tt>).
  189. Fazendo isso, automaticamente o compilador traduz essa expressão deslocando o número de <i>bytes</i> do tipo envolvido
  190. e por isso, fazer <tt>v+3</tt>, é o mesmo que pegar o elemento da posição 3 ou <tt>v[3]</tt>.
  191. </p>
  192. <p>
  193. Como a declaração de uma variável apontadora é feita usando um asterisco (como em <tt><verm>int</verm> *apont;</tt>),
  194. vamos apresentar um código simples que declara um vetor e depois usamos um apontador para mostrar que, com ele,
  195. também podemos "passear" por todos os elementos do vetor.
  196. </p>
  197. <div class="exemplo"><i>Exemplo 3</i>. Construindo um vetor e imprimindo seus elementos via um apontador.
  198. </div><!-- class="exemplo" -->
  199. <div class="codigo">
  200. <pre><incl1>#include</incl1> &lt;stdio.h&gt;
  201. <verm>void</verm> imprimeVetor (<verm>int</verm> *apont, <verm>int</verm> n) {
  202. <verm>int</verm> i;
  203. <verd>printf</verd>("Vetor:"); <cyan>// supondo X ser o primeiro endereco em 'apont'</cyan>
  204. for (i=0; i&lt;n; i++)
  205. <verd>printf</verd>(" %d", *(apont+i)); <cyan>// pegar elemento na posicao 'X + i*sizeof(int) - isso e' o mesmo que apont[i]</cyan>
  206. <verd>printf</verd>("\n");
  207. }
  208. <verm>int</verm> main (<verm>void</verm>) {
  209. <verm>int</verm> vet1[] = { 5, 4, 3, 2, 1 }; <cyan>// define vetor com 5 posicoes de 0 ate' 4</cyan>
  210. <verm>int</verm> *apont;
  211. <verm>int</verm> N = 5;
  212. imprimeVetor(vet1, N); <cyan>// passa para "apont" o endereco inicial do vetor</cyan>
  213. return 0;
  214. }</pre>
  215. </div><!-- class="codigo" -->
  216. <p>
  217. Assim, também é possível alterar os valores em qualquer posição do vetor a partir do endereço.
  218. Por exemplo, se fizermos<br/>
  219. <tt>
  220. &nbsp; <verm>int</verm> vet1[5], i; <cyan>// no lugar de linha 1 da main</cyan><br/>
  221. &nbsp; apont = vet1; <cyan>// ou apont = &vet1; ou apont = &vet1[0];</cyan><br/>
  222. &nbsp; for (i=0; i&lt;5; i++) *(apont+i) = 5-i;</tt><br/>
  223. geraríamos novamente o vetor <tt>vet1 = { 5, 4, 3, 2, 1}</tt>.
  224. Experimente!
  225. </p>
  226. <!-- secao -->
  227. <p class="secao">4. Funções úteis da biblioteca <i>string.h</i></p>
  228. </a>
  229. <p>
  230. A implementação da função <tt>strlen</tt> (que está na biblioteca <tt>string.h</tt>) usa esse fato, a existência de um
  231. caractere especial que só pode ser utilizado em "string" como finalizador para encontrar o tamanho da "string".
  232. Assim, se fizer um comando como <tt>string[10] = '\0'; <verd>printf</verd>("%s\n", string);</tt>, será impresso na tela
  233. <tt>0123456789</tt>.
  234. </p>
  235. <p>
  236. Existem outras funções na biblioteca <tt>string.h</tt>, uma delas é a <tt>strcpy(str1,str2)</tt> que copia o conteúdo da "string"
  237. <i>str2</i> sobre a <i>str1</i>, desde que a declaração delas seja compatível (ou seja, <i>str2</i> não pode ter mais
  238. caracteres do que a declaração inicial de <i>str1</i>).
  239. Outra função bastante útil é a <tt>strcmp</tt> que compara lexicograficamente (ordem dos dicionários) duas "strings",
  240. do seguinte modo, o comando <tt>strcmp(str1, str2)</tt> devolve
  241. <ul>
  242. <li>negativo, se <i>str1</i> menor lexicograficamente que <i>str2</i></li>
  243. <li>zero, se <i>str1</i> igual a <i>str2</i></li>
  244. <li>positivo, se <i>str1</i> maior lexicograficamente que <i>str2</i></li>
  245. </ul>
  246. </p>
  247. <!-- secao -->
  248. <a name="matriz">
  249. <p class="secao">5. Defininido vetor de vetor (ou matriz)</p>
  250. </a>
  251. <p>
  252. Uma vez que um vetor/lista é armazenado consecutivamente na memória, então podemos armazenar
  253. vários vetores também consecutivamente para obter algo que represente (e seja tratado como) uma
  254. <b style="color:#00aa00">matriz</b>.
  255. Como na imagem abaixo, em que cada alocamos <i>nl</i> vetores consecutivos na memória,
  256. cada vetor com <i>nc</i> posições de memória, desde <tt>vet[0]</tt> até <tt>vet[nc-1]</tt>.
  257. Assim, podemos ver este agregado de dados como uma matriz <tt>mat[][]</tt>, cuja primeira linha é
  258. o primeiro vetor e assim por diante. Isso está ilustrado na imagem abaixo.
  259. <center>
  260. <img src="img/int_vet_vet_representacao.png" title="representacao matriz e como fica em memoria como vetor de vetor"/>
  261. </center>
  262. </p>
  263. <p>
  264. Desse modo obtemos uma estrutura com dois índices que pode ser manipulada como uma matriz (como em <i>mat[i][j]</i>).
  265. No exemplo abaixo ilustramos isso de dois modos, imprimindo as linhas da matriz
  266. e mostrando que pode-se passar como parâmetro uma linha de matriz para uma função que
  267. tenha como <i>parâmetro formal</i> um vetor.
  268. </p>
  269. <div class="exemplo"><i>Exemplo 4</i>. Construindo matriz como vetor de vetor e ilustrando que cada linha dela
  270. é um vetor, podendo portanto ser usado para chamar uma função que tem como parâmetro um vetor.
  271. </div><!-- class="exemplo" -->
  272. <div class="codigo">
  273. <pre><incl1>#include</incl1> &lt;stdio.h&gt;
  274. <def>#define</def> MAXL 10 <cyan>// declarar constantes (para ser usada como dimensoes maximas da matriz)</cyan>
  275. <def>#define</def> MAXC 10
  276. <cyan>// Funcao que soma elementos no vetor (precisa do numero de elementos no vetor para saber quando parar)</cyan>
  277. <verm>int</verm> soma_linha (<verm>int</verm> linha[], <verm>int</verm> n) { <cyan>// usando como parametro um vetor (NAO precisa da dimensa, explicacao abaixo)</cyan>
  278. <verm>int</verm> i, soma = 0;
  279. for (i=0; i&lt;n; i++)
  280. soma += linha[i];
  281. return soma;
  282. }
  283. <cyan>// Copiar aqui a funcao do exemplo 1: imprime_vetor1</cyan>
  284. <cyan>// Funcao para imprimir linhas de matriz (linha por linha): usa 'imprime_vetor1(...)' para imprimir uma linha</cyan>
  285. <cyan>// Precisa do numero de colunas pois na pratica os elementos estao em linhas de MAXC elementos</cyan>
  286. <verm>void</verm> imprime_matriz (<verm>int</verm> mat[][MAXC], <verm>int</verm> numLinhas, <verm>int</verm> numColunas) {
  287. <verm>int</verm> i;
  288. for (i=0; i&lt;numLinhas; i++)
  289. imprime_vetor1(mat[i], numColunas); <cyan>// para pegar inicio de 'mat[i]' usa-se o valor de MAX</cyan>
  290. }
  291. <verm>void</verm> main (<verm>void</verm>) {
  292. <verm>int</verm> mat1[MAXL][MAXC]; <cyan>// alocar MAXL*MAXC posicoes para a matriz 'mat1' ('mat1' e' um vetor de vetor)</cyan>
  293. <verm>int</verm> n = 10, i, j, nl, nc, prim, seg;
  294. <cyan>// Vetor de vetor ou matriz</cyan>
  295. nl = 3; nc = 4;
  296. for (i=0; i&lt;nl; i++) <cyan>// foram alocados na memoria MAXL*MAXC</cyan>
  297. for (j=0; j&lt;nc; j++) <cyan>// mas usaremos apenas nl*nc</cyan>
  298. mat1[i][j] = i*nc + j;
  299. <cyan>// Pegando o primeiro e segundo elemento da terceira linha de mat1: mat1[2][1]</cyan>
  300. prim = mat1[2][0]; seg = mat1[2][1]; <cyan>// pegar primeiro e segundo elemento da linha mat1[2]</cyan>
  301. <verd>printf</verd>("O primeiro e segundo elemento da terceira linha da matriz: %d e %d\n", prim, seg);
  302. <cyan>// Imprime a matriz</cyan>
  303. <verd>printf</verd>("\nA matriz: \n"); <cyan>// informe o que vira impresso a seguir (na mesma linha devido ao parametro end=""</cyan>
  304. imprime_matriz(mat1, nl, nc);
  305. <cyan>// Verifique que cada linha da matriz e' de fato um vetor</cyan>
  306. <cyan>// Usar a funcao 'somalinha(...)' que soma elementos em vetor</cyan>
  307. for (i=0; i&lt;nl; i++)
  308. <verd>printf</verd>("Soma da linha %2d = %3d\n", i, soma_linha(mat1[i], nc)); <cyan>// note que cada linha 'mat1[i]' tem 'nc' elementos uteis</cyan>
  309. }
  310. </pre>
  311. </div><!-- class="codigo" -->
  312. <!-- secao -->
  313. <a name="dinamica">
  314. <p class="secao">6. Defininido vetor de vetor (ou matriz) de modo dinâmico.</p>
  315. </a>
  316. <p>
  317. Uma vez que um vetor é armazenado consecutivamente na memória, então podemos armazenar
  318. vetores de modo consecutivo para obter algo que represente (e seja tratado como) <i>matriz</i>.
  319. Neste caso obtemos uma estrutura com dois índices (como em <i>mat[i][j]</i>).
  320. No exemplo abaixo ilustramos isso de dois modos, imprimindo as linhas da matriz
  321. e mostrando que pode-se passar como parâmetro uma linha de matriz para uma função que
  322. tenha como <i>parâmetro formal</i> um vetor.
  323. </p>
  324. <div class="exemplo"><i>Exemplo 5</i>. Construindo matriz como vetor de vetor e ilustrando que cada linha dela
  325. é um vetor, podendo portanto ser usado para chamar uma função que tem como parâmetro um vetor.
  326. </div><!-- class="exemplo" -->
  327. <div class="codigo">
  328. <pre><incl1>#include</incl1> &lt;stdio.h&gt;
  329. <incl1>#include</incl1> &lt;stdlib.h&gt; <cyan>// para 'malloc' e 'free'</cyan>
  330. <def>#define</def> MAXL 10 <cyan>// declarar constantes (para ser usada como dimensoes maximas da matriz)</cyan>
  331. <def>#define</def> MAXC 10
  332. // Copiar aqui a funcao do exemplo 1: imprime_vetor1
  333. // Funcao para imprimir elementos de vetor em uma mesma linha - usando aritmetica de ponteiro
  334. <verm>void</verm> imprime_vetor2 (<verm>int</verm> *pont, <verm>int</verm> tam) {
  335. <verm>int</verm> i;
  336. for (i=0; i&lt;tam; i++) <cyan>// "*(pont+i)" significa, pegar a posicao do primeiro elemento</cyan>
  337. <verd>printf</verd>("%d ", *(pont+i)); <cyan>// (em 'linha') e deslocar i posicoes (do tipo 'int')</cyan>
  338. <verd>printf</verd>("\n"); <cyan>// ao final quebre a linha</cyan>
  339. }
  340. // Funcao que soma elementos no vetor: outra versao tratando o vetor como apontador
  341. <verm>int</verm> soma_linha (<verm>int</verm> *linha, <verm>int</verm> n) { <cyan>// usando como parametro apontador para inteiro</cyan>
  342. <verm>int</verm> i, soma = 0;
  343. <cyan>// Uma vez que um vetor e' na verdade uma sequencia de posicoes de memoria, C</cyan>
  344. <cyan>// simplesmente anota o endereco da primeira posicao no nome do vetor 'linha',</cyan>
  345. <cyan>// por isso e' a mesma coisa que declarar como parametro formal o apontador '<verm>int</verm> *linha'</cyan>
  346. for (i=0; i&lt;n; i++)
  347. soma += *(linha + i);
  348. return soma;
  349. }
  350. // Funcao para imprimir linhas de matriz (linha por linha): usa funcao 'imprime_vetor1(...)'
  351. // Precisa do numero de colunas pois na pratica os elementos estao em linhas de MAXC elementos
  352. <verm>void</verm> imprime_matriz (<verm>int</verm> mat[][MAXC], <verm>int</verm> numLinhas, <verm>int</verm> numColunas) {
  353. <verm>int</verm> i;
  354. for (i=0; i&lt;numLinhas; i++)
  355. imprime_vetor2(mat[i], numColunas); <cyan>// para pegar inicio de 'mat[i]' usa-se o valor de MAX</cyan>
  356. }
  357. <verm>void</verm> main (<verm>void</verm>) {
  358. <verm>int</verm> *vet2; <cyan>// declara um apontador para inteiro que depois apontara' para o vetor dinamico</cyan>
  359. <verm>int</verm> mat1[MAXL][MAXC]; <cyan>// alocar MAX*MAX posicoes para a matriz 'mat1' ('mat1' e' um vetor de vetor)</cyan>
  360. <verm>int</verm> (*apontador)[MAXC]; <cyan>// declara um apontador para linhas com MAXC elementos, se usar apenas '<verm>int</verm> *apontador',</cyan>
  361. <cyan>// '*(apontador[i]+j) = i*nc+j;' poderia resultar advertencia indicada em (1)</cyan>
  362. <verm>int</verm> n = 10, i, j, nl, nc, prim, seg;
  363. <cyan>// Vetor de vetor ou matriz</cyan>
  364. <cyan>// Definir a amtriz de 2 modos (com indices de matriz ou como apontador)</cyan>
  365. nl = 3; nc = 4;
  366. apontador = mat1; <cyan>// pegue o endereco inicial da matriz - (1) se usar "int *apontador", na declaracao</cyan>
  367. <cyan>// acima, poderia resultar advertencia: "warning: assignment from incompatible pointer type"</cyan>
  368. for (i=0; i&lt;nl; i++)
  369. for (j=0; j&lt;nc; j++) <cyan>// ilustra 2 forma de manipular matriz/vetor</cyan>
  370. if (j%2) <cyan>// se j impar => definir com indices</cyan>
  371. mat1[i][j] = i*nc + j;
  372. else <cyan>// se j par => definir com apontador</cyan>
  373. *(apontador[i] + j) = i*nc + j; <cyan>// deslocar i linhas (i*MAXC) e depois deslocar j elementos</cyan>
  374. <cyan>// Pegando o primeiro e segundo elemento da terceira linha de mat1: mat1[2][1]</cyan>
  375. prim = mat1[2][0]; seg = mat1[2][1]; <cyan>// pegar primeiro e segundo elemento da linha mat1[2]</cyan>
  376. <verd>printf</verd>("O primeiro e segundo elemento da terceira linha da matriz: %d e %d\n", prim, seg);
  377. <cyan>// Imprime a matriz</cyan>
  378. <verd>printf</verd>("\nA matriz: \n"); <cyan>// informe o que vira impresso a seguir (na mesma linha devido ao parametro end=""</cyan>
  379. imprime_matriz(mat1, nl, nc);
  380. <cyan>// Verifique que cada linha da matriz e' de fato um vetor</cyan>
  381. <cyan>// Usar a funcao 'somalinha(...)' que soma elementos em vetor</cyan>
  382. for (i=0; i&lt;nl; i++)
  383. <verd>printf</verd>("Soma da linha %2d = %3d\n", i, soma_linha(mat1[i], nc)); <cyan>// note que cada linha 'mat1[i]' tem 'nc' elementos uteis</cyan>
  384. <cyan>// Agora definindo vetor com tamanho dinamico</cyan>
  385. n = 6;
  386. vet2 = malloc(sizeof(int) * n); <cyan>// aloca dinamicamente n posicoes para inteiros ('Memory ALLOCation')</cyan>
  387. <cyan>// Define vetor com n elementos exatamente</cyan>
  388. for (i=0; i&lt;n; i++)
  389. *(vet2+i) = 10 + i;
  390. <cyan>// Imprime o vetor/lista de uma so' vez (na mesma linha)</cyan>
  391. <verd>printf</verd>("\nO vetor definido via alocacao dinamica: ");
  392. imprime_vetor1(vet2, n); <cyan>// em C NAO e' possivel imprimir todos os dados de um vetor => fazer uma funcao...</cyan>
  393. free(vet2); <cyan>// depois de usar pode-se devolver as posicoes para sistema operacional</cyan>
  394. }
  395. </pre>
  396. </div><!-- class="codigo" -->
  397. <p class="autoria">
  398. <a href="https://www.ime.usp.br/~leo" target="_blank" title="seguir para a pagina do prof. Leônidas">Leônidas de Oliveira Brandão</a><br/>
  399. <a href="http://www.ime.usp.br/~leo" target="_blank" title="seguir para a página do LInE">http://line.ime.usp.br</a>
  400. </p>
  401. <p class="rodape">
  402. <b>Alterações</b>:<br/>
  403. 2020/10/20: pequenos acertos léxicos e na introdução da seção 3 (ajuda da Priscila Lima), acerto em comentário no código "Exemplo 2" (ajuda do Felipe C. Lourenço)<br/>
  404. <!-- Exemplo 2: eliminado 'ord(.)' -->
  405. 2020/08/13: novo formato, pequenas revisões<br/>
  406. domingo, 17 May 2020, 18:30<br/>
  407. segunda, 03 May 2018, 16:00
  408. </p>
  409. </div>