C
Minha tarefa de casa é pegar uma corda e dividi-la em pedaços a cada nova linha. Eu não tenho ideia do que fazer! Por favor ajude!
Problema complicado para uma classe de programação C inicial! Primeiro você precisa entender algumas noções básicas sobre esse assunto complicado.
Uma sequência é uma sequência composta apenas de caracteres . Isso significa que, para que os programadores indiquem uma coisa "invisível" (que não é um espaço, que conta como um personagem), é necessário usar uma sequência especial de caracteres de alguma forma para significar essa coisa invisível.
No Windows , a nova linha é uma sequência de dois caracteres na sequência: barra invertida n (ou a sequência "\n"
)
Nos Macs Linux ou OS / X , é uma sequência de quatro caracteres: barra invertida, n, barra invertida e, em seguida, r: (ou "\n\r"
).
(Nota histórica interessante: em Macintoshes mais antigos, havia uma sequência diferente de quatro caracteres: "\ r \ n" ... totalmente ao contrário de como o Unix fazia as coisas! A história toma caminhos estranhos.)
Pode parecer que o Linux é mais inútil que o Windows, mas na verdade é uma idéia melhor usar uma sequência mais longa. Como o Windows usa uma sequência tão curta, o tempo de execução do idioma C não pode imprimir as letras reais \n
sem usar chamadas especiais do sistema. Geralmente, você pode fazer isso no Linux sem uma chamada do sistema (pode até imprimir \n\
ou \n\q
... qualquer coisa, menos \n\r
). Porém, como C é uma plataforma cruzada, ele aplica o menor denominador comum. Então você sempre estará vendo \n
em seu livro.
(Nota: se você está se perguntando como estamos falando \n
sem obter novas linhas sempre que o fizermos, o StackOverflow é escrito quase inteiramente em HTML ... não em C. Portanto, é muito mais moderno. Muitos desses aspectos antigos de C são sendo abordado por coisas que você já deve ter ouvido falar, como CLANG e LLVM.)
Mas voltando ao que estamos trabalhando. Vamos imaginar uma string com três peças e duas novas linhas, como:
"foo\nbaz\nbar"
Você pode ver que o comprimento dessa string é 3 + 2 + 3 + 2 + 3 = 13. Portanto, é necessário fazer um buffer de tamanho 13 para isso, e os programadores C sempre adicionam um ao tamanho de suas matrizes para garantir a segurança. Portanto, faça seu buffer e copie a string para ele:
/* REMEMBER: always add one to your array sizes in C, for safety! */
char buffer[14];
strcpy(buffer, "foo\nbaz\nbar");
Agora, o que você precisa fazer é procurar o padrão de dois caracteres que representa a nova linha. Você não pode procurar apenas uma barra invertida. Como o C é usado bastante para a divisão de cadeias de caracteres, ocorrerá um erro se você tentar. Você pode ver isso se tentar escrever:
char pattern[2];
strcpy(pattern, "\");
(Nota: existe uma configuração no compilador para se você estiver escrevendo um programa que apenas procure barras invertidas. Mas isso é extremamente incomum; as barras invertidas são muito raramente usadas, e é por isso que foram escolhidas para esse fim. Não vamos mudar isso ligar.)
Então, vamos fazer o padrão que realmente queremos, assim:
char pattern[3];
strcpy(pattern, "\n");
Quando queremos comparar duas strings de um certo comprimento, usamos strncmp
. Ele compara um certo número de caracteres de uma sequência potencialmente maior e informa se eles correspondem ou não. Então strncmp("\nA", "\nB", 2)
retorna 1 (verdadeiro). Isso ocorre mesmo que as strings não sejam inteiramente iguais ao longo de três ... mas porque apenas dois caracteres são necessários.
Então, vamos percorrer nosso buffer, um caractere de cada vez, procurando a correspondência de dois caracteres com o nosso padrão. Sempre que encontrarmos uma sequência de dois caracteres de uma barra invertida seguida por um n, usaremos a chamada de sistema muito especial (ou "syscall") putc
para colocar um tipo especial de caractere: código ASCII 10 , para obter uma nova linha física .
#include "stdio.h"
#include "string.h"
char buffer[14]; /* actual length 13 */
char pattern[3]; /* actual length 2 */
int i = 0;
int main(int argc, char* argv[]) {
strcpy(buffer, "foo\nbar\nbaz");
strcpy(pattern, "\n");
while (i < strlen(buffer)) {
if (1 == strncmp(buffer + i, pattern, 2)) {
/* We matched a backslash char followed by n */
/* Use syscall for output ASCII 10 */
putc(10, stdout);
/* bump index by 2 to skip both backslash and n */
i += 2;
} else {
/* This position didn't match the pattern for a newline */
/* Print character with printf */
printf("%c", buffer[i]);
/* bump index by 1 to go to next matchable position */
i += 1;
}
}
/* final newline and return 1 for success! */
putc(10, stdout);
return 1;
}
A saída deste programa é o resultado desejado ... a string dividida!
foo
baz
bar
\t
é para \ trolling ...
Absolutamente incorreto de cima para baixo. No entanto, cheio de bobagens plausíveis que embaralharam informações como o que está no livro ou na Wikipedia. A lógica do programa parece transparente no contexto das informações erradas, mas é completamente enganosa. Mesmo variáveis globais e retornando um código de erro, para uma boa medida ...
...
Obviamente, há apenas um caractere na representação da sequência C da sequência literal da fonte de dois caracteres \n
. Mas aumentar um buffer é inofensivo, desde que strlen()
seja usado para obter o comprimento real para operar.
...
Tentamos convencer o leitor de que strncmp
é uma operação booleana que corresponde (1) ou não (0). Mas, na verdade, ele tem três valores de retorno (-1 correspondendo menos, 0 para igual, 1 para correspondendo maior) . Nosso "padrão" de dois caracteres sendo comparado não é [ \
, n
], mas sim [ \n
, \0
] ... captando o terminador nulo implícito. Como essa sequência desliza pela sequência, nunca será maior que uma sequência de dois caracteres com a qual é comparada ... na melhor das hipóteses, será zero se houver uma nova linha final na sequência de entrada.
...
Então, tudo isso faz um loop pela string e imprime um caractere de cada vez. O ramo superior nunca é executado. (Embora você possa fazer isso se sua string tiver \n
códigos inferiores a ele, diga tab ... que pode ser usado para omitir misteriosamente caracteres da saída :-P)