Суть в том, что вы не можете выделить достаточно места для buffer
и, скорее всего, вызовете Неопределенное поведение , когда вы попытаетесь сохранить больше символов, чем у вас есть места в buffer
. Вы дополнительно вызываете Неопределенное поведение , когда вы пытаетесь на write
больше символов до stdout
, чем у вас есть символы для (у вас на счету не по одному (или больше) символов в строковых литералах, поскольку "\n"
- это один символ ( символ новой строки , ASCII 10
или 0xa
), а не несколько символов '\'
и 'n'
.
К сожалению, это только верхушка айсберга. Во-первых, как пара замечаний, избегайте жесткого кодирования Magi c -Numbers в вашем коде (10
является Magi c -Номер ) и избегать жесткого кодирования имен файлов). Если вам нужно изменить число, например 10
, потому что вы хотите 11
целых чисел, посмотрите, сколько изменений необходимо. Если вы хотите записать в другой файл, вы должны пересобрать свой код. Вместо этого:
#define NINT 10 /* if you need a constant, #define one (or more) */
#define INTCHARS 32 /* adequate for LLONG_MIN or ULLONG_MAX (20+1 chars) */
#define FCRMODE S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH
Теперь у вас есть единственное место для изменения константы в верхней части кода, если вам нужно внести изменения.
Для вашего имени файла вы можете указать значение по умолчанию , но ваша программа принимает аргумент для main
, когда он объявлен как:
int main (int argc, char **argv) {
Передайте имя файла в качестве аргумента вашей программе или используйте жестко закодированное имя файла только по умолчанию. Пример:
char *filename = argc > 1 ? argv[1] : "/home/privateinfo/5/output";
Если указан аргумент, он используется в качестве имени файла, в противном случае используется значение по умолчанию.
В вашем выделении:
char *buffer = malloc(sizeof(int));
Вы выделяете только 4 байта для buffer
, что означает, что вы можете хранить максимум 3 цифры и символ с нулевым окончанием , или, так как вы также включаете символ '\n'
, вы больше не можете хранить чем 2-ди git число. Вместо этого нет причин выделять для буфера. Самый длинный long long int
или unsigned long long
на 64-разрядном компьютере составляет 20 символов (включая знак '-'
минус) +1
для завершающего нуль символа , всего 21 символ необходимо. Просто определите 32-байтовый буфер, и вы можете включить свой '\n'
с 10 символами безопасности, например,
char buffer[INTCHARS] = "";
Далее, не считайте символы для write
. Если вы печатаете String-Literals , простое использование strlen()
даст вам правильное количество символов для вывода. Или, если вам нужно создать строку для записи с sprintf
, , сохраните возвращаемую , она сообщит вам, сколько символов было записано в буфер (не включая nul определяющий символ), например
/* read NINT integers from keyboard and store in array*/
nchar = sprintf (buffer, "Enter %d integers:\n", NINT);
write (STDOUT_FILENO, buffer, nchar); /* (or simply use printf) */
(почему вы используете write
- загадка, когда вы можете просто printf
строку с преобразованием непосредственно в stdout
)
Не возвращать отрицательные значения в оболочку. POSIX требует, чтобы возвращались только положительные значения. Вот почему макрос EXIT_FAILURE
определяется как 1
.
Остальные остатки ошибок являются лишь дополнительным включением того, что обсуждалось выше. В целом, вы можете сделать:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#define NINT 10 /* if you need a constant, #define one (or more) */
#define INTCHARS 32 /* adequate for LLONG_MIN or ULLONG_MAX (20+1 chars) */
#define FCRMODE S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH
int main (int argc, char **argv) {
int fd, i, input, nchar, *tenInts;
char *filename = argc > 1 ? argv[1] : "/home/privateinfo/5/output";
char buffer[INTCHARS] = "";
if (!(tenInts = malloc (NINT * sizeof *tenInts))) {
perror ("malloc-tenInts");
return 1;
}
/* open the file for writing */
if ((fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT, FCRMODE)) < 0) {
perror ("fopen-filename");
return 1;
}
/* read NINT integers from keyboard and store in array*/
nchar = sprintf (buffer, "Enter %d integers:\n", NINT);
write (STDOUT_FILENO, buffer, nchar); /* (or simply use printf) */
for (i = 0; i < NINT; i++) {
if (scanf ("%d", &input) != 1) {
fputs ("error: invalid integer input.\n", stderr);
return 1;
}
tenInts[i] = input;
}
write (STDOUT_FILENO, "\nThe integers reversed are:\n",
strlen ("\nThe integers reversed are:\n"));
/* print array in reverse and write to file*/
for (i = NINT-1; i >= 0; i--) {
nchar = sprintf (buffer, "%d\n", tenInts[i]);
write (STDOUT_FILENO, buffer, nchar);
if (write (fd, buffer, nchar) < 0) {
write (STDERR_FILENO, "There was an error writing to the file.\n",
strlen ("There was an error writing to the file.\n"));
return 1;
}
}
/* ALWAYS validate close of file (after a write) */
if (close (fd) == -1)
perror ("close-fd");
return 0;
}
Теперь у вас не будет выводиться забавных блоков (хороший признак Неопределенное поведение ) при запуске вашего кода.
Пример использования / Вывод
$ ./bin/tenintwrite dat/tenintwrite.txt
Enter 10 integers:
10 20 30 40 50 60 70 80 90 100
The integers reversed are:
100
90
80
70
60
50
40
30
20
10
Выходной файл
$ cat dat/tenintwrite.txt
100
90
80
70
60
50
40
30
20
10
Просмотрите все и дайте мне знать, если у вас есть дальнейшие вопросы.