Eu quero imprimir o conteúdo de um vetor em C ++, aqui está o que eu tenho:
#include <iostream>
#include <fstream>
#include <string>
#include <cmath>
#include <vector>
#include <sstream>
#include <cstdio>
using namespace std;
int main()
{
ifstream file("maze.txt");
if (file) {
vector<char> vec(istreambuf_iterator<char>(file), (istreambuf_iterator<char>()));
vector<char> path;
int x = 17;
char entrance = vec.at(16);
char firstsquare = vec.at(x);
if (entrance == 'S') {
path.push_back(entrance);
}
for (x = 17; isalpha(firstsquare); x++) {
path.push_back(firstsquare);
}
for (int i = 0; i < path.size(); i++) {
cout << path[i] << " ";
}
cout << endl;
return 0;
}
}
Como imprimo o conteúdo do vetor na tela?
Respostas:
Para responder sua pergunta, você pode usar um iterador:
Se você deseja modificar o conteúdo do vetor no loop for, use em
iterator
vez deconst_iterator
.Mas há muito mais a ser dito sobre isso. Se você quer apenas uma resposta que possa usar, pode parar por aqui; caso contrário, continue a ler.
auto (C ++ 11) / typedef
Esta não é outra solução, mas um complemento para a
iterator
solução acima . Se você estiver usando o padrão C ++ 11 (ou posterior), poderá usar aauto
palavra-chave para ajudar na legibilidade:Mas o tipo de
i
será não-const (ou seja, o compilador usarástd::vector<char>::iterator
como o tipo dei
).Nesse caso, você também pode usar um
typedef
(não restrito ao C ++ 11 e muito útil para usar):contador
Obviamente, você pode usar um tipo inteiro para registrar sua posição no
for
loop:Se você fizer isso, é melhor usar os tipos de membros do contêiner, se estiverem disponíveis e adequados.
std::vector
possui um tipo de membro chamadosize_type
para este trabalho: é o tipo retornado pelosize
métodoPor que não usar isso sobre a
iterator
solução? Em casos simples, você pode também, mas o ponto é que aiterator
classe é um objeto projetado para fazer esse trabalho em objetos mais complicados, onde essa solução não será ideal.loop for baseado em intervalo (C ++ 11)
Veja a solução de Jefffrey . No C ++ 11 (e posterior), você pode usar o novo
for
loop baseado em intervalo , que se parece com isso:Como
path
é um vetor de itens (explicitamentestd::vector<char>
), o objetoi
é do tipo do item do vetor (ou seja, explicitamente, é do tipochar
). O objetoi
tem um valor que é uma cópia do item real nopath
objeto. Portanto, todas as alteraçõesi
no loop não são preservadas porpath
si só. Além disso, se você deseja reforçar o fato de que não deseja alterar o valor copiadoi
no loop, pode forçar o tipoi
a serconst char
assim:Se você deseja modificar os itens
path
, pode usar uma referência:e mesmo se você não quiser modificar
path
, se a cópia de objetos for cara, use uma referência const em vez de copiar por valor:std :: copy
Veja a resposta de Josué . Você pode usar o algoritmo STL
std::copy
para copiar o conteúdo do vetor no fluxo de saída. Esta é uma solução elegante se você se sentir confortável com ela (e, além disso, é muito útil, não apenas no caso de imprimir o conteúdo de um vetor).std :: for_each
Veja a solução de Max . O uso
std::for_each
é um exagero neste cenário simples, mas é uma solução muito útil se você deseja fazer mais do que apenas imprimir na tela: o usostd::for_each
permite fazer qualquer operação (sensível) no conteúdo do vetor.sobrecarga ostream :: operator <<
Veja a resposta de Chris , isso é mais um complemento para as outras respostas, pois você ainda precisará implementar uma das soluções acima na sobrecarga. Em seu exemplo, ele usou um contador em um
for
loop. Por exemplo, é assim que você pode usar rapidamente a solução de Joshua :O uso de qualquer uma das outras soluções deve ser direto.
conclusão
Qualquer uma das soluções apresentadas aqui funcionará. Depende de você e do código em qual é o "melhor". Qualquer coisa mais detalhada do que isso é provavelmente deixada para outra pergunta em que os prós / contras possam ser avaliados adequadamente; mas, como sempre, a preferência do usuário sempre desempenhará um papel: nenhuma das soluções apresentadas está errada, mas algumas parecerão mais agradáveis para cada codificador individual.
termo aditivo
Esta é uma solução expandida de uma anterior que eu publiquei. Como esse post continuava recebendo atenção, decidi expandi-lo e me referir às outras excelentes soluções que foram publicadas aqui. Meu post original teve uma observação que mencionou que se você foram a intenção de modificar o seu vector dentro de um
for
circuito, em seguida, existem dois métodos fornecidos pelastd::vector
a elementos de acesso:std::vector::operator[]
o que não fazer verificação de limites, estd::vector::at
que faz executar verificação de limites. Em outras palavras,at
será lançado se você tentar acessar um elemento fora do vetor eoperator[]
não o faria. Apenas adicionei esse comentário, originalmente, para mencionar algo que talvez seja útil saber se alguém já não o fez. E não vejo diferença agora. Daí este adendo.fonte
0
meiovector::size()
e o vetor não for modificado dentro do loop, não há necessidade de usarat()
e incorrer nos limites adicionais de verificação de sobrecarga. Dito isto, eu iria com um iterador, como você sugere.at
se nada no loop modifica o vetor, mas pensei em mencioná-lo apenas no caso de o vetor ser modificado no loop (não recomendado como isso pode ser) e porque nunca recebe um mencionar e pode ser útil, pelo menos, conhecê-lo.for (auto const &i: path) std::cout << i << ' ';
Uma maneira muito mais fácil de fazer isso é com o algoritmo de cópia padrão :
O ostream_iterator é o que chamamos de adaptador iterador . Ele é modelado sobre o tipo para imprimir no fluxo (neste caso,
char
).cout
(também conhecido como saída do console) é o fluxo no qual queremos gravar e o caractere de espaço (" "
) é o que queremos imprimir entre cada elemento armazenado no vetor.Esse algoritmo padrão é poderoso e muitos outros. O poder e a flexibilidade que a biblioteca padrão oferece são o que a torna tão excelente. Imagine: você pode imprimir um vetor no console com apenas uma linha de código. Você não precisa lidar com casos especiais com o caractere separador. Você não precisa se preocupar com loops. A biblioteca padrão faz tudo por você.
fonte
vector<pair<int, struct node>>
. Como uso o método acima para imprimir esse vetor?operator<<
função para o seu par específico <>.No C ++ 11, agora você pode usar um loop for baseado em intervalo :
fonte
char
s, é provável que a passagem por referência constante seja realmente mais cara do que por valor. Mas aqui estamos falando de super otimizações micro.Eu acho que a melhor maneira de fazer isso é sobrecarregar
operator<<
adicionando esta função ao seu programa:Então você pode usar o
<<
operador em qualquer vetor possível, assumindo que seus elementos também tenhamostream& operator<<
definido:Saídas:
fonte
last
parasize_t
.size_t last = v.size() - 1;
parece redundante, você pode usar aif (i) out << ", ";
condição antes doout << v[i];
linkoperator<<
. Exemploif (i != last)
cada vez no loop? Em vez disso, se o contêiner não estiver vazio, (a) envie o primeiro elemento e, em seguida, (b) envie os elementos restantes em loop , imprimindo primeiro o separador (como prefixo). Nenhum teste de loop interno (além da própria condição do loop) é necessário. Apenas um teste fora de loop é necessário.Que tal
for_each
expressão + lambda :Obviamente, uma solução baseada em faixa é a solução mais elegante para essa tarefa concreta, mas essa também oferece muitas outras possibilidades.
Explicação
O
for_each
algoritmo pega um intervalo de entrada e um objeto que pode ser chamado, chamando esse objeto em todos os elementos do intervalo. Um intervalo de entrada é definido por dois iteradores . Um objeto que pode ser chamado pode ser uma função, um ponteiro para funcionar, um objeto de uma classe que sobrecarrega() operator
ou, nesse caso, uma expressão lambda . O parâmetro para esta expressão corresponde ao tipo dos elementos do vetor.A beleza dessa implementação é o poder que você obtém das expressões lambda - você pode usar essa abordagem para muito mais coisas do que apenas imprimir o vetor.
fonte
Basta copiar o contêiner para o console.
Saída deve:
fonte
O problema é provavelmente no circuito anterior:
(x = 17; isalpha(firstsquare); x++)
. Esse loop não será executado (sefirstsquare
não for alfa) ou será executado para sempre (se for alfa). O motivo é quefirstsquare
não muda conformex
é incrementado.fonte
No C ++ 11, um loop for baseado em intervalo pode ser uma boa solução:
Resultado:
fonte
Usando
std::copy
mas sem separador de arrasto extraUma abordagem alternativa / modificada usando
std::copy
(como originalmente usado na resposta @JoshuaKravtiz ), mas sem incluir um separador de arrasto adicional após o último elemento:Exemplo de uso aplicado ao contêiner de um tipo POD personalizado:
fonte
Eu vejo dois problemas. Como apontado em,
for (x = 17; isalpha(firstsquare); x++)
existe um loop infinito ou nunca é executado, e tambémif (entrance == 'S')
se o caractere de entrada for diferente de 'S', nada será empurrado para o vetor de caminho, deixando-o vazio e imprimindo nada na tela. Você pode testar a última verificaçãopath.empty()
ou impressãopath.size()
.De qualquer maneira, não seria melhor usar uma string em vez de um vetor? Você também pode acessar o conteúdo da string como uma matriz, buscar caracteres, extrair substrings e imprimir a string facilmente (sem um loop).
Fazer tudo com strings pode ser a maneira de escrever de uma maneira menos complicada e mais fácil de identificar o problema.
fonte
operador de sobrecarga <<:
Uso:
fonte
Esta resposta é baseada na resposta de Zorawar, mas não pude deixar um comentário lá.
Você pode criar a versão auto (C ++ 11) / typedef const usando cbegin e cend
fonte
Em C ++ 11 ''
fonte
fonte
Isso funcionou para mim:
fonte
Para aqueles que estão interessados: eu escrevi uma solução generalizada que tira o melhor dos dois mundos, é mais generalizada para qualquer tipo de intervalo e coloca aspas em torno de tipos não aritméticos (desejados para tipos semelhantes a cordas). Além disso, essa abordagem não deve ter problemas de ADL e também evitar 'surpresas' (uma vez que é adicionada explicitamente caso a caso):
Agora é bastante fácil de usar em qualquer faixa:
A verificação semelhante a uma corda deixa espaço para melhorias. Também tenho
static_assert
check-in na minha solução para evitarstd::basic_string<>
, mas deixei-o aqui por simplicidade.fonte
Você pode escrever sua própria função:
fonte
Para pessoas que desejam one-liners sem loops:
Não acredito que ninguém tenha pensado nisso, mas talvez seja por causa da abordagem mais parecida com o C. De qualquer forma, é perfeitamente seguro fazer isso sem um loop, em uma linha, ASSUMINDO que o terminal
std::vector<char>
é nulo:Mas eu colocaria isso no
ostream
operador, como sugeriu @Zorawar, apenas para garantir:Podemos obter um comportamento semelhante usando
printf
:NOTA:
O
ostream
operador sobrecarregado precisa aceitar o vetor como não const. Isso pode tornar o programa inseguro ou introduzir código incorreto. Além disso, como o caractere nulo é anexado, uma realocação dostd::vector
pode ocorrer. Portanto, o uso de loops for iteradores provavelmente será mais rápido.fonte
fprintf(stdout, "%s\n", &test[0]);
não é diferente destd::cout << test.data()
, ambos requerem um vetor terminado em nulo. 2. "Mas eu colocaria isso no operador ostream"<<
operador que modifica o operando certo é uma péssima idéia.fprintf(stdout, "%s\n", &test[0]);
há muito tempo no código sem que isso me cause problemas. Interessante! E eu concordo que não é tão bom modificar o vetor noostream
operador, mas não gosto de fazer loop manualmente e usar iteradores. De alguma forma, acho que para operações simples, como imprimir umastd::vector<char>
biblioteca padrão, deve esconder essas coisas. Mas o C ++ está se desenvolvendo constantemente, pode vir em breve.