LINUX.ORG.RU

Сравнение строк, содержащих числа (только цифры). Критика

 


1

1

Критика нужна: желательно объективно и без перехода на личности.

Отредактировано с учетом комментариев ниже! Еще раз отредактировано с учетом комментариев ниже! Спасибо всем за помощь, друзья!

C проверкой на знак - отрицания. Посл. вариант: True

/*Данная программа сравнивает две строки, содержащие числа (только).
Возвращает A > B,  A < B или A = B, коды 1, -1 и 0. Ответ 3 - неправильный ввод 
или отсутствие аргументов.
This program compares two strings, which contains numbers (only).
It returns: A > B,  A < B or A = B, codes 1, -1 and 0. Code 3 - incorrect or empty input.
*/


#include <stdio.h>

  /*Функция печати результата*/
  int ret(int r) {

/*Если нужен код ответа (например, для PHP), раскомментируйте строку ниже*/
    //printf("%d", r);

  /*Коды  ответов и вывод на экран сообщений*/
 switch ( r ) {
        case 1:
            printf("A > B\n");
            break;
        case -1:
            printf("A < B\n");
            break;
        case 0:
            printf("A = B\n");
            break;
        case 3:
             printf("Перезапустите с двумя аргументами так: программа 123 321\n");
            break;
    }

    return r;
  }

//Функция конвертации аргумента в целое
int convert_to_int(char * ar1, int i) {

  int a = 0;

  for (i; ar1[i]; i++) a = a * 10 + (ar1[i] - '0');

  return a;
}

int main(int argc, char * argv[]) {

  /*Проверим ввод аргументов*/
  if (argc != 3)   return ret(3);

  /*Проверим знаки - если один с минусом, другой нет (и обратно)*/
  if (argv[1][0] == '-' && argv[2][0] != '-') return ret(-1);
  if (argv[2][0] == '-' && argv[1][0] != '-') return ret(1);

  int i = 0;

  /*Если оба аргумента без знаков минус. Достаточно проверить один*/
  if (argv[1][0] != '-') {
    if (convert_to_int(argv[1], 0) > convert_to_int(argv[2], 0)) return ret(1);
    if (convert_to_int(argv[1], 0) < convert_to_int(argv[2], 0)) return ret(-1);
  }
  /*Если с минусами*/
  else {
    if (convert_to_int(argv[1], 1) > convert_to_int(argv[2], 1)) return ret(-1);
    if (convert_to_int(argv[1], 1) < convert_to_int(argv[2], 1)) return ret(1);
  }
  /*Если равны*/
  return ret(0);
}


if (argc < 3 || argc > 3) {
    printf("Enter arguments - one or two strings: ");

Что-то тут не то.

//Считаем число символов в аргументах
  while (argv[1][i] != '\0') i++;
  while (argv[2][j] != '\0') j++;

Чем это лучше strlen?

akk ★★★★★ ()

Это полностью вынесло мозг:

  if (argc < 3 || argc > 3) {
    printf("Enter arguments - one or two strings: ");
	return 0;
  }

Если «one or two strings″, то почему argc обязательно должен быть равен 3, если это сообщение об ошибке, а не приглашение ввода, почему в конце двоеточие...

mky ★★★★★ ()
Ответ на: комментарий от mky

Ага, да. Кусок остался из начала (было немного другой смысл сейчас. когда начинал, сейчас поправлю) Т.е. следует вводить так: программы арг1 арг2 Спасибо!

AnonymUser ()
Ответ на: комментарий от x905

x905, Я думал, достаточно, что главная функция вернет r. Но понял, вроде бы. Спасибо!

AnonymUser ()
Ответ на: комментарий от anonymous

Нормальные сишники делают это примерно вот так

Это же защита от padding oracle attack. ТС'у эти заморочки зачем?

i-rinat ★★★★★ ()
if (j > i) {
if (j < i) {

//Если число знаков равно,
//то ищем первый больший знак от начала аргументов
if (j == i) {

Хоть и очевидно, но на всякий случай влепил if, да? А вдруг!

anonymous ()
Ответ на: комментарий от AnonymUser

Да такой же, сравнивает до первого неравного символа и смотрит, какой больше. Если одна строка короче, то она меньше. Т.е. разницы в поведении быть не должно, кроме однократного прохода по строкам в strcmp().

xaizek ★★★★★ ()
Ответ на: комментарий от AnonymUser

И кстати не оставляй такие большие if в конце (когда они будут нужны). Надо проверять отрицание условия с return, как в двух if выше.

И в while тоже сразу return делай. Нафига break? Тогда цикл сократится до

	//Если B < A
      if (argv[1][i] < argv[2][i]) return ret(2);
      //Если A > B
      if (argv[1][i] > argv[2][i]) return ret(1);
      //Если аргументы равны
      if (i == j - 1 && argv[1][i - 1] == argv[2][i - 1]) return ret(3);
      i++;

anonymous ()
Ответ на: комментарий от xaizek

Тестировал вот этот код, но при значениях переменных как в данном случае результат: returned by strcmp() is: -3 Т.е. мной strcmp осмыслялось как просто проверка на равенство.

#include<stdio.h>
#include<string.h>

int main()
{ 
    
    char leftStr[] = "0323";
    char rightStr[] = "3230";
    
    // Using strcmp()
    int res = strcmp(leftStr, rightStr);
    
    if (res==0)
        printf("Strings are equal");
    else 
        printf("Strings are unequal");
    
    printf("\nValue returned by strcmp() is:  %d" , res);
    return 0;
}
AnonymUser ()
Ответ на: комментарий от AnonymUser
The strcmp() and strncmp() functions return an integer less than, equal to, or greater than zero if s1 (or the first n bytes thereof) is found, respectively, to be less than, to match, or be greater than s2.

-3

Т.е. первая строка меньше второй.

xaizek ★★★★★ ()
Ответ на: комментарий от anonymous

Там просто вариантов-то 3, в цикле или больше или меньше И выходы сразу стоят.

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

AnonymUser ()
Ответ на: комментарий от xaizek

Убрал проверку просто посмотрел коды ответов

 
 char leftStr[] = "23";
    char rightStr[] = "15";
Program finished with exit code 1

 
    char leftStr[] = "23";
    char rightStr[] = "415";

Program finished with exit code 254

 char leftStr[] = "0000235995";
    char rightStr[] = "415";
Program finished with exit code 252

char leftStr[] = "000029";
    char rightStr[] = "415";

Program finished with exit code 252

AnonymUser ()
Ответ на: комментарий от AnonymUser

Вообще всё можно сделать одним циклом (а не тремя). Как-то так:

int i = 0;
while (1) {
  // Строки одинаковые
  if (argv[1][i] == '\0' && argv[2][i] == '\0') return ret(3);
  //Если A < B
  if (argv[1][i] == '\0') return ret(1);
  if (argv[1][i] < argv[2][i])  return ret(1);
  //Если A > B
  if (argv[2][i] == '\0') return ret(2);
  if (argv[2][i] < argv[1][i])  return ret(2);
  //next
  i++;
}

anonymous ()
Ответ на: комментарий от AnonymUser

Если учесть, что '\0' меньше всех, то даже две лишние:

int i = 0;
while (1) {
  // Строки одинаковые
  if (argv[1][i] == '\0' && argv[2][i] == '\0') return ret(3);
  //Если A < B
  if (argv[1][i] < argv[2][i])  return ret(1);
  //Если A > B
  if (argv[2][i] < argv[1][i])  return ret(2);
  //next
  i++;
}

anonymous ()
Ответ на: комментарий от AnonymUser

Да, придётся тогда считать длину заранее. Но тогда проще двумя циклами перевести в int и после просто их сравнить.

anonymous ()

Скажите ему уже кто-то, что возвращать нужно -1, 0 и 1.

urxvt ★★★★★ ()
Ответ на: комментарий от anonymous

Но тогда это strcmp, которое сравнивает строки А тут строки содержащие целые числа (только числа). Единственный не вариант когда: А=123, 0044, но если вызов из PHP, то там есть (int). А так расчет на целые числа без нулей в начале.

И я хотел тренировки ради это все прописать максимально руками, поэтому так много кода изначально получилось.

Спасибо огромное!

AnonymUser ()
Ответ на: комментарий от AnonymUser

254

-2

252

-4

Просто коды возвратов программы беззнаковые в системе.

xaizek ★★★★★ ()
Ответ на: комментарий от anonymous

Я еще про проверку знака забыл. Пока так придумал:

  if (argv[1][0]=='-' && argv[2][0]!='-') return ret(2);
  if (argv[2][0]=='-' && argv[1][0]!='-') return ret(1);
AnonymUser ()
Ответ на: комментарий от anonymous

Если не заморачиваться с отрицательными числами, то есть совсем простой вариант:

#include <stdio.h>

/*Функция печати результата*/ int ret(int r) { printf(«%d», r); return r; }

int main(int argc, char * argv[])
{

int  i = 0;
int a=0;
int b=0;

for(i=0; argv[1][i]!='\0'; i++)
a = a * 10 + ( argv[1][i] - '0');
for(i=0; argv[2][i]!='\0'; i++)
b = b* 10 + ( argv[2][i] - '0');

   if (a > b) return ret(1);
   if (a < b) return ret(-1);
   if (a == b) return ret(0);

}

AnonymUser ()
Ответ на: комментарий от AnonymUser

Ну и с минусами, если не сокращать, то получается самый айс-варинт

#include <stdio.h>

  /*Функция печати результата*/
  int ret(int r) {
    printf("%d", r);
    return r;
  }

int main(int argc, char * argv[])
{

 int r = 0;
  /*Переменная с кодом результата
   Проверим ввод аргументов*/
  if (argc != 3) {
    printf("Restart it with two arguments!\n");
    return ret(0);
  }

/*Проверим знаки*/
  if (argv[1][0] == '-' && argv[2][0] != '-') return ret(2);
  if (argv[2][0] == '-' && argv[1][0] != '-') return ret(1);
int  i = 0;
int a=0;
int b=0;


/*Если оба аргумента без знаков минус*/
 if (argv[2][0] != '-' && argv[1][0] != '-') {

	for(i=0; argv[1][i]!='\0'; i++)
	a = a * 10 + ( argv[1][i] - '0');
	for(i=0; argv[2][i]!='\0'; i++)
	b = b* 10 + ( argv[2][i] - '0');

   if (a > b) return ret(1);
   if (a < b) return ret(2);
     }
     /*Если с минусами*/
    else
     {

	for(i=1; argv[1][i]!='\0'; i++)
	a = a * 10 + ( argv[1][i] - '0');
	for(i=1; argv[2][i]!='\0'; i++)
	b = b* 10 + ( argv[2][i] - '0');

   if (a > b) return ret(2);
   if (a < b) return ret(1);
   }
   /*Если равны*/
   if (a == b) return ret(3);
}

Но можно сократить еще

AnonymUser ()
Ответ на: комментарий от AnonymUser

И из PHP уже можно не приводить тип. Все работает и так Можно передавать даже без кавычек.

AnonymUser ()
Ответ на: комментарий от AnonymUser

Опять ты if огромный оставил! Логическое выражение можно отрицать по законам моргана: !(a & b) == !a | !b

Ну и «Если равны» в конце умиляет. Во-первых какие ещё варианты? А во вторых если не сработает условие, то по-умолчанию вернётся 0.

anonymous ()
Ответ на: комментарий от AnonymUser

Или

 if ((argv[2][0] && argv[1][0]) != '-')
Но тут вообще уже можно один аргумент проверять
 if ((argv[2][0]  != '-')
Любой Так как выше есть проверка, если у одного аргумента минус

AnonymUser ()
Ответ на: комментарий от AnonymUser

Финиш для командной строки, из php не проверял


#include <stdio.h>

  /*Функция печати результата*/
  int ret(int r) {
    printf("%d", r);
    return r;
  }

int main(int argc, char * argv[]) {


  /*Проверим ввод аргументов*/
  if (argc != 3) {
    printf("Restart it with two arguments!\n");
    return ret(0);
  }

  /*Проверим знаки*/
  if (argv[1][0] == '-' && argv[2][0] != '-') return ret(2);
  if (argv[2][0] == '-' && argv[1][0] != '-') return ret(1);
  
  int i = 0;
  int a = 0;
  int b = 0;

  /*Если  аргументы без знака минус*/
  if (argv[1][0] != '-') {

    for (i = 0; argv[1][i] != '\0'; i++)
      a = a * 10 + (argv[1][i] - '0');
    for (i = 0; argv[2][i] != '\0'; i++)
      b = b * 10 + (argv[2][i] - '0');

    if (a > b) return ret(1);
    if (a < b) return ret(2);
  }
  /*Если с минусами*/
  else {

    for (i = 1; argv[1][i] != '\0'; i++)
      a = a * 10 + (argv[1][i] - '0');
    for (i = 1; argv[2][i] != '\0'; i++)
      b = b * 10 + (argv[2][i] - '0');

    if (a > b) return ret(2);
    if (a < b) return ret(1);
  }
  /*Если равны*/
  return ret(3);
}
AnonymUser ()
Ответ на: комментарий от AnonymUser
for (i = 0; argv[1][i] != '\0'; i++)
      a = a * 10 + (argv[1][i] - '0');
for (i = 0; argv[2][i] != '\0'; i++)
      b = b * 10 + (argv[2][i] - '0');

Повторяющийся код вынеси из if. Вычисление числа вынеси в функцию. != '\0' можно убрать, т.к. 0 в C == ложь.

anonymous ()
Ответ на: комментарий от anonymous

Все! Вроде код идеален! : ))



#include <stdio.h>

  /*Функция печати результата*/
  int ret(int r) {
    printf("%d", r);
    return r;
  }
/*Функция конвертации аргумента в целое*/
int cycles(char * ar1, int i) {

  int a = 0;
  for (i = i; ar1[i] != '\0'; i++)
    a = a * 10 + (ar1[i] - '0');

  return a;
}

int main(int argc, char * argv[]) {

  /*Проверим ввод аргументов*/
  if (argc != 3) {
    printf("Restart it with two arguments!\n");
    return ret(0);
  }

  /*Проверим знаки*/
  if (argv[1][0] == '-' && argv[2][0] != '-') return ret(2);
  if (argv[2][0] == '-' && argv[1][0] != '-') return ret(1);

  int i = 0;

  /*Если оба аргумента без знаков минус*/
  if (argv[1][0] != '-') {
    if (cycles(argv[1], 0) > cycles(argv[2], 0)) return ret(1);
    if (cycles(argv[1], 0) < cycles(argv[2], 0)) return ret(2);
  }
  /*Если с минусами*/
  else {
    if (cycles(argv[1], 1) > cycles(argv[2], 1)) return ret(2);
    if (cycles(argv[1], 1) < cycles(argv[2], 1)) return ret(1);
  }
  /*Если равны*/
  return ret(3);
}


AnonymUser ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.