Это, по-видимому, (недокументированное) расширение «GNU»: [ correction : Наконец, я нашел упоминание в документах. См. Ниже.]
Следующая команда использует параметр -dM
для печати всех препроцессоров; поскольку входной «файл» пуст, он показывает точно предопределенные макросы. Он был запущен с gcc-4.7.3 на стандартной установке ubuntu. Вы можете видеть, что препроцессор является стандартным. Всего существует 243 макроса с -std=gnu99
и 240 с -std=c99
; Я отфильтровал вывод для релевантности.
$ cpp --std=c89 -dM < /dev/null | grep linux
#define __linux 1
#define __linux__ 1
#define __gnu_linux__ 1
$ cpp --std=gnu89 -dM < /dev/null | grep linux
#define __linux 1
#define __linux__ 1
#define __gnu_linux__ 1
#define linux 1
$ cpp --std=c99 -dM < /dev/null | grep linux
#define __linux 1
#define __linux__ 1
#define __gnu_linux__ 1
$ cpp --std=gnu99 -dM < /dev/null | grep linux
#define __linux 1
#define __linux__ 1
#define __gnu_linux__ 1
#define linux 1
Стандарты «gnu standard» также #define unix
. (Использование c11
и gnu11
дает те же результаты.)
Я полагаю, что у них были свои причины, но мне кажется, что я устанавливаю установку gcc по умолчанию (которая компилирует код C с -std=gnu89
если не указано иное) несоответствия, и - как в этом вопросе - удивительно. Загрязнение глобального пространства имен макросами, имена которых не начинаются с символа подчеркивания, не допускается в соответствии с реализацией. (6.8.10p2: «Любые другие предопределенные имена макросов начинаются с верхнего подчеркивания, за которым следует буква верхнего регистра или второй символ подчеркивания», но, как упоминалось в Приложении J.5 (проблемы с переносимостью), такие имена часто предопределены.)
Когда я изначально написал этот ответ, мне не удалось найти какую-либо документацию в gcc об этой проблеме, но я, наконец, обнаружил ее, а не в C, определяемом реализацией поведения и в расширениях C , но в разделе cpp
руководства 3.7.3 , где он отмечает, что:
Мы постепенно прекращаем работу предопределенные макросы, которые находятся за пределами зарезервированного пространства имен. Вы никогда не должны использовать их в новых программах & hellip;
blockquote>
Я не вижу заданного вопроса, поэтому я также опубликую свою собственную реализацию, которая действительно работает, так как весь ваш код является беспорядком. Не стесняйтесь ничего спрашивать.
#include <stdio.h>
#include <string.h>
int isPalindrome(char*);
int main(int argc, char * argv[])
{
/* Skip filepath (argv[0]); end of command line is marked with NULL. */
for(int argIndex = 1; argv[argIndex] != NULL; ++argIndex)
{
isPalindrome(argv[argIndex])
? fprintf(stdout, "%s is a palindrome.\n", argv[argIndex])
: fprintf(stdout, "%s is NOT a palindrome.\n", argv[argIndex]);
}
return 0;
}
int isPalindrome(char* pString)
{
/* Ignore the terminator. */
size_t lastIndex = strlen(pString) - 1;
size_t middle = lastIndex / 2;
/* Include the middle index in case the string length is an odd number. */
for (size_t offset = 0; offset <= middle; ++offset)
{
/* No need for flags, stop as soon as you see different letters. */
if (pString[offset] != pString[lastIndex - offset])
{
return 0;
}
}
/* Line only reached if all symmetrical letters are not different. */
return 1;
}
Именован исполняемый файл myNewProgram. Это мой консольный ввод-вывод в Ubuntu. Естественно, кавычки должны явно выражать аргументы, чтобы они не были разделены пробелами.
/home/don/myNewProgram "TEST" "TET" "" "HUH" "OOMPA LOOMPA" "OOOOO"
TEST is NOT a palindrome.
TET is a palindrome.
is NOT a palindrome.
HUH is a palindrome.
OOMPA LOOMPA is NOT a palindrome.
OOOOO is a palindrome.
Если вы запускаете командную строку в Windows, попробуйте
<path to program>/<name of program>.exe "TEST" "TET" "" "HUH" "OOMPA LOOMPA" "OOOOO"
blockquote>
it is command line based c program to check for palindrome string and my answer is coming right but i had to supply arguments 2 times in the terminal....
Ваша программа не может дать правильные результаты, потому что цикл
for
используется для определения того, является ли входная строка палиндром или не повторяется не один раз. [подробнее см. ниже]Я не знаю, что именно означает -
i had to supply arguments 2 times in the terminal
By глядя на ваш код, могу только сказать, что вы должны передать строку (чтобы проверить, является ли она палиндром или нет) в качестве аргумента командной строки, и поскольку ваш
main()
имеетgets()
, поэтому он останавливается там и ждет ввода пользователя и там вы должны указывать ту же строку, которую вы передаете в качестве аргумента командной строки для программы. Кажется, это то, что вы подразумеваете под своим утверждением -i had to supply arguments 2 times...
Прежде всего, не используйте gets (). Это небезопасно и, кроме того, оно устарело. Проверьте на этом . Вместо этого используйте fgets (). Проверьте этот .
Есть два способа получить вход -
- Возьмите его у пользователя во время выполнения (вы можете использовать
fgets()
для это)- Передайте его как аргумент командной строки
Так как в аннотациях вы упомянули -
it is command line based c program to check for palindrome string and my answer is...
Итак, в моем ответ, я буду принимать ввод как аргумент командной строки.Если вы используете компилятор
gcc
, программа компиляции с параметрами-Wall -Wextra
и компилятором выдает предупреждающее сообщение для этого оператора(argv[1]) == string;
warning: statement with no effect
В цикле
for
функцииpalindrome()
вы прерываете цикл на первой итерации:for (i = 0; i < strlen(string); i++) { if (string[i] == string[strlen(string) - i - 1]) flag = 1; break; // <--- will break the loop in first iteration }
И функция
palindrome()
заканчивает сообщение о палиндроме на основе того, будет ли первый и последний символ входной строки такой же или нет.Вы должны разбить цикл только тогда, когда любой символ в позиции
i
в первой половине строки не совпадает с символом в позицииstring_len - i -1
во второй половине строки. Кроме того, вам не нужно итерировать всю строку, чтобы проверить, является ли она палиндром или нет:for (i = 0; i < strlen(string); i++) { ^^^^^^^^^^^^^
Вам просто нужно перевести строку в ее середину, чтобы определить, является ли строка палиндром или нет .
Тип возврата
strlen()
-size_t
, который являетсяunsigned integer
. Итак, лучше взять итератор цикла одного и того же типа.Между заголовком файла и скобкой угла открытия и закрытия не должно быть пробелов
<,>
:#include < stdio.h > #include < string.h >
Пока ищет заголовочный файл, компилятор также включает пробел в имени и не обрезает ведущее и конечное пространство и сообщит об ошибке
' stdio.h '
заголовочного файла.Объединяя все это вместе, вы можете сделать :
#include <stdio.h> #include <string.h> int palindrome(char *p_string) { int flag = 0; size_t len = strlen(p_string); if (len == 1) flag = 1; for (size_t i = 0; i < (len/2); i++) { if (p_string[i] == p_string[len - i - 1]) flag = 1; else break; } if (flag == 1) printf("palindrome string\n"); else printf("not palindrome string\n"); return 0; } int main(int argc, char * argv[]) { /* Check for number of expected arguments */ if (argc != 2) { fprintf (stderr, "Invalid number of arguments\nUsage:%s <string>\n", argv[0]); return -1; } palindrome(argv[1]); return 0; }
Вы можете использовать его следующим образом:
$ ./a.out abc not palindrome string $ ./a.out aba palindrome string $ ./a.out abccba palindrome string
Как указано в комментариях, строка (argv[1]) == string
ничего не делает (gcc
, который сказал бы вам warning: statement with no effect [-Wunused-value]
)
Кроме того, функция gets
не используется, даже для тестовых программ, fgets
выполнит одно и то же задание более надежно:
/* assuming string is an array: */
fgets(string, sizeof string, stdin);
/* when string points on at least `size` bytes: */
fgets(string, size, stdin);
Итак, ваш исправленный код main()
может быть:
int main(int argc, char * argv[])
{
char string[200];
fgets(string, sizeof string, stdin);
return palindrome(string);
}
Но есть логичный проблема в функции palindrome
, посмотрите на:
int flag = 0;
for (i = 0; i < strlen(string); i++) {
if (string[i] == string[strlen(string) - i - 1])
flag = 1;
break;
}
При размещенном здесь break
вы будете тестировать только i = 0
(вы можете добавить один printf("testing i=%d", i);
непосредственно перед if
], чтобы увидеть это.
Итак, каждая строка, которая начинается и заканчивается с той же буквой, будет считаться палиндром ...
А также вы должны инвертировать тест. flag
следует установить в 1
и установить на 0
, если две проверенные буквы различны.
Ваш цикл for
должен выглядеть так:
int flag = 1;
for (i = 0; i < strlen(string); i++) {
printf("testing %d vs %d\n", i, strlen(string)-i-1);
if (string[i] != string[strlen(string) - i - 1])
{
flag = 0;
break;
}
}
Чтобы идти дальше, данный код может быть улучшен:
strlen()
, где одного вызова будет достаточно, for
может быть лучше ...