2017-05-24 104 views
2

我構建了一個程序來顯示警衛的行爲。首先有100個(我在代碼中放10個,因爲更容易發現錯誤)(1到100個)燈。起初,他們都在,但: -當運行代碼時它不響應(但它在後臺運行正常)

  1. 他經過他們第一次後,他把他們全部關閉。
  2. 第二次經過他們之後,他改變了燈號 ,這些燈號代替了2及其倍數(2 4 6 8 ...) - ,這些燈號是現在開啓的,而相反的。
  3. 第三次他改變了第三名和 3(3 6 9 ....)的倍數 - 那些現在和現在相反的人。
  4. 第四時間他改變在第四位的那些和 4的倍數(4 8 12 ....)

程序顯示許多燈如何在端部均關閉。 現在我構建的代碼編譯器顯示沒有警告或錯誤,但運行時它會停止響應。 (編譯器設置爲顯示所有警告。)

有沒有人知道代碼有什麼問題?

#include<stdio.h> 
#define N 100 
int firstwalk(int light[N]); 
int secondtwalk(int light[N]); 
int thirdtwalk(int light[N]); 
int fourthtwalk(int light[N]); 
int main() 
{ 
    int light[N] = {0}; 
    int i; 
    for (i = 0;i < N;i++) 
    { 
     light[i] = 1; 
    } 
    printf("Lights before the first walk- "); 
    for (i = 0;i < N;i++) 
    { 
     printf("%d ", light[i]); 
    } 
    firstwalk(light); 
    secondtwalk(light); 
    thirdtwalk(light); 
    fourthtwalk(light); 
    printf("the lights that were off are :- "); 
    for (i = 0;i < N;i++) 
    { 
     if (light[i] == 0) 
      printf("%d ", i+1); 
    } 

} 
int firstwalk(int light[N]) 
{ 
    int i; 
    for (i = 0;i < N;i++) 
    { 
     light[i] = 0; 
    } 
    printf("Lights after the first walk- "); 
    for (i = 0;i < N;i++) 
    { 
     printf("%d ", light[i]); 
    } 
    printf("\n"); 
    return light; 

} 
int secondtwalk(int light[N]) 
{ 
    int i; 
    for (i = 1;i < N;i= i * 2 + 1) 
    { 
     light[i] = 1; 

    } 
    printf("Lights after the second walk- "); 
    for (i = 0;i < N;i++) 
    { 
     printf("%d ", light[i]); 
    } 
    printf("\n"); 
    return light; 
} 
int thirdtwalk(int light[N]) 
{ 
    int i; 
    for (i = 2;i < N;i= i * 3 + 2) 
    { 
     if (light[i] == 1) 
      light[i] = 0; 
     else light[i] = 1; 
    } 
    printf("Lights after the third walk- "); 
    for (i = 0;i < N;i++) 
    { 
     printf("%d ", light[i]); 
    } 
    printf("\n"); 
    return light; 
} 
int fourthtwalk(int light[N]) 
{ 
    int i; 
    for (i = 3;i < N;i= i * 4 + 3) 
    { 
     if (light[i] == 1) 
      light[i] = 0; 
     else light[i] = 1; 
    } 
    printf("Lights after the third walk- "); 
    for (i = 0;i < N;i++) 
    { 
     printf("%d ", light[i]); 
    } 
    printf("\n"); 
    return light; 
} 

謝謝。

+0

C不檢查您是否打破界限的數組。你只需要做對。在開發時,您可以先計算數組索引,然後根據限制進行檢查,然後使用索引。 –

+0

請注意,您的函數應該返回一個整數,但它們返回一個指向int的指針...並且不使用返回值(這不是您的bug,只是一個觀察) – Gam

+0

使用'valgrind'和'gdb'調試你的代碼 –

回答

4

在你的代碼的主要缺陷基本上是你所訪問的陣列的方式,你會超越數組邊界的時候,這裏有一個可能的版本是固定:

#include <stdio.h> 

#define N 10 

void show_lights_all(char *label, int light[N]); 
void show_lights_off(char *label, int light[N]); 
void firstwalk(int light[N]); 
void secondtwalk(int light[N]); 
void thirdtwalk(int light[N]); 
void fourthtwalk(int light[N]); 

int main() { 
    int light[N] = {0}; 
    show_lights_all("Initial state of lights- ", light); 
    firstwalk(light); 
    secondtwalk(light); 
    thirdtwalk(light); 
    fourthtwalk(light); 
    show_lights_off("\nLights that were off are :- ", light); 
} 

void show_lights_all(char *label, int light[N]) { 
    printf(label); 
    for (int i = 0; i < N; i++) { 
     printf("%d ", light[i]); 
    } 
} 

void show_lights_off(char *label, int light[N]) { 
    printf(label); 
    for (int i = 0; i < N; i++) { 
     if (light[i] == 0) printf("%d ", i + 1); 
    } 
} 

void firstwalk(int light[N]) { 
    show_lights_all("\nLights before the first walk- ", light); 
    for (int i = 0; i < N; i++) { 
     light[i] = 0; 
    } 
    show_lights_all("Lights after the first walk- ", light); 
} 

void secondtwalk(int light[N]) { 
    show_lights_all("\nLights before the second walk- ", light); 
    for (int i = 1; i < N; i += 2) { 
     light[i] = 1; 
    } 
    show_lights_all("Lights after the second walk- ", light); 
} 

void thirdtwalk(int light[N]) { 
    show_lights_all("\nLights before the third walk- ", light); 
    for (int i = 2; i < N; i += 3) { 
     light[i] = light[i] == 1 ? 0 : 1; 
    } 
    show_lights_all("Lights after the third walk- ", light); 
} 

void fourthtwalk(int light[N]) { 
    show_lights_all("\nLights before the fourth walk- ", light); 
    for (int i = 3; i < N; i += 4) { 
     light[i] = light[i] == 1 ? 0 : 1; 
    } 
    show_lights_all("Lights after the fourth walk- ", light); 
} 

想想吧,假設你正在做類似for(int i=0;i<N;i++) light[i * 3 + 2]的事情,現在...當我= 3->光[11],我= 4->光[14],等等......並且您只分配了內存一個10個元素的數組。

一個更好的模式將被取代是這樣的:

for(int i=0;i<N;i++) light[i*k1+k2] 

通過類似:

for(int i=k2;i<N;i+=k1) light[i] 

這是它保證不會超出數組邊界

你之後」一個更安全的版本我已經理解了上面的解釋,下一步將會將代碼重構成不那麼冗長的東西:

#include <stdio.h> 

#define N 10 

#define LIGHTS_ALL -1 
#define LIGHTS_OFF 0 
#define LIGHTS_ON 1 

char *lights_str(int light[N], int status_light) { 
    char s[256] = {0}; 
    int n = 0; 

    for (int i = 0; i < N; i++) { 
     if (status_light == LIGHTS_OFF) { 
      if (light[i] == LIGHTS_OFF) n += sprintf(&s[n], "%d ", i); 
      continue; 
     } 
     if (status_light == LIGHTS_ON) { 
      if (light[i] == LIGHTS_ON) n += sprintf(&s[n], "%d ", i); 
      continue; 
     } 

     n += sprintf(&s[n], "%d", light[i]); 
    } 

    return s; 
} 

void firstwalk(int light[N]) { 
    for (int i = 0; i < N; i++) { 
     light[i] = 0; 
    } 
} 

void secondtwalk(int light[N]) { 
    for (int i = 1; i < N; i += 2) { 
     light[i] = 1; 
    } 
} 

void thirdtwalk(int light[N]) { 
    for (int i = 2; i < N; i += 3) { 
     light[i] = light[i] == 1 ? 0 : 1; 
    } 
} 

void fourthtwalk(int light[N]) { 
    for (int i = 3; i < N; i += 4) { 
     light[i] = light[i] == 1 ? 0 : 1; 
    } 
} 


int main() { 
    int light[N] = {0}; 
    char *walks[256] = {"first", "second", "third", "fourth"}; 

    void (*p[4])(int light[N]); 
    p[0] = firstwalk; 
    p[1] = secondtwalk; 
    p[2] = thirdtwalk; 
    p[3] = fourthtwalk; 
    for (int i = 0; i < 4; i++) { 
     printf("\nLights before the %s walk-\t%s", walks[i], 
       lights_str(light, LIGHTS_ALL)); 
     p[i](light); 
     printf("\tLights after the %s walk-\t%s", walks[i], 
       lights_str(light, LIGHTS_ALL)); 
    } 
    printf("\n\nFinal status\tLights on\t%s\tLights off\t%s", 
      lights_str(light, LIGHTS_OFF), lights_str(light, LIGHTS_ON)); 
} 

其實,不要停在這裏,試圖進一步重構,直到代碼變得越來越好...我會這個任務留給你:)

+1

Lot是很好的東西,但是C不允許像'char * lights_str(int light [N],int status_light = -1)那樣的默認參數' - 這是C++的一個特性。 –

+0

切換燈的狀態:而不是'light [i] = light [i] == 1? 0:1;',考慮'light [i] =!light [i]; - 但請記住'!='不是賦值運算符。 –

+0

@JonathanLeffler哦,謝謝,你是對的,c標籤在這裏:P。順便說一句,我懷疑我是否應該發佈第二個重構或不,我認爲OP的經驗是c-begginner和函數指針是中間的。我的意思是,我可以進行更多的重構...但是,這是否值得?光結構,動態數組,而不是使用靜態的作爲函數參數,... – BPL

相關問題