Разделение на триады. В чем ошибка? - C (СИ)

Узнай цену своей работы

Формулировка задачи:

Помогите, пожалуйста, разобраться! При запуске программа запрашивает все необходимые данные и прекращает работу. В чем у меня ошибка? Заранее спасибо) Задание выглядело примено так: Функция в текстовом режиме выводит число num в 10-системе счисления группами по 3 цифры (триадами), отделяя их друг от друга символом term и возвращая 0.
#include <STDIO.H>
#include <CONIO.H>

#define MAXY 20
#define MAXX 64

long GetLongNum( char *query,  
        long  minnum, 
        long  maxnum  
      )
 
{
long n; 
 
    printf( "\n%s = ", query );
    fflush( stdin );
    if ( scanf( "%D", &n ) != 1 )
        n = (minnum + maxnum) / 2;
    else if ( n < minnum )
        n = minnum;
    else if ( n > maxnum )
        n = maxnum;
    return n;
}

int GetNum( char *query, /* *текст запроса целого числа* */
        int  minnum,
        int  maxnum  
      )
 
{
int n; /* буфер введенного числа */
 
    printf( "\n%s = ", query );
    fflush( stdin );
    if ( scanf( "%d", &n ) != 1 )
        n = (minnum + maxnum) / 2;
    else if ( n < minnum )
        n = minnum;
    else if ( n > maxnum )
        n = maxnum;
    return n;
}

int YesNo( char *text )
 
{
int c; 
 
    printf( "\n%s [Y/N]?", text );
    fflush( stdin );
    c = getchar();
    if ( (c == 'y') || (c == 'Y') )
        return 1;
    else
        return 0;
}
 
void LongToBits ( long num, char *bits )
{
int k;
int n;
long c;
 
k = 1000000000;
 
    for ( n = 0; n < 31; n++ )
        {
        c = num/k;
        num = num - c*k;
        k = k/10;
        if( c == 0) bits[n] = '0';
        if( c == 1) bits[n] = '1';
        if( c == 2) bits[n] = '2';
        if( c == 3) bits[n] = '3';
        if( c == 4) bits[n] = '4';
        if( c == 5) bits[n] = '5';
        if( c == 6) bits[n] = '6';
        if( c == 7) bits[n] = '7';
        if( c == 8) bits[n] = '8';
        if( c == 9) bits[n] = '9';
 
        }
 
}

int TPutDecLong (
int x, int y,
long num,
char term )
 
{

char bits[32];
int i;
int n;
int n1;         /* номер позиции в тройке */
int n2;         /* *номер тройки в числе */
char three[4];  /* строка в 3 символа* */
char devider[1];/* символ-разделитель */
int ccolor;     /*цвет текста по умолчанию */
 
    for ( i=0; i< 2; i++) devider[i] = '0';
 
devider[0] = term;
devider[1] = '\0';
 
clrscr();

if ( y < 0 || y > MAXY ) return -1;         /* слишком длинный столбец* */
if ( x < 0 || x > MAXX - 40 ) return -2;    /* слишком длинная строка */

    LongToBits( num, bits );
 
clrscr();

for ( n = 0; n < y; n++ ) printf( "\n" );
 
for ( n = 0; n < x; n++ ) printf( " " );
 
for ( n2 = 0; n2 < 9; n2++ )
{
    for ( n1 = 0; n1 < 3; n1++ )
    {
        n = 31 - 3 * n2 - n1;
 
        three[n1] = bits[n];

    }
    three[4] = '\0';
 
    cprintf ( three );

cprintf ( devider );
}
 
printf ( "\n" );
 
ccolor = WHITE;
textcolor ( ccolor );
 
return 0;
 
}

void main (void)
{
 
extern int TPutDecLong (int x, int y,long num,
                            char term );
extern int YesNo( char *text );
extern long GetLongNum( char *query,long minnum, long maxnum );
extern int GetNum( char *query,int minnum, int maxnum );

long number;
long maxnum = 2000000000; /* 2*10^9 */
long minnum = -2000000000;  
int x,y;
char term;
int dcolor;
int tcolor;
int error;
int ccolor = WHITE;

do
{
    clrscr();

    textcolor ( ccolor );
    number = GetLongNum ( "\nВведите число", minnum, maxnum );
 
    x = GetNum ( "\nВведите координату Х", 0, 64 );
    y = GetNum ( "\nВведите координату Y", 0, 20 );
 
    printf (  "\nВведите символ-разделитель триад" );
    term = getch();
    error =  TPutDecLong ( x, y, number, term );
 
    if ( error == -1 ) printf ( "\nНеверно задано Х" );
    if ( error == -2 ) printf ( "\nНевернозадано Y" );
 
printf ( "\nВведенное число:", number );
printf ( "\nКоордината Х: %d", x );
printf ( "\nКоордината Y: %d", y );
printf ( "\nСимвол-разделитель: %c", term );

}
 
while ( YesNo ( "Повторить?" ) );
clrscr();
}
Вместо вот этого куска :
k = 1000000000;
 
    for ( n = 0; n < 31; n++ )
        {
        c = num/k;
        num = num - c*k;
        k = k/10;
        if( c == 0) bits[n] = '0';
        if( c == 1) bits[n] = '1';
        if( c == 2) bits[n] = '2';
        if( c == 3) bits[n] = '3';
        if( c == 4) bits[n] = '4';
        if( c == 5) bits[n] = '5';
        if( c == 6) bits[n] = '6';
        if( c == 7) bits[n] = '7';
        if( c == 8) bits[n] = '8';
        if( c == 9) bits[n] = '9';
 
        }
Вставлен вот этот:
k = 10;
c = num;
do {
    for ( n = 0; n < 31; n++ )
 
{ temp = c%k;
 c = c/k;
 bits[n] = temp;
}
 }
while (c != 0);
Теперь на экран выводится результат в виде непонятных случайных символов. Проблема, как я понимаю в том, что temp у меня задана как int, а массив bits чаровый. Вопрос остается тем же: как это можно исправить?

Решение задачи: «Разделение на триады. В чем ошибка?»

textual
Листинг программы
#include <stdio.h>
#include <stdlib.h>
 
void Reverse(char* begin, char* end)
{
   char tmp;
   for (; begin < end; ++begin, --end)
   {
      tmp = *begin;
      *begin = *end;
      *end = tmp;
   }
}
 
const char* GetIntAsAnsi(unsigned digit, char delim)
{
   static char ansi[32] = {'\0'};
   char* pstr = ansi;
 
   while (digit)
   {
      *pstr++ = digit % 10 + '0';
      digit /= 10;
 
      if (digit && ((pstr - ansi + 1) % 4 == 0))
      {
         *pstr++ = delim;
      }
   }
 
   *pstr = '\0';
 
   Reverse(ansi, pstr - 1);
 
   return ansi;
}
 
int main()
{
   printf("%s\n", GetIntAsAnsi(1234567, ':'));
   printf("%s\n", GetIntAsAnsi(12345, '.'));
   printf("%s\n", GetIntAsAnsi(123456789, '^'));
 
   return 0;
}

Объяснение кода листинга программы

  1. В функции Reverse происходит переполнение буфера при копировании символов в обратном порядке. Причина в том, что в цикле не контролируется выход за границы выделенной памяти. В результате, при копировании последнего символа, происходит запись за пределы выделенного массива.
  2. В функции GetIntAsAnsi есть ошибка в расчете индекса для добавления разделителя. Рассчитывается ((pstr - ansi + 1) % 4 == 0), но нужно ((pstr - ansi + 1) % (4 + 1) == 0). То есть, при расчете необходимо увеличить размер блока на 1, чтобы корректно определять момент добавления разделителя.
  3. В функции GetIntAsAnsi есть отсутствие проверки на null-терминатор перед добавлением символа в строку. В результате, если последний символ числа (представляющий собой 0) будет принят за символ разделителя, то будет записано лишнее значение, и строка не будет корректно интерпретироваться как число.
  4. В функции GetIntAsAnsi нет обработки случая, когда входное значение равно 0. В этом случае, функция будет пытаться разделить строку, которая состоит только из нулей, что приведет к неопределенному поведению.
  5. В функции main нет проверки на то, что функция GetIntAsAnsi возвращает корректное значение. Если функция вернет некорректное значение (например, не будет содержать нужного количества символов), то программа может работать некорректно.

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

13   голосов , оценка 4.154 из 5
Похожие ответы