Pergunta

Eu estou escrevendo um programa que é suposto para ler duas cordas que podem conter quebras de linha e outros caracteres. Portanto, eu estou usando EOF (Ctrl-Z ou Ctrl-D) para terminar a string.

Esta multa trabalha com a primeira variável, mas com a segunda variável, no entanto, este parece ser problemático, pois, aparentemente, algo está preso no buffer de entrada eo usuário não consegue digitar nada.

Eu tentei limpar o buffer com while (getchar() != '\n'); e diversas variações semelhantes, mas nada parece ajudar. Todas as tentativas de limpeza resultaram em um loop infinito, e sem limpeza, adicionando a segunda variável é impossível.

Os caracteres para ambas as variáveis ??são lidas em um loop como este: while((c = getchar()) != EOF), o que sugere que é EOF que tenho preso na minha memória intermédia. Ou que afecta o comportamento do programa de alguma outra forma? Existe errado alguma coisa com a lógica que estou usando?

Eu estou começando a ficar pouco desesperado depois de lutar com isso por horas.

[edit: adicionado código abaixo]

[edit 2:. Clearerr () parece fazer este trabalho solução EOF afinal

Parece funcionar na sua forma original, como eu pretendia no Linux, eu estava tentando lo com o Windows ontem.]

código:

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

int main(void)
{
    int x = 0;
    int c;
    char a[100];
    char b[100];

    printf("Enter a: ");
    while((c = getchar()) != EOF)
    {
        a[x] = c;
        x++;
    }
    a[x] = '\0';
    x = 0;

    /*while (getchar() != '\n'); - the non-working loop*/

    printf("\nEnter b: ");
    while((c = getchar()) != EOF)
    {
        b[x] = c;
        x++;
    }
    b[x] = '\0';

    printf("\n\nResults:\na: %s\n", a);
    printf("b: %s\n", b);

    return(0);
}

[editar 3:]

problema de memória dinâmica:

O meu programa também é suposto cordas punho mais de 100 caracteres. Originalmente eu pretendia resolver isso por alocação dinâmica de memória, mas quando eu tive problemas com o loop infinito descrito acima e memória relacionada com acidentes Deixei-o e mudou para char [100].

Eu acho que o que eu tentei era geralmente algo como isto:

while((c = getchar()) != EOF)
{
  a = malloc(sizeof(char));
  a[x] = c;
  x++;
}

Isso é uma maneira possível (ou sensível) para fazer isso? Eu estou tentando alocar mais memória para cada personagem que está sendo tratado lá. Individualmente. Com código assim (este exemplo contém erros de sintaxe provavelmente) eu experimentei acidentes, por isso, parece-me malloc pode não ser a função aqui, ou eu estou tentando errado. Supondo que é mesmo possível.

Foi útil?

Solução

Depois de recebido um EOF do terminal, você não receberá quaisquer dados adicionais . Não há nenhuma maneira de un-EOF-ing a entrada -. O final do arquivo é, assim, o fim

Portanto, você deve definir que cada variável é de entrada em uma linha separada, e têm o usuário pressionar Enter em vez de EOF. Você ainda precisa verificar se recebeu eof, porque isso significa que o usuário realmente digitadas EOF, e você não vai ver qualquer outra coisa - neste caso, você precisa sair do loop e imprimir uma mensagem de erro

Outras dicas

EOF não é um personagem - é um valor especial que as funções de entrada voltar para indicar um condição , que o "fim de arquivo" na esse fluxo de entrada tem foi atingido. Como Martin v. Löwis diz, uma vez que a condição de "fim de arquivo" ocorre, significa que não mais entrada estará disponível na esse fluxo.

A confusão surge porque:

  • Muitos tipos de terminais reconhecer uma tecla especial para sinalizar "final de ficheiro", quando o "ficheiro" é um terminal interactivo (Ctrl-Z por exemplo, ou Ctrl-D.); e
  • O valor EOF é um dos valores que podem ser retornados pela família getchar() de funções.

Você vai precisar usar um valor de caráter real para separar as entradas - o '\0' caracteres ASCII nul pode ser uma boa escolha, se isso não pode aparecer como um valor válido dentro das próprias entradas

.

executar o código na minha caixa de linux, aqui está o resultado:

Enter a: qwer
asdf<Ctrl-D><Ctrl-D>
Enter b: 123
456<Ctrl-D><Ctrl-D>

Results:
a: qwer
asdf
b: 123
456

Dois Ctrl-D foi necessária porque o tampão terminal de entrada não estava vazio.

Você pode usar o caractere nulo ('\0') para separar as variáveis. Várias ferramentas UNIX (por exemplo find) são capazes de separar seus itens de produção, desta forma, o que sugere que é um método bastante normal.

Outra vantagem disso é que você pode ler o fluxo em um único buffer e, em seguida, criar uma matriz de char*s para apontar para as cordas individuais, e cada corda será corretamente '\0' terminada sem que você tenha de mudar nada no buffer manualmente. Isso significa menos alocação de memória sobrecarga, o que pode tornar o programa executado visivelmente mais rápido, dependendo de quantas variáveis ??que você está lendo. Claro, isso só é necessário se você precisa para realizar todas as variáveis ??na memória, ao mesmo tempo -. Se você está lidando com eles um-em-um-tempo, você não obter esta vantagem particular

O que você está tentando é fundamentalmente impossível com EOF.

Embora ele se comporta como um em algumas maneiras, EOF não é um personagem no fluxo, mas uma macro definida pelo ambiente que representa o final do fluxo. Eu não vi o seu código, mas eu reunir você está fazendo é algo como isto:

while ((c=getchar()) != EOF) {
    // do something
}
while ((c=getchar()) != EOF) {
    // do something else
}

Quando você digitar o caractere EOF pela primeira vez, para terminar a primeira corda, o fluxo é irrevogavelmente fechado. Ou seja, o status do fluxo é que ele está fechada.

Assim, o conteúdo do segundo circuito, enquanto são nunca ficar.

Em vez de parar a entrada de leitura em EOF - que não é um personagem -. Parada em ENTER

while((c = getchar()) != '\n')
{
    if (c == EOF) /* oops, something wrong, input terminated too soon! */;
    a[x] = c;
    x++;
}

EOF é um sinal de que a entrada terminada. Você está quase garantido que todas as entradas do usuário final com '\ n': essa é a última tecla que o usuário digita !!!


Edit:. Você ainda pode usar Ctrl-D e clearerr() para repor o fluxo de entrada

#include <stdio.h>

int main(void) {
  char a[100], b[100];
  int c, k;

  printf("Enter a: "); fflush(stdout);
  k = 0;
  while ((k < 100) && ((c = getchar()) != EOF)) {
    a[k++] = c;
  }
  a[k] = 0;

  clearerr(stdin);

  printf("Enter b: "); fflush(stdout);
  k = 0;
  while ((k < 100) && ((c = getchar()) != EOF)) {
    b[k++] = c;
  }
  b[k] = 0;

  printf("a is [%s]; b is [%s]\n", a, b);
  return 0;
}
$ ./a.out
Enter a: two
lines (Ctrl+D right after the next ENTER)
Enter b: three
lines
now (ENTER + Ctrl+D)
a is [two
lines (Ctrl+D right after the next ENTER)
]; b is [three
lines
now (ENTER + Ctrl+D)
]
$

Como você entrar nulo no programa?

Você pode implementar a função -print0 usando:

putchar(0);

Isto irá imprimir um ASCII caráter nul '\ 0' para sdtout.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top