The OpenNET Project / Index page

[ новости/++ | форум | wiki | теги ]

форумы  помощь  поиск  регистрация  вход/выход  слежка  RSS
"Нормальный ли код получился? (Переворот строки Си)."
Вариант для распечатки  
Пред. тема | След. тема 
Форум Программирование под UNIX (C/C++)
Изначальное сообщение [ Отслеживать ]

"Нормальный ли код получился? (Переворот строки Си)."  +/
Сообщение от dcc0 on 14-Сен-16, 20:10 
Тренировался, нужно было написать функцию переворачивания строки, strrev не хотелось использовать. Нету ли ничего шибко крамольного в коде?

#include <stdio.h>
const char *prnt(int k, char *a) {
char  new_s[k]={0};
int i=0;
    while(k !=0 ) {
     k--;
        new_s[i]=a[k];
     ++i;

    }
    printf("%s", new_s);
        return (new_s);
}

main (int argc, char *argv[]) {
char *a=argv[1];
    if(argv[1]==0) {
        return 0;
    }
    int k=0;
    while (a[k] != 0) {
k++;    
    }
    prnt( k, a);
}

Ответить | Правка | Cообщить модератору

Оглавление

Сообщения по теме [Сортировка по времени | RSS]


1. "Нормальный ли код получился? (Переворот строки Си)."  +/
Сообщение от f2404 email(ok) on 14-Сен-16, 21:15 
>[оверквотинг удален]
>  char *a=argv[1];
>  if(argv[1]==0) {
>   return 0;
>  }
>  int k=0;
>  while (a[k] != 0) {
> k++;
>  }
>  prnt( k, a);
> }

Этот код не собирается - variable-sized массивы нельзя инициализировать.

Кроме того, вы возвращаете из функции prnt() указатель на локальную переменную - так делать нельзя. Но вам и не нужно ничего возвращать в данном случае.

Ну и стиль хромает, мелких замечаний можно много сделать.

Ответить | Правка | ^ к родителю #0 | Наверх | Cообщить модератору

2. "Нормальный ли код получился? (Переворот строки Си)."  +/
Сообщение от dcc0 on 14-Сен-16, 21:39 
>[оверквотинг удален]
>>  while (a[k] != 0) {
>> k++;
>>  }
>>  prnt( k, a);
>> }
> Этот код не собирается - variable-sized массивы нельзя инициализировать.
> Кроме того, вы возвращаете из функции prnt() указатель на локальную переменную -
> так делать нельзя. Но вам и не нужно ничего возвращать в
> данном случае.
> Ну и стиль хромает, мелких замечаний можно много сделать.

Простите, про variable-sized char *a=argv[1]; это  имеется указатель a на argv[1]?


Ответить | Правка | ^ к родителю #1 | Наверх | Cообщить модератору

3. "Нормальный ли код получился? (Переворот строки Си)."  +/
Сообщение от Asgard on 14-Сен-16, 21:44 
>>[оверквотинг удален]
> Простите, про variable-sized char *a=argv[1]; это  имеется указатель a на argv[1]?

Скорее, по это:
> char  new_s[k]={0};

Ответить | Правка | ^ к родителю #2 | Наверх | Cообщить модератору

5. "Нормальный ли код получился? (Переворот строки Си)."  +/
Сообщение от dcc0 on 14-Сен-16, 21:49 
>>>[оверквотинг удален]
>> Простите, про variable-sized char *a=argv[1]; это  имеется указатель a на argv[1]?
> Скорее, по это:
>> char  new_s[k]={0};

ААА... не подумал что-то... У меня скомпилировался

Ответить | Правка | ^ к родителю #3 | Наверх | Cообщить модератору

4. "Нормальный ли код получился? (Переворот строки Си)."  +/
Сообщение от dcc0 on 14-Сен-16, 21:48 
>[оверквотинг удален]
>>  while (a[k] != 0) {
>> k++;
>>  }
>>  prnt( k, a);
>> }
> Этот код не собирается - variable-sized массивы нельзя инициализировать.
> Кроме того, вы возвращаете из функции prnt() указатель на локальную переменную -
> так делать нельзя. Но вам и не нужно ничего возвращать в
> данном случае.
> Ну и стиль хромает, мелких замечаний можно много сделать.

Так будет корректней?

#include <stdio.h>
main (int argc, char *argv[]) {
    int k=0;
    int i=0;
    
    
    if(argv[1]==0) {
        return 0;    
        }
    
    while (argv[1][k] != 0) {
k++;    
    }

    char  new_s[k]={0};
    while(k !=0 ) {
         k--;
        new_s[i]=argv[1][k];
         ++i;
}
    printf("%s", new_s);

}

Ответить | Правка | ^ к родителю #1 | Наверх | Cообщить модератору

6. "Нормальный ли код получился? (Переворот строки Си)."  +/
Сообщение от dcc0 on 14-Сен-16, 22:23 
Т.е. в итоге либо так
#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
main (int argc, char *argv[]) {
    int k=0;
    int i=0;
    
    if(argv[1]==0) {
        return 0;    
        }
    
    while (argv[1][k] != 0) {
k++;    
    }
    char new_s[120]={0};
    
    while(k !=0 ) {
         k--;
        new_s[i]=argv[1][k];
         ++i;
}
    printf("%s", new_s);

}


ЛИбо использовать malloc?

Ответить | Правка | ^ к родителю #4 | Наверх | Cообщить модератору

7. "Нормальный ли код получился? (Переворот строки Си)."  +/
Сообщение от Asgard on 14-Сен-16, 22:25 
>>[оверквотинг удален]

-> char  new_s[k]={0};
Разве что-то изменилось?
Если внутри [ ] стоит не цифра, а переменная, то конструкцией ={0} пользоваться негоже.
Лучше пользовать memset из библиотеки string.h

#include <string.h>
....
char new_s[k];
memset ((void *) &new_s[0], 0, (k * sizeof (char));

К примеру так...

Ответить | Правка | ^ к родителю #4 | Наверх | Cообщить модератору

8. "Нормальный ли код получился? (Переворот строки Си)."  +/
Сообщение от dcc0 on 14-Сен-16, 22:33 
>[оверквотинг удален]
> -> char  new_s[k]={0};
> Разве что-то изменилось?
> Если внутри [ ] стоит не цифра, а переменная, то конструкцией ={0}
> пользоваться негоже.
> Лучше пользовать memset из библиотеки string.h
> #include <string.h>
> ....
> char new_s[k];
> memset ((void *) &new_s[0], 0, (k * sizeof (char));
> К примеру так...

Понял, немного выше отписал.

А с malloc верно будет так? У меня работает...

#include <stdio.h>
#include <malloc.h>
main (int argc, char *argv[]) {
    int k=0;
    int i=0;
    int n = sizeof(argv[1]);
    char *new_s;
    if(argv[1]==0) {
        return 0;    
        }    
    while (argv[1][k] != 0) {
        k++;    
    }
new_s = (char*) malloc(n*sizeof(int));    

    while(k !=0 ) {
         k--;
        new_s[i]=argv[1][k];
         ++i;
}
    printf("%s", new_s);

}

ЗАранее спасибо за терпеливые ответы

Ответить | Правка | ^ к родителю #7 | Наверх | Cообщить модератору

9. "Нормальный ли код получился? (Переворот строки Си)."  +/
Сообщение от dcc0 on 14-Сен-16, 22:38 
Уже понял, что неправильно ушел читать про дин. выделение памяти...

Ответить | Правка | ^ к родителю #8 | Наверх | Cообщить модератору

10. "Нормальный ли код получился? (Переворот строки Си)."  +/
Сообщение от dcc0 on 14-Сен-16, 22:41 
> Уже понял, что неправильно ушел читать про дин. выделение памяти...

А точно ж "инициализировать" головая уже плывет, я ж и правда забиваю нулями

Ответить | Правка | ^ к родителю #9 | Наверх | Cообщить модератору

11. "Нормальный ли код получился? (Переворот строки Си)."  +/
Сообщение от Asgard on 14-Сен-16, 22:56 
>>[оверквотинг удален]

Как говорила моя учительница математики в 5-м классе (наверняка кого-то цитировала): "Если вы получили правильный ответ, это вовсе не значит, что ваше решение верное... Возможно, вы просто допустили чётное количество ошибок!"

Что бросается навскидку...
char *argv[] --> Следовательно argv - массив указателей. sizeof от элемента массива вернёт размер этого массива, т. е.  int n = sizeof(argv[1]); дат Вам размер указателя на char, а не размер массива байтов отведённого под строку, которая хранится по адресу argv[1].
Если хотите получить длину соответствующей строки, используйте strlen (argv[1])... strlen лежит в библиотеке string.h

То что Вы при этом записывая в new_s[i] не попали в чью-то чужую память и не огребли segmentation fault скорее везение и наличие больших гигов свободной оперативки в системнике.

Второе: Кусок оперативной памяти выдаваемый Вам malloc'ом отдаётся Вам в полноценное пользование и больше никем не контролируется. Т. е. до ближайшего ребута компа система о нём больше знать ничего не хочет. Она только будет поглядывать обним глазом, чтобы кто-то чужой в него не писал ничего. Следовательно, если не хотите утечек памяти, когда закончили работать - не забывайте делать (в Вашем случае) free (new_s);


Ответить | Правка | ^ к родителю #8 | Наверх | Cообщить модератору

12. "Нормальный ли код получился? (Переворот строки Си)."  +/
Сообщение от Asgard on 14-Сен-16, 23:18 
>> То что Вы при этом записывая в new_s[i] не попали в чью-то чужую память

А не попали Вы, собственно из-за ещё одной достаточно грубой ошибки (которую я, признаться, сначала проглядел замыленным взглядом)

new_s = (char*) malloc(n*sizeof(int));

Тут Вы выделяете, грубо говоря, выделяете память под n int'ов, предполагая работать с нею как с char'овскими данными.
Ошибка заключается в том, что обычно sizeof (int) = 4, когда sizeof (char) = 1.

Т. е. Вы выделяете памяти с четырёхкратным запасом! Для учебного примера это не так критично. Но, если Вам надо было обработать строку в 10000 символов, Ваш код сожрал бы на это почти 40 кб вместо 10. Иногда это бывает весьма критично. Особенно если не освобождать память при помощи free ()

Ответить | Правка | ^ к родителю #11 | Наверх | Cообщить модератору

13. "Нормальный ли код получился? (Переворот строки Си)."  +/
Сообщение от dcc0 on 15-Сен-16, 18:49 
>[оверквотинг удален]
> new_s = (char*) malloc(n*sizeof(int));
> Тут Вы выделяете, грубо говоря, выделяете память под n int'ов, предполагая работать
> с нею как с char'овскими данными.
> Ошибка заключается в том, что обычно sizeof (int) = 4, когда sizeof
> (char) = 1.
> Т. е. Вы выделяете памяти с четырёхкратным запасом! Для учебного примера это
> не так критично. Но, если Вам надо было обработать строку в
> 10000 символов, Ваш код сожрал бы на это почти 40 кб
> вместо 10. Иногда это бывает весьма критично. Особенно если не освобождать
> память при помощи free ()

Спасибо огромное. Именно учебный пример.  В чужую память конечно же залез...
Со strlen как то все достаточно понятно,  так strrev именно так и устроен,  но мне хотелось повертеть самую голую базу си

Ответить | Правка | ^ к родителю #12 | Наверх | Cообщить модератору

14. "Нормальный ли код получился? (Переворот строки Си)."  +/
Сообщение от dcc0 on 15-Сен-16, 18:58 

После php –это все как америка

А если не инициализировать массив, как это было в самом начале, то это терпимо?
И сделать,  конечно же ограничение на длину строки

Ответить | Правка | ^ к родителю #13 | Наверх | Cообщить модератору

15. "Нормальный ли код получился? (Переворот строки Си)."  +/
Сообщение от dcc0 on 15-Сен-16, 19:01 
Ладно,  сейчас до дому доберуст,  буду еще экспериментировать,  а то программировать в электричке на мобильном. Как то не айс
Ответить | Правка | ^ к родителю #14 | Наверх | Cообщить модератору

17. "Нормальный ли код получился? (Переворот строки Си)."  +/
Сообщение от dcc0 email on 15-Сен-16, 22:39 
Вообще если честно посмотреть на ситуацию, считывать все в новый массив и не нужно.

#include <stdio.h>

int main(int argc, char *argv[])
{
  if(argc < 2) {
    printf("String is no set!");
return 0;
  }
  int i = 0;
  while (argv[1][i] != 0) {
        ++i;
        }

while(i !=0 ) {
         i--;
        printf("%c", argv[1][i]);
        }
  return 1;
}

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

Ответить | Правка | ^ к родителю #15 | Наверх | Cообщить модератору

19. "Нормальный ли код получился? (Переворот строки Си)."  +/
Сообщение от f2404 email(ok) on 15-Сен-16, 22:53 
> Вообще если честно посмотреть на ситуацию, считывать все в новый массив и
> не нужно.

Ну это не переворот строки, а печатание её задом наперёд.


Ответить | Правка | ^ к родителю #17 | Наверх | Cообщить модератору

21. "Нормальный ли код получился? (Переворот строки Си)."  +/
Сообщение от dcc0 email on 15-Сен-16, 23:38 
>> Вообще если честно посмотреть на ситуацию, считывать все в новый массив и
>> не нужно.
> Ну это не переворот строки, а печатание её задом наперёд.

Таак...
strrev делает тоже самое, я даже проверил.
Вот вопрос , что Вы понимаете под переворотом строки?
Я именно и понимаю - вывод задом наперед.


Я вроде бы добился чего хотел, даже немножко поигрался, чтобы все-таки сделать через printf ("%s", var)

#include <stdio.h>
int main(int argc, char *argv[])
{
  if(argc < 2) {
    printf("String is no set!");
return 0;
  }
  int i = 0;
  while (argv[1][i] != 0) {
        
        if (i > 100) {
            printf("String is too long!");
            return 0;  
            }
            ++i;
        }
char c;
int k=0;
while(i > k ) {
     i--;      
           c=argv[1][i];
           argv[1][i]=argv[1][k];    
           argv[1][k]=c;  
    ++k;
        }
  printf("%s", argv[1]);
  return 1;
}

Ответить | Правка | ^ к родителю #19 | Наверх | Cообщить модератору

27. "Нормальный ли код получился? (Переворот строки Си)."  +/
Сообщение от f2404 email(ok) on 16-Сен-16, 09:17 
>>> Вообще если честно посмотреть на ситуацию, считывать все в новый массив и
>>> не нужно.
>> Ну это не переворот строки, а печатание её задом наперёд.
> Таак...
> strrev делает тоже самое, я даже проверил.
> Вот вопрос , что Вы понимаете под переворотом строки?
> Я именно и понимаю - вывод задом наперед.

Переворот строки - это функция берёт строку и возвращает строку, обратную исходной. То есть, в результате у нас есть исходная строка (нетронутая) и новая строка. strrev работает именно так.

Ответить | Правка | ^ к родителю #21 | Наверх | Cообщить модератору

24. "Нормальный ли код получился? (Переворот строки Си)."  +/
Сообщение от dcc0 email on 16-Сен-16, 00:27 
Если имелось ввиду отображение букв в другую сторону, то такой такую гаррипоттеровскую магию я не имею = )
Ответить | Правка | ^ к родителю #19 | Наверх | Cообщить модератору

28. "Нормальный ли код получился? (Переворот строки Си)."  +/
Сообщение от f2404 email(ok) on 16-Сен-16, 09:17 
> Если имелось ввиду отображение букв в другую сторону, то такой такую гаррипоттеровскую
> магию я не имею = )

Нет, этого я не имел в виду, хотя идея интересная :)

Ответить | Правка | ^ к родителю #24 | Наверх | Cообщить модератору

20. "Нормальный ли код получился? (Переворот строки Си)."  +/
Сообщение от Asgard on 15-Сен-16, 23:18 
> Хотя, наверное, и от второго цикла можно избавиться, если найти способ сразу
> определить конец массива.

Тут можно будет "напороться". Массив строк - это, по сути, двумерный массив символов, в котором первая размерность определяет строки, а вторая - символ в строке. Поэтому размер строки будет соответствовать длине самой длинной строки в массиве. С другой стороны какая-то строка в массиве может быть короче других. В этом случае длина строки не равна размеру строки.
Например:
char *str[] = { "Some", "Plain", "Strings" }; // Аналогично объявлению argv
Здесь str можно рассматривать, как двумерный массив на 3 строки длиной, достаточной для размещения самой длинной строки - "Strings" + символ завершения строки - десятичный 0.
Т. о. размер строки тут будет strlen ("Strings") + 1, т. е. 8, а длина строки будет 4, 5 и 7 соответственно.
Другими словами, str в данном случае можно рассматривать и как char str[3][8] = { ... };

Ответить | Правка | ^ к родителю #17 | Наверх | Cообщить модератору

16. "Нормальный ли код получился? (Переворот строки Си)."  +/
Сообщение от dcc0 email on 15-Сен-16, 21:36 
А ну таки да -
Если строка с пробелом, то в ее первая часть попадет в argv[1]
а остальная часть в argv[2]
Так как, если я верно понял Ваше сообщаение argv хранит указатели (на аргументы) на массивы символов

Ответить | Правка | ^ к родителю #12 | Наверх | Cообщить модератору

18. "Нормальный ли код получился? (Переворот строки Си)."  +/
Сообщение от Asgard on 15-Сен-16, 22:41 
> А ну таки да -
> Если строка с пробелом, то в ее первая часть попадет в argv[1]
> а остальная часть в argv[2]
> Так как, если я верно понял Ваше сообщаение argv хранит указатели (на
> аргументы) на массивы символов

Да, верно. в массиве argv хранятся указатели на аргументы (параметры), переданные программе в командной строке. Аргументы разделяются пробелами. Собственное имя программы (текущее имя запускаемого файла) располагается по адресу argv[0]. Количество элементов массива argv передаётся в argc.

По поводу необходимости инициализации выделяемой памяти. Зависит от того, как Вы её "получили" и что будете с ней делать. Если Вы просто объявили переменную/массив (например, int arr[12], x;), или выделили место с помощью malloc, то данный кусок памяти не будет пустым (x или arr[i] будут не равны нулю) - там будет лежать то, что осталось от какой-то программы, которая "пользовалась" этой памятью до Вас, или просто случайный мусор. С другой стороны, если для выделения памяти используется операция calloc, то она гарантированно чистит (заполняет нулями) выделяемую память. Если после выделения памяти вы сразу же всю её заполняете своими данными, то Вам, по большому счёту, наплевать что там было при выделении памяти. Но так бывает не всегда. Поэтому, для собственной подстраховки, да и просто как правило хорошего тона, выделенную память лучше сразу почистить/проинициализировать.

Ответить | Правка | ^ к родителю #16 | Наверх | Cообщить модератору

22. "Нормальный ли код получился? (Переворот строки Си)."  +/
Сообщение от dcc0 email on 15-Сен-16, 23:46 
>[оверквотинг удален]
> переменную/массив (например, int arr[12], x;), или выделили место с помощью malloc,
> то данный кусок памяти не будет пустым (x или arr[i] будут
> не равны нулю) - там будет лежать то, что осталось от
> какой-то программы, которая "пользовалась" этой памятью до Вас, или просто случайный
> мусор. С другой стороны, если для выделения памяти используется операция calloc,
> то она гарантированно чистит (заполняет нулями) выделяемую память. Если после выделения
> памяти вы сразу же всю её заполняете своими данными, то Вам,
> по большому счёту, наплевать что там было при выделении памяти. Но
> так бывает не всегда. Поэтому, для собственной подстраховки, да и просто
> как правило хорошего тона, выделенную память лучше сразу почистить/проинициализировать.

Чувствую на теме выделения памяти застряну, т.к. пока не все прозрачно, но это чуть позже.

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

Ответить | Правка | ^ к родителю #18 | Наверх | Cообщить модератору

23. "Нормальный ли код получился? (Переворот строки Си)."  +/
Сообщение от dcc0 email on 15-Сен-16, 23:53 
Хотя, наверное, проще сделать транслитерацию.
Ответить | Правка | ^ к родителю #22 | Наверх | Cообщить модератору

25. "Нормальный ли код получился? (Переворот строки Си)."  +/
Сообщение от Asgard on 16-Сен-16, 02:20 
> Хотя, наверное, проще сделать транслитерацию.

Отработайте логику на английском алфавите, а потом перепозайте на wchar (wchar.h и иже с ними) и многобайтовость. Там уже не будет ничего сложного

Ответить | Правка | ^ к родителю #23 | Наверх | Cообщить модератору

26. "Нормальный ли код получился? (Переворот строки Си)."  +/
Сообщение от dcc0 email on 16-Сен-16, 08:38 
>[оверквотинг удален]
> new_s = (char*) malloc(n*sizeof(int));
> Тут Вы выделяете, грубо говоря, выделяете память под n int'ов, предполагая работать
> с нею как с char'овскими данными.
> Ошибка заключается в том, что обычно sizeof (int) = 4, когда sizeof
> (char) = 1.
> Т. е. Вы выделяете памяти с четырёхкратным запасом! Для учебного примера это
> не так критично. Но, если Вам надо было обработать строку в
> 10000 символов, Ваш код сожрал бы на это почти 40 кб
> вместо 10. Иногда это бывает весьма критично. Особенно если не освобождать
> память при помощи free ()

Просто для для проверки понимания:
Т.е. должно быть

так примерно int n = strlen(argv[1]);
а потом > new_s = (char*) malloc(n*sizeof(char));
И в конце free(new_s)
Верно ли теперь?

Ответить | Правка | ^ к родителю #12 | Наверх | Cообщить модератору

29. "Нормальный ли код получился? (Переворот строки Си)."  +/
Сообщение от f2404 email(ok) on 16-Сен-16, 09:20 
> Просто для для проверки понимания:
> Т.е. должно быть
> так примерно int n = strlen(argv[1]);
> а потом > new_s = (char*) malloc(n*sizeof(char));
> И в конце free(new_s)
> Верно ли теперь?

Почти верно.
Вместо int для размеров лучше использовать size_t.
Выделять нужно не n, а n+1 байт: последний байт для нуль-терминатора.
В С не нужно приводить результат malloc к типу, то есть (char*) не нужен.

Ответить | Правка | ^ к родителю #26 | Наверх | Cообщить модератору

30. "Нормальный ли код получился? (Переворот строки Си)."  +/
Сообщение от dcc0 email on 16-Сен-16, 11:16 
>[оверквотинг удален]
>> Т.е. должно быть
>> так примерно int n = strlen(argv[1]);
>> а потом > new_s = (char*) malloc(n*sizeof(char));
>> И в конце free(new_s)
>> Верно ли теперь?
> Почти верно.
> Вместо int для размеров лучше использовать size_t.
> Выделять нужно не n, а n+1 байт: последний байт для нуль-терминатора.
> В С не нужно приводить результат malloc к типу, то есть (char*)
> не нужен.

ОК, Спсибо огромное, все стало чуть-чуть яснее.

Сила - Великая штука, у меня даже получилось сделать свой урезанный substr.

Ответить | Правка | ^ к родителю #29 | Наверх | Cообщить модератору

31. "Нормальный ли код получился? (Переворот строки Си)."  –1 +/
Сообщение от dcc0 email on 16-Сен-16, 11:26 
Последний пост.
Код моего урезанного substr отрабатывает корректно только два варианта, т.е. с двумя или тремя аргументами.
substr(string 0 1)
substr(string 1)
Больше мне и не нужно было, код довольно запутанный и не аккуратный, выкладываю только для того, чтобы если кому-то придёт мысль написать свой substr, можно посмотреть, как я мыслил. Код свое отработал и переворот, и substr писались для алгоритма нерекурсивных перестановок на чистом си, в целях обучения все тому же си.
Правда, получилось не совсем чистый си, хотелось без библиотек ,  пришлось заюзать
stdlib.h , так как понадобилось преобразование типов из char в int - функция atoi

Код не чистил:

#include <stdio.h>
#include <stdlib.h>
#include <tchar.h>
#include <locale.h>
#ifdef UNICODE
    typedef wchar_t TCHAR;
#else
    typedef char TCHAR;
#endif
int main(int argc, char *argv[])
{
    setlocale( LC_CTYPE, ".1251" );
char *a=argv[1];

  
  if(argc < 2) {
    printf("String is no set!");
return 0;
  }
  int i = 0;
  while (a[i] != 0) {
        
        if (i > 100) {
            printf("String is too long!");
            return 0;  
            }
            ++i;
        }
if (argv[2]!=0 && argv[3]!=0 ) {

      int c_end;
      c_end = atoi(argv[3]);
      
       if (i < c_end) {
          printf("Nothing to cut!");  
           return 0;  
          }
      if (i  >=  c_end) {
  
      i=c_end;
      }
               int k=0;
               if (k ==i ) {
printf("%s", argv[1]);  
return 1;  
}
while(k !=i ) {
            
  printf("%c", argv[1][k]);
        k++;
        }
  return 1;
}
if (argv[2]!=0 && argv[3]==0 ) {
               int c_end;
                c_end = atoi(argv[2]);
      
       if (i < c_end) {
          printf("Nothing to cut!");  
          }
  
int k=c_end;
if (k > i) {
printf("%s", argv[1]);
return 1;    
}    

while(k != i ) {  
  printf("%c", argv[1][k]);
         k++;
        }
  return 1;
        
              
}

}


Ответить | Правка | ^ к родителю #30 | Наверх | Cообщить модератору

32. "Нормальный ли код получился? (Переворот строки Си)."  +/
Сообщение от dcc0 email on 16-Сен-16, 14:58 
Второй вариант вроде тоже корректный получился.
Можно вводить строки с пробелом, но тогда надо брать в кавычки. В общем и русскими символами все тоже работает. Мусора вроде нет.


#include <stdio.h>
#include <locale.h>
#include <tchar.h>
#ifdef UNICODE
    typedef wchar_t TCHAR;
#else
    typedef char TCHAR;
#endif

char stev(char * a, int i) {
    
      int k=0;
      char c;

while( i > k ) {  
         i--;      
         c=a[k];
         a[k]=a[i];
         a[i]=c;
          k++;
            
        }
}
int main (int argc, char *argv[]) {
     setlocale( LC_CTYPE, ".1251" );
if (argc  == 1) {
printf("Enter the string!");  
return 0;
}
if (argc > 1) {
         char *a=argv[1];
         int z = 0;
while (argv[1][z] != 0) {
      ++z;
        }
        stev(argv[1], z);
        printf("%s", a);
         }  
}

Ответить | Правка | ^ к родителю #31 | Наверх | Cообщить модератору

33. "Нормальный ли код получился? (Переворот строки Си)."  +/
Сообщение от f2404 (ok) on 16-Сен-16, 15:02 
> Второй вариант вроде тоже корректный получился.
> Можно вводить строки с пробелом, но тогда надо брать в кавычки. В
> общем и русскими символами все тоже работает. Мусора вроде нет.

А зачем вы определяете TCHAR и не используете его?

Ответить | Правка | ^ к родителю #32 | Наверх | Cообщить модератору

34. "Нормальный ли код получился? (Переворот строки Си)."  +/
Сообщение от dcc0 email on 16-Сен-16, 17:23 
>> Второй вариант вроде тоже корректный получился.
>> Можно вводить строки с пробелом, но тогда надо брать в кавычки. В
>> общем и русскими символами все тоже работает. Мусора вроде нет.
> А зачем вы определяете TCHAR и не используете его?

Не разобрался еще с этим, забыл выкинуть из кода.
В это еще предстоит вникнуть

Ответить | Правка | ^ к родителю #33 | Наверх | Cообщить модератору

36. "Нормальный ли код получился? (Переворот строки Си)."  +/
Сообщение от Asgard on 16-Сен-16, 18:02 
> if (argc > 1) {
>          char *a=argv[1];
>          int z = 0;
> while (argv[1][z] != 0) {
>       ++z;
>         }
>         stev(argv[1], z);
>         printf("%s", a);
>          }
> }

Вы установили в коде, что работать собираетесь с указателем a (char *a=argv[1];). Почему далее по коду (цикл while и вызов stev()) Вы обращаетесь к argv[1]?

Да, пример всё ещё учебный... Но именно на учебных примерах надо оттачивать свою внимательность. Иначе в реальном коде это может легко привести к многочасовым (а иногда и многодневным) поискам серой кошки в тёмной комнате :)

Ответить | Правка | ^ к родителю #32 | Наверх | Cообщить модератору

35. "Нормальный ли код получился? (Переворот строки Си)."  +/
Сообщение от Asgard on 16-Сен-16, 17:50 
> В С не нужно приводить результат malloc к типу, то есть (char*)
> не нужен.

Возможно... Но, когда man malloc говорит, что void *malloc(size_t size); я лично предпочту сделать явное приведение типа. Да, тот же товарищ man ниже говорит что выданный шмат сала, т. е. памяти "suitably aligned for any built-in type"... Но человеку, пользующему не только лишь built-in type, вполне простительно выработать привычку делать приведение типов всегда, нежели каждый раз думать: "В эту кучу я буду сваливать что-то из соседского typedef'а или акуратно разложу свои буилд-ины?.."

Ответить | Правка | ^ к родителю #29 | Наверх | Cообщить модератору

37. "Нормальный ли код получился? (Переворот строки Си)."  +1 +/
Сообщение от f2404 (ok) on 16-Сен-16, 18:21 
>> В С не нужно приводить результат malloc к типу, то есть (char*)
>> не нужен.
> Возможно... Но, когда man malloc говорит, что void *malloc(size_t size); я лично
> предпочту сделать явное приведение типа. Да, тот же товарищ man ниже
> говорит что выданный шмат сала, т. е. памяти "suitably aligned for
> any built-in type"... Но человеку, пользующему не только лишь built-in type,
> вполне простительно выработать привычку делать приведение типов всегда, нежели каждый
> раз думать: "В эту кучу я буду сваливать что-то из соседского
> typedef'а или акуратно разложу свои буилд-ины?.."

Дело ваше, но

MEM02-C-EX1: Do not immediately cast the results of malloc() for code that will be compiled using a C90-conforming compiler because it is possible for the cast to hide a more critical defect (see DCL31-C. Declare identifiers before using them for a code example that uses malloc() without first declaring it).

https://www.securecoding.cert.org/confluence/display/c/MEM02...

Ответить | Правка | ^ к родителю #35 | Наверх | Cообщить модератору

38. "Нормальный ли код получился? (Переворот строки Си)."  +/
Сообщение от dcc0 on 20-Сен-16, 15:42 
Дособирал я все-таки этот код:
Вроде все стандартно, вот только не знаю на любой ли машине скомпилится и корректно отработает.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
//This cut x
  char  subb (char * x, int i) {
               x[i]='\0';  
}
//This cut y
  char  subb2 (char * y, int i) {
               int k = 0;
               while (k != strlen(y)+1) {
                     y[k]=y[i];
                    i++;
                    k++;
              }  
  }
//It gets an argumet like 1234 or abcd. All symbols must be uniqe
        int main (int argc, char *argv[]) {
             if (argc < 2) {
             printf("Enter an argument. Example 1234");
             return 0;        
                      }          
             char b[strlen(argv[1])];
             char a[strlen(argv[1])];
             int ij=0;
             while (ij!=strlen(argv[1])) {
                   a[ij]=argv[1][ij];
                   b[ij]=argv[1][ij];
                   ij++;
                   }
                   a[ij]='\0';
                   b[ij]='\0';
                    strrev(a);
                    printf("%s\n", a);
             int i;
             int j;
             char c;
            
          while (strcmp (a, b) !=0 ) {
          i=0;

          while(a[i] > a[i-1]) {
          i++;
          }
          
          j=0;
          while(a[j] < a[i]) {
          j++;    
}

      c=a[j];
      a[j]=a[i];
      a[i]=c;
    
      char x[strlen(a)+1];
      char y[strlen(a)+1];
      strcpy(x,a);
      strcpy(y,a);
      subb(x, i);
      
      strrev(x);
  
      subb2(y, i);
      sprintf(a, "%s%s", x,y);      
      printf("%s\n", a);
      

   }

}

Ответить | Правка | ^ к родителю #37 | Наверх | Cообщить модератору

Архив | Удалить

Рекомендовать для помещения в FAQ | Индекс форумов | Темы | Пред. тема | След. тема


  Закладки на сайте
  Проследить за страницей
Created 1996-2017 by Maxim Chirkov  
ДобавитьРекламаВебмастеруГИД  
Hosting by Ihor