Как вывести таблицу в си
Перейти к содержимому

Как вывести таблицу в си

Как вывести таблицу в си

Профиль
Группа: Участник
Сообщений: 3
Регистрация: 8.2.2010

Репутация: нет
Всего: нет

Всем привет:
Задача:Дан файл, содержащий информацию о движении пригородных поездов. Структура записи файла:
— номер поезда;
— время отправления;
— станция назначения;
— время прибытия;
— дни недели движения (е — ежедневно, р — рабочие дни, с — субботние и воскресные дни).
Написать программу, выдающую
— информацию о поездах, следующих до заданной станции по выходным дням, с указанием времени в пути (в порядке возрастания времени отправления);
Входная таблица
101 14:34 vnukovo 15:30 e
112 14:40 pulkovo 16:23 c
115 13:00 odincovo 15:00 p
205 15:00 moskva 19:00 e
132 12:05 vnukovo 14:20 c
345 15:00 vnukovo 17:00 p
234 16:45 kazan 18:50 p
567 16:40 vnukovo 17:55 e
Вызов:
int main()
.
clrscr();
poiskST(ms, &n);
sort(ms, n);
vyvod(ms,n);
.

void poiskST(struct POEZD ms[NMAX], int *n)
<
FILE *f;
char zstnaz[15]; /* zadannui pynkt otpravlenia*/
int a=0; /*nomer*/
int p=0;//min
int k=0; //perevod v sec
int c=0;//chas
int u=0;//perevod v sec
int n1=0;//perevod v sec
int i1=0;//perevod v sec
int i=0;
int j=0;
struct POEZD tz; /* tekyshaia zapis faila*/
clrscr();
f=fopen("F1.txt", "r");
if (f==NULL)
<
puts ("Fail poezda.txt ne naiden");
getch();
return;
>
puts("\nVvedite pynkt naznachenia:");
gets(zstnaz);
u=strlen(zstnaz);
rewind(f);
*n=0;
while (fgets(&tz,sizeof(struct POEZD),f)!= NULL)
< if ((strncmp(tz.stnaz, zstnaz ,u)==0) && (tz.den[0]=='c' || tz.den[0] =='e') )
<
n1=atoi(&tz.prib);// просчет времени в пути
i1=atoi(&tz.prib[3]);
k=atoi(&tz.otpr);
j=atoi(&tz.otpr[3]);
n1=(n1*60)+i1;
k=(k*60)+j;
p=n1-k;
c=0;
while (p>=60)
< p=p-60;
c=c+1;
>
tz.nom[3]='\0';
tz.stnaz[14]='\0';
tz.den[2]='\0';
strcpy(ms[*n].nom, tz.nom); //запись в массив
strcpy(ms[*n].otpr, tz.otpr);
strcpy(ms[*n].prib, tz.prib);
strcpy(ms[*n].stnaz, tz.stnaz);
(*n)++;
>
>//while
fclose(f);
>

// Funkcia sortirovki po nomeru
void sort (struct POEZD ms[NMAX], int n)
<
int k,i; // parametry ciklov
struct POEZD s; //dlia perestanovki elementov
for (k=n-1; k>0; k—)
for (i=0; i<k; i++)
if (atof(ms[i].otpr) > atof(ms[i+1].otpr))
<
// perestanovka elementov
s=ms[i];
ms[i]=ms[i+1];
ms[i+1]=s;
>
>
void vyvod (struct POEZD ms[NMAX], int n)
for ( i=0; i<n; i++)
<
printf("%s %s \n",ms[i].nom, ms[i].otpr);
if ((i+1)%20 == 0)
<
puts("\nDlia prodolgenia nagmite lubuu klavishu");
getch();
>
>
>
Проблема в том что я не могу вывести правильно таблицу результатов
сейчас он выводит
132 12:05 vnukovo
101 14:34 vnukovo
567 16:40 vnukovo а надо

132 12:05 vnukovo 2с15m
101 14:34 vnukovo 0c56m
567 16:40 vnukovo 1c15m

Профиль
Группа: Участник
Сообщений: 291
Регистрация: 7.2.2009

Репутация: 2
Всего: 10

Профиль
Группа: Участник
Сообщений: 3
Регистрация: 8.2.2010

Репутация: нет
Всего: нет

Профиль
Группа: Участник
Сообщений: 291
Регистрация: 7.2.2009

Репутация: 2
Всего: 10

Код
void vyvod (struct POEZD ms[NMAX], int n)
int departure_hour;
int departure_min;
int arrival_hour;
int arrival_min;
int tour_hour;
int tour_min;
for ( i=0; i<n; i++)
<

// вычисление продолжительности пути
sscanf(ms[i].otpr,"%d:%d",&departure_hour,&departure_min);
sscanf(ms[i].prib,"%d:%d",&arrival_hour, &arrival_min);
tour_min=(60*arrival_hour+arrival_min)-(60*departure_hour+departure_min);
if (tour_min<0) tour_min+=60*24;
tour_hour=tour_min / 60;
tour_min=tour_min % 60;

С массивом я не проверял (лень заполнять вручную), а с простыми строками типа "12:12" всё вычислялось.

Профиль
Группа: Участник
Сообщений: 3
Регистрация: 8.2.2010

Репутация: нет
Всего: нет

ВНИМАНИЕ! Прежде чем создавать темы, или писать сообщения в данный раздел, ознакомьтесь, пожалуйста, с Правилами форума и конкретно этого раздела.
Несоблюдение правил может повлечь за собой самые строгие меры от закрытия/удаления темы до бана пользователя!

  • Название темы должно отражать её суть! (Не следует добавлять туда слова «помогите», «срочно» и т.п.)
  • При создании темы, первым делом в квадратных скобках укажите область, из которой исходит вопрос (язык, дисциплина, диплом). Пример: [C++].
  • В названии темы не нужно указывать происхождение задачи (например «школьная задача», «задача из учебника» и т.п.), не нужно указывать ее сложность («простая задача», «легкий вопрос» и т.п.). Все это можно писать в тексте самой задачи.
  • Если Вы ошиблись при вводе названия темы, отправьте письмо любому из модераторов раздела (через личные сообщения или report).
  • Для подсветки кода пользуйтесь тегами [code][/code] (выделяйте код и нажимаете на кнопку «Код»). Не забывайте выбирать при этом соответствующий язык.
  • Помните: один топик — один вопрос!
  • В данном разделе запрещено поднимать темы , т.е. при отсутствии ответов на Ваш вопрос добавлять новые ответы к теме, тем самым поднимая тему на верх списка.
  • Если вы хотите, чтобы вашу проблему решили при помощи определенного алгоритма, то не забудьте описать его!
  • Если вопрос решён, то воспользуйтесь ссылкой «Пометить как решённый», которая находится под кнопками создания темы или специальным флажком при ответе.

Если Вам помогли и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, Poseidon, Rodman

0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Центр помощи | Следующая тема »

[ Время генерации скрипта: 0.1078 ] [ Использовано запросов: 21 ] [ GZIP включён ]

Формат вывода в таблице, C++

Как я могу выводить данные на консоль в таблице на C++? Есть вопрос для этого в C#, но мне это нужно в C++.

Это, за исключением C++:как: лучший способ нарисовать таблицу в консольном приложении (C#)

4 ответов

не можете ли вы сделать что-то очень похожее на пример C#:

вот небольшой пример того, что имеет iomanip:

есть и другие вещи, которые вы также можете сделать, например, установить точность чисел с плавающей запятой, изменить символ, используемый в качестве заполнения при использовании setw, вывод чисел в чем-то другом, кроме базы 10, и так далее.

Я не мог найти то, что мне понравилось, поэтому я сделал один. Найдите его вhttps://github.com/haarcuba/text-table

вот exmaple его вывода:

проверьте длину значения столбца, а также имейте в виду длину значения для форматирования.

посмотрите, как был разработан интерфейс оболочки MySQL, это даст вам хорошую идею.

Язык Си в примерах/Таблица умножения

Примета работы программы (построение таблицы умножения для n = 5):

Ниже мы разберем работу данной программы, начиная с завершающих ее циклов вычисления и вывода результатов и двигаясь далее к началу.

Цикл строк [ править ]

В данном примере мы используем оператор цикла for , являющийся обобщением уже рассмотренного нами в разделе Максимум оператора while . [1] А именно, запись while ( выражение ) тело равносильна for (; выражение ; ) тело . С другой стороны, цикл строк в примере выше можно было бы записать с использованием while следующим образом:

Иными словами, для первой итерации цикла мы присваиваем переменной i значение 1. Затем, мы выводим очередную ( i -ую) строку пока i не превысит заданного пользователем значения n . Завершает тело цикла инкремент (увеличение на 1) номера строки i .

С точки зрения языка, содержимое «скобок» оператора for состоит из трех разделенных точкой с запятой ( ; ) частей, каждая из которых может быть или пустой, или совершенно произвольным выражением; например: i = 1 , f (42) , x *= 3 , a = b = c . При этом:

  1. первое выражение — инициализация — вычисляется перед началом цикла, — как если бы было записано непосредственно перед самим оператором for ;
  2. второе выражение — условие — вычисляется перед каждой итерацией, — совершенно аналогично условию для оператора while ;
  3. наконец, третье выражение — изменение — выполняется в конце («после») каждой итерации.

Можно было бы сказать, что оператор for является избыточным при наличии while , однако в языке существует также оператор continue , досрочно завершающий текущую итерацию [2] (с переходом к проверке условия и, при его выполнении, — к следующей итерации.) При использовании while , выражение «изменения» («перехода к следующей итерации») пришлось бы дублировать возможно перед каждым случаем использования оператора continue . Напротив, в случае for , выражение изменения выполняется после любой итерации — даже если таковая завершена досрочно.

Цикл значений [ править ]

Телом цикла строк должна стать, очевидно, некая процедура вывода заданной строки, которую мы вновь оформляем как цикл — использующий уже новую переменную j :

В данном коде, мы встречаемся с двумя новыми возможностями языка. Первая из них — указатель * переменной разрядности преобразования в строке формата функции printf . [3] В данном случае, наличие этого указателя (в форме %*ld ) означает, что вместо одного аргумента, функция printf использует для форматного преобразования два (а именно: width и произведение i × j .) При этом, первый аргумент задает разрядность преобразования, второй — само подлежащее преобразованию (и выводу) значение.

Вторая возможность — функция putchar , выводящая на стандартный вывод заданный символ (код); [4] в данном случае, ‘\n’ — управляющий код (или управляющий символ) перевода (разрыва, завершения) строки. Обратите внимание на использование одинарных кавычек при записи символьных констант (в отличие от строковых — для которых используются двойные кавычки.)

Если бы было заранее известно, что значение произведения не превышает, например, 9999, можно было бы обойтись фиксированной разрядностью ( » %4ld», i * j — или, что то же, — « %*ld», 4, i * j .) Однако коль скоро в задаче требуется обрабатывать широкий диапазон чисел (наибольшее значение типа long согласно стандарту C11 должно быть не менее порядка 2 × 10⁹), разрядность результата необходимо вычислять исходя из заданного пользователем значения n .

Поскольку мы также предваряем дополнительным пробелом каждое выводимое число, общая ширина каждого столбца окажется на единицу большей, чем используемое значение разрядности width . Вычислению последнего, в свою очередь, посвящен следующий раздел.

Вычисление предельной разрядности [ править ]

Для получения ровных столбцов в выводе программы, каждое выводимое значение должно состоять из равного количества знаков. Ясно, что из всех возможных произведений i × j , i = 1, …, n , j = 1, …, n , максимальное значение имеет n × n = n 2 , а значит именно количество знаков в записи этого числа и будет предельным для таблицы умножения n × n .

Далее, мы пользуемся тем фактом, что позиционная (в частности — десятичная) запись числа является его разложением по степеням основания системы счисления. Ясно, что максимальная степень n в разложении положительного целого числа x по степеням основания b равна ⌊log b x ⌋, а общее число разрядов (включая единицы — при нулевой степени основания) — на единицу больше n .

Для получения конечной формулы, нам остается лишь воспользоваться следующими простыми свойствами логарифмов:

  • log b ( x n ) = n log b x ;
  • log b x = log a x ∕ log a b = ln x ∕ ln b .

В итоговом выражении — ( int ) ceil ( 2 * log ( 1 + n ) / log ( 10 )) — мы используем функции ceil и log , значением которых являются результат округления «от нуля» (в сторону роста абсолютного значения) и натуральный логарифм аргумента, соответственно. Эти функции являются частью стандартной библиотеки и объявлены в заголовке math.h . [5] [6]

Ясно, что данное выражение теряет смысл при n < 0. Кроме того, при n = 0, реализованные нами циклы вычисления—вывода сформируют пустой результат, который также можно считать ошибочным. Чтобы этого избежать, перед вычислением искомого выражения мы требуем (макроподстановкой assert [7] ) выполнения условия n >= 1 .

Здесь же мы требуем, чтобы значение n не превышало квадратного корня из максимального допустимого значения для используемого нами типа long (макроподстановка LONG_MAX — объявлена в заголовке limits.h стандартной библиотеки.) В противном случае, один или более из результатов умножения может переполнить разрядность данного типа. (Отметим, впрочем, что формирование таблицы умножения теряет практический смысл уже при много меньших значениях n .)

Разбор аргументов командной строки [ править ]

Наконец, рассмотрим получение в программе переданного как аргумент командной строки значения n .

Данный фрагмент кода начинается требованием (макроподстановкой assert [7] ) наличия единственного аргумента командной строки. Здесь следует отметить, что переменная argc отражает общую длину массива argv , в который входит — нулевым элементом — имя самой программы: argv [0] . Тем самым, условие наличия и единственности аргумента может быть записано как argc == 2 — или же как приведено в коде.

В свою очередь, переменные argc и argv являются аргументами главной функции main , при объявлении ее следующим образом: [8]

Мы объявляем переменную n и, в отдельном вложенном блоке, — указатель tail . Вызываем функцию strtol (объявленную в заголовке stdlib.h ) преобразования строкового представления числа в «машинное» — значение типа long ; [9] результат сохраняем в переменной n . Первый аргумент функции — строка, подлежащая преобразованию; третий — основание системы счисления, или 0 — для использования правил языка Си для числовых констант (например: 0x12 — 12₁₆; 012 — 12₈; 12 — 12₁₀.)

Функция strtol пропускает любые пробельные символы в начале строки (если они есть) и пытается разобрать следующее за ними число. При этом, указатель на первый же символ (код), не являющийся частью такого числа, помещается по адресу, переданному вторым аргументом (если не 0); в нашем случае — в переменную tail . Кроме того, если за ведущими пробельными символами не следует ничего похожего на число (в соответствии с указанной третьим аргументом формой записи), то по данному адресу помещается значение первого аргумента.

После выполнения данного преобразования, мы требуем истинности следующих двух условий, смысл которых сводится к тому, что первый аргумент командной строки содержит одно число (возможно — предваряемое ведущими пробельными символами) и ничего после него:

  1. tail > argv[1] — некое число было обнаружено в данной строке (и извлечено из нее);
  2. *tail == ‘\0’ — за этим числом сразу же следует признак конца строки (код 0.)

В заключение отметим, что во-первых, можно, конечно, обобщить данную программу на случай произвольного количества аргументов — последовательно обрабатывая их в цикле. (В отсутствие аргументов можно выводить таблицу некоего явно определенного в коде размера; например: 10 × 10.) С другой стороны, возможны и другие обобщения.

Во-вторых, аргументы командной строки используются как правило для передачи данных в дополнение к передаваемым через файловые потоки, и в частности — стандартный ввод. Данную программу можно без значимого ущерба для функциональности или удобства переписать для получения значений n со стандартного ввода — применив цикл, аналогичный рассмотренному в разделе Максимум.

Видимость переменных [ править ]

В примере выше мы «по мере необходимости», в различных точках программы, определили ряд требуемых нам переменных ( n , width , i , j ) — пользуясь тем, что стандарт (начиная с версии C11) позволяет определять переменные в любой точке кода, где допустимо утверждение. (В версии C99 и более ранних, определения переменных были допустимы только в начале блока — до первого утверждения.) Возникает вопрос: где именно в коде можно использовать каждую из определенных таким образом переменных?

Областью видимости (англ. scope ) переменной (или идентификатора в общем) как правило оказывается часть содержащего переменную блока — от точки определения и до закрытия этого блока. Однако, вложенные блоки могут скрывать переменные вышестоящих блоков, объявляя свои собственные переменные с теми же именами. Так, например, функция foo в следующем примере выведет на стандартный вывод код перевода строки (из переменной a внутреннего блока) и вернет значение 1 (из одноименной переменной внешнего):

Хорошей практикой представляется определение переменных так, чтобы область их видимости была не большей, чем строго необходимо. (Но не в ущерб ясности кода.) В этом случае, при перемещении (копировании) кода, случайное использование переменной там, где она не имеет смысла, с большей вероятностью будет диагностировано непосредственно реализацией языка.

Вариант «мультисистемный» [ править ]

Используея нами для преобразования строкового представления числа в «машинное» функция strtol определяет систему счисления по префиксу строкового представления числа. В следующем примере мы частично воссоздаем эту логику для вывода таблицы умножения в шестнадцатеричном, восьмеричном или десятичном представлении в зависимости от способа записи аргумента командной строки.

Пример работы программы (построение таблицы умножения для n = 5 в шестнадцатиричном представлении):

По сравнению с исходным вариантом, пример дополнился следующим фрагментом кода:

Кроме того, две из исходных констант ( 10 при вычислении предельной разрядности и « %*ld» в качестве строки формата функции printf ) заменены в данном варианте переменными base и fmt , соответственно.

Во фрагменте выше, мы используем функцию strchr (объявленную в заголовке string.h ) поиска первого вхождения символа (кода) в строку [10] — в данном случае, поиска символа 0 в аргументе командной строки.

Функция возвращает нулевой указатель (0 или NULL ) если символ не найден. [10] Поскольку это означает, что аргумент командной строки не содержит символа 0 вовсе, очевидно, что он не может содержать его и как часть префикса системы счисления ( 0x или 0 ), а значит следует использовать десятичную систему счисления при вычислении предельной разрядности и указатель представления d — «десятичное число»: base = 10 ; fmt = " %*ld" ; .

Точно так же обрабатывается случай, когда найденному символу 0 предшествует любая десятичная цифра — p > argv [ 1 ] && isdigit ( p [ -1 ]) . Используемая в этом условии функция isdigit (объявлена в заголовке ctype.h ) возвращает истину (отличное от 0 значение) в том и только том случае, когда ее аргумент — десятичная цифра; в противном случае — возвращается 0. [11] Разумеется, обращение к предшествующему символу имеет смысл только в том случае, когда найденный символ 0 не является первым в строке — p > argv [ 1 ] .

Следующим мы проверяем условие p [ 1 ] == 'x' || p [ 1 ] == 'X' — наличие после 0 признака шестнадцатиричного представления x или X . В этом случае, base присваивается значение 16, fmt — « %*lx» или « %*lX» (в зависимости от регистра символа x в аргументе.)

Наконец, если условия выше (наличие цифры перед 0 или x , X — после) — не выполнены, мы присваиваем base значение 8, fmt — « %*lo» .

Логика выше не покрывает всех возможных значений аргумента командной строки, однако она вполне корректна — поскольку мы предполагаем успешное завершение функции strtol (используя макроподстановки assert выше — при получении значения n ), что уже накладывает нужные нам дополнительные ограничения на запись данного аргумента.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *