Пара замечаний по кодированию.Не используйте жестко закодированные имена файлов или числа (называемые «магическими числами» ), например,
fp = fopen("mountainList.txt", "r");
...
if(p != 32)
. Они затрудняют чтение вашего кода и, что более важно, затрудняют его поддержку, поскольку длинаваших программ растут.Вместо этого передайте ваше имя файла вашей программе в качестве аргумента или прочитайте имя файла из вашего кода.Вместо использования магического числа 32
используйте символьный литерал ' '
, чтобы было понятно, что пробел предназначен.
Если вам нужна числовая константа или строкаконстанта, #define
их в начале вашего кода.Это обеспечивает единственное удобное расположение для внесения одного изменения, если в дальнейшем понадобятся изменения.
Хотя в использовании getc
(fgetc
) нет ничего плохого, рассмотрите возможность использования строчно-ориентированного функция ввода для чтения строки ввода за один раз, например fgets()
или POSIX getline()
.Затем вы можете использовать строковые функции, которые могут автоматически сообщать о количестве пробельных символов, которые должны быть удалены.
В качестве альтернативы проверке каждого символа и сохранению индекса или продвижению указателя, вы можете сделать один вызовstrspn
предоставляя буфер, содержащий вашу строку, а затем строку, определяющую пробельные символы, которые необходимо учитывать, и он вернет начальное количество символов в вашей строке, состоящее полностью из пробелов.
Например, следующееимя файла для чтения в качестве первого аргумента программы (или чтение из stdin
по умолчанию, если имя файла не задано), а затем после проверки файл открыт для чтения, читает строку-на-a-time, передавая строку strspn
вместе со строкой, содержащей пробельные символы " \t"
(пробел, табуляция).Возвращаемое значение strspn
- это начальное количество символов, состоящее полностью из символов в строке пробела, которое вы затем можете использовать в качестве смещения (или индекса) для печати вашей строки, пропуская начальный пробел, например,
#include <stdio.h>
#include <string.h>
#define MAXC 1024 /* if you need a constant, #define one (or more) */
#define WS " \t" /* leading whitespace characters to remove */
int main (int argc, char **argv) {
char line[MAXC]; /* buffer to hold line (don't skimp on buffer size) */
/* use filename provided as 1st argument (stdin by default) */
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* validate file open for reading */
perror ("file open failed");
return 1;
}
while (fgets (line, MAXC, fp)) /* read each line */
printf ("%s", &line[strspn (line, WS)]); /* output w/o leading ws */
if (fp != stdin) fclose (fp); /* close file if not stdin */
return 0;
}
Или, если вы предпочитаете печать с использованием указателя и смещения, вы можете заменить вызов на printf
на:
printf ("%s", line + strspn (line, WS)); /* output w/o leading ws */
( note: , если вы хотите удалитьстрок, содержащих все пробелы, проверьте наличие конца строки при смещении, возвращаемом strspn
и просто пропустите печать строки)
Использование вашего примера ввода приведет к следующему:
$ /bin/removews <dat/wslines.txt
this is a test file
this is a file of text
text is in this file
Как упоминалось в начале, нет ничего плохого в подходе для чтения файла с getc
, но знайте другой вариант подходе , ориентированном на строкичтение всей строки в буфер может затем сделать функции из string.h
доступными для использования в самом буфере.
Посмотрите вещи и дайте мне знать, если у вас есть дальнейшиевопросы.