Я подозреваю, что проблема связана с этим:
Я работаю в C над окнами и выполняю команды в подсистеме Ubuntu.
Предположительно, вы создалифайл mapper.txt
, использующий инструменты Windows, поэтому у него есть окончания строки Windows. Тем не менее, я думаю, что подсистема Ubuntu не знает об окончаниях строк Windows, и поэтому, даже если вы открываете файл в режиме 'r'
, он не переводит CR-LF в один \n
. Когда вы затем удаляете \n
в конце ввода, вы все равно оставляете \r
.
, который \r
не будет виден при печати строки, поскольку все, что он делает, этопереместите курсор в начало строки, и следующий символьный вывод будет \n
. Обычно хорошей идеей является окружение строк другим текстом при печати отладочных сообщений, поскольку это может дать вам представление о такой проблеме. Если бы вы использовали:
printf("Failed to open file path: '%s'\n", txt_path);
, возможно, вы видели ошибку:
'ailed to open filepath: '/mnt/c/users/adam/documents/csci_4061/projects/blackbeards/testtext.txt
Здесь намек на то, что в конце строки есть \r
, этоперезапись первого символа сообщения завершающим апострофом.
Не совсем точно сказать, что fgets
"добавляет \n
символ в конец [прочитанной строки]". Точнее сказать, что этот символ не удаляется, если он присутствует. Вполне возможно, что в конце строки нет новой строки. Например, строка может быть последней строкой в текстовом файле, которая не заканчивается символом новой строки. Или fgets
мог быть прерван из-за достигнутого вами ограничения на количество символов, а не из-за поиска символа новой строки.
Так что вам, безусловно, лучше использовать интерфейс getline
, который имеет два преимущества: (а) он выделяет память для самой строки, поэтому вам не нужно заранее угадывать максимальную длину, и (б) он точно сообщает вам, сколько символов он прочитал, поэтому вам не нужно считать их.
Используя эту информацию, вы можете затем удалить \n
, который находится в конце строки, если он есть, и затем удалить предшествующий \r
, если он есть:
char* line = NULL;
size_t n_line = 0;
for (;;) {
ssize_t n_read = getline(&line, &n_line, mapper_fp);
if (n_read < 0) break; /* EOF or some kind of read error */
if (n_read > 0 && line[n_read - 1] == '\n')
line[nread--] = 0;
if (n_read > 0 && line[n_read - 1] == '\r')
line[nread--] = 0;
if (nread == 0) continue; /* blank line */
/* Handle the line read */
}
if (ferr(mapper_fp))
perror("Error reading mapper file");
free(line);