සී හි ගොල්ෆ් ක්‍රීඩා කිරීම සඳහා උපදෙස්


147

සී හි ගොල්ෆ් ක්‍රීඩා කිරීම සඳහා ඔබට ඇති පොදු උපදෙස් මොනවාද? මම සොයන්නේ කේත ගොල්ෆ් ගැටලුවලට පොදුවේ අවම වශයෙන් තරමක් විශේෂිත වූ කේත ගොල්ෆ් ගැටලුවලට අදාළ කළ හැකි අදහස් (උදා: "අදහස් ඉවත් කිරීම" පිළිතුරක් නොවේ). කරුණාකර පිළිතුරකට එක් ඉඟියක් පළ කරන්න. ඔබේ ඉඟිය C89 සහ / හෝ C99 සඳහා අදාළ වන්නේ නම් සහ එය ක්‍රියාත්මක වන්නේ යම් යම් සම්පාදකයින් මත පමණක්ද යන්න කරුණාකර ඇතුළත් කරන්න.


9
මම හිතන්නේ ලොකුම තනි වාක්‍ය ඉඟිය: IOCCC වෙත ඉදිරිපත් කළ ජයග්‍රාහී කේත කියවන්න.
vsz

Answers:


113

නිඛිල අතර අසමානතාවය පරීක්ෂා කිරීමට bitwise XOR භාවිතා කරන්න:

if(a^b)if(a!=b)අක්ෂර 1 ක් ඉතිරි කරනවා වෙනුවට .


76
a-bඔබට එකම බලපෑමක් ලබා දෙයි.
ugoren

23
ඒ හා සමානව ඔබට a*bඒ වෙනුවට භාවිතා කළ හැකිය a&&b(වෙනස් ප්‍රමුඛතාවයක් ඇත, නරක විය හැකිය හෝ නොවිය හැක). ඔබ / = -b දන්නවා නම් (උදා: ඒවා අත්සන් කර නැත) එවිට a||b==a+b
walpen

3
වඩා හොඳ නමුත් එය එල්විස් ක්‍රියාකරු සමඟ ඒකාබද්ධ කරන්න ?:(එසේ නම් වෙනුවට): වෙනස් නම් යමක් කිරීමට නිදහස් වීම සඳහා: a^b?_diff_:;
ඔලිවියර් ඩුලැක්

1
L ඔලිවියර් ඩියුලැක් ව්‍යාජ ශාඛාවක් නම් හිස් ත්‍රිත්වයක් පිළිගන්නා සම්පාදකයෙකු සිටීද?
ජොනතන් ෆ්‍රෙච්

1
LOlivierDulac ඔබට පරීක්ෂා කළ හැකිය. මා දන්නා දෙයින්, GCC සතුව ?:ක්‍රියාකරු සතුව ඇතa ? a : b
Chromium

79
  • mainපූර්ණ සංඛ්‍යා විචල්‍යයන් එකක් හෝ කිහිපයක් ප්‍රකාශ කිරීම සඳහා අපයෝජන තර්ක ලැයිස්තුව:

    main(a){for(;++a<28;)putchar(95+a);}
    

    ( ක්‍රමලේඛන භාෂාවලින් හෝඩියට පිළිතුර )

    මෙම විසඳුම a(අකා argc) ආරම්භ වන්නේ 1, තර්කයකින් තොරව වැඩසටහන කැඳවනු ලැබුවහොත් ය.

  • දේවල් බිංදුවට ආරම්භ කිරීමට ගෝලීය විචල්‍යයන් භාවිතා කරන්න:

    t[52],i;main(c){for(;i<52;)(c=getchar())<11?i+=26:t[i+c-97]++;
    for(i=27;--i&&t[i-1]==t[i+25];);puts(i?"false":"true");}
    

    ( ඇනග්‍රෑම් කෝඩ් ගොල්ෆ් ක්‍රීඩාවට පිළිතුර ! )


විචල්‍යයන් සඳහා අර්ථ දක්වා ඇති දත්ත වර්ග නොමැත, ප්‍රධාන ශ්‍රිතයේ ආපසු පැමිණීමේ වර්ගයක් නොමැත. මෙය වලංගු C වාක්‍ය ඛණ්ඩයක්ද?
pavi2410

2
Av පවිත්‍රා: ඔව්, මෙය පොදුවේ හැඳින්වෙන්නේ "පූර්ව ඇන්සි " හෝ "කේ ඇන්ඩ් ආර්" සී ප්‍රභේදය ලෙසිනි . පැහැදිළිව ප්‍රකාශිත වර්ගයක් නොමැති විචල්‍යයක් a int. එතැන් සිට මෙය අවලංගු කර ඇති අතර සියලු විචල්‍යයන් සහ කාර්යයන් වර්ගයකින් ප්‍රකාශ කිරීම අවශ්‍ය වේ.
ඩැනියෙල් කමිල් කොසාර්

67

වරහන් වළක්වා ගනිමින් එකම කොටසක බහුවිධ ප්‍රකාශන ක්‍රියාත්මක කිරීමට කොමා ක්‍රියාකරු භාවිතා කළ හැකිය:

main(){                                                                                     

int i = 0;                                                                                  
int j = 1;                                                                                  
if(1)                                                                                       
    i=j,j+=1,printf("%d %d\n",i,j); // multiple statements are all executed                                                  
else                                                                                        
    printf("failed\n");                                                                     

}

නිමැවුම්: 1 2


එක් ප්‍රකාශයක් නම් ක්‍රියා නොකරයි break.
මැක්සිම් මිහයිලොව්

10
Ax මැක්ස්ලෝන්බෝයි breakයනු ප්‍රකාශයක් වන අතර මෙම පිළිතුර ප්‍රකාශන ගැන කතා කරයි.
NieDzejkob

64

ව්‍යසනකාරී ශ්‍රිත-තර්ක වර්ග ප්‍රකාශ කිරීමෙන් වළකින්න

ඔබ තර්ක පහම පවතින ශ්‍රිතයක් ප්‍රකාශ කරන්නේ intනම් ජීවිතය හොඳයි. ඔබට සරලව ලිවිය හැකිය

f(a,b,c,d,e){

නමුත් , හෝ, හෝ dවිය යුතු යැයි සිතමු . එවිට ඔබ ඉස්කුරුප්පු කර ඇත! එක් පරාමිතියකට පෙර වර්ගයක් තිබේ නම්, ඒවා සියල්ලම විය යුත්තේ:charint*

f(int a,int b,int c,int*d,int e){

නමුත් ඉන්න! නිෂ් less ල චරිත මෙම විනාශකාරී පිපිරීම වටා ක්‍රමයක් තිබේ. එය මෙසේ ය:

f(a,b,c,d,e) int *d; {

mainඔබට විධාන රේඛා තර්ක භාවිතා කිරීමට අවශ්‍ය නම් මෙය සම්මත ප්‍රකාශයක් මත ඉතිරි වේ :

main(c,v)char**v;{

බයිට් දෙකක් වඩා කෙටි වේ

main(int c,char**v){

පීපීසීජී හි මා මෙතෙක් හමු නොවූ හෙයින් මෙය සොයා ගැනීම ගැන මා පුදුමයට පත් විය.


7
පෘථිවියේ එය ක්‍රියාත්මක වන්නේ ඇයි ??
නතානියෙල්

31
පෙනෙන විදිහට මෙය K&R ශෛලිය ලෙස හැඳින්වෙන අතර එය ANSI C ට පෙර දශකයක් ගතවේ.
ඩෙනිස්

1
K&R විශේෂාංග සහ නවතම ('99 කියන්න) විශේෂාංග එකට භාවිතා කිරීම නැත හෝ කළ නොහැකි බව සලකන්න. ඔබේ සම්පාදකයා මත රඳා පවතී.
dmckee --- හිටපු උපපරිපාලක පූස් පැටවා

5
mdmckee හරි. C99 මඟින් ව්‍යංග int ට ඉඩ නොදේ, එබැවින් ඔබ භාවිතා කළ යුතු -std=gnu99අතර දැන් ඔබ අතේ ගෙන යා නොහැක. Clc-speak හි, ඔබ "C" කේතයක් ලියන්නේ නැත, නමුත් "Gnu99-C". මෙහි වටය අපි බොහෝ දුරට එය නොසලකා හරිමු, නමුත් ඔබ සම්පාදක විශේෂිත කේතයක් පළ කරන්නේ නම් එය සඳහන් කිරීම හොඳය. සමහර වෙලාවට මිනිස්සු ඇත්තටම කරන්න බාගත සහ අපේ මෙම වැඩසටහන් ක්රියාත්මක කිරීම. :)
luser droog

@luserdroog: -std=c89පැරණි කේතය අනුව ඔබේ කේතය සම්පාදනය කිරීමට ඔබට gcc හෝ clang ට පැවසීමට භාවිතා කළ හැකිය , එමඟින් අනතුරු ඇඟවීමක් පමණක් සහිත ව්‍යංගාර්ථයට ඉඩ ලබා දේ.
පීටර් කෝර්ඩ්ස්

40

GCC වැනි ඇතැම් සම්පාදකයින් ඔබට මූලික #includes, param සහ return වර්ග අතහැර දැමීමට ඉඩ දෙයි main.

පහත දැක්වෙන්නේ වලංගු C89 සහ C99 වැඩසටහනක් වන අතර එය GCC සමඟ (අනතුරු ඇඟවීම් සමඟ) සම්පාදනය කරයි:

main(i) { printf("%d", i); }

බව දැනුම් #includeසඳහා stdio.h අතුරුදහන් සඳහා, නැවත වර්ගය mainඅතුරුදහන් වන අතර, සඳහා වර්ගය ප්රකාශ iඅතුරුදහන් කර ඇත.


19
ප්‍රධාන වශයෙන් ශුන්‍ය හෝ පරාමිති දෙකක් පිළිගන්නා බැවින් තාක්ෂණික වශයෙන් එය ප්‍රමිතීන්ට අනුව වලංගු නොවේ. කේත ගොල්ෆ් ක්‍රීඩාව ගැන කිසිවෙකු සැලකිලිමත් නොවන බව නොවේ.
කොන්රාඩ් බොරොව්ස්කි

printf()මූලාකෘතියක් නොමැතිව ඇමතීම (හෝ ඕනෑම විචල්‍ය ශ්‍රිතයක්) නිර්වචනය නොකළ හැසිරීමට හේතු වේ . GCC පෙරනිමියෙන් සම්මත C සම්පාදනය නොකරයි. ඔබ C89 මාදිලියේ ( gcc -ansi -pedantic) හෝ C99 මාදිලියේ ( gcc -std=c99 -pedantic) gcc අයැදුම් කරන්නේ නම් , ඔබට පැමිණිලි කිහිපයක් ලැබෙනු ඇත.
Nisse Engström

Is NisseEngström: ප්‍රධාන ධාරාවේ C ක්‍රියාත්මක කිරීම් පිළිබඳ ඇමතුම් සම්මුතීන් මඟින් මූලාකෘති නොමැතිව විචල්‍ය ශ්‍රිතයන් ඇමතීම ආරක්ෂිත කරයි. එබැවින් බොහෝ සී ක්‍රියාත්මක කිරීම් මඟින් හැසිරීම අර්ථ දක්වයි.
පීටර් කෝර්ඩ්ස්

39

සංසන්දනාත්මක අගයන් බිංදුවට වඩා ඉහළින් ඇති විට> = සහ <= වෙනුවට ඔබට පූර්ණ සංඛ්‍යා බෙදීම (/) භාවිතා කළ හැකිය, එමඟින් එක් අක්ෂරයක් ඉතිරි වේ. උදාහරණයක් වශයෙන්:

putchar(c/32&&126/c?c:46); //Prints the character, but if it is unprintable print "."

ඇත්ත වශයෙන්ම තවමත් හැකිලෙන, උදාහරණයක් ලෙස> සහ using භාවිතා කිරීම (සමහර අවස්ථාවල ලිවීමෙන් වැළකී සිටීමට හොඳ ක්‍රමයක් && හෝ ||).

putchar(c>31^c>126?c:46);

අක්‍ෂරයක් සුරකින බැවින් සංඛ්‍යා 100 ට වඩා අඩු දැයි තීරණය කිරීමට නිඛිල බෙදීම් උපක්‍රමය උදාහරණයක් ලෙස ප්‍රයෝජනවත් වේ:

a<100 vs 99/a

ඉහළ ප්‍රමුඛතාවයක් අවශ්‍ය අවස්ථාවන්හිදී මෙය ද හොඳ ය.


ඔබට ලිවිය හැකියputchar(c>31&c<127?c:46);
ජින් එක්ස්

31

තෘතීය කොන්දේසි සහිත ක්‍රියාකරු ?:බොහෝ විට සරල if- elseප්‍රකාශ සඳහා සැලකිය යුතු ඉතිරියක් සඳහා භාවිතා කළ හැකිය .

මෙන් නොව C ++ සමාන ක්රියාකරු නිල වශයෙන් lvalue දොසක් නො , නමුත් සමහර අවස්තා (සැලකිය යුතු gcc) ලස්සන ප්රසාද වන, ඔබ එය ගැනීමට ඔහුට ඉඩ ඇත.


එකතු කිරීම: ඔබට අවශ්‍ය වන්නේ, නමුත් වෙනත් එකක් නොවේ නම්, ත්‍රිකෝණය තවමත් ප්‍රයෝජනවත් විය හැකිය.
කේසි

9
&&හා ||ද භාවිතා කළ හැක: if(x==3)f()ඔබගේ යෝජනාව සමග බවට පත් x==3?f():0, හා තවදුරටත් වැඩි දියුණු කළ හැකි x==3&&f(). නමුත් ක්‍රියාකරුගේ ප්‍රමුඛතාවය ගැන සැලකිලිමත් වන්න - f()එය ප්‍රතිස්ථාපනය කරන්නේ y=1නම්, &&විසඳුමට අමතර වරහන් කට්ටලයක් අවශ්‍ය වේ.
ugoren

1
Gcc හි ?:ields ලදාව අඩු අගයක් ගන්නා බව මම කිසි විටෙකත් නොදැන සිටියෙමි . නිෂ්පාදන කේතයේ මට එය භාවිතා කළ හැකිද? lol
ජෙෆ් බර්ජස්

4
@ugoren: x==3&&f()තව දුරටත් ගොල්ෆ් කළ හැකියx^3||f()
fgrieu

gfgrieu, ඔව්, එය හරියටම මෙහි මාතෘකාව නොවුනත් ( මෙම පිළිතුරෙන් එය යෝජනා කරයි).
ugoren

28

http://graphics.stanford.edu/~seander/bithacks.html

බිටු හොඳයි.

~-x = x - 1
-~x = x + 1

නමුත් විවිධ පූර්වාදර්ශයන් සමඟ, x සහ ++ වැනි වෙනස් නොකරන්න. ඔබට මෙය විශේෂිත අවස්ථාවන්හිදී භාවිතා කළ හැකිය: ~ 9 -10 ට වඩා කෙටි වේ.

if(!(x&y)) x | y == x ^ y == x + y
if(!(~x&y)) x ^ y == x - y

එය වඩාත් විචක්ෂණශීලී ය, නමුත් මට එය භාවිතා කිරීමට සිදුවීමක් තිබේ. ඔබ කෙටි පරිපථ ගැන තැකීමක් නොකරන්නේ නම්

x*y == x && y
if(x!=-y) x+y == x || y

තවද:

if(x>0 && y>0) x/y == x>=y   

5
අවසාන ඉඟිය ( (x/y) == (x>=y)) සැබවින්ම ප්‍රයෝජනවත් වේ.
ugoren

27

ලැම්බඩාස් (භාවිතා කළ නොහැකි) භාවිතා කරන්න

වෙනුවට

f(int*a,int*b){return*a>*b?1:-1;}
...
qsort(a,b,4,f);

හෝ (gcc පමණි)

qsort(a,b,4,({int L(int*a,int*b){a=*a>*b?1:-1;}L;}));

හෝ (බ්ලොක් ආධාරයෙන් ගැටගැසීම)

qsort_b(a,b,4,^(const void*a,const void*b){return*(int*)a>*(int*)b?1:-1;});

වැනි දෙයක් උත්සාහ කරන්න

qsort(a,b,4,"\x8b\7+\6\xc3");

... මෙහි වචනාර්ථයෙන් ඔබේ "ලැම්බඩා" ශ්‍රිතයේ යන්ත්‍ර භාෂා උපදෙස් අඩංගු වේ (සියලුම වේදිකා ABI අවශ්‍යතාවයන්ට අනුකූල වේ).

මෙය ක්‍රියාත්මක වන්නේ නූල් නියතයන් ක්‍රියාත්මක කළ හැකි ලෙස සලකුණු කර ඇති පරිසරවල ය. පෙරනිමියෙන් මෙය ලිනක්ස් සහ ඕඑස්එක්ස් වල සත්‍ය වන නමුත් වින්ඩෝස් නොවේ.

ඔබේම "ලැම්බඩා" ශ්‍රිත ලිවීමට ඉගෙන ගත හැකි එක් මෝඩ ක්‍රමයක් නම්, ශ්‍රිතය C හි ලිවීම, එය සම්පාදනය කිරීම, එය වැනි දෙයක් සමඟ පරීක්ෂා කර objdump -Dඅනුරූප හෙක්ස් කේතය නූලකට පිටපත් කිරීමයි. උදාහරණයක් වශයෙන්,

int f(int*a, int*b){return *a-*b;}

... gcc -Os -cලිනක්ස් x86_64 ඉලක්කයක් සඳහා සම්පාදනය කරන විට වැනි දෙයක් ජනනය කරයි

0:   8b 07                   mov    (%rdi),%eax
2:   2b 06                   sub    (%rsi),%eax
4:   c3                      retq

එම්ඩී එක්ස්එෆ් සරල "ලැම්බඩා" කාර්යයන් ලිවීමට උපකාරී වන බාෂ් පිටපතක් ලිවීය .

GNU CC goto:

ඔබට මෙම "ලැම්බඩා කාර්යයන්" කෙලින්ම ඇමතිය හැකි නමුත් ඔබ අමතන කේතය පරාමිතීන් නොගෙන නැවත නොඑන්නේ නම්, ඔබට gotoබයිට් කිහිපයක් ඉතිරි කිරීමට භාවිතා කළ හැකිය . ඒ වෙනුවට

((int(*)())L"ﻫ")();

හෝ (ඔබේ පරිසරයට අරාබි ග්ලයිෆස් නොමැති නම්)

((int(*)())L"\xfeeb")();

උත්සාහ කරන්න

goto*&L"ﻫ";

හෝ

goto*&L"\xfeeb";

මෙම උදාහරණයේ දී, eb fex86 යන්ත්‍ර භාෂාව වැනි දෙයක් සඳහා වන for(;;);අතර එය පරාමිතීන් නොගෙන නැවත නොඑන දෙයකට සරල උදාහරණයකි :-)

gotoඇමතුම් දෙමාපියෙකු වෙත නැවත කේත කළ හැකි බව එයින් පෙනේ.

#include<stdio.h>
int f(int a){
 if(!a)return 1;
 goto*&L"\xc3c031"; // return 0;
 return 2; // never gets here
}
int main(){
 printf("f(0)=%d f(1)=%d\n",f(0),f(1));
}

ඉහත උදාහරණය (ලිනක්ස් සමඟ සම්පාදනය කර ක්‍රියාත්මක විය හැක gcc -O) තොග පිරිසැලසුමට සංවේදී වේ.

සංස්කරණය කරන්න: ඔබගේ මෙවලම් කට්ටලය මත පදනම්ව, ඔබට -zexecstack(gcc සඳහා) හෝ -Wl,-z,execstack(ක්ලැන්ග් සඳහා) සම්පාදක ධජය භාවිතා කිරීමට සිදුවනු ඇත .

එය ක්ෂණිකව නොපෙනේ නම්, මෙම පිළිතුර ප්‍රධාන වශයෙන් ලියා ඇත්තේ ලොල්වරුන් සඳහා ය. මෙය කියවීමෙන් වඩා හොඳ හෝ නරක ගොල්ෆ් ක්‍රීඩා කිරීම හෝ අහිතකර මානසික ප්‍රති come ල සඳහා මම කිසිදු වගකීමක් නොගනිමි.


3
සී ශ්‍රිතයක කොටස් සම්මතයෙන් කියවා සී ලැම්බඩා මුද්‍රණය කිරීම සඳහා මම පිටපතක් ලියා ඇත්තෙමි . ඔබේ පිළිතුරෙහි සඳහන් කිරීම වටී, ඔබ මෙය මුලින් ම කිරීමට මට ඉගැන්වූ බැවින් ඔබට දැකීම සතුටක් විය හැකිය.
MD XF

24

විචල්යයන් වෙනුවට පරාමිතීන් නිර්වචනය කරන්න.

f(x){int y=x+1;...}

f(x,y){y=x+1;...}

ඔබට දෙවන පරාමිතිය සැබවින්ම සමත් වීමට අවශ්‍ය නැත.

තවද, වරහන් සුරැකීමට ඔබට ක්‍රියාකරු ප්‍රමුඛතාවය භාවිතා කළ හැකිය.
උදාහරණයක් ලෙස, විය (x+y)*2හැකිය x+y<<1.


නැතහොත් x+y*2, තවත් වර්‍ගයක් ඉතිරි කිරීම.
බ්‍රැඩන් හොඳම

6
x+y*2Operator ක්‍රියාකරුගේ ප්‍රමුඛතාවය නිසා B1KMusic එක සමාන නොවේ.
ugoren

1
හරි, ලොල්. එය x + (y * 2) වනු ඇත. මා x+y<<1උදාහරණයකට සවි කර ඇති අතර , එය තක්සේරු කරනු ලැබේ යැයි උපකල්පනය කර ඒ වෙනුවට x+(y<<1)යෝජනා කළෙමි *2. බිට්ෂිෆ්ට් මෙහෙයුම් ඇගයීමට ලක් කර ඇති බව මා දැන සිටියේ නැත(x+y)<<2
බ්‍රැඩන් හොඳම

24

දර්ශක වෙනුවට කර්සර භාවිතා කරන්න . brk()ආරම්භයේදීම සීරීමට හා එය පාදක දර්ශකයක් ලෙස භාවිතා කරන්න .

char*m=brk();

මතක ප්‍රවේශය සඳහා # අර්ථ දැක්වීමක් කරන්න.

#define M [m]

M*පූර්ණ සංඛ්‍යා සඳහා යොදන පෝස්ට්ෆික්ස් බවට පත්වේ . (පැරණි a [x] == x [a] උපක්‍රමය.)

නමුත්, තවත් බොහෝ දේ ඇත! එවිට ඔබට සාර්ව වලට වඩා කෙටි වන ශ්‍රිතයන්හි දර්ශක ආග් සහ ප්‍රතිලාභ ලබා ගත හැකිය (විශේෂයෙන් ඔබ 'ආපසු' යන්න කෙටියෙන් නම්):

f(x){return x M;} //implicit ints, but they work like pointers
#define f(x) (x M)

දර්ශකයකින් කර්සරයක් සෑදීම සඳහා, ඔබ පාදක දර්ශකය අඩු කර, ptrdiff_t ලබා දෙන අතර එය int එකකට කපා දමයි, පාඩු yer biz වේ.

char *p = sbrk(sizeof(whatever)) - m;
strcpy(m+p, "hello world");

ටයිප් නොකළ ලැම්බඩා කැල්කියුලස් සඳහා පරිවර්තකයෙකු ලිවීමට මගේ පිළිතුරෙහි මෙම තාක්ෂණය භාවිතා වේ .


22

තෘතීය ක්‍රියාකරුට ?:වෙනම කැබලි දෙකක් තිබීම අසාමාන්‍යය. මේ නිසා, එය සම්මත ක්‍රියාකරු ප්‍රමුඛතා නීතිවලට සුළු අඩුපාඩුවක් සපයයි. වරහන් වර්‍ග වළක්වා ගැනීම සඳහා මෙය ප්‍රයෝජනවත් වේ.

පහත උදාහරණය ගන්න:

if (t()) a = b, b = 0;  /* 15 chars */

සුපුරුදු ෙගොල්ෆ් ප්රවේශය ප්රතිස්ථාපනය කිරීමයි ifසමග &&, නමුත් නිසා කොමා ක්රියාකරු පහළ තැනක්ද, ඔබට වරහන් වැඩිපුර යුගල අවශ්ය:

t() && (a = b, b = 0);  /* still 15 chars */

තෘතීය ක්‍රියාකරුගේ මැද කොටසට වරහන් අවශ්‍ය නොවේ.

t() ? a = b, b = 0 : 0;  /* 14 chars */

අරාව ග්‍රාහක සඳහා සමාන අදහස් අදාළ වේ.


7
මෙම උදාහරණයේ දී b-=a=bඊටත් වඩා කෙටි ය. මෙම ?:උපක්රමය, තවමත් ප්රයෝජනවත් වේ -=ද අඩු මනාප ඇති බැවින්.
ugoren

හොඳ කරුණක්; මගේ ආදර්ශය අනවශ්‍ය ලෙස සංකීර්ණ විය.
පාන් පෙට්ටිය

තවත් කරුණක් නම්, සමහර විට ඔබට තත්වය වෙනස් කිරීමට අවශ්‍ය වේ: මක්නිසාද යත් x>0||(y=3), x>0?0:(y=3)නිෂ් less ල ය, නමුත් x<1?y=3:0කාර්යය ඉටු කරයි.
ugoren

ක්ලැන්ග් සහ ජීසීසී යන දෙකම ත්‍රිත්වයේ හිස් සත්‍ය නඩුවක් සඳහා ඉඩ ලබා දේ . මඟ හැරී ඇත්නම්, එහි වටිනාකම යනු තත්වයේ වටිනාකමයි. උදාහරණයක් ලෙස,x>5?:y=1
ක්‍රිස් උස්ඩාවිනිස්

20

සාමාන්‍යයෙන් EOF == -1, EOF සඳහා පරීක්ෂා කිරීම සඳහා bitwise NOT ක්‍රියාකරු භාවිතා කරන්න: while(~(c=getchar()))හෝ while(c=getchar()+1)සෑම තැනකම c හි අගය වෙනස් කරන්න


1
මම සී ගැන හොඳට දන්නේ නැහැ, නමුත් while(1+c=getchar())වැඩ කරන්නේ නැද්ද?
ɐɔıʇǝɥʇuʎs

6
No. ɐɔıʇǝɥʇuʎs නැත. එකතු කිරීමේ ක්‍රියාකරුට +පැවරුම් ක්‍රියාකරුට වඩා ඉහළ ප්‍රමුඛතාවයක් ඇත =, එබැවින් 1+c=getchar()සමාන වේ (1+c)=getchar(), එය සම්පාදනය (1+c)නොකෙරේ.
user12205

20

ඔබගේ කේතයේ ඕනෑම කොටසක් කිහිප වතාවක් පුනරාවර්තනය වන අතර එය පෙර සකසනය සමඟ ප්‍රතිස්ථාපනය සඳහා අපේක්ෂකයෙකි.

#define R return

ඔබ කේතයන් කාර්යයන් කිහිපයකට වඩා සම්බන්ධ කරන්නේ නම් එය ඉතා පොදු භාවිත අවස්ථාවකි. වෙනත් longish ප්රධාන වචන කැමති while, double, switch, සහ caseද අපේක්ෂකයන් ය; ඔබේ කේතයේ රූපමය වශයෙන් ඕනෑම දෙයක්.

මම සාමාන්‍යයෙන් ලොකු අකුරු මෙම කාර්යය සඳහා වෙන් කරමි.


2
කෙටි ආදේශනයක් වනු ඇත -DR=return. ඔබ යම් අක්ෂර ඇතුළත් කරන්නේ නම්, අර්ථ දැක්වීම වටා තනි හෝ ද්විත්ව උපුටා දැක්වීම් අවශ්‍ය විය හැකි බව සලකන්න -DP='puts("hello")'.

16

ඔබගේ වැඩසටහන එක් එක් පියවර පදනම මත එක් කියවීම හෝ ලිවීමෙන් නම් සෑම විටම භාවිතා කිරීමට උත්සාහ කියවීමට හා ලිවීම් වෙනුවට කාර්යය getchar () හා putchar () .

උදාහරණය ( stdout ආපසු හරවා stdout මත තබන්න )

main(_){write(read(0,&_,1)&&main());}

ව්‍යායාම: මෙහි හොඳ ලකුණු ලබා ගැනීමට මෙම තාක්ෂණය භාවිතා කරන්න .


සෑම පියවරකින්ම ඔබ අදහස් කරන්නේ කුමක්ද?
කේසි

කේසි: මම හිතන්නේ ඔවුන් අදහස් කරන්නේ වැඩසටහන යමක් කියවනවා නම්, එය ක්‍රියාත්මක වන්නේ නම් සහ ප්‍රතිදානය ලියන්නේ නම්. ප්‍රවාහය ආකාරයෙන්, එසේ කීමට. සියලුම ආදාන එකවර කියවා හැසිරවිය යුතු ප්‍රවේශයකට ප්‍රතිවිරුද්ධව.
ජෝයි

ජෝයි හරි, මමත් ඒ දේම කිව්වා, සමාවෙන්න මම අද වන තුරු මගේ එන ලිපි පරීක්ෂා කළේ නැහැ.
ක්වික්සෝටික්

8
එම තොග හැසිරවීම ඉතා අලංකාරයි.
ඇන්ඩ්‍රියා බියන්ඩෝ

16

ඔබට කවදා හෝ තනි අළුත් අක්ෂරයක් ( \n) ප්‍රතිදානය කිරීමට අවශ්‍ය නම් putchar(10), භාවිතා නොකරන්න , භාවිතා නොකරන්න puts("").


16

ප්‍රතිලෝම ලූප

ඔබට හැකි නම්, ප්රතිස්ථාපනය කිරීමට උත්සාහ කරන්න

for(int i=0;i<n;i++){...}

සමග

for(int i=n;i--;){...}

14

ප්‍රතිලාභ අගයන් ශුන්‍ය දේ සඳහා භාවිතා කරන්න. ඔබ යම් ශ්‍රිතයක් අමතන්නේ නම් සහ එම ශ්‍රිතය සාමාන්‍ය තත්වයන් යටතේ ශුන්‍ය වේ නම්, ඔබට එය බිංදුව අපේක්ෂා කරන ස්ථානයක තැබිය හැකිය. ඒ හා සමානව ඔබ දන්නේ නම්, ශ්‍රිතය ශුන්‍ය නොවන ලෙසට ලැබෙනු ඇත. ඇත්තෙන්ම, ඔබ කිසිම අවස්ථාවක කේත ගොල්ෆ් ක්‍රීඩාවකදී නිසි ලෙස හැසිරවීම සිදු නොකරයි, නේද?

උදාහරණ:

close(fd);foo=0;   →  foo=close(fd);    /* saves two bytes */
putchar(c);bar=0;  →  bar=!putchar(c);  /* saves one byte  */

13

නැවත පැමිණීම වෙනුවට පවරන්න.

මෙය සැබවින්ම සම්මත C නොවේ, නමුත් මා දන්නා සෑම සම්පාදකයෙකු හා CPU සමඟ ක්‍රියා කරයි:

int sqr(int a){return a*a;}

සමාන බලපෑමක් ඇත:

int sqr(int a){a*=a;}

පළමු තර්කය ප්‍රතිලාභ අගය ලෙස එකම CPU ලේඛනයේ ගබඩා කර ඇති බැවිනි.

සටහන: එක් විවරණයක සඳහන් කර ඇති පරිදි, මෙය නිර්වචනය නොකළ හැසිරීමක් වන අතර සෑම මෙහෙයුමක් සඳහාම වැඩ කිරීමට සහතික නොවේ. ඕනෑම සම්පාදක ප්‍රශස්තිකරණයක් එය මඟ හැරෙනු ඇත.

එක්ස්-මැක්‍රෝස්

තවත් ප්‍රයෝජනවත් අංගයක්: ඔබට විචල්‍ය ලැයිස්තුවක් ඇති විට එක්ස්-මැක්‍රෝස් ඔබට උදව් කළ හැකි අතර ඒ සියල්ල සම්බන්ධ වන යම් මෙහෙයුමක් කළ යුතුය:

https://en.wikipedia.org/wiki/X_Macro


3
මම මෙය උපුටා දැක්වූ අතර මා නිවැරදි කරන ලදි, මෙය සරලවම සත්‍ය නොවේ. එය ක්‍රියාත්මක වන්නේ ගුණ කිරීම හා බෙදීම් සමඟ පමණක් වන අතර ප්‍රශස්තිකරණය අක්‍රිය කළ විට පමණි. මෙයට හේතුව මෙහෙයුම් දෙකම ඔවුන්ගේ ප්‍රති results ල නැවත ලබා ගැනීම සඳහා වන පොදු ලේඛනය වන eax තුළට දැමීමයි. පරාමිතීන් තොගයේ හෝ ecx හෝ edx තුළ ගබඩා කර ඇත. එය ඔබම උත්සාහ කරන්න.
ගෑස්පා 79

3
ඔබ හරි, එය නිර්වචනය නොකළ හැසිරීම, එය සම්පාදකයා සහ ගෘහ නිර්මාණ ශිල්පය මත ද රඳා පවතී, මෙම උපක්‍රමය භාවිතා කර ඕනෑම පිළිතුරක් පළ කිරීමට පෙර මම සාමාන්‍යයෙන් x86 සහ armv7 මත gcc සමඟ පරීක්ෂා කරමි. ඇත්ත වශයෙන්ම ඔබ ප්‍රශස්තිකරණය සක්‍රීය කරන්නේ නම්, ඕනෑම ස්මාර්ට් සම්පාදකයෙකු අනවශ්‍ය ගුණ කිරීම මකා දමනු ඇත.
ජීබී

3
මම මෙම කාර්යය GCC සමඟ දැක ඇති නමුත් අනෙක් අය නොවේ
ඇල්බට් රෙන්ෂෝ

1
Asp Gaspa79: -O0ප්‍රතිලාභ අගය ලේඛනයේ ප්‍රකාශන ඇගයීමට gcc සෑම විටම තෝරා ගනී. මම අවම වශයෙන් x86, ARM, සහ MIPS දෙස බැලුවෙමි ( gcc.godbolt.org හි ), සහ gcc එය කිරීමට පිටත්ව යන බවක් පෙනේ -O0. එහෙත්, ඔබ, මේ වාසිය ලබා ගැනීමට නම් මතක භාෂාව ඔබ කියන්නේ ඉන්නේ වැඩසටහන් gcc -O0, නෑ සී , ඔබ නොකරන C වැනි, ඒ අනුව ඔබගේ පිළිතුර ලේබල් ගැසීම කළ යුතුය . එය -O0නිදොස් කිරීමේ මාදිලිය හැර වෙනත් ප්‍රශස්තිකරණ මට්ටමකින් අසමත් වන අතර ක්ලැන්ග් IIRC සමඟ ක්‍රියා නොකරයි.
පීටර් කෝර්ඩ්ස්

12
  1. අරාවෙහි පළමු අංගයට ප්‍රවේශ වීම *aවෙනුවට භාවිතා කරන්න a[0].

  2. සම්බන්ධතා ක්‍රියාකරුවන් ( !=,, >ආදිය) ලබා දෙයි 0හෝ 1. තත්වය සත්‍යද අසත්‍යද යන්න මත පදනම්ව විවිධ ඕෆ්සෙට් ලබා දීමට අංක ගණිත ක්‍රියාකරුවන් සමඟ මෙය භාවිතා කරන්න: a[1+2*(i<3)]ප්‍රවේශ a[1]වන්නේ නම් i >= 3සහ a[3]වෙනත් ආකාරයකින්.


12
a[i<3?3:1]අක්ෂර දෙකකට වඩා කෙටි වේ a[1+2*(i<3)].
Reto Koradi

10

ඔබට අයිඕසීසීසී ලේඛනාගාරය (ජාත්‍යන්තර අපැහැදිලි සී කේත තරගය) සොයා බැලිය හැකිය.

සැලකිය යුතු උපක්‍රමයක් නම්, ව්‍යාප්තියේ අසමතුලිත වරහන් / වරහන් වැනි මැක්‍රෝස් # අර්ථ දැක්වීම ය

#define P printf(

16
නොගැලපෙන වරහන් තුළ තමන් තුළ කිසිදු වටිනාකමක් නැත. කාරණය වන්නේ හැකි තරම් පුනරාවර්තන රටාව නිර්වචනය කිරීමයි. ඔබට තවත් ඉදිරියට යාමට අවශ්‍ය විය හැකිය #define P;printf(.
ugoren

මෙය කෙටි බයිට් ගණන ගණනය කරන්නේ කෙසේද? සමහරවිට උදාහරණයක් දෙන්න පුළුවන්ද?
සයොස්

2
YCyoce උදාහරණයක් ලෙස මෙම පිළිතුර බලන්න .
ජොනතන් ෆ්‍රෙච්

9

forවෙනුවට භාවිතා කරන්නwhile

ඕනෑම දෙයක් එකම දිගකින් whileවෙනස් කළ හැකිය for:

while(*p++)
for(;*p++;)

තනිවම, එය ගොල්ෆ් නොවේ. නමුත් දැන් අපට පූර්ව ප්‍රකාශයක් වර්‍ගයට ගෙනයාමට අවස්ථාවක් තිබේ. අපට ලූපයේ අවසානයේ සිට ප්‍රකාශන ප්‍රකාශයක් එසවීමටද හැකිය; ලූපයේ ප්‍රකාශ දෙකක් අඩංගු නම්, අපට වරහන් ද සුරැකිය හැකිය:

a=5;while(*p++){if(p[a])--a;++b;}

for(a=5;*p++;++b)if(p[a])--a;

do...whileලූප පවා ලූප මගින් ප්‍රතිස්ථාපනය කළ යුතුය for. for(;foo,bar,baz;);වඩා කෙටි වේ do foo,bar;while(baz);.


8

for(int i=0;i<n;i++){a(i);b(i);} ක්‍රම කිහිපයකින් කෙටි කළ හැකිය:

for(int i=0;i<n;){a(i);b(i++);} -1 චලනය සඳහා ++පසුගිය කිරීමට iකම්බියක් දී

for(int i=0;i<n;b(i++))a(i); එක් ප්‍රකාශයක් හැර අනෙක් සියල්ල ප්‍රධාන ලූපයෙන් ඉහළට සහ පිටතට ගෙනයාම සඳහා වරහන් ඉවත් කිරීම සඳහා තවත් -3 ක්


1
කොමා ක්‍රියාකරු භාවිතා කිරීම සමහර අවස්ථාවල වරහන් වළක්වා ගැනීමට තවත් ක්‍රමයකි.
පීටර් කෝර්ඩ්ස්

8

ක්‍රියාකාරී වන්න!

එකම අත්සනකින් සහ තනි ප්‍රකාශන ලෙස අර්ථ දක්වා ඇති සරල කාර්යයන් දක්වා ඔබේ ගැටළුව අඩු කළ හැකි නම්, එවිට ඔබට #define r returnශ්‍රිතයක් නිර්වචනය කිරීම සඳහා බොයිලේරු සියල්ලටම වඩා හොඳින් කළ හැකිය .

#define D(f,...)f(x){return __VA_ARGS__;}
D(f,x+2)
D(g,4*x-4)
D(main,g(4))

වැඩසටහන් ප්‍රති result ලය යනු එහි තත්ව අගය මෙහෙයුම් පද්ධතිය වෙත ආපසු යැවීම හෝ ෂෙල් හෝ අයිඩීඊ පාලනය කිරීමයි.

භාවිතා කිරීමෙන් __VA_ARGS__ඔබට මෙම ක්‍රියාකාරී ප්‍රකාශනවල අනුක්‍රමික ලකුණු හඳුන්වා දීමට කොමා ක්‍රියාකරු භාවිතා කිරීමට ඉඩ ලබා දේ . මෙය අවශ්‍ය නොවේ නම්, සාර්ව කෙටි විය හැක.

#define D(f,b)f(x){return b;}

7
  1. scanf("%*d ");ව්‍යාජ ආදානය කියවීමට භාවිතා කරන්න. (වැඩිදුර වැඩසටහනේ ආදානය අර්ථ විරහිත නම්) එය scanf("%d",&t);ඔබට විචල්‍යය t ප්‍රකාශ කිරීමට අවශ්‍ය ස්ථානයට වඩා කෙටි වේ .

  2. අක්ෂර අරාවෙහි අක්ෂර ගබඩා කිරීම වඩා හොඳය. උදාහරණයක්.

    s[],t;main(c){for(scanf("%*d ");~(c=getchar());s[t++]=c)putchar(s[t]);}


3
ඇත්ත වශයෙන්ම, මම %*dscanf("%[^\n]%*c",str);
ගොල්ෆ්හි

7

භාවිතා කිරීම asprintf() ඔබට පැහැදිලි වෙන් කිරීමක් ඉතිරි වේ char*. මෙය කේත ගොල්ෆ් ක්‍රීඩාවට එතරම් ප්‍රයෝජනවත් නොවනු ඇත, නමුත් එදිනෙදා වැඩ කටයුතු වර්‍ග අරා සමඟ පහසු කරයි. 21 වන සියවසේ තවත් හොඳ උපදෙස් කිහිපයක් තිබේ .

භාවිත උදාහරණය:

#define _GNU_SOURCE
#include <stdio.h>

int main(int argc, char** argv) {
  char* foo;
  asprintf(&foo, "%s", argv[1]);
  printf("%s",foo);
}

7

උත්සාහ කරන්න cpow()ඒ වෙනුවටcos()

වෙනුවට

double y=cos(M_PI*2*x);

වැනි දෙයක් උත්සාහ කරන්න

double y=cpow(-1,x*2);

මෙය යුලර්ගේ සූත්‍රය , ටිකක් සංකීර්ණ විශ්ලේෂණයක් සහ සංකීර්ණයක් දෙකට පැවරීමෙන් සැබෑ කොටස ලබා ගත හැකි බව නිරීක්ෂණය කරයි (විචල්‍ය ශ්‍රිත ඇමතුම් සහ වෙනත් සියුම්කම් සමඟ ප්‍රවේශම් වන්න).

cos2πx+jපාපය2πx=j2πx=jπ2x=(-1)2x

අඩු කිරීම සඳහා මෙම වර්ගයේ උපක්රම භාවිතා කළ හැකිය

double y=cpow(-1,x/2);

වෙත

double y=cpow(1i,x);

නිසා (-1)x2=j2x2=jx

සංස්කරණය කරන්න: සමීකරණ දැන් පේළියේ එල්ටීx රූප වෙනුවට.


6

ඒ වෙනුවට අක්ෂරයක් මුද්‍රණය කර කරත්ත ආපසු එවන්න:

printf("%c\n",c);

හෝ

putchar(c);putchar('\n'); // or its ascii value, whatever!

සරලව, c යනු int ලෙස ප්‍රකාශ කරන්න සහ:

puts(&c);

9
මෙය කුඩා එන්ඩියන් ගෘහ නිර්මාණ ශිල්පය මත රඳා පවතින බව පෙන්වා දීම වටී. C යනු විශාල එන්ඩියන් ඉන්ටර් එකක් නම්, එවිට ඔබට කරත්ත ආපසු ලැබෙනු ඇත. (අනෙක් අතට, c යනු වර්‍ගයක් නම්, ඔබට කරත්ත ආපසු යැවීම වෙනුවට අහඹු ලෙස කුණු කසළ ලැබෙනු ඇත.)
පාන් පෙට්ටිය

read බ්‍රෙඩ්බොක්ස් ඔව්, ඔබ සම්පූර්ණයෙන්ම හරි; මම දැන් සංස්කරණය කළෙමි: අවසාන උපුටා ගැනීම c භාවිතා කළ යුත්තේ int ලෙසය (එය නිතර ප්‍රකාශ කිරීමට පහසුය).
moala

නැහැ puts(&c)ඇත්තටම වැඩ ද? එය අනිවාර්යයෙන්ම අවලංගු නොවේ.
පලතුරු වෙන් කිරීම

1
So එසොලන්ජිංෆෘට් බිට් 32 අඟල් සහිත කුඩා එන්ඩියන් මත, int 0 ≤ c <256 බයිට් අනුක්‍රමය c 0 0 0 ලෙස ගබඩා වේ. ලිපිනය භාෂණ විට ලෙස char *චරිතය: අපි තනි string බලන්න වූ ශූන්ය බයිට විසින් අනුගමනය,.
ඩෙනිස්

6

import ඔබට අවශ්‍ය නම්

පළමු පිළිතුරේ සඳහන් කළ පරිදි , සමහර සම්පාදකයින් (විශේෂයෙන්, ජීසීසී සහ ක්ලැන්ග්) #includeසම්මත පුස්තකාල කාර්යයන් සඳහා අතහැර දැමීමෙන් ගැලවීමට ඔබට ඉඩ සලසයි .

ඔබ පමණක් ඉවත් කල නොහැකි වුවද #include, තිබිය හැකි එය වළක්වා ගැනීමට වෙනත් ක්රම , නමුත් එම සෑම විටම ප්රායෝගික හෝ විශේෂයෙන් golfy නොවේ.

ඉතිරි අවස්ථා වලදී, ඔබට බයිට් එකක් ඉතිරි කිරීම #import<header file>වෙනුවට භාවිතා කළ හැකිය #include<header file>. මෙය GNU දිගුවක් වන අතර එය අතහැර දැමූ දෙයක් ලෙස සලකනු ලැබේ, නමුත් එය අවම වශයෙන් gcc 4.8, gcc 5.1 සහ clang 3.7 හි ක්‍රියා කරයි.


5

මෙන්න මම මගේ වාසිය සඳහා භාවිතා කළ ඉඟි කිහිපයක්. මම නිර්ලජ්ජිතව ඒවා අන් අයගෙන් සොරකම් කර ඇත්තෙමි, එබැවින් මා හැර වෙන කිසිවෙකුට ගෞරවය දෙන්න:

කාර්ය ඇමතුම් සමඟ පැවරුම ඒකාබද්ධ කරන්න

මේ වෙනුවට:

r = /* Some random expression */
printf("%d", r);

මෙය කරන්න:

printf("%d", r = /* Some random expression */);

බහු විචල්‍යයන් එකට ආරම්භ කරන්න (හැකි විට)

මේ වෙනුවට:

for(i=0,j=0;...;...){ /* ... */ }

මෙය කරන්න:

for(i=j=0;...;...){ /* ... */ }

ශුන්‍ය / nonzero අගයන් බිඳ දමන්න

මෙය මා මෙහි සිටින අයෙකුගෙන් ලබාගත් ඉතා හොඳ උපක්‍රමයකි (මතක තබා ගන්න කවුද, සමාවෙන්න). ඔබට පූර්ණ සංඛ්‍යාවක් ඇති විට එය 1 හෝ 0 දක්වා බිඳ දැමිය යුතු විට, ඔබට !!එය පහසුවෙන් කළ හැකිය. මෙය සමහර විට වෙනත් විකල්ප සඳහා වාසිදායක වේ ?:.

මෙම තත්වය ගන්න:

n=2*n+isupper(s[j])?1:0; /* 24 */

ඔබට ඒ වෙනුවට මෙය කළ හැකිය:

n=n*2+!!isupper(s[j]); /* 22 */

තවත් උදාහරණයක්:

r=R+(memcmp(b+6,"---",3)?R:0); /* 30 */

මෙසේ නැවත ලිවිය හැකිය:

r=R+R*!!memcmp(b+6,"---",3)); /* 29 */

1
සමහර විටR*-~!!mxxxx
l4m2
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.