#c
Вопрос:
У меня есть структура, определенная как таковая
typedef struct box
{
float x;
float y;
float z;
float volume;
int order;
}box;
и файл, который мне дают, представляет данные таким образом:
3 2.5 3
4.4 5 6
8.7 6.5 9.5
2.5 6.5 7.3
7.6 5.1 6.2
с каждым числом, представляющим размер параллелепипеда
printf("%f %f %f %fn", A[i]->x, A[i]->y, A[i]->z, A[i]->volume)
поскольку я являюсь циклом for и массив, в котором я храню структуры, дает мне этот вывод
3 2.5 3 22.5
4.4 5 6 132
8.7 6.5 9.5 537.225
2.5 6.5 7.3 118.625
5.7 8.7 9.8 485.982
7.6 5.1 6.2 240.312
Как я могу распечатать его организованно, как входной файл?
одна из проблем заключается в том, что входные данные также могут выглядеть по-другому, например.
5.244231 2.231432 7.232432
поэтому мне нужна моя распечатка для размещения чисел разной длины, хотя форматы не смешиваются, поэтому, например, это не может быть 5 4.52653 3.674
Комментарии:
1. Разделены ли числа во входном файле пробелами или символами табуляции?
2. Может быть, это может вам помочь: Спецификаторы формата в C
3. Ты в курсе, что можешь делать подобное
printf("?"
?4. Проще всего: используйте вкладки (или просто одиночные пробелы).
5. @AndreasWenzel они разделены вкладками
Ответ №1:
учитывайте различную длину чисел
float
значения обычно варьируются от /-1,4…e-45F до /-3,4…e 38F, /-0, бесконечность и различные не-числа.
"%f"
печатает с 6 цифрами после .
as, поэтому печатает 0.000000
для многих маленьких float
и со многими неинформативными цифрами, когда очень большие, как, таким образом, неудовлетворительно.
Для общей печати начните с использования "%g"
, которое адаптирует свой вывод (используя экспоненциальную нотацию для больших и малых значений) и усекает конечные нули.
Используйте ширину, которая определяет минимальное количество символов для печати.
float
обычно требуется до 9 значащих цифр, чтобы отличить их от других float
. Рассмотрим точность.
Используйте объединение исходных текстов, чтобы разрешить только 1 определение желаемого формата.
// printf("%f %f %f %fn", A[i]->x, A[i]->y, A[i]->z, A[i]->volume)
#define FMT_F "%-15.9g"
// ^ precision
// ^^ width
// ^ left justify
printf(FMT_F " " FMT_F " " FMT_F " " FMT_F "n",
A[i]->x, A[i]->y, A[i]->z, A[i]->volume)
// Example output
4.4 5 6 132
8.7 6.5 9.5 537.225
1.40129846e-45 -3.40282347e 38 123.4 -5.88417018e-05
Более продвинутый код будет использовать ширину и точность, зависящие от компилятора.
Ответ №2:
Мне нужна распечатка для размещения чисел разной длины, хотя форматы не смешиваются, поэтому, например, она не может быть 5 4,52653 3,674
Это просто (хорошо, это не так просто)! Просто:
- Выделите 2d массив выходных строк.
- Выведите все элементы этого массива.
- Для каждого столбца в выходном массиве:
- получите самый длинный элемент этого столбца.
- Выведите каждый столбец, заполненный пробелами, до самого длинного элемента.
- Печатайте пробелы между столбцами и новые строки между строками.
Для вдохновения см. утилиту util-linux/column.c.
И, ну, пример кода: с массивом из двух int с разными значениями, давайте распечатаем их:
#define _GNU_SOURCE 1 // for asprintf
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
typedef struct {
int a;
int b;
} data_t;
#define DATA_ELEMS 2 // the count of output columns
#define COUNT 3 // the count of output rows
int main() {
// some data we are going to print
const data_t data[COUNT] = {
{rand(),rand()},
{rand(),rand()},
{1,2},
};
// Print all elements to this array.
char *strs[COUNT][DATA_ELEMS] = {0};
for (size_t i = 0; i < COUNT; i) {
const data_t *it = amp;data[i];
asprintf(amp;strs[i][0], "%d", it->a);
asprintf(amp;strs[i][1], "%d", it->b);
// TODO: error checking
}
// For each column in the output array:
// get the longest element of this column.
size_t collens[DATA_ELEMS] = {0};
for (size_t i = 0; i < COUNT; i) {
for (size_t j = 0; j < DATA_ELEMS; j) {
if (collens[j] < strlen(strs[i][j])) {
collens[j] = strlen(strs[i][j]);
}
}
}
for (size_t i = 0; i < COUNT; i) {
// Print each column padded with spaces to the longest element.
for (size_t j = 0; j < DATA_ELEMS; j) {
printf("%*s", (int)collens[j], strs[i][j]);
// Print spaces between columns.
putchar(j 1 == DATA_ELEMS ? 'n' : ' ');
}
}
for (size_t i = 0; i < COUNT; i) {
for (size_t j = 0; j < DATA_ELEMS; j) {
free(strs[i][j]);
}
}
}
будет например выводить на godbolt:
1804289383 846930886
1681692777 1714636915
1 2
Ответ №3:
Вы можете указать ширину столбца, поместив число между %
и f
так, например:
printf("||f|f|f|f||n", box.x, box.y, box.z, box.volume);
бы напечатать:
|| 3.100000| 2.000000| 9.500000| 58.899998||
Обратите внимание, что они выровнены по правому краю. Если вы поставите знак минус перед шириной столбца, вы можете выровнять его по левому краю.
printf("||f|f|f|%-10f||n", box.x, box.y, box.z, box.volume);
напечатает:
|| 3.100000| 2.000000| 9.500000|58.899998 ||
Также полезно знать, что вы можете контролировать количество цифр, отображаемых после десятичной точки, указав .<count>
ширину столбца после:
printf("||.2f|.2f|.2f|.4f||n", box.x, box.y, box.z, box.volume);
напечатает
|| 3.10| 2.00| 9.50| 58.9000||
Обновление:
Похоже, вы добавили больше деталей к своему вопросу. Вот дополнительная информация, которую вы могли бы использовать.
Числа ширины и точности не обязательно должны быть константами в строке формата. Вы можете заменить любой или все из них звездочкой » * » и указать переменную, подобную этой:
for (int precision = 1; precision < 5; precision) {
int width = precision * 4;
printf("||%*.*f|%*.*f|%*.*f|%*.*f||n",
width, precision, box.x,
width, precision, box.y,
width, precision, box.z,
width, precision, box.volume);
}
Это приведет к:
|| 3.1| 2.0| 9.5|58.9||
|| 3.10| 2.00| 9.50| 58.90||
|| 3.100| 2.000| 9.500| 58.900||
|| 3.1000| 2.0000| 9.5000| 58.9000||
Быстрый способ определения количества цифр перед десятичной запятой — это:
int digits = (int)log(values[i])/log(10) 1;
поэтому, если вы предварительно просмотрите свои данные, вы сможете выбрать подходящую ширину столбца.
Что касается цифр после десятичной точки, то это решение зависит от вас; причуды представлений с плавающей запятой могут привести к тому, что конечный пользователь может счесть их запутанными. Например, в данных, которые я использовал выше 3.1 * 2.0 * 9.5 печатается как 58.899998, если разрешено печатать все цифры, тогда как 5.9-это, вероятно, то, что ожидали бы конечные пользователи.